summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp27
1 files changed, 27 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 05d13aeabe5..c723ba0a683 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -1899,6 +1899,33 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
}
{
+ // If we are subtracting the select with one hand matching the value
+ // we are subtracting from, sink subtraction into hands of select:
+ // sub %Op0, (select %Cond, %TrueVal, %FalseVal)
+ // ->
+ // select %Cond, (sub %Op0, %TrueVal), (sub %Op0, %FalseVal)
+ // This will result in select between new subtraction and 0.
+ Value *Cond, *TrueVal, *FalseVal;
+ if (match(Op1, m_OneUse(m_Select(m_Value(Cond), m_Value(TrueVal),
+ m_Value(FalseVal)))) &&
+ (Op0 == TrueVal || Op0 == FalseVal)) {
+ // While it is really tempting to just create two subtractions and let
+ // InstCombine fold one of those to 0, it isn't possible to do so
+ // because of worklist visitation order. So ugly it is.
+ bool SubtractingFromTrueVal = Op0 == TrueVal;
+ Value *NewSub =
+ Builder.CreateSub(Op0, SubtractingFromTrueVal ? FalseVal : TrueVal);
+ Constant *Zero = Constant::getNullValue(I.getType());
+ SelectInst *NewSel =
+ SelectInst::Create(Cond, SubtractingFromTrueVal ? Zero : NewSub,
+ SubtractingFromTrueVal ? NewSub : Zero);
+ // Preserve prof metadata if any.
+ NewSel->copyMetadata(cast<Instruction>(*Op1));
+ return NewSel;
+ }
+ }
+
+ {
// If we are subtracting from select with one hand matching the value
// we are subtracting, sink subtraction into hands of select:
// sub (select %Cond, %TrueVal, %FalseVal), %Op1
OpenPOWER on IntegriCloud