summaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-03 14:10:23 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-07-03 14:10:23 +0000
commit145449b1e420787bb99721a429341fa6be3adfb6 (patch)
tree1d56ae694a6de602e348dd80165cf881a36600ed /llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
parentecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (diff)
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp115
1 files changed, 65 insertions, 50 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 0598f751febe..f4d8b79a5311 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -693,9 +693,6 @@ unsigned FAddCombine::calcInstrNumber(const AddendVect &Opnds) {
unsigned OpndNum = Opnds.size();
unsigned InstrNeeded = OpndNum - 1;
- // The number of addends in the form of "(-1)*x".
- unsigned NegOpndNum = 0;
-
// Adjust the number of instructions needed to emit the N-ary add.
for (const FAddend *Opnd : Opnds) {
if (Opnd->isConstant())
@@ -707,9 +704,6 @@ unsigned FAddCombine::calcInstrNumber(const AddendVect &Opnds) {
continue;
const FAddendCoef &CE = Opnd->getCoef();
- if (CE.isMinusOne() || CE.isMinusTwo())
- NegOpndNum++;
-
// Let the addend be "c * x". If "c == +/-1", the value of the addend
// is immediately available; otherwise, it needs exactly one instruction
// to evaluate the value.
@@ -1277,7 +1271,7 @@ static Instruction *factorizeMathWithShlOps(BinaryOperator &I,
}
Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
- if (Value *V = SimplifyAddInst(I.getOperand(0), I.getOperand(1),
+ if (Value *V = simplifyAddInst(I.getOperand(0), I.getOperand(1),
I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V);
@@ -1375,6 +1369,13 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
}
}
+ // (A & 2^C1) + A => A & (2^C1 - 1) iff bit C1 in A is a sign bit
+ if (match(&I, m_c_Add(m_And(m_Value(A), m_APInt(C1)), m_Deferred(A))) &&
+ C1->isPowerOf2() && (ComputeNumSignBits(A) > C1->countLeadingZeros())) {
+ Constant *NewMask = ConstantInt::get(RHS->getType(), *C1 - 1);
+ return BinaryOperator::CreateAnd(A, NewMask);
+ }
+
// 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);
@@ -1528,7 +1529,7 @@ static Instruction *factorizeFAddFSub(BinaryOperator &I,
}
Instruction *InstCombinerImpl::visitFAdd(BinaryOperator &I) {
- if (Value *V = SimplifyFAddInst(I.getOperand(0), I.getOperand(1),
+ if (Value *V = simplifyFAddInst(I.getOperand(0), I.getOperand(1),
I.getFastMathFlags(),
SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V);
@@ -1687,7 +1688,8 @@ Value *InstCombinerImpl::OptimizePointerDifference(Value *LHS, Value *RHS,
// Require at least one GEP with a common base pointer on both sides.
if (auto *LHSGEP = dyn_cast<GEPOperator>(LHS)) {
// (gep X, ...) - X
- if (LHSGEP->getOperand(0) == RHS) {
+ if (LHSGEP->getOperand(0)->stripPointerCasts() ==
+ RHS->stripPointerCasts()) {
GEP1 = LHSGEP;
} else if (auto *RHSGEP = dyn_cast<GEPOperator>(RHS)) {
// (gep X, ...) - (gep X, ...)
@@ -1749,7 +1751,7 @@ Value *InstCombinerImpl::OptimizePointerDifference(Value *LHS, Value *RHS,
}
Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
- if (Value *V = SimplifySubInst(I.getOperand(0), I.getOperand(1),
+ if (Value *V = simplifySubInst(I.getOperand(0), I.getOperand(1),
I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V);
@@ -2014,6 +2016,37 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
}
}
+ if (auto *II = dyn_cast<MinMaxIntrinsic>(Op1)) {
+ {
+ // sub(add(X,Y), s/umin(X,Y)) --> s/umax(X,Y)
+ // sub(add(X,Y), s/umax(X,Y)) --> s/umin(X,Y)
+ Value *X = II->getLHS();
+ Value *Y = II->getRHS();
+ if (match(Op0, m_c_Add(m_Specific(X), m_Specific(Y))) &&
+ (Op0->hasOneUse() || Op1->hasOneUse())) {
+ Intrinsic::ID InvID = getInverseMinMaxIntrinsic(II->getIntrinsicID());
+ Value *InvMaxMin = Builder.CreateBinaryIntrinsic(InvID, X, Y);
+ return replaceInstUsesWith(I, InvMaxMin);
+ }
+ }
+
+ {
+ // sub(add(X,Y),umin(Y,Z)) --> add(X,usub.sat(Y,Z))
+ // sub(add(X,Z),umin(Y,Z)) --> add(X,usub.sat(Z,Y))
+ Value *X, *Y, *Z;
+ if (match(Op1, m_OneUse(m_UMin(m_Value(Y), m_Value(Z))))) {
+ if (match(Op0, m_OneUse(m_c_Add(m_Specific(Y), m_Value(X)))))
+ return BinaryOperator::CreateAdd(
+ X, Builder.CreateIntrinsic(Intrinsic::usub_sat, I.getType(),
+ {Y, Z}));
+ if (match(Op0, m_OneUse(m_c_Add(m_Specific(Z), m_Value(X)))))
+ return BinaryOperator::CreateAdd(
+ X, Builder.CreateIntrinsic(Intrinsic::usub_sat, I.getType(),
+ {Z, Y}));
+ }
+ }
+ }
+
{
// If we have a subtraction between some value and a select between
// said value and something else, sink subtraction into select hands, i.e.:
@@ -2089,36 +2122,6 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
return BinaryOperator::CreateSub(X, Not);
}
- // TODO: This is the same logic as above but handles the cmp-select idioms
- // for min/max, so the use checks are increased to account for the
- // extra instructions. If we canonicalize to intrinsics, this block
- // can likely be removed.
- {
- Value *LHS, *RHS, *A;
- Value *NotA = Op0, *MinMax = Op1;
- SelectPatternFlavor SPF = matchSelectPattern(MinMax, LHS, RHS).Flavor;
- if (!SelectPatternResult::isMinOrMax(SPF)) {
- NotA = Op1;
- MinMax = Op0;
- SPF = matchSelectPattern(MinMax, LHS, RHS).Flavor;
- }
- if (SelectPatternResult::isMinOrMax(SPF) &&
- match(NotA, m_Not(m_Value(A))) && (NotA == LHS || NotA == RHS)) {
- if (NotA == LHS)
- std::swap(LHS, RHS);
- // LHS is now Y above and expected to have at least 2 uses (the min/max)
- // NotA is expected to have 2 uses from the min/max and 1 from the sub.
- if (isFreeToInvert(LHS, !LHS->hasNUsesOrMore(3)) &&
- !NotA->hasNUsesOrMore(4)) {
- Value *Not = Builder.CreateNot(MinMax);
- if (NotA == Op0)
- return BinaryOperator::CreateSub(Not, A);
- else
- return BinaryOperator::CreateSub(A, Not);
- }
- }
- }
-
// Optimize pointer differences into the same array into a size. Consider:
// &A[10] - &A[0]: we should compile this to "10".
Value *LHSOp, *RHSOp;
@@ -2149,11 +2152,11 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
// 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));
+ Value *IsNeg = Builder.CreateIsNeg(A);
// 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);
+ Value *NegA = Builder.CreateNeg(A, "", I.hasNoUnsignedWrap(),
+ I.hasNoSignedWrap());
+ return SelectInst::Create(IsNeg, NegA, A);
}
// If we are subtracting a low-bit masked subset of some value from an add
@@ -2187,12 +2190,23 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
return replaceInstUsesWith(
I, Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {X, Op1}));
+ // Op0 - umin(X, Op0) --> usub.sat(Op0, X)
+ if (match(Op1, m_OneUse(m_c_UMin(m_Value(X), m_Specific(Op0)))))
+ return replaceInstUsesWith(
+ I, Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {Op0, X}));
+
// Op0 - umax(X, Op0) --> 0 - usub.sat(X, Op0)
if (match(Op1, m_OneUse(m_c_UMax(m_Value(X), m_Specific(Op0))))) {
Value *USub = Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {X, Op0});
return BinaryOperator::CreateNeg(USub);
}
+ // umin(X, Op1) - Op1 --> 0 - usub.sat(Op1, X)
+ if (match(Op0, m_OneUse(m_c_UMin(m_Value(X), m_Specific(Op1))))) {
+ Value *USub = Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {Op1, X});
+ return BinaryOperator::CreateNeg(USub);
+ }
+
// C - ctpop(X) => ctpop(~X) if C is bitwidth
if (match(Op0, m_SpecificInt(Ty->getScalarSizeInBits())) &&
match(Op1, m_OneUse(m_Intrinsic<Intrinsic::ctpop>(m_Value(X)))))
@@ -2264,7 +2278,7 @@ static Instruction *hoistFNegAboveFMulFDiv(Instruction &I,
Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) {
Value *Op = I.getOperand(0);
- if (Value *V = SimplifyFNegInst(Op, I.getFastMathFlags(),
+ if (Value *V = simplifyFNegInst(Op, I.getFastMathFlags(),
getSimplifyQuery().getWithInstruction(&I)))
return replaceInstUsesWith(I, V);
@@ -2287,10 +2301,11 @@ Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) {
// Unlike most transforms, this one is not safe to propagate nsz unless
// it is present on the original select. (We are conservatively intersecting
// the nsz flags from the select and root fneg instruction.)
- auto propagateSelectFMF = [&](SelectInst *S) {
+ auto propagateSelectFMF = [&](SelectInst *S, bool CommonOperand) {
S->copyFastMathFlags(&I);
if (auto *OldSel = dyn_cast<SelectInst>(Op))
- if (!OldSel->hasNoSignedZeros())
+ if (!OldSel->hasNoSignedZeros() && !CommonOperand &&
+ !isGuaranteedNotToBeUndefOrPoison(OldSel->getCondition()))
S->setHasNoSignedZeros(false);
};
// -(Cond ? -P : Y) --> Cond ? P : -Y
@@ -2298,14 +2313,14 @@ Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) {
if (match(X, m_FNeg(m_Value(P)))) {
Value *NegY = Builder.CreateFNegFMF(Y, &I, Y->getName() + ".neg");
SelectInst *NewSel = SelectInst::Create(Cond, P, NegY);
- propagateSelectFMF(NewSel);
+ propagateSelectFMF(NewSel, P == Y);
return NewSel;
}
// -(Cond ? X : -P) --> Cond ? -X : P
if (match(Y, m_FNeg(m_Value(P)))) {
Value *NegX = Builder.CreateFNegFMF(X, &I, X->getName() + ".neg");
SelectInst *NewSel = SelectInst::Create(Cond, NegX, P);
- propagateSelectFMF(NewSel);
+ propagateSelectFMF(NewSel, P == X);
return NewSel;
}
}
@@ -2314,7 +2329,7 @@ Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) {
}
Instruction *InstCombinerImpl::visitFSub(BinaryOperator &I) {
- if (Value *V = SimplifyFSubInst(I.getOperand(0), I.getOperand(1),
+ if (Value *V = simplifyFSubInst(I.getOperand(0), I.getOperand(1),
I.getFastMathFlags(),
getSimplifyQuery().getWithInstruction(&I)))
return replaceInstUsesWith(I, V);