aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstructionCombining.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstructionCombining.cpp619
1 files changed, 456 insertions, 163 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index afd6e034f46d..f072f5cec309 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -130,13 +130,6 @@ STATISTIC(NumReassoc , "Number of reassociations");
DEBUG_COUNTER(VisitCounter, "instcombine-visit",
"Controls which instructions are visited");
-// FIXME: these limits eventually should be as low as 2.
-#ifndef NDEBUG
-static constexpr unsigned InstCombineDefaultInfiniteLoopThreshold = 100;
-#else
-static constexpr unsigned InstCombineDefaultInfiniteLoopThreshold = 1000;
-#endif
-
static cl::opt<bool>
EnableCodeSinking("instcombine-code-sinking", cl::desc("Enable code sinking"),
cl::init(true));
@@ -145,12 +138,6 @@ static cl::opt<unsigned> MaxSinkNumUsers(
"instcombine-max-sink-users", cl::init(32),
cl::desc("Maximum number of undroppable users for instruction sinking"));
-static cl::opt<unsigned> InfiniteLoopDetectionThreshold(
- "instcombine-infinite-loop-threshold",
- cl::desc("Number of instruction combining iterations considered an "
- "infinite loop"),
- cl::init(InstCombineDefaultInfiniteLoopThreshold), cl::Hidden);
-
static cl::opt<unsigned>
MaxArraySize("instcombine-maxarray-size", cl::init(1024),
cl::desc("Maximum array size considered when doing a combine"));
@@ -358,15 +345,19 @@ static bool simplifyAssocCastAssoc(BinaryOperator *BinOp1,
// Fold the constants together in the destination type:
// (op (cast (op X, C2)), C1) --> (op (cast X), FoldedC)
+ const DataLayout &DL = IC.getDataLayout();
Type *DestTy = C1->getType();
- Constant *CastC2 = ConstantExpr::getCast(CastOpcode, C2, DestTy);
- Constant *FoldedC =
- ConstantFoldBinaryOpOperands(AssocOpcode, C1, CastC2, IC.getDataLayout());
+ Constant *CastC2 = ConstantFoldCastOperand(CastOpcode, C2, DestTy, DL);
+ if (!CastC2)
+ return false;
+ Constant *FoldedC = ConstantFoldBinaryOpOperands(AssocOpcode, C1, CastC2, DL);
if (!FoldedC)
return false;
IC.replaceOperand(*Cast, 0, BinOp2->getOperand(0));
IC.replaceOperand(*BinOp1, 1, FoldedC);
+ BinOp1->dropPoisonGeneratingFlags();
+ Cast->dropPoisonGeneratingFlags();
return true;
}
@@ -542,12 +533,12 @@ bool InstCombinerImpl::SimplifyAssociativeOrCommutative(BinaryOperator &I) {
BinaryOperator::Create(Opcode, A, B);
if (isa<FPMathOperator>(NewBO)) {
- FastMathFlags Flags = I.getFastMathFlags();
- Flags &= Op0->getFastMathFlags();
- Flags &= Op1->getFastMathFlags();
- NewBO->setFastMathFlags(Flags);
+ FastMathFlags Flags = I.getFastMathFlags() &
+ Op0->getFastMathFlags() &
+ Op1->getFastMathFlags();
+ NewBO->setFastMathFlags(Flags);
}
- InsertNewInstWith(NewBO, I);
+ InsertNewInstWith(NewBO, I.getIterator());
NewBO->takeName(Op1);
replaceOperand(I, 0, NewBO);
replaceOperand(I, 1, CRes);
@@ -749,7 +740,16 @@ static Value *tryFactorization(BinaryOperator &I, const SimplifyQuery &SQ,
// 2) BinOp1 == BinOp2 (if BinOp == `add`, then also requires `shl`).
//
// -> (BinOp (logic_shift (BinOp X, Y)), Mask)
+//
+// (Binop1 (Binop2 (arithmetic_shift X, Amt), Mask), (arithmetic_shift Y, Amt))
+// IFF
+// 1) Binop1 is bitwise logical operator `and`, `or` or `xor`
+// 2) Binop2 is `not`
+//
+// -> (arithmetic_shift Binop1((not X), Y), Amt)
+
Instruction *InstCombinerImpl::foldBinOpShiftWithShift(BinaryOperator &I) {
+ const DataLayout &DL = I.getModule()->getDataLayout();
auto IsValidBinOpc = [](unsigned Opc) {
switch (Opc) {
default:
@@ -768,11 +768,13 @@ Instruction *InstCombinerImpl::foldBinOpShiftWithShift(BinaryOperator &I) {
// constraints.
auto IsCompletelyDistributable = [](unsigned BinOpc1, unsigned BinOpc2,
unsigned ShOpc) {
+ assert(ShOpc != Instruction::AShr);
return (BinOpc1 != Instruction::Add && BinOpc2 != Instruction::Add) ||
ShOpc == Instruction::Shl;
};
auto GetInvShift = [](unsigned ShOpc) {
+ assert(ShOpc != Instruction::AShr);
return ShOpc == Instruction::LShr ? Instruction::Shl : Instruction::LShr;
};
@@ -796,23 +798,23 @@ Instruction *InstCombinerImpl::foldBinOpShiftWithShift(BinaryOperator &I) {
// Otherwise, need mask that meets the below requirement.
// (logic_shift (inv_logic_shift Mask, ShAmt), ShAmt) == Mask
- return ConstantExpr::get(
- ShOpc, ConstantExpr::get(GetInvShift(ShOpc), CMask, CShift),
- CShift) == CMask;
+ Constant *MaskInvShift =
+ ConstantFoldBinaryOpOperands(GetInvShift(ShOpc), CMask, CShift, DL);
+ return ConstantFoldBinaryOpOperands(ShOpc, MaskInvShift, CShift, DL) ==
+ CMask;
};
auto MatchBinOp = [&](unsigned ShOpnum) -> Instruction * {
Constant *CMask, *CShift;
Value *X, *Y, *ShiftedX, *Mask, *Shift;
if (!match(I.getOperand(ShOpnum),
- m_OneUse(m_LogicalShift(m_Value(Y), m_Value(Shift)))))
+ m_OneUse(m_Shift(m_Value(Y), m_Value(Shift)))))
return nullptr;
if (!match(I.getOperand(1 - ShOpnum),
m_BinOp(m_Value(ShiftedX), m_Value(Mask))))
return nullptr;
- if (!match(ShiftedX,
- m_OneUse(m_LogicalShift(m_Value(X), m_Specific(Shift)))))
+ if (!match(ShiftedX, m_OneUse(m_Shift(m_Value(X), m_Specific(Shift)))))
return nullptr;
// Make sure we are matching instruction shifts and not ConstantExpr
@@ -836,6 +838,18 @@ Instruction *InstCombinerImpl::foldBinOpShiftWithShift(BinaryOperator &I) {
if (!IsValidBinOpc(I.getOpcode()) || !IsValidBinOpc(BinOpc))
return nullptr;
+ if (ShOpc == Instruction::AShr) {
+ if (Instruction::isBitwiseLogicOp(I.getOpcode()) &&
+ BinOpc == Instruction::Xor && match(Mask, m_AllOnes())) {
+ Value *NotX = Builder.CreateNot(X);
+ Value *NewBinOp = Builder.CreateBinOp(I.getOpcode(), Y, NotX);
+ return BinaryOperator::Create(
+ static_cast<Instruction::BinaryOps>(ShOpc), NewBinOp, Shift);
+ }
+
+ return nullptr;
+ }
+
// If BinOp1 == BinOp2 and it's bitwise or shl with add, then just
// distribute to drop the shift irrelevant of constants.
if (BinOpc == I.getOpcode() &&
@@ -857,7 +871,8 @@ Instruction *InstCombinerImpl::foldBinOpShiftWithShift(BinaryOperator &I) {
if (!CanDistributeBinops(I.getOpcode(), BinOpc, ShOpc, CMask, CShift))
return nullptr;
- Constant *NewCMask = ConstantExpr::get(GetInvShift(ShOpc), CMask, CShift);
+ Constant *NewCMask =
+ ConstantFoldBinaryOpOperands(GetInvShift(ShOpc), CMask, CShift, DL);
Value *NewBinOp2 = Builder.CreateBinOp(
static_cast<Instruction::BinaryOps>(BinOpc), X, NewCMask);
Value *NewBinOp1 = Builder.CreateBinOp(I.getOpcode(), Y, NewBinOp2);
@@ -924,13 +939,17 @@ InstCombinerImpl::foldBinOpOfSelectAndCastOfSelectCondition(BinaryOperator &I) {
// If the value used in the zext/sext is the select condition, or the negated
// of the select condition, the binop can be simplified.
- if (CondVal == A)
- return SelectInst::Create(CondVal, NewFoldedConst(false, TrueVal),
+ if (CondVal == A) {
+ Value *NewTrueVal = NewFoldedConst(false, TrueVal);
+ return SelectInst::Create(CondVal, NewTrueVal,
NewFoldedConst(true, FalseVal));
+ }
- if (match(A, m_Not(m_Specific(CondVal))))
- return SelectInst::Create(CondVal, NewFoldedConst(true, TrueVal),
+ if (match(A, m_Not(m_Specific(CondVal)))) {
+ Value *NewTrueVal = NewFoldedConst(true, TrueVal);
+ return SelectInst::Create(CondVal, NewTrueVal,
NewFoldedConst(false, FalseVal));
+ }
return nullptr;
}
@@ -1167,6 +1186,8 @@ void InstCombinerImpl::freelyInvertAllUsersOf(Value *I, Value *IgnoredUser) {
break;
case Instruction::Xor:
replaceInstUsesWith(cast<Instruction>(*U), I);
+ // Add to worklist for DCE.
+ addToWorklist(cast<Instruction>(U));
break;
default:
llvm_unreachable("Got unexpected user - out of sync with "
@@ -1268,7 +1289,7 @@ static Value *foldOperationIntoSelectOperand(Instruction &I, SelectInst *SI,
Value *NewOp, InstCombiner &IC) {
Instruction *Clone = I.clone();
Clone->replaceUsesOfWith(SI, NewOp);
- IC.InsertNewInstBefore(Clone, *SI);
+ IC.InsertNewInstBefore(Clone, SI->getIterator());
return Clone;
}
@@ -1302,6 +1323,21 @@ Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
return nullptr;
}
+ // Test if a FCmpInst instruction is used exclusively by a select as
+ // part of a minimum or maximum operation. If so, refrain from doing
+ // any other folding. This helps out other analyses which understand
+ // non-obfuscated minimum and maximum idioms. And in this case, at
+ // least one of the comparison operands has at least one user besides
+ // the compare (the select), which would often largely negate the
+ // benefit of folding anyway.
+ if (auto *CI = dyn_cast<FCmpInst>(SI->getCondition())) {
+ if (CI->hasOneUse()) {
+ Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1);
+ if ((TV == Op0 && FV == Op1) || (FV == Op0 && TV == Op1))
+ return nullptr;
+ }
+ }
+
// Make sure that one of the select arms constant folds successfully.
Value *NewTV = constantFoldOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ true);
Value *NewFV = constantFoldOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ false);
@@ -1316,6 +1352,47 @@ Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
return SelectInst::Create(SI->getCondition(), NewTV, NewFV, "", nullptr, SI);
}
+static Value *simplifyInstructionWithPHI(Instruction &I, PHINode *PN,
+ Value *InValue, BasicBlock *InBB,
+ const DataLayout &DL,
+ const SimplifyQuery SQ) {
+ // NB: It is a precondition of this transform that the operands be
+ // phi translatable! This is usually trivially satisfied by limiting it
+ // to constant ops, and for selects we do a more sophisticated check.
+ SmallVector<Value *> Ops;
+ for (Value *Op : I.operands()) {
+ if (Op == PN)
+ Ops.push_back(InValue);
+ else
+ Ops.push_back(Op->DoPHITranslation(PN->getParent(), InBB));
+ }
+
+ // Don't consider the simplification successful if we get back a constant
+ // expression. That's just an instruction in hiding.
+ // Also reject the case where we simplify back to the phi node. We wouldn't
+ // be able to remove it in that case.
+ Value *NewVal = simplifyInstructionWithOperands(
+ &I, Ops, SQ.getWithInstruction(InBB->getTerminator()));
+ if (NewVal && NewVal != PN && !match(NewVal, m_ConstantExpr()))
+ return NewVal;
+
+ // Check if incoming PHI value can be replaced with constant
+ // based on implied condition.
+ BranchInst *TerminatorBI = dyn_cast<BranchInst>(InBB->getTerminator());
+ const ICmpInst *ICmp = dyn_cast<ICmpInst>(&I);
+ if (TerminatorBI && TerminatorBI->isConditional() &&
+ TerminatorBI->getSuccessor(0) != TerminatorBI->getSuccessor(1) && ICmp) {
+ bool LHSIsTrue = TerminatorBI->getSuccessor(0) == PN->getParent();
+ std::optional<bool> ImpliedCond =
+ isImpliedCondition(TerminatorBI->getCondition(), ICmp->getPredicate(),
+ Ops[0], Ops[1], DL, LHSIsTrue);
+ if (ImpliedCond)
+ return ConstantInt::getBool(I.getType(), ImpliedCond.value());
+ }
+
+ return nullptr;
+}
+
Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) {
unsigned NumPHIValues = PN->getNumIncomingValues();
if (NumPHIValues == 0)
@@ -1344,29 +1421,11 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) {
Value *InVal = PN->getIncomingValue(i);
BasicBlock *InBB = PN->getIncomingBlock(i);
- // NB: It is a precondition of this transform that the operands be
- // phi translatable! This is usually trivially satisfied by limiting it
- // to constant ops, and for selects we do a more sophisticated check.
- SmallVector<Value *> Ops;
- for (Value *Op : I.operands()) {
- if (Op == PN)
- Ops.push_back(InVal);
- else
- Ops.push_back(Op->DoPHITranslation(PN->getParent(), InBB));
- }
-
- // Don't consider the simplification successful if we get back a constant
- // expression. That's just an instruction in hiding.
- // Also reject the case where we simplify back to the phi node. We wouldn't
- // be able to remove it in that case.
- Value *NewVal = simplifyInstructionWithOperands(
- &I, Ops, SQ.getWithInstruction(InBB->getTerminator()));
- if (NewVal && NewVal != PN && !match(NewVal, m_ConstantExpr())) {
+ if (auto *NewVal = simplifyInstructionWithPHI(I, PN, InVal, InBB, DL, SQ)) {
NewPhiValues.push_back(NewVal);
continue;
}
- if (isa<PHINode>(InVal)) return nullptr; // Itself a phi.
if (NonSimplifiedBB) return nullptr; // More than one non-simplified value.
NonSimplifiedBB = InBB;
@@ -1402,7 +1461,7 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) {
// Okay, we can do the transformation: create the new PHI node.
PHINode *NewPN = PHINode::Create(I.getType(), PN->getNumIncomingValues());
- InsertNewInstBefore(NewPN, *PN);
+ InsertNewInstBefore(NewPN, PN->getIterator());
NewPN->takeName(PN);
NewPN->setDebugLoc(PN->getDebugLoc());
@@ -1417,7 +1476,7 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) {
else
U = U->DoPHITranslation(PN->getParent(), NonSimplifiedBB);
}
- InsertNewInstBefore(Clone, *NonSimplifiedBB->getTerminator());
+ InsertNewInstBefore(Clone, NonSimplifiedBB->getTerminator()->getIterator());
}
for (unsigned i = 0; i != NumPHIValues; ++i) {
@@ -1848,8 +1907,8 @@ Instruction *InstCombinerImpl::narrowMathIfNoOverflow(BinaryOperator &BO) {
Constant *WideC;
if (!Op0->hasOneUse() || !match(Op1, m_Constant(WideC)))
return nullptr;
- Constant *NarrowC = ConstantExpr::getTrunc(WideC, X->getType());
- if (ConstantExpr::getCast(CastOpc, NarrowC, BO.getType()) != WideC)
+ Constant *NarrowC = getLosslessTrunc(WideC, X->getType(), CastOpc);
+ if (!NarrowC)
return nullptr;
Y = NarrowC;
}
@@ -1940,7 +1999,7 @@ Instruction *InstCombinerImpl::visitGEPOfGEP(GetElementPtrInst &GEP,
APInt Offset(DL.getIndexTypeSizeInBits(PtrTy), 0);
if (NumVarIndices != Src->getNumIndices()) {
// FIXME: getIndexedOffsetInType() does not handled scalable vectors.
- if (isa<ScalableVectorType>(BaseType))
+ if (BaseType->isScalableTy())
return nullptr;
SmallVector<Value *> ConstantIndices;
@@ -2048,12 +2107,126 @@ Instruction *InstCombinerImpl::visitGEPOfGEP(GetElementPtrInst &GEP,
return nullptr;
}
+Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
+ BuilderTy *Builder,
+ bool &DoesConsume, unsigned Depth) {
+ static Value *const NonNull = reinterpret_cast<Value *>(uintptr_t(1));
+ // ~(~(X)) -> X.
+ Value *A, *B;
+ if (match(V, m_Not(m_Value(A)))) {
+ DoesConsume = true;
+ return A;
+ }
+
+ Constant *C;
+ // Constants can be considered to be not'ed values.
+ if (match(V, m_ImmConstant(C)))
+ return ConstantExpr::getNot(C);
+
+ if (Depth++ >= MaxAnalysisRecursionDepth)
+ return nullptr;
+
+ // The rest of the cases require that we invert all uses so don't bother
+ // doing the analysis if we know we can't use the result.
+ if (!WillInvertAllUses)
+ return nullptr;
+
+ // Compares can be inverted if all of their uses are being modified to use
+ // the ~V.
+ if (auto *I = dyn_cast<CmpInst>(V)) {
+ if (Builder != nullptr)
+ return Builder->CreateCmp(I->getInversePredicate(), I->getOperand(0),
+ I->getOperand(1));
+ return NonNull;
+ }
+
+ // If `V` is of the form `A + B` then `-1 - V` can be folded into
+ // `(-1 - B) - A` if we are willing to invert all of the uses.
+ if (match(V, m_Add(m_Value(A), m_Value(B)))) {
+ if (auto *BV = getFreelyInvertedImpl(B, B->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateSub(BV, A) : NonNull;
+ if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateSub(AV, B) : NonNull;
+ return nullptr;
+ }
+
+ // If `V` is of the form `A ^ ~B` then `~(A ^ ~B)` can be folded
+ // into `A ^ B` if we are willing to invert all of the uses.
+ if (match(V, m_Xor(m_Value(A), m_Value(B)))) {
+ if (auto *BV = getFreelyInvertedImpl(B, B->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateXor(A, BV) : NonNull;
+ if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateXor(AV, B) : NonNull;
+ return nullptr;
+ }
+
+ // If `V` is of the form `B - A` then `-1 - V` can be folded into
+ // `A + (-1 - B)` if we are willing to invert all of the uses.
+ if (match(V, m_Sub(m_Value(A), m_Value(B)))) {
+ if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateAdd(AV, B) : NonNull;
+ return nullptr;
+ }
+
+ // If `V` is of the form `(~A) s>> B` then `~((~A) s>> B)` can be folded
+ // into `A s>> B` if we are willing to invert all of the uses.
+ if (match(V, m_AShr(m_Value(A), m_Value(B)))) {
+ if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateAShr(AV, B) : NonNull;
+ return nullptr;
+ }
+
+ // Treat lshr with non-negative operand as ashr.
+ if (match(V, m_LShr(m_Value(A), m_Value(B))) &&
+ isKnownNonNegative(A, SQ.getWithInstruction(cast<Instruction>(V)),
+ Depth)) {
+ if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateAShr(AV, B) : NonNull;
+ return nullptr;
+ }
+
+ Value *Cond;
+ // LogicOps are special in that we canonicalize them at the cost of an
+ // instruction.
+ bool IsSelect = match(V, m_Select(m_Value(Cond), m_Value(A), m_Value(B))) &&
+ !shouldAvoidAbsorbingNotIntoSelect(*cast<SelectInst>(V));
+ // Selects/min/max with invertible operands are freely invertible
+ if (IsSelect || match(V, m_MaxOrMin(m_Value(A), m_Value(B)))) {
+ if (!getFreelyInvertedImpl(B, B->hasOneUse(), /*Builder*/ nullptr,
+ DoesConsume, Depth))
+ return nullptr;
+ if (Value *NotA = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
+ DoesConsume, Depth)) {
+ if (Builder != nullptr) {
+ Value *NotB = getFreelyInvertedImpl(B, B->hasOneUse(), Builder,
+ DoesConsume, Depth);
+ assert(NotB != nullptr &&
+ "Unable to build inverted value for known freely invertable op");
+ if (auto *II = dyn_cast<IntrinsicInst>(V))
+ return Builder->CreateBinaryIntrinsic(
+ getInverseMinMaxIntrinsic(II->getIntrinsicID()), NotA, NotB);
+ return Builder->CreateSelect(Cond, NotA, NotB);
+ }
+ return NonNull;
+ }
+ }
+
+ return nullptr;
+}
+
Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
Value *PtrOp = GEP.getOperand(0);
SmallVector<Value *, 8> Indices(GEP.indices());
Type *GEPType = GEP.getType();
Type *GEPEltType = GEP.getSourceElementType();
- bool IsGEPSrcEleScalable = isa<ScalableVectorType>(GEPEltType);
+ bool IsGEPSrcEleScalable = GEPEltType->isScalableTy();
if (Value *V = simplifyGEPInst(GEPEltType, PtrOp, Indices, GEP.isInBounds(),
SQ.getWithInstruction(&GEP)))
return replaceInstUsesWith(GEP, V);
@@ -2221,7 +2394,7 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
NewGEP->setOperand(DI, NewPN);
}
- NewGEP->insertInto(GEP.getParent(), GEP.getParent()->getFirstInsertionPt());
+ NewGEP->insertBefore(*GEP.getParent(), GEP.getParent()->getFirstInsertionPt());
return replaceOperand(GEP, 0, NewGEP);
}
@@ -2264,11 +2437,43 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
return CastInst::CreatePointerBitCastOrAddrSpaceCast(Y, GEPType);
}
}
-
// We do not handle pointer-vector geps here.
if (GEPType->isVectorTy())
return nullptr;
+ if (GEP.getNumIndices() == 1) {
+ // Try to replace ADD + GEP with GEP + GEP.
+ Value *Idx1, *Idx2;
+ if (match(GEP.getOperand(1),
+ m_OneUse(m_Add(m_Value(Idx1), m_Value(Idx2))))) {
+ // %idx = add i64 %idx1, %idx2
+ // %gep = getelementptr i32, ptr %ptr, i64 %idx
+ // as:
+ // %newptr = getelementptr i32, ptr %ptr, i64 %idx1
+ // %newgep = getelementptr i32, ptr %newptr, i64 %idx2
+ auto *NewPtr = Builder.CreateGEP(GEP.getResultElementType(),
+ GEP.getPointerOperand(), Idx1);
+ return GetElementPtrInst::Create(GEP.getResultElementType(), NewPtr,
+ Idx2);
+ }
+ ConstantInt *C;
+ if (match(GEP.getOperand(1), m_OneUse(m_SExt(m_OneUse(m_NSWAdd(
+ m_Value(Idx1), m_ConstantInt(C))))))) {
+ // %add = add nsw i32 %idx1, idx2
+ // %sidx = sext i32 %add to i64
+ // %gep = getelementptr i32, ptr %ptr, i64 %sidx
+ // as:
+ // %newptr = getelementptr i32, ptr %ptr, i32 %idx1
+ // %newgep = getelementptr i32, ptr %newptr, i32 idx2
+ auto *NewPtr = Builder.CreateGEP(
+ GEP.getResultElementType(), GEP.getPointerOperand(),
+ Builder.CreateSExt(Idx1, GEP.getOperand(1)->getType()));
+ return GetElementPtrInst::Create(
+ GEP.getResultElementType(), NewPtr,
+ Builder.CreateSExt(C, GEP.getOperand(1)->getType()));
+ }
+ }
+
if (!GEP.isInBounds()) {
unsigned IdxWidth =
DL.getIndexSizeInBits(PtrOp->getType()->getPointerAddressSpace());
@@ -2362,6 +2567,26 @@ static bool isAllocSiteRemovable(Instruction *AI,
unsigned OtherIndex = (ICI->getOperand(0) == PI) ? 1 : 0;
if (!isNeverEqualToUnescapedAlloc(ICI->getOperand(OtherIndex), TLI, AI))
return false;
+
+ // Do not fold compares to aligned_alloc calls, as they may have to
+ // return null in case the required alignment cannot be satisfied,
+ // unless we can prove that both alignment and size are valid.
+ auto AlignmentAndSizeKnownValid = [](CallBase *CB) {
+ // Check if alignment and size of a call to aligned_alloc is valid,
+ // that is alignment is a power-of-2 and the size is a multiple of the
+ // alignment.
+ const APInt *Alignment;
+ const APInt *Size;
+ return match(CB->getArgOperand(0), m_APInt(Alignment)) &&
+ match(CB->getArgOperand(1), m_APInt(Size)) &&
+ Alignment->isPowerOf2() && Size->urem(*Alignment).isZero();
+ };
+ auto *CB = dyn_cast<CallBase>(AI);
+ LibFunc TheLibFunc;
+ if (CB && TLI.getLibFunc(*CB->getCalledFunction(), TheLibFunc) &&
+ TLI.has(TheLibFunc) && TheLibFunc == LibFunc_aligned_alloc &&
+ !AlignmentAndSizeKnownValid(CB))
+ return false;
Users.emplace_back(I);
continue;
}
@@ -2451,9 +2676,10 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) {
// If we are removing an alloca with a dbg.declare, insert dbg.value calls
// before each store.
SmallVector<DbgVariableIntrinsic *, 8> DVIs;
+ SmallVector<DPValue *, 8> DPVs;
std::unique_ptr<DIBuilder> DIB;
if (isa<AllocaInst>(MI)) {
- findDbgUsers(DVIs, &MI);
+ findDbgUsers(DVIs, &MI, &DPVs);
DIB.reset(new DIBuilder(*MI.getModule(), /*AllowUnresolved=*/false));
}
@@ -2493,6 +2719,9 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) {
for (auto *DVI : DVIs)
if (DVI->isAddressOfVariable())
ConvertDebugDeclareToDebugValue(DVI, SI, *DIB);
+ for (auto *DPV : DPVs)
+ if (DPV->isAddressOfVariable())
+ ConvertDebugDeclareToDebugValue(DPV, SI, *DIB);
} else {
// Casts, GEP, or anything else: we're about to delete this instruction,
// so it can not have any valid uses.
@@ -2531,9 +2760,15 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) {
// If there is a dead store to `%a` in @trivially_inlinable_no_op, the
// "arg0" dbg.value may be stale after the call. However, failing to remove
// the DW_OP_deref dbg.value causes large gaps in location coverage.
+ //
+ // FIXME: the Assignment Tracking project has now likely made this
+ // redundant (and it's sometimes harmful).
for (auto *DVI : DVIs)
if (DVI->isAddressOfVariable() || DVI->getExpression()->startsWithDeref())
DVI->eraseFromParent();
+ for (auto *DPV : DPVs)
+ if (DPV->isAddressOfVariable() || DPV->getExpression()->startsWithDeref())
+ DPV->eraseFromParent();
return eraseInstFromFunction(MI);
}
@@ -2612,7 +2847,7 @@ static Instruction *tryToMoveFreeBeforeNullTest(CallInst &FI,
for (Instruction &Instr : llvm::make_early_inc_range(*FreeInstrBB)) {
if (&Instr == FreeInstrBBTerminator)
break;
- Instr.moveBefore(TI);
+ Instr.moveBeforePreserving(TI);
}
assert(FreeInstrBB->size() == 1 &&
"Only the branch instruction should remain");
@@ -2746,55 +2981,77 @@ Instruction *InstCombinerImpl::visitUnconditionalBranchInst(BranchInst &BI) {
return nullptr;
}
+void InstCombinerImpl::addDeadEdge(BasicBlock *From, BasicBlock *To,
+ SmallVectorImpl<BasicBlock *> &Worklist) {
+ if (!DeadEdges.insert({From, To}).second)
+ return;
+
+ // Replace phi node operands in successor with poison.
+ for (PHINode &PN : To->phis())
+ for (Use &U : PN.incoming_values())
+ if (PN.getIncomingBlock(U) == From && !isa<PoisonValue>(U)) {
+ replaceUse(U, PoisonValue::get(PN.getType()));
+ addToWorklist(&PN);
+ MadeIRChange = true;
+ }
+
+ Worklist.push_back(To);
+}
+
// Under the assumption that I is unreachable, remove it and following
-// instructions.
-bool InstCombinerImpl::handleUnreachableFrom(Instruction *I) {
- bool Changed = false;
+// instructions. Changes are reported directly to MadeIRChange.
+void InstCombinerImpl::handleUnreachableFrom(
+ Instruction *I, SmallVectorImpl<BasicBlock *> &Worklist) {
BasicBlock *BB = I->getParent();
for (Instruction &Inst : make_early_inc_range(
make_range(std::next(BB->getTerminator()->getReverseIterator()),
std::next(I->getReverseIterator())))) {
if (!Inst.use_empty() && !Inst.getType()->isTokenTy()) {
replaceInstUsesWith(Inst, PoisonValue::get(Inst.getType()));
- Changed = true;
+ MadeIRChange = true;
}
if (Inst.isEHPad() || Inst.getType()->isTokenTy())
continue;
+ // RemoveDIs: erase debug-info on this instruction manually.
+ Inst.dropDbgValues();
eraseInstFromFunction(Inst);
- Changed = true;
+ MadeIRChange = true;
}
- // Replace phi node operands in successor blocks with poison.
+ // RemoveDIs: to match behaviour in dbg.value mode, drop debug-info on
+ // terminator too.
+ BB->getTerminator()->dropDbgValues();
+
+ // Handle potentially dead successors.
for (BasicBlock *Succ : successors(BB))
- for (PHINode &PN : Succ->phis())
- for (Use &U : PN.incoming_values())
- if (PN.getIncomingBlock(U) == BB && !isa<PoisonValue>(U)) {
- replaceUse(U, PoisonValue::get(PN.getType()));
- addToWorklist(&PN);
- Changed = true;
- }
+ addDeadEdge(BB, Succ, Worklist);
+}
- // TODO: Successor blocks may also be dead.
- return Changed;
+void InstCombinerImpl::handlePotentiallyDeadBlocks(
+ SmallVectorImpl<BasicBlock *> &Worklist) {
+ while (!Worklist.empty()) {
+ BasicBlock *BB = Worklist.pop_back_val();
+ if (!all_of(predecessors(BB), [&](BasicBlock *Pred) {
+ return DeadEdges.contains({Pred, BB}) || DT.dominates(BB, Pred);
+ }))
+ continue;
+
+ handleUnreachableFrom(&BB->front(), Worklist);
+ }
}
-bool InstCombinerImpl::handlePotentiallyDeadSuccessors(BasicBlock *BB,
+void InstCombinerImpl::handlePotentiallyDeadSuccessors(BasicBlock *BB,
BasicBlock *LiveSucc) {
- bool Changed = false;
+ SmallVector<BasicBlock *> Worklist;
for (BasicBlock *Succ : successors(BB)) {
// The live successor isn't dead.
if (Succ == LiveSucc)
continue;
- if (!all_of(predecessors(Succ), [&](BasicBlock *Pred) {
- return DT.dominates(BasicBlockEdge(BB, Succ),
- BasicBlockEdge(Pred, Succ));
- }))
- continue;
-
- Changed |= handleUnreachableFrom(&Succ->front());
+ addDeadEdge(BB, Succ, Worklist);
}
- return Changed;
+
+ handlePotentiallyDeadBlocks(Worklist);
}
Instruction *InstCombinerImpl::visitBranchInst(BranchInst &BI) {
@@ -2840,14 +3097,17 @@ Instruction *InstCombinerImpl::visitBranchInst(BranchInst &BI) {
return &BI;
}
- if (isa<UndefValue>(Cond) &&
- handlePotentiallyDeadSuccessors(BI.getParent(), /*LiveSucc*/ nullptr))
- return &BI;
- if (auto *CI = dyn_cast<ConstantInt>(Cond))
- if (handlePotentiallyDeadSuccessors(BI.getParent(),
- BI.getSuccessor(!CI->getZExtValue())))
- return &BI;
+ if (isa<UndefValue>(Cond)) {
+ handlePotentiallyDeadSuccessors(BI.getParent(), /*LiveSucc*/ nullptr);
+ return nullptr;
+ }
+ if (auto *CI = dyn_cast<ConstantInt>(Cond)) {
+ handlePotentiallyDeadSuccessors(BI.getParent(),
+ BI.getSuccessor(!CI->getZExtValue()));
+ return nullptr;
+ }
+ DC.registerBranch(&BI);
return nullptr;
}
@@ -2866,14 +3126,6 @@ Instruction *InstCombinerImpl::visitSwitchInst(SwitchInst &SI) {
return replaceOperand(SI, 0, Op0);
}
- if (isa<UndefValue>(Cond) &&
- handlePotentiallyDeadSuccessors(SI.getParent(), /*LiveSucc*/ nullptr))
- return &SI;
- if (auto *CI = dyn_cast<ConstantInt>(Cond))
- if (handlePotentiallyDeadSuccessors(
- SI.getParent(), SI.findCaseValue(CI)->getCaseSuccessor()))
- return &SI;
-
KnownBits Known = computeKnownBits(Cond, 0, &SI);
unsigned LeadingKnownZeros = Known.countMinLeadingZeros();
unsigned LeadingKnownOnes = Known.countMinLeadingOnes();
@@ -2906,6 +3158,16 @@ Instruction *InstCombinerImpl::visitSwitchInst(SwitchInst &SI) {
return replaceOperand(SI, 0, NewCond);
}
+ if (isa<UndefValue>(Cond)) {
+ handlePotentiallyDeadSuccessors(SI.getParent(), /*LiveSucc*/ nullptr);
+ return nullptr;
+ }
+ if (auto *CI = dyn_cast<ConstantInt>(Cond)) {
+ handlePotentiallyDeadSuccessors(SI.getParent(),
+ SI.findCaseValue(CI)->getCaseSuccessor());
+ return nullptr;
+ }
+
return nullptr;
}
@@ -3532,7 +3794,7 @@ Instruction *InstCombinerImpl::foldFreezeIntoRecurrence(FreezeInst &FI,
Value *StartV = StartU->get();
BasicBlock *StartBB = PN->getIncomingBlock(*StartU);
bool StartNeedsFreeze = !isGuaranteedNotToBeUndefOrPoison(StartV);
- // We can't insert freeze if the the start value is the result of the
+ // We can't insert freeze if the start value is the result of the
// terminator (e.g. an invoke).
if (StartNeedsFreeze && StartBB->getTerminator() == StartV)
return nullptr;
@@ -3583,19 +3845,27 @@ bool InstCombinerImpl::freezeOtherUses(FreezeInst &FI) {
// *all* uses if the operand is an invoke/callbr and the use is in a phi on
// the normal/default destination. This is why the domination check in the
// replacement below is still necessary.
- Instruction *MoveBefore;
+ BasicBlock::iterator MoveBefore;
if (isa<Argument>(Op)) {
MoveBefore =
- &*FI.getFunction()->getEntryBlock().getFirstNonPHIOrDbgOrAlloca();
+ FI.getFunction()->getEntryBlock().getFirstNonPHIOrDbgOrAlloca();
} else {
- MoveBefore = cast<Instruction>(Op)->getInsertionPointAfterDef();
- if (!MoveBefore)
+ auto MoveBeforeOpt = cast<Instruction>(Op)->getInsertionPointAfterDef();
+ if (!MoveBeforeOpt)
return false;
+ MoveBefore = *MoveBeforeOpt;
}
+ // Don't move to the position of a debug intrinsic.
+ if (isa<DbgInfoIntrinsic>(MoveBefore))
+ MoveBefore = MoveBefore->getNextNonDebugInstruction()->getIterator();
+ // Re-point iterator to come after any debug-info records, if we're
+ // running in "RemoveDIs" mode
+ MoveBefore.setHeadBit(false);
+
bool Changed = false;
- if (&FI != MoveBefore) {
- FI.moveBefore(MoveBefore);
+ if (&FI != &*MoveBefore) {
+ FI.moveBefore(*MoveBefore->getParent(), MoveBefore);
Changed = true;
}
@@ -3798,7 +4068,7 @@ bool InstCombinerImpl::tryToSinkInstruction(Instruction *I,
/// the new position.
BasicBlock::iterator InsertPos = DestBlock->getFirstInsertionPt();
- I->moveBefore(&*InsertPos);
+ I->moveBefore(*DestBlock, InsertPos);
++NumSunkInst;
// Also sink all related debug uses from the source basic block. Otherwise we
@@ -3808,10 +4078,19 @@ bool InstCombinerImpl::tryToSinkInstruction(Instruction *I,
// here, but that computation has been sunk.
SmallVector<DbgVariableIntrinsic *, 2> DbgUsers;
findDbgUsers(DbgUsers, I);
- // Process the sinking DbgUsers in reverse order, as we only want to clone the
- // last appearing debug intrinsic for each given variable.
+
+ // For all debug values in the destination block, the sunk instruction
+ // will still be available, so they do not need to be dropped.
+ SmallVector<DbgVariableIntrinsic *, 2> DbgUsersToSalvage;
+ SmallVector<DPValue *, 2> DPValuesToSalvage;
+ for (auto &DbgUser : DbgUsers)
+ if (DbgUser->getParent() != DestBlock)
+ DbgUsersToSalvage.push_back(DbgUser);
+
+ // Process the sinking DbgUsersToSalvage in reverse order, as we only want
+ // to clone the last appearing debug intrinsic for each given variable.
SmallVector<DbgVariableIntrinsic *, 2> DbgUsersToSink;
- for (DbgVariableIntrinsic *DVI : DbgUsers)
+ for (DbgVariableIntrinsic *DVI : DbgUsersToSalvage)
if (DVI->getParent() == SrcBlock)
DbgUsersToSink.push_back(DVI);
llvm::sort(DbgUsersToSink,
@@ -3847,7 +4126,10 @@ bool InstCombinerImpl::tryToSinkInstruction(Instruction *I,
// Perform salvaging without the clones, then sink the clones.
if (!DIIClones.empty()) {
- salvageDebugInfoForDbgValues(*I, DbgUsers);
+ // RemoveDIs: pass in empty vector of DPValues until we get to instrumenting
+ // this pass.
+ SmallVector<DPValue *, 1> DummyDPValues;
+ salvageDebugInfoForDbgValues(*I, DbgUsersToSalvage, DummyDPValues);
// The clones are in reverse order of original appearance, reverse again to
// maintain the original order.
for (auto &DIIClone : llvm::reverse(DIIClones)) {
@@ -4093,43 +4375,52 @@ public:
}
};
-/// Populate the IC worklist from a function, by walking it in depth-first
-/// order and adding all reachable code to the worklist.
+/// Populate the IC worklist from a function, by walking it in reverse
+/// post-order and adding all reachable code to the worklist.
///
/// This has a couple of tricks to make the code faster and more powerful. In
/// particular, we constant fold and DCE instructions as we go, to avoid adding
/// them to the worklist (this significantly speeds up instcombine on code where
/// many instructions are dead or constant). Additionally, if we find a branch
/// whose condition is a known constant, we only visit the reachable successors.
-static bool prepareICWorklistFromFunction(Function &F, const DataLayout &DL,
- const TargetLibraryInfo *TLI,
- InstructionWorklist &ICWorklist) {
+bool InstCombinerImpl::prepareWorklist(
+ Function &F, ReversePostOrderTraversal<BasicBlock *> &RPOT) {
bool MadeIRChange = false;
- SmallPtrSet<BasicBlock *, 32> Visited;
- SmallVector<BasicBlock*, 256> Worklist;
- Worklist.push_back(&F.front());
-
+ SmallPtrSet<BasicBlock *, 32> LiveBlocks;
SmallVector<Instruction *, 128> InstrsForInstructionWorklist;
DenseMap<Constant *, Constant *> FoldedConstants;
AliasScopeTracker SeenAliasScopes;
- do {
- BasicBlock *BB = Worklist.pop_back_val();
+ auto HandleOnlyLiveSuccessor = [&](BasicBlock *BB, BasicBlock *LiveSucc) {
+ for (BasicBlock *Succ : successors(BB))
+ if (Succ != LiveSucc && DeadEdges.insert({BB, Succ}).second)
+ for (PHINode &PN : Succ->phis())
+ for (Use &U : PN.incoming_values())
+ if (PN.getIncomingBlock(U) == BB && !isa<PoisonValue>(U)) {
+ U.set(PoisonValue::get(PN.getType()));
+ MadeIRChange = true;
+ }
+ };
- // We have now visited this block! If we've already been here, ignore it.
- if (!Visited.insert(BB).second)
+ for (BasicBlock *BB : RPOT) {
+ if (!BB->isEntryBlock() && all_of(predecessors(BB), [&](BasicBlock *Pred) {
+ return DeadEdges.contains({Pred, BB}) || DT.dominates(BB, Pred);
+ })) {
+ HandleOnlyLiveSuccessor(BB, nullptr);
continue;
+ }
+ LiveBlocks.insert(BB);
for (Instruction &Inst : llvm::make_early_inc_range(*BB)) {
// ConstantProp instruction if trivially constant.
if (!Inst.use_empty() &&
(Inst.getNumOperands() == 0 || isa<Constant>(Inst.getOperand(0))))
- if (Constant *C = ConstantFoldInstruction(&Inst, DL, TLI)) {
+ if (Constant *C = ConstantFoldInstruction(&Inst, DL, &TLI)) {
LLVM_DEBUG(dbgs() << "IC: ConstFold to: " << *C << " from: " << Inst
<< '\n');
Inst.replaceAllUsesWith(C);
++NumConstProp;
- if (isInstructionTriviallyDead(&Inst, TLI))
+ if (isInstructionTriviallyDead(&Inst, &TLI))
Inst.eraseFromParent();
MadeIRChange = true;
continue;
@@ -4143,7 +4434,7 @@ static bool prepareICWorklistFromFunction(Function &F, const DataLayout &DL,
auto *C = cast<Constant>(U);
Constant *&FoldRes = FoldedConstants[C];
if (!FoldRes)
- FoldRes = ConstantFoldConstant(C, DL, TLI);
+ FoldRes = ConstantFoldConstant(C, DL, &TLI);
if (FoldRes != C) {
LLVM_DEBUG(dbgs() << "IC: ConstFold operand of: " << Inst
@@ -4163,37 +4454,39 @@ static bool prepareICWorklistFromFunction(Function &F, const DataLayout &DL,
}
}
- // Recursively visit successors. If this is a branch or switch on a
- // constant, only visit the reachable successor.
+ // If this is a branch or switch on a constant, mark only the single
+ // live successor. Otherwise assume all successors are live.
Instruction *TI = BB->getTerminator();
if (BranchInst *BI = dyn_cast<BranchInst>(TI); BI && BI->isConditional()) {
- if (isa<UndefValue>(BI->getCondition()))
+ if (isa<UndefValue>(BI->getCondition())) {
// Branch on undef is UB.
+ HandleOnlyLiveSuccessor(BB, nullptr);
continue;
+ }
if (auto *Cond = dyn_cast<ConstantInt>(BI->getCondition())) {
bool CondVal = Cond->getZExtValue();
- BasicBlock *ReachableBB = BI->getSuccessor(!CondVal);
- Worklist.push_back(ReachableBB);
+ HandleOnlyLiveSuccessor(BB, BI->getSuccessor(!CondVal));
continue;
}
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
- if (isa<UndefValue>(SI->getCondition()))
+ if (isa<UndefValue>(SI->getCondition())) {
// Switch on undef is UB.
+ HandleOnlyLiveSuccessor(BB, nullptr);
continue;
+ }
if (auto *Cond = dyn_cast<ConstantInt>(SI->getCondition())) {
- Worklist.push_back(SI->findCaseValue(Cond)->getCaseSuccessor());
+ HandleOnlyLiveSuccessor(BB,
+ SI->findCaseValue(Cond)->getCaseSuccessor());
continue;
}
}
-
- append_range(Worklist, successors(TI));
- } while (!Worklist.empty());
+ }
// Remove instructions inside unreachable blocks. This prevents the
// instcombine code from having to deal with some bad special cases, and
// reduces use counts of instructions.
for (BasicBlock &BB : F) {
- if (Visited.count(&BB))
+ if (LiveBlocks.count(&BB))
continue;
unsigned NumDeadInstInBB;
@@ -4210,11 +4503,11 @@ static bool prepareICWorklistFromFunction(Function &F, const DataLayout &DL,
// of the function down. This jives well with the way that it adds all uses
// of instructions to the worklist after doing a transformation, thus avoiding
// some N^2 behavior in pathological cases.
- ICWorklist.reserve(InstrsForInstructionWorklist.size());
+ Worklist.reserve(InstrsForInstructionWorklist.size());
for (Instruction *Inst : reverse(InstrsForInstructionWorklist)) {
// DCE instruction if trivially dead. As we iterate in reverse program
// order here, we will clean up whole chains of dead instructions.
- if (isInstructionTriviallyDead(Inst, TLI) ||
+ if (isInstructionTriviallyDead(Inst, &TLI) ||
SeenAliasScopes.isNoAliasScopeDeclDead(Inst)) {
++NumDeadInst;
LLVM_DEBUG(dbgs() << "IC: DCE: " << *Inst << '\n');
@@ -4224,7 +4517,7 @@ static bool prepareICWorklistFromFunction(Function &F, const DataLayout &DL,
continue;
}
- ICWorklist.push(Inst);
+ Worklist.push(Inst);
}
return MadeIRChange;
@@ -4234,7 +4527,7 @@ static bool combineInstructionsOverFunction(
Function &F, InstructionWorklist &Worklist, AliasAnalysis *AA,
AssumptionCache &AC, TargetLibraryInfo &TLI, TargetTransformInfo &TTI,
DominatorTree &DT, OptimizationRemarkEmitter &ORE, BlockFrequencyInfo *BFI,
- ProfileSummaryInfo *PSI, unsigned MaxIterations, LoopInfo *LI) {
+ ProfileSummaryInfo *PSI, LoopInfo *LI, const InstCombineOptions &Opts) {
auto &DL = F.getParent()->getDataLayout();
/// Builder - This is an IRBuilder that automatically inserts new
@@ -4247,6 +4540,8 @@ static bool combineInstructionsOverFunction(
AC.registerAssumption(Assume);
}));
+ ReversePostOrderTraversal<BasicBlock *> RPOT(&F.front());
+
// Lower dbg.declare intrinsics otherwise their value may be clobbered
// by instcombiner.
bool MadeIRChange = false;
@@ -4256,35 +4551,33 @@ static bool combineInstructionsOverFunction(
// Iterate while there is work to do.
unsigned Iteration = 0;
while (true) {
- ++NumWorklistIterations;
++Iteration;
- if (Iteration > InfiniteLoopDetectionThreshold) {
- report_fatal_error(
- "Instruction Combining seems stuck in an infinite loop after " +
- Twine(InfiniteLoopDetectionThreshold) + " iterations.");
- }
-
- if (Iteration > MaxIterations) {
- LLVM_DEBUG(dbgs() << "\n\n[IC] Iteration limit #" << MaxIterations
+ if (Iteration > Opts.MaxIterations && !Opts.VerifyFixpoint) {
+ LLVM_DEBUG(dbgs() << "\n\n[IC] Iteration limit #" << Opts.MaxIterations
<< " on " << F.getName()
- << " reached; stopping before reaching a fixpoint\n");
+ << " reached; stopping without verifying fixpoint\n");
break;
}
+ ++NumWorklistIterations;
LLVM_DEBUG(dbgs() << "\n\nINSTCOMBINE ITERATION #" << Iteration << " on "
<< F.getName() << "\n");
- MadeIRChange |= prepareICWorklistFromFunction(F, DL, &TLI, Worklist);
-
InstCombinerImpl IC(Worklist, Builder, F.hasMinSize(), AA, AC, TLI, TTI, DT,
ORE, BFI, PSI, DL, LI);
IC.MaxArraySizeForCombine = MaxArraySize;
-
- if (!IC.run())
+ bool MadeChangeInThisIteration = IC.prepareWorklist(F, RPOT);
+ MadeChangeInThisIteration |= IC.run();
+ if (!MadeChangeInThisIteration)
break;
MadeIRChange = true;
+ if (Iteration > Opts.MaxIterations) {
+ report_fatal_error(
+ "Instruction Combining did not reach a fixpoint after " +
+ Twine(Opts.MaxIterations) + " iterations");
+ }
}
if (Iteration == 1)
@@ -4307,7 +4600,8 @@ void InstCombinePass::printPipeline(
OS, MapClassName2PassName);
OS << '<';
OS << "max-iterations=" << Options.MaxIterations << ";";
- OS << (Options.UseLoopInfo ? "" : "no-") << "use-loop-info";
+ OS << (Options.UseLoopInfo ? "" : "no-") << "use-loop-info;";
+ OS << (Options.VerifyFixpoint ? "" : "no-") << "verify-fixpoint";
OS << '>';
}
@@ -4333,7 +4627,7 @@ PreservedAnalyses InstCombinePass::run(Function &F,
&AM.getResult<BlockFrequencyAnalysis>(F) : nullptr;
if (!combineInstructionsOverFunction(F, Worklist, AA, AC, TLI, TTI, DT, ORE,
- BFI, PSI, Options.MaxIterations, LI))
+ BFI, PSI, LI, Options))
// No changes, all analyses are preserved.
return PreservedAnalyses::all();
@@ -4382,8 +4676,7 @@ bool InstructionCombiningPass::runOnFunction(Function &F) {
nullptr;
return combineInstructionsOverFunction(F, Worklist, AA, AC, TLI, TTI, DT, ORE,
- BFI, PSI,
- InstCombineDefaultMaxIterations, LI);
+ BFI, PSI, LI, InstCombineOptions());
}
char InstructionCombiningPass::ID = 0;