summaryrefslogtreecommitdiff
path: root/lib/Transforms/InstCombine/InstCombineAddSub.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/InstCombine/InstCombineAddSub.cpp')
-rw-r--r--lib/Transforms/InstCombine/InstCombineAddSub.cpp428
1 files changed, 283 insertions, 145 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 688897644848..aa31e0d850dd 100644
--- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -511,7 +511,8 @@ Value *FAddCombine::performFactorization(Instruction *I) {
}
Value *FAddCombine::simplify(Instruction *I) {
- assert(I->isFast() && "Expected 'fast' instruction");
+ assert(I->hasAllowReassoc() && I->hasNoSignedZeros() &&
+ "Expected 'reassoc'+'nsz' instruction");
// Currently we are not able to handle vector type.
if (I->getType()->isVectorTy())
@@ -855,48 +856,6 @@ Value *FAddCombine::createAddendVal(const FAddend &Opnd, bool &NeedNeg) {
return createFMul(OpndVal, Coeff.getValue(Instr->getType()));
}
-/// \brief Return true if we can prove that:
-/// (sub LHS, RHS) === (sub nsw LHS, RHS)
-/// This basically requires proving that the add in the original type would not
-/// overflow to change the sign bit or have a carry out.
-/// TODO: Handle this for Vectors.
-bool InstCombiner::willNotOverflowSignedSub(const Value *LHS,
- const Value *RHS,
- const Instruction &CxtI) const {
- // If LHS and RHS each have at least two sign bits, the subtraction
- // cannot overflow.
- if (ComputeNumSignBits(LHS, 0, &CxtI) > 1 &&
- ComputeNumSignBits(RHS, 0, &CxtI) > 1)
- return true;
-
- KnownBits LHSKnown = computeKnownBits(LHS, 0, &CxtI);
-
- KnownBits RHSKnown = computeKnownBits(RHS, 0, &CxtI);
-
- // Subtraction of two 2's complement numbers having identical signs will
- // never overflow.
- if ((LHSKnown.isNegative() && RHSKnown.isNegative()) ||
- (LHSKnown.isNonNegative() && RHSKnown.isNonNegative()))
- return true;
-
- // TODO: implement logic similar to checkRippleForAdd
- return false;
-}
-
-/// \brief Return true if we can prove that:
-/// (sub LHS, RHS) === (sub nuw LHS, RHS)
-bool InstCombiner::willNotOverflowUnsignedSub(const Value *LHS,
- const Value *RHS,
- const Instruction &CxtI) const {
- // If the LHS is negative and the RHS is non-negative, no unsigned wrap.
- KnownBits LHSKnown = computeKnownBits(LHS, /*Depth=*/0, &CxtI);
- KnownBits RHSKnown = computeKnownBits(RHS, /*Depth=*/0, &CxtI);
- if (LHSKnown.isNegative() && RHSKnown.isNonNegative())
- return true;
-
- return false;
-}
-
// Checks if any operand is negative and we can convert add to sub.
// This function checks for following negative patterns
// ADD(XOR(OR(Z, NOT(C)), C)), 1) == NEG(AND(Z, C))
@@ -964,7 +923,7 @@ Instruction *InstCombiner::foldAddWithConstant(BinaryOperator &Add) {
if (!match(Op1, m_Constant(Op1C)))
return nullptr;
- if (Instruction *NV = foldOpWithConstantIntoOperand(Add))
+ if (Instruction *NV = foldBinOpIntoSelectOrPhi(Add))
return NV;
Value *X;
@@ -1031,17 +990,148 @@ Instruction *InstCombiner::foldAddWithConstant(BinaryOperator &Add) {
return nullptr;
}
-Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
- bool Changed = SimplifyAssociativeOrCommutative(I);
- if (Value *V = SimplifyVectorOp(I))
- return replaceInstUsesWith(I, V);
+// Matches multiplication expression Op * C where C is a constant. Returns the
+// constant value in C and the other operand in Op. Returns true if such a
+// match is found.
+static bool MatchMul(Value *E, Value *&Op, APInt &C) {
+ const APInt *AI;
+ if (match(E, m_Mul(m_Value(Op), m_APInt(AI)))) {
+ C = *AI;
+ return true;
+ }
+ if (match(E, m_Shl(m_Value(Op), m_APInt(AI)))) {
+ C = APInt(AI->getBitWidth(), 1);
+ C <<= *AI;
+ return true;
+ }
+ return false;
+}
+
+// Matches remainder expression Op % C where C is a constant. Returns the
+// constant value in C and the other operand in Op. Returns the signedness of
+// the remainder operation in IsSigned. Returns true if such a match is
+// found.
+static bool MatchRem(Value *E, Value *&Op, APInt &C, bool &IsSigned) {
+ const APInt *AI;
+ IsSigned = false;
+ if (match(E, m_SRem(m_Value(Op), m_APInt(AI)))) {
+ IsSigned = true;
+ C = *AI;
+ return true;
+ }
+ if (match(E, m_URem(m_Value(Op), m_APInt(AI)))) {
+ C = *AI;
+ return true;
+ }
+ if (match(E, m_And(m_Value(Op), m_APInt(AI))) && (*AI + 1).isPowerOf2()) {
+ C = *AI + 1;
+ return true;
+ }
+ return false;
+}
+// Matches division expression Op / C with the given signedness as indicated
+// by IsSigned, where C is a constant. Returns the constant value in C and the
+// other operand in Op. Returns true if such a match is found.
+static bool MatchDiv(Value *E, Value *&Op, APInt &C, bool IsSigned) {
+ const APInt *AI;
+ if (IsSigned && match(E, m_SDiv(m_Value(Op), m_APInt(AI)))) {
+ C = *AI;
+ return true;
+ }
+ if (!IsSigned) {
+ if (match(E, m_UDiv(m_Value(Op), m_APInt(AI)))) {
+ C = *AI;
+ return true;
+ }
+ if (match(E, m_LShr(m_Value(Op), m_APInt(AI)))) {
+ C = APInt(AI->getBitWidth(), 1);
+ C <<= *AI;
+ return true;
+ }
+ }
+ return false;
+}
+
+// Returns whether C0 * C1 with the given signedness overflows.
+static bool MulWillOverflow(APInt &C0, APInt &C1, bool IsSigned) {
+ bool overflow;
+ if (IsSigned)
+ (void)C0.smul_ov(C1, overflow);
+ else
+ (void)C0.umul_ov(C1, overflow);
+ return overflow;
+}
+
+// Simplifies X % C0 + (( X / C0 ) % C1) * C0 to X % (C0 * C1), where (C0 * C1)
+// does not overflow.
+Value *InstCombiner::SimplifyAddWithRemainder(BinaryOperator &I) {
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
- if (Value *V =
- SimplifyAddInst(LHS, RHS, I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
- SQ.getWithInstruction(&I)))
+ Value *X, *MulOpV;
+ APInt C0, MulOpC;
+ bool IsSigned;
+ // Match I = X % C0 + MulOpV * C0
+ if (((MatchRem(LHS, X, C0, IsSigned) && MatchMul(RHS, MulOpV, MulOpC)) ||
+ (MatchRem(RHS, X, C0, IsSigned) && MatchMul(LHS, MulOpV, MulOpC))) &&
+ C0 == MulOpC) {
+ Value *RemOpV;
+ APInt C1;
+ bool Rem2IsSigned;
+ // Match MulOpC = RemOpV % C1
+ if (MatchRem(MulOpV, RemOpV, C1, Rem2IsSigned) &&
+ IsSigned == Rem2IsSigned) {
+ Value *DivOpV;
+ APInt DivOpC;
+ // Match RemOpV = X / C0
+ if (MatchDiv(RemOpV, DivOpV, DivOpC, IsSigned) && X == DivOpV &&
+ C0 == DivOpC && !MulWillOverflow(C0, C1, IsSigned)) {
+ Value *NewDivisor =
+ ConstantInt::get(X->getType()->getContext(), C0 * C1);
+ return IsSigned ? Builder.CreateSRem(X, NewDivisor, "srem")
+ : Builder.CreateURem(X, NewDivisor, "urem");
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+/// Fold
+/// (1 << NBits) - 1
+/// Into:
+/// ~(-(1 << NBits))
+/// Because a 'not' is better for bit-tracking analysis and other transforms
+/// than an 'add'. The new shl is always nsw, and is nuw if old `and` was.
+static Instruction *canonicalizeLowbitMask(BinaryOperator &I,
+ InstCombiner::BuilderTy &Builder) {
+ Value *NBits;
+ if (!match(&I, m_Add(m_OneUse(m_Shl(m_One(), m_Value(NBits))), m_AllOnes())))
+ return nullptr;
+
+ Constant *MinusOne = Constant::getAllOnesValue(NBits->getType());
+ Value *NotMask = Builder.CreateShl(MinusOne, NBits, "notmask");
+ // Be wary of constant folding.
+ if (auto *BOp = dyn_cast<BinaryOperator>(NotMask)) {
+ // Always NSW. But NUW propagates from `add`.
+ BOp->setHasNoSignedWrap();
+ BOp->setHasNoUnsignedWrap(I.hasNoUnsignedWrap());
+ }
+
+ return BinaryOperator::CreateNot(NotMask, I.getName());
+}
+
+Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
+ if (Value *V = SimplifyAddInst(I.getOperand(0), I.getOperand(1),
+ I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
+ SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V);
+ if (SimplifyAssociativeOrCommutative(I))
+ return &I;
+
+ if (Instruction *X = foldShuffledBinop(I))
+ return X;
+
// (A*B)+(A*C) -> A*(B+C) etc
if (Value *V = SimplifyUsingDistributiveLaws(I))
return replaceInstUsesWith(I, V);
@@ -1051,6 +1141,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
// FIXME: This should be moved into the above helper function to allow these
// transforms for general constant or constant splat vectors.
+ Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
Type *Ty = I.getType();
if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
Value *XorLHS = nullptr; ConstantInt *XorRHS = nullptr;
@@ -1123,6 +1214,14 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
if (Value *V = checkForNegativeOperand(I, Builder))
return replaceInstUsesWith(I, V);
+ // (A + 1) + ~B --> A - B
+ // ~B + (A + 1) --> A - B
+ if (match(&I, m_c_BinOp(m_Add(m_Value(A), m_One()), m_Not(m_Value(B)))))
+ return BinaryOperator::CreateSub(A, B);
+
+ // X % C0 + (( X / C0 ) % C1) * C0 => X % (C0 * C1)
+ if (Value *V = SimplifyAddWithRemainder(I)) return replaceInstUsesWith(I, V);
+
// A+B --> A|B iff A and B have no bits set in common.
if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT))
return BinaryOperator::CreateOr(LHS, RHS);
@@ -1253,26 +1352,15 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
}
// (add (xor A, B) (and A, B)) --> (or A, B)
- if (match(LHS, m_Xor(m_Value(A), m_Value(B))) &&
- match(RHS, m_c_And(m_Specific(A), m_Specific(B))))
- return BinaryOperator::CreateOr(A, B);
-
// (add (and A, B) (xor A, B)) --> (or A, B)
- if (match(RHS, m_Xor(m_Value(A), m_Value(B))) &&
- match(LHS, m_c_And(m_Specific(A), m_Specific(B))))
+ if (match(&I, m_c_BinOp(m_Xor(m_Value(A), m_Value(B)),
+ m_c_And(m_Deferred(A), m_Deferred(B)))))
return BinaryOperator::CreateOr(A, B);
// (add (or A, B) (and A, B)) --> (add A, B)
- if (match(LHS, m_Or(m_Value(A), m_Value(B))) &&
- match(RHS, m_c_And(m_Specific(A), m_Specific(B)))) {
- I.setOperand(0, A);
- I.setOperand(1, B);
- return &I;
- }
-
// (add (and A, B) (or A, B)) --> (add A, B)
- if (match(RHS, m_Or(m_Value(A), m_Value(B))) &&
- match(LHS, m_c_And(m_Specific(A), m_Specific(B)))) {
+ if (match(&I, m_c_BinOp(m_Or(m_Value(A), m_Value(B)),
+ m_c_And(m_Deferred(A), m_Deferred(B))))) {
I.setOperand(0, A);
I.setOperand(1, B);
return &I;
@@ -1281,6 +1369,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
// TODO(jingyue): Consider willNotOverflowSignedAdd and
// willNotOverflowUnsignedAdd to reduce the number of invocations of
// computeKnownBits.
+ bool Changed = false;
if (!I.hasNoSignedWrap() && willNotOverflowSignedAdd(LHS, RHS, I)) {
Changed = true;
I.setHasNoSignedWrap(true);
@@ -1290,39 +1379,35 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
I.setHasNoUnsignedWrap(true);
}
+ if (Instruction *V = canonicalizeLowbitMask(I, Builder))
+ return V;
+
return Changed ? &I : nullptr;
}
Instruction *InstCombiner::visitFAdd(BinaryOperator &I) {
- bool Changed = SimplifyAssociativeOrCommutative(I);
- Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
-
- if (Value *V = SimplifyVectorOp(I))
- return replaceInstUsesWith(I, V);
-
- if (Value *V = SimplifyFAddInst(LHS, RHS, I.getFastMathFlags(),
+ if (Value *V = SimplifyFAddInst(I.getOperand(0), I.getOperand(1),
+ I.getFastMathFlags(),
SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V);
- if (isa<Constant>(RHS))
- if (Instruction *FoldedFAdd = foldOpWithConstantIntoOperand(I))
- return FoldedFAdd;
+ if (SimplifyAssociativeOrCommutative(I))
+ return &I;
- // -A + B --> B - A
- // -A + -B --> -(A + B)
- if (Value *LHSV = dyn_castFNegVal(LHS)) {
- Instruction *RI = BinaryOperator::CreateFSub(RHS, LHSV);
- RI->copyFastMathFlags(&I);
- return RI;
- }
+ if (Instruction *X = foldShuffledBinop(I))
+ return X;
- // A + -B --> A - B
- if (!isa<Constant>(RHS))
- if (Value *V = dyn_castFNegVal(RHS)) {
- Instruction *RI = BinaryOperator::CreateFSub(LHS, V);
- RI->copyFastMathFlags(&I);
- return RI;
- }
+ if (Instruction *FoldedFAdd = foldBinOpIntoSelectOrPhi(I))
+ return FoldedFAdd;
+
+ Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
+ Value *X;
+ // (-X) + Y --> Y - X
+ if (match(LHS, m_FNeg(m_Value(X))))
+ return BinaryOperator::CreateFSubFMF(RHS, X, &I);
+ // Y + (-X) --> Y - X
+ if (match(RHS, m_FNeg(m_Value(X))))
+ return BinaryOperator::CreateFSubFMF(LHS, X, &I);
// Check for (fadd double (sitofp x), y), see if we can merge this into an
// integer add followed by a promotion.
@@ -1386,12 +1471,12 @@ Instruction *InstCombiner::visitFAdd(BinaryOperator &I) {
if (Value *V = SimplifySelectsFeedingBinaryOp(I, LHS, RHS))
return replaceInstUsesWith(I, V);
- if (I.isFast()) {
+ if (I.hasAllowReassoc() && I.hasNoSignedZeros()) {
if (Value *V = FAddCombine(Builder).simplify(&I))
return replaceInstUsesWith(I, V);
}
- return Changed ? &I : nullptr;
+ return nullptr;
}
/// Optimize pointer differences into the same array into a size. Consider:
@@ -1481,21 +1566,20 @@ Value *InstCombiner::OptimizePointerDifference(Value *LHS, Value *RHS,
}
Instruction *InstCombiner::visitSub(BinaryOperator &I) {
- Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
-
- if (Value *V = SimplifyVectorOp(I))
+ if (Value *V = SimplifySubInst(I.getOperand(0), I.getOperand(1),
+ I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
+ SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V);
- if (Value *V =
- SimplifySubInst(Op0, Op1, I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
- SQ.getWithInstruction(&I)))
- return replaceInstUsesWith(I, V);
+ if (Instruction *X = foldShuffledBinop(I))
+ return X;
// (A*B)-(A*C) -> A*(B-C) etc
if (Value *V = SimplifyUsingDistributiveLaws(I))
return replaceInstUsesWith(I, V);
// If this is a 'B = x-(-A)', change to B = x+A.
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (Value *V = dyn_castNegVal(Op1)) {
BinaryOperator *Res = BinaryOperator::CreateAdd(Op0, V);
@@ -1519,12 +1603,28 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
if (match(Op0, m_AllOnes()))
return BinaryOperator::CreateNot(Op1);
+ // (~X) - (~Y) --> Y - X
+ Value *X, *Y;
+ if (match(Op0, m_Not(m_Value(X))) && match(Op1, m_Not(m_Value(Y))))
+ return BinaryOperator::CreateSub(Y, X);
+
if (Constant *C = dyn_cast<Constant>(Op0)) {
+ bool IsNegate = match(C, m_ZeroInt());
Value *X;
- // C - zext(bool) -> bool ? C - 1 : C
- if (match(Op1, m_ZExt(m_Value(X))) &&
- X->getType()->getScalarSizeInBits() == 1)
+ if (match(Op1, m_ZExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) {
+ // 0 - (zext bool) --> sext bool
+ // C - (zext bool) --> bool ? C - 1 : C
+ if (IsNegate)
+ return CastInst::CreateSExtOrBitCast(X, I.getType());
return SelectInst::Create(X, SubOne(C), C);
+ }
+ if (match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) {
+ // 0 - (sext bool) --> zext bool
+ // C - (sext bool) --> bool ? C + 1 : C
+ if (IsNegate)
+ return CastInst::CreateZExtOrBitCast(X, I.getType());
+ return SelectInst::Create(X, AddOne(C), C);
+ }
// C - ~X == X + (1+C)
if (match(Op1, m_Not(m_Value(X))))
@@ -1544,16 +1644,6 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
Constant *C2;
if (match(Op1, m_Add(m_Value(X), m_Constant(C2))))
return BinaryOperator::CreateSub(ConstantExpr::getSub(C, C2), X);
-
- // Fold (sub 0, (zext bool to B)) --> (sext bool to B)
- if (C->isNullValue() && match(Op1, m_ZExt(m_Value(X))))
- if (X->getType()->isIntOrIntVectorTy(1))
- return CastInst::CreateSExtOrBitCast(X, Op1->getType());
-
- // Fold (sub 0, (sext bool to B)) --> (zext bool to B)
- if (C->isNullValue() && match(Op1, m_SExt(m_Value(X))))
- if (X->getType()->isIntOrIntVectorTy(1))
- return CastInst::CreateZExtOrBitCast(X, Op1->getType());
}
const APInt *Op0C;
@@ -1575,6 +1665,22 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
Value *ShAmtOp = cast<Instruction>(Op1)->getOperand(1);
return BinaryOperator::CreateLShr(X, ShAmtOp);
}
+
+ if (Op1->hasOneUse()) {
+ Value *LHS, *RHS;
+ SelectPatternFlavor SPF = matchSelectPattern(Op1, LHS, RHS).Flavor;
+ if (SPF == SPF_ABS || SPF == SPF_NABS) {
+ // This is a negate of an ABS/NABS pattern. Just swap the operands
+ // of the select.
+ SelectInst *SI = cast<SelectInst>(Op1);
+ Value *TrueVal = SI->getTrueValue();
+ Value *FalseVal = SI->getFalseValue();
+ SI->setTrueValue(FalseVal);
+ SI->setFalseValue(TrueVal);
+ // Don't swap prof metadata, we didn't change the branch behavior.
+ return replaceInstUsesWith(I, SI);
+ }
+ }
}
// Turn this into a xor if LHS is 2^n-1 and the remaining bits are known
@@ -1678,6 +1784,27 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
if (Value *Res = OptimizePointerDifference(LHSOp, RHSOp, I.getType()))
return replaceInstUsesWith(I, Res);
+ // Canonicalize a shifty way to code absolute value to the common pattern.
+ // There are 2 potential commuted variants.
+ // We're relying on the fact that we only do this transform when the shift has
+ // exactly 2 uses and the xor has exactly 1 use (otherwise, we might increase
+ // instructions).
+ Value *A;
+ const APInt *ShAmt;
+ Type *Ty = I.getType();
+ if (match(Op1, m_AShr(m_Value(A), m_APInt(ShAmt))) &&
+ Op1->hasNUses(2) && *ShAmt == Ty->getScalarSizeInBits() - 1 &&
+ match(Op0, m_OneUse(m_c_Xor(m_Specific(A), m_Specific(Op1))))) {
+ // B = ashr i32 A, 31 ; smear the sign bit
+ // sub (xor A, B), B ; flip bits if negative and subtract -1 (add 1)
+ // --> (A < 0) ? -A : A
+ Value *Cmp = Builder.CreateICmpSLT(A, ConstantInt::getNullValue(Ty));
+ // Copy the nuw/nsw flags from the sub to the negate.
+ Value *Neg = Builder.CreateNeg(A, "", I.hasNoUnsignedWrap(),
+ I.hasNoSignedWrap());
+ return SelectInst::Create(Cmp, Neg, A);
+ }
+
bool Changed = false;
if (!I.hasNoSignedWrap() && willNotOverflowSignedSub(Op0, Op1, I)) {
Changed = true;
@@ -1692,21 +1819,32 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
}
Instruction *InstCombiner::visitFSub(BinaryOperator &I) {
- Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
-
- if (Value *V = SimplifyVectorOp(I))
- return replaceInstUsesWith(I, V);
-
- if (Value *V = SimplifyFSubInst(Op0, Op1, I.getFastMathFlags(),
+ if (Value *V = SimplifyFSubInst(I.getOperand(0), I.getOperand(1),
+ I.getFastMathFlags(),
SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V);
+ if (Instruction *X = foldShuffledBinop(I))
+ return X;
+
+ // Subtraction from -0.0 is the canonical form of fneg.
// fsub nsz 0, X ==> fsub nsz -0.0, X
- if (I.getFastMathFlags().noSignedZeros() && match(Op0, m_Zero())) {
- // Subtraction from -0.0 is the canonical form of fneg.
- Instruction *NewI = BinaryOperator::CreateFNeg(Op1);
- NewI->copyFastMathFlags(&I);
- return NewI;
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+ if (I.hasNoSignedZeros() && match(Op0, m_PosZeroFP()))
+ return BinaryOperator::CreateFNegFMF(Op1, &I);
+
+ // If Op0 is not -0.0 or we can ignore -0.0: Z - (X - Y) --> Z + (Y - X)
+ // Canonicalize to fadd to make analysis easier.
+ // This can also help codegen because fadd is commutative.
+ // Note that if this fsub was really an fneg, the fadd with -0.0 will get
+ // killed later. We still limit that particular transform with 'hasOneUse'
+ // because an fneg is assumed better/cheaper than a generic fsub.
+ Value *X, *Y;
+ if (I.hasNoSignedZeros() || CannotBeNegativeZero(Op0, SQ.TLI)) {
+ if (match(Op1, m_OneUse(m_FSub(m_Value(X), m_Value(Y))))) {
+ Value *NewSub = Builder.CreateFSubFMF(Y, X, &I);
+ return BinaryOperator::CreateFAddFMF(Op0, NewSub, &I);
+ }
}
if (isa<Constant>(Op0))
@@ -1714,34 +1852,34 @@ Instruction *InstCombiner::visitFSub(BinaryOperator &I) {
if (Instruction *NV = FoldOpIntoSelect(I, SI))
return NV;
- // If this is a 'B = x-(-A)', change to B = x+A, potentially looking
- // through FP extensions/truncations along the way.
- if (Value *V = dyn_castFNegVal(Op1)) {
- Instruction *NewI = BinaryOperator::CreateFAdd(Op0, V);
- NewI->copyFastMathFlags(&I);
- return NewI;
- }
- if (FPTruncInst *FPTI = dyn_cast<FPTruncInst>(Op1)) {
- if (Value *V = dyn_castFNegVal(FPTI->getOperand(0))) {
- Value *NewTrunc = Builder.CreateFPTrunc(V, I.getType());
- Instruction *NewI = BinaryOperator::CreateFAdd(Op0, NewTrunc);
- NewI->copyFastMathFlags(&I);
- return NewI;
- }
- } else if (FPExtInst *FPEI = dyn_cast<FPExtInst>(Op1)) {
- if (Value *V = dyn_castFNegVal(FPEI->getOperand(0))) {
- Value *NewExt = Builder.CreateFPExt(V, I.getType());
- Instruction *NewI = BinaryOperator::CreateFAdd(Op0, NewExt);
- NewI->copyFastMathFlags(&I);
- return NewI;
- }
+ // X - C --> X + (-C)
+ // But don't transform constant expressions because there's an inverse fold
+ // for X + (-Y) --> X - Y.
+ Constant *C;
+ if (match(Op1, m_Constant(C)) && !isa<ConstantExpr>(Op1))
+ return BinaryOperator::CreateFAddFMF(Op0, ConstantExpr::getFNeg(C), &I);
+
+ // X - (-Y) --> X + Y
+ if (match(Op1, m_FNeg(m_Value(Y))))
+ return BinaryOperator::CreateFAddFMF(Op0, Y, &I);
+
+ // Similar to above, but look through a cast of the negated value:
+ // X - (fptrunc(-Y)) --> X + fptrunc(Y)
+ if (match(Op1, m_OneUse(m_FPTrunc(m_FNeg(m_Value(Y)))))) {
+ Value *TruncY = Builder.CreateFPTrunc(Y, I.getType());
+ return BinaryOperator::CreateFAddFMF(Op0, TruncY, &I);
+ }
+ // X - (fpext(-Y)) --> X + fpext(Y)
+ if (match(Op1, m_OneUse(m_FPExt(m_FNeg(m_Value(Y)))))) {
+ Value *ExtY = Builder.CreateFPExt(Y, I.getType());
+ return BinaryOperator::CreateFAddFMF(Op0, ExtY, &I);
}
// Handle specials cases for FSub with selects feeding the operation
if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1))
return replaceInstUsesWith(I, V);
- if (I.isFast()) {
+ if (I.hasAllowReassoc() && I.hasNoSignedZeros()) {
if (Value *V = FAddCombine(Builder).simplify(&I))
return replaceInstUsesWith(I, V);
}