[llvm] 74bd92d - Revert "[IndVarSimplify] Add safety check for getTruncateExpr in genLoopLimit (#172234)"
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 12 05:52:25 PST 2026
Author: Nikita Popov
Date: 2026-02-12T14:52:14+01:00
New Revision: 74bd92d6e2e5d8f1c541564bfc51d423001ba033
URL: https://github.com/llvm/llvm-project/commit/74bd92d6e2e5d8f1c541564bfc51d423001ba033
DIFF: https://github.com/llvm/llvm-project/commit/74bd92d6e2e5d8f1c541564bfc51d423001ba033.diff
LOG: Revert "[IndVarSimplify] Add safety check for getTruncateExpr in genLoopLimit (#172234)"
This reverts commit 4f551b55aeb316cd2d8f8f911908ea5bd4ced16b.
This change reformatted the file.
Added:
Modified:
llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
Removed:
llvm/test/Transforms/IndVarSimplify/scev-update-loop-opt.ll
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index 4428600093d31..f377c192371ea 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -83,11 +83,11 @@ using namespace SCEVPatternMatch;
#define DEBUG_TYPE "indvars"
-STATISTIC(NumWidened, "Number of indvars widened");
-STATISTIC(NumReplaced, "Number of exit values replaced");
-STATISTIC(NumLFTR, "Number of loop exit tests replaced");
-STATISTIC(NumElimExt, "Number of IV sign/zero extends eliminated");
-STATISTIC(NumElimIV, "Number of congruent IVs eliminated");
+STATISTIC(NumWidened , "Number of indvars widened");
+STATISTIC(NumReplaced , "Number of exit values replaced");
+STATISTIC(NumLFTR , "Number of loop exit tests replaced");
+STATISTIC(NumElimExt , "Number of IV sign/zero extends eliminated");
+STATISTIC(NumElimIV , "Number of congruent IVs eliminated");
static cl::opt<ReplaceExitVal> ReplaceExitValue(
"replexitval", cl::Hidden, cl::init(OnlyCheapRepl),
@@ -106,25 +106,25 @@ static cl::opt<ReplaceExitVal> ReplaceExitValue(
"always replace exit value whenever possible")));
static cl::opt<bool> UsePostIncrementRanges(
- "indvars-post-increment-ranges", cl::Hidden,
- cl::desc("Use post increment control-dependent ranges in IndVarSimplify"),
- cl::init(true));
+ "indvars-post-increment-ranges", cl::Hidden,
+ cl::desc("Use post increment control-dependent ranges in IndVarSimplify"),
+ cl::init(true));
static cl::opt<bool>
- DisableLFTR("disable-lftr", cl::Hidden, cl::init(false),
- cl::desc("Disable Linear Function Test Replace optimization"));
+DisableLFTR("disable-lftr", cl::Hidden, cl::init(false),
+ cl::desc("Disable Linear Function Test Replace optimization"));
static cl::opt<bool>
- LoopPredication("indvars-predicate-loops", cl::Hidden, cl::init(true),
- cl::desc("Predicate conditions in read only loops"));
+LoopPredication("indvars-predicate-loops", cl::Hidden, cl::init(true),
+ cl::desc("Predicate conditions in read only loops"));
static cl::opt<bool> LoopPredicationTraps(
"indvars-predicate-loop-traps", cl::Hidden, cl::init(true),
cl::desc("Predicate conditions that trap in loops with only local writes"));
static cl::opt<bool>
- AllowIVWidening("indvars-widen-indvars", cl::Hidden, cl::init(true),
- cl::desc("Allow widening of indvars to eliminate s/zext"));
+AllowIVWidening("indvars-widen-indvars", cl::Hidden, cl::init(true),
+ cl::desc("Allow widening of indvars to eliminate s/zext"));
namespace {
@@ -159,8 +159,8 @@ class IndVarSimplify {
bool rewriteFirstIterationLoopExitValues(Loop *L);
bool linearFunctionTestReplace(Loop *L, BasicBlock *ExitingBB,
- const SCEV *ExitCount, PHINode *IndVar,
- SCEVExpander &Rewriter);
+ const SCEV *ExitCount,
+ PHINode *IndVar, SCEVExpander &Rewriter);
bool sinkUnusedInvariants(Loop *L);
@@ -564,7 +564,8 @@ bool IndVarSimplify::rewriteFirstIterationLoopExitValues(Loop *L) {
// traces which lead to this exit being taken on the 2nd iteration
// aren't.) Note that this is about whether the exit branch is
// executed, not about whether it is taken.
- if (!L->getLoopLatch() || !DT->dominates(IncomingBB, L->getLoopLatch()))
+ if (!L->getLoopLatch() ||
+ !DT->dominates(IncomingBB, L->getLoopLatch()))
continue;
// Get condition that leads to the exit path.
@@ -616,7 +617,8 @@ bool IndVarSimplify::rewriteFirstIterationLoopExitValues(Loop *L) {
/// Update information about the induction variable that is extended by this
/// sign or zero extend operation. This is used to determine the final width of
/// the IV before actually widening it.
-static void visitIVCast(CastInst *Cast, WideIVInfo &WI, ScalarEvolution *SE,
+static void visitIVCast(CastInst *Cast, WideIVInfo &WI,
+ ScalarEvolution *SE,
const TargetTransformInfo *TTI) {
bool IsSigned = Cast->getOpcode() == Instruction::SExt;
if (!IsSigned && Cast->getOpcode() != Instruction::ZExt)
@@ -641,9 +643,10 @@ static void visitIVCast(CastInst *Cast, WideIVInfo &WI, ScalarEvolution *SE,
// because at least an ADD is required to increment the induction variable. We
// could compute more comprehensively the cost of all instructions on the
// induction variable when necessary.
- if (TTI && TTI->getArithmeticInstrCost(Instruction::Add, Ty) >
- TTI->getArithmeticInstrCost(Instruction::Add,
- Cast->getOperand(0)->getType())) {
+ if (TTI &&
+ TTI->getArithmeticInstrCost(Instruction::Add, Ty) >
+ TTI->getArithmeticInstrCost(Instruction::Add,
+ Cast->getOperand(0)->getType())) {
return;
}
@@ -682,7 +685,7 @@ class IndVarSimplifyVisitor : public IVVisitor {
IndVarSimplifyVisitor(PHINode *IV, ScalarEvolution *SCEV,
const TargetTransformInfo *TTI,
const DominatorTree *DTree)
- : SE(SCEV), TTI(TTI), IVPhi(IV) {
+ : SE(SCEV), TTI(TTI), IVPhi(IV) {
DT = DTree;
WI.NarrowIV = IVPhi;
}
@@ -698,7 +701,8 @@ class IndVarSimplifyVisitor : public IVVisitor {
/// candidates for simplification.
///
/// Sign/Zero extend elimination is interleaved with IV simplification.
-bool IndVarSimplify::simplifyAndExtend(Loop *L, SCEVExpander &Rewriter,
+bool IndVarSimplify::simplifyAndExtend(Loop *L,
+ SCEVExpander &Rewriter,
LoopInfo *LI) {
SmallVector<WideIVInfo, 8> WideIVs;
@@ -735,7 +739,7 @@ bool IndVarSimplify::simplifyAndExtend(Loop *L, SCEVExpander &Rewriter,
if (Visitor.WI.WidestNativeType) {
WideIVs.push_back(Visitor.WI);
}
- } while (!LoopPhis.empty());
+ } while(!LoopPhis.empty());
// Continue if we disallowed widening.
if (!WidenIndVars)
@@ -744,8 +748,8 @@ bool IndVarSimplify::simplifyAndExtend(Loop *L, SCEVExpander &Rewriter,
for (; !WideIVs.empty(); WideIVs.pop_back()) {
unsigned ElimExt;
unsigned Widened;
- if (PHINode *WidePhi = createWideIV(WideIVs.back(), LI, SE, Rewriter, DT,
- DeadInsts, ElimExt, Widened,
+ if (PHINode *WidePhi = createWideIV(WideIVs.back(), LI, SE, Rewriter,
+ DT, DeadInsts, ElimExt, Widened,
HasGuards, UsePostIncrementRanges)) {
NumElimExt += ElimExt;
NumWidened += Widened;
@@ -865,7 +869,7 @@ static bool needsLFTR(Loop *L, BasicBlock *ExitingBB) {
/// Recursive helper for hasConcreteDef(). Unfortunately, this currently boils
/// down to checking that all operands are constant and listing instructions
/// that may hide undef.
-static bool hasConcreteDefImpl(Value *V, SmallPtrSetImpl<Value *> &Visited,
+static bool hasConcreteDefImpl(Value *V, SmallPtrSetImpl<Value*> &Visited,
unsigned Depth) {
if (isa<Constant>(V))
return !isa<UndefValue>(V);
@@ -880,14 +884,14 @@ static bool hasConcreteDefImpl(Value *V, SmallPtrSetImpl<Value *> &Visited,
return false;
// Load and return values may be undef.
- if (I->mayReadFromMemory() || isa<CallInst>(I) || isa<InvokeInst>(I))
+ if(I->mayReadFromMemory() || isa<CallInst>(I) || isa<InvokeInst>(I))
return false;
// Optimistically handle other instructions.
for (Value *Op : I->operands()) {
if (!Visited.insert(Op).second)
continue;
- if (!hasConcreteDefImpl(Op, Visited, Depth + 1))
+ if (!hasConcreteDefImpl(Op, Visited, Depth+1))
return false;
}
return true;
@@ -899,7 +903,7 @@ static bool hasConcreteDefImpl(Value *V, SmallPtrSetImpl<Value *> &Visited,
/// TODO: If we decide that this is a good approach to checking for undef, we
/// may factor it into a common location.
static bool hasConcreteDef(Value *V) {
- SmallPtrSet<Value *, 8> Visited;
+ SmallPtrSet<Value*, 8> Visited;
Visited.insert(V);
return hasConcreteDefImpl(V, Visited, 0);
}
@@ -907,7 +911,8 @@ static bool hasConcreteDef(Value *V) {
/// Return true if the given phi is a "counter" in L. A counter is an
/// add recurance (of integer or pointer type) with an arbitrary start, and a
/// step of 1. Note that L must have exactly one latch.
-static bool isLoopCounter(PHINode *Phi, Loop *L, ScalarEvolution *SE) {
+static bool isLoopCounter(PHINode* Phi, Loop *L,
+ ScalarEvolution *SE) {
assert(Phi->getParent() == L->getHeader());
assert(L->getLoopLatch());
@@ -932,8 +937,8 @@ static bool isLoopCounter(PHINode *Phi, Loop *L, ScalarEvolution *SE) {
/// valid count without scaling the address stride, so it remains a pointer
/// expression as far as SCEV is concerned.
static PHINode *FindLoopCounter(Loop *L, BasicBlock *ExitingBB,
- const SCEV *BECount, ScalarEvolution *SE,
- DominatorTree *DT) {
+ const SCEV *BECount,
+ ScalarEvolution *SE, DominatorTree *DT) {
uint64_t BCWidth = SE->getTypeSizeInBits(BECount->getType());
Value *Cond = cast<BranchInst>(ExitingBB->getTerminator())->getCondition();
@@ -1026,17 +1031,10 @@ static Value *genLoopLimit(PHINode *IndVar, BasicBlock *ExitingBB,
// exit count add(zext(add)) expression.
if (IndVar->getType()->isIntegerTy() &&
SE->getTypeSizeInBits(AR->getType()) >
- SE->getTypeSizeInBits(ExitCount->getType())) {
+ SE->getTypeSizeInBits(ExitCount->getType())) {
const SCEV *IVInit = AR->getStart();
- if (!isa<SCEVConstant>(IVInit) || !isa<SCEVConstant>(ExitCount)) {
- const SCEV *TruncExpr = SE->getTruncateExpr(AR, ExitCount->getType());
-
- // The following bailout is necessary due to the interaction with
- // the depth limit in SCEV analysis.
- if (!isa<SCEVAddRecExpr>(TruncExpr))
- return nullptr;
- AR = cast<SCEVAddRecExpr>(TruncExpr);
- }
+ if (!isa<SCEVConstant>(IVInit) || !isa<SCEVConstant>(ExitCount))
+ AR = cast<SCEVAddRecExpr>(SE->getTruncateExpr(AR, ExitCount->getType()));
}
const SCEVAddRecExpr *ARBase = UsePostInc ? AR->getPostIncExpr(*SE) : AR;
@@ -1052,14 +1050,14 @@ static Value *genLoopLimit(PHINode *IndVar, BasicBlock *ExitingBB,
/// able to rewrite the exit tests of any loop where the SCEV analysis can
/// determine a loop-invariant trip count of the loop, which is actually a much
/// broader range than just linear tests.
-bool IndVarSimplify::linearFunctionTestReplace(Loop *L, BasicBlock *ExitingBB,
- const SCEV *ExitCount,
- PHINode *IndVar,
- SCEVExpander &Rewriter) {
+bool IndVarSimplify::
+linearFunctionTestReplace(Loop *L, BasicBlock *ExitingBB,
+ const SCEV *ExitCount,
+ PHINode *IndVar, SCEVExpander &Rewriter) {
assert(L->getLoopLatch() && "Loop no longer in simplified form?");
assert(isLoopCounter(IndVar, L, SE));
- Instruction *const IncVar =
- cast<Instruction>(IndVar->getIncomingValueForBlock(L->getLoopLatch()));
+ Instruction * const IncVar =
+ cast<Instruction>(IndVar->getIncomingValueForBlock(L->getLoopLatch()));
// Initialize CmpIndVar to the preincremented IV.
Value *CmpIndVar = IndVar;
@@ -1083,15 +1081,6 @@ bool IndVarSimplify::linearFunctionTestReplace(Loop *L, BasicBlock *ExitingBB,
}
}
- Value *ExitCnt =
- genLoopLimit(IndVar, ExitingBB, ExitCount, UsePostInc, L, Rewriter, SE);
- if (!ExitCnt)
- return false;
-
- assert(ExitCnt->getType()->isPointerTy() ==
- IndVar->getType()->isPointerTy() &&
- "genLoopLimit missed a cast");
-
// It may be necessary to drop nowrap flags on the incrementing instruction
// if either LFTR moves from a pre-inc check to a post-inc check (in which
// case the increment might have previously been poison on the last iteration
@@ -1112,6 +1101,12 @@ bool IndVarSimplify::linearFunctionTestReplace(Loop *L, BasicBlock *ExitingBB,
BO->setHasNoSignedWrap(AR->hasNoSignedWrap());
}
+ Value *ExitCnt = genLoopLimit(
+ IndVar, ExitingBB, ExitCount, UsePostInc, L, Rewriter, SE);
+ assert(ExitCnt->getType()->isPointerTy() ==
+ IndVar->getType()->isPointerTy() &&
+ "genLoopLimit missed a cast");
+
// Insert a new icmp_ne or icmp_eq instruction before the branch.
BranchInst *BI = cast<BranchInst>(ExitingBB->getTerminator());
ICmpInst::Predicate P;
@@ -1147,19 +1142,19 @@ bool IndVarSimplify::linearFunctionTestReplace(Loop *L, BasicBlock *ExitingBB,
const SCEV *IV = SE->getSCEV(CmpIndVar);
const SCEV *TruncatedIV = SE->getTruncateExpr(IV, ExitCnt->getType());
const SCEV *ZExtTrunc =
- SE->getZeroExtendExpr(TruncatedIV, CmpIndVar->getType());
+ SE->getZeroExtendExpr(TruncatedIV, CmpIndVar->getType());
if (ZExtTrunc == IV) {
Extended = true;
- ExitCnt =
- Builder.CreateZExt(ExitCnt, IndVar->getType(), "wide.trip.count");
+ ExitCnt = Builder.CreateZExt(ExitCnt, IndVar->getType(),
+ "wide.trip.count");
} else {
const SCEV *SExtTrunc =
- SE->getSignExtendExpr(TruncatedIV, CmpIndVar->getType());
+ SE->getSignExtendExpr(TruncatedIV, CmpIndVar->getType());
if (SExtTrunc == IV) {
Extended = true;
- ExitCnt =
- Builder.CreateSExt(ExitCnt, IndVar->getType(), "wide.trip.count");
+ ExitCnt = Builder.CreateSExt(ExitCnt, IndVar->getType(),
+ "wide.trip.count");
}
}
@@ -1167,8 +1162,8 @@ bool IndVarSimplify::linearFunctionTestReplace(Loop *L, BasicBlock *ExitingBB,
bool Discard;
L->makeLoopInvariant(ExitCnt, Discard);
} else
- CmpIndVar =
- Builder.CreateTrunc(CmpIndVar, ExitCnt->getType(), "lftr.wideiv");
+ CmpIndVar = Builder.CreateTrunc(CmpIndVar, ExitCnt->getType(),
+ "lftr.wideiv");
}
LLVM_DEBUG(dbgs() << "INDVARS: Rewriting loop exit condition to:\n"
<< " LHS:" << *CmpIndVar << '\n'
@@ -1201,12 +1196,10 @@ bool IndVarSimplify::linearFunctionTestReplace(Loop *L, BasicBlock *ExitingBB,
/// exit block to reduce register pressure in the loop.
bool IndVarSimplify::sinkUnusedInvariants(Loop *L) {
BasicBlock *ExitBlock = L->getExitBlock();
- if (!ExitBlock)
- return false;
+ if (!ExitBlock) return false;
BasicBlock *Preheader = L->getLoopPreheader();
- if (!Preheader)
- return false;
+ if (!Preheader) return false;
bool MadeAnyChanges = false;
for (Instruction &I : llvm::make_early_inc_range(llvm::reverse(*Preheader))) {
@@ -1250,7 +1243,8 @@ bool IndVarSimplify::sinkUnusedInvariants(Loop *L) {
Instruction *User = cast<Instruction>(U.getUser());
BasicBlock *UseBB = User->getParent();
if (PHINode *P = dyn_cast<PHINode>(User)) {
- unsigned i = PHINode::getIncomingValueNumForOperand(U.getOperandNo());
+ unsigned i =
+ PHINode::getIncomingValueNumForOperand(U.getOperandNo());
UseBB = P->getIncomingBlock(i);
}
if (UseBB == Preheader || L->contains(UseBB)) {
@@ -1527,7 +1521,7 @@ bool IndVarSimplify::canonicalizeExitCondition(Loop *L) {
// rely on them which results in SCEV caching sub-optimal answers. The
// concern about caching sub-optimal results is why we only query SCEVs of
// the loop invariant RHS here.
- SmallVector<BasicBlock *, 16> ExitingBlocks;
+ SmallVector<BasicBlock*, 16> ExitingBlocks;
L->getExitingBlocks(ExitingBlocks);
bool Changed = false;
for (auto *ExitingBB : ExitingBlocks) {
@@ -1654,7 +1648,7 @@ bool IndVarSimplify::canonicalizeExitCondition(Loop *L) {
}
bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
- SmallVector<BasicBlock *, 16> ExitingBlocks;
+ SmallVector<BasicBlock*, 16> ExitingBlocks;
L->getExitingBlocks(ExitingBlocks);
// Remove all exits which aren't both rewriteable and execute on every
@@ -1699,20 +1693,20 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
// all exits must dominate the latch, so there is a total dominance order
// between them.
llvm::sort(ExitingBlocks, [&](BasicBlock *A, BasicBlock *B) {
- // std::sort sorts in ascending order, so we want the inverse of
- // the normal dominance relation.
- if (A == B)
- return false;
- if (DT->properlyDominates(A, B))
- return true;
- else {
- assert(DT->properlyDominates(B, A) && "expected total dominance order!");
- return false;
- }
+ // std::sort sorts in ascending order, so we want the inverse of
+ // the normal dominance relation.
+ if (A == B) return false;
+ if (DT->properlyDominates(A, B))
+ return true;
+ else {
+ assert(DT->properlyDominates(B, A) &&
+ "expected total dominance order!");
+ return false;
+ }
});
#ifdef ASSERT
for (unsigned i = 1; i < ExitingBlocks.size(); i++) {
- assert(DT->dominates(ExitingBlocks[i - 1], ExitingBlocks[i]));
+ assert(DT->dominates(ExitingBlocks[i-1], ExitingBlocks[i]));
}
#endif
@@ -1842,7 +1836,7 @@ static bool crashingBBWithoutEffect(const BasicBlock &BB) {
}
bool IndVarSimplify::predicateLoopExits(Loop *L, SCEVExpander &Rewriter) {
- SmallVector<BasicBlock *, 16> ExitingBlocks;
+ SmallVector<BasicBlock*, 16> ExitingBlocks;
L->getExitingBlocks(ExitingBlocks);
// Finally, see if we can rewrite our exit conditions into a loop invariant
@@ -1887,7 +1881,7 @@ bool IndVarSimplify::predicateLoopExits(Loop *L, SCEVExpander &Rewriter) {
// within the loop which contains them. This assumes trivially lcssa phis
// have already been removed; TODO: generalize
BasicBlock *ExitBlock =
- BI->getSuccessor(L->contains(BI->getSuccessor(0)) ? 1 : 0);
+ BI->getSuccessor(L->contains(BI->getSuccessor(0)) ? 1 : 0);
if (!ExitBlock->phis().empty())
return true;
@@ -2018,7 +2012,8 @@ bool IndVarSimplify::predicateLoopExits(Loop *L, SCEVExpander &Rewriter) {
}
Value *NewCond;
if (ExitCount == ExactBTC) {
- NewCond = L->contains(BI->getSuccessor(0)) ? B.getFalse() : B.getTrue();
+ NewCond = L->contains(BI->getSuccessor(0)) ?
+ B.getFalse() : B.getTrue();
} else {
Value *ECV = Rewriter.expandCodeFor(ExitCount);
if (!ExactBTCV)
@@ -2029,8 +2024,8 @@ bool IndVarSimplify::predicateLoopExits(Loop *L, SCEVExpander &Rewriter) {
ECV = B.CreateZExt(ECV, WiderTy);
RHS = B.CreateZExt(RHS, WiderTy);
}
- auto Pred = L->contains(BI->getSuccessor(0)) ? ICmpInst::ICMP_NE
- : ICmpInst::ICMP_EQ;
+ auto Pred = L->contains(BI->getSuccessor(0)) ?
+ ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ;
NewCond = B.CreateICmp(Pred, ECV, RHS);
}
Value *OldCond = BI->getCondition();
@@ -2105,7 +2100,7 @@ bool IndVarSimplify::run(Loop *L) {
Changed |= canonicalizeExitCondition(L);
// Try to eliminate loop exits based on analyzeable exit counts
- if (optimizeLoopExits(L, Rewriter)) {
+ if (optimizeLoopExits(L, Rewriter)) {
Changed = true;
// Given we've changed exit counts, notify SCEV
// Some nested loops may share same folded exit basic block,
@@ -2126,7 +2121,7 @@ bool IndVarSimplify::run(Loop *L) {
if (!DisableLFTR) {
BasicBlock *PreHeader = L->getLoopPreheader();
- SmallVector<BasicBlock *, 16> ExitingBlocks;
+ SmallVector<BasicBlock*, 16> ExitingBlocks;
L->getExitingBlocks(ExitingBlocks);
for (BasicBlock *ExitingBB : ExitingBlocks) {
// Can't rewrite non-branch yet.
@@ -2166,8 +2161,9 @@ bool IndVarSimplify::run(Loop *L) {
if (!Rewriter.isSafeToExpand(ExitCount))
continue;
- Changed |=
- linearFunctionTestReplace(L, ExitingBB, ExitCount, IndVar, Rewriter);
+ Changed |= linearFunctionTestReplace(L, ExitingBB,
+ ExitCount, IndVar,
+ Rewriter);
}
}
// Clear the rewriter cache, because values that are in the rewriter's cache
diff --git a/llvm/test/Transforms/IndVarSimplify/scev-update-loop-opt.ll b/llvm/test/Transforms/IndVarSimplify/scev-update-loop-opt.ll
deleted file mode 100644
index f716796745fb7..0000000000000
--- a/llvm/test/Transforms/IndVarSimplify/scev-update-loop-opt.ll
+++ /dev/null
@@ -1,149 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt %s -passes="loop(loop-idiom,indvars,loop-deletion,loop-unroll-full)" -S | FileCheck %s
-; REQUIRES: asserts
-
-target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-
-define void @loop_limit_test(i32 %conv5, i1 %cmp13, i1 %cmp20, i1 %cmp27, i1 %cmp34, i1 %cmp41) local_unnamed_addr {
-; CHECK-LABEL: define void @loop_limit_test(
-; CHECK-SAME: i32 [[CONV5:%.*]], i1 [[CMP13:%.*]], i1 [[CMP20:%.*]], i1 [[CMP27:%.*]], i1 [[CMP34:%.*]], i1 [[CMP41:%.*]]) local_unnamed_addr {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[CONV5]], 1
-; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
-; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[CONV5]] to i64
-; CHECK-NEXT: br label %[[FOR_COND:.*]]
-; CHECK: [[FOR_COND_LOOPEXIT:.*]]:
-; CHECK-NEXT: br label %[[FOR_COND]]
-; CHECK: [[FOR_COND]]:
-; CHECK-NEXT: br label %[[FOR_COND2:.*]]
-; CHECK: [[FOR_COND2]]:
-; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[FOR_COND_CLEANUP14:.*]] ], [ 0, %[[FOR_COND]] ]
-; CHECK-NEXT: [[CMP6:%.*]] = icmp samesign ult i64 [[INDVARS_IV]], [[TMP2]]
-; CHECK-NEXT: br i1 [[CMP6]], label %[[FOR_COND9_PREHEADER:.*]], label %[[FOR_COND_LOOPEXIT]]
-; CHECK: [[FOR_COND9_PREHEADER]]:
-; CHECK-NEXT: br label %[[FOR_COND9:.*]]
-; CHECK: [[FOR_COND9_LOOPEXIT:.*]]:
-; CHECK-NEXT: br label %[[FOR_COND9]]
-; CHECK: [[FOR_COND9]]:
-; CHECK-NEXT: br i1 [[CMP13]], label %[[FOR_COND16_PREHEADER:.*]], label %[[FOR_COND_CLEANUP14]]
-; CHECK: [[FOR_COND16_PREHEADER]]:
-; CHECK-NEXT: br label %[[FOR_COND16:.*]]
-; CHECK: [[FOR_COND_CLEANUP14]]:
-; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
-; CHECK-NEXT: br label %[[FOR_COND2]]
-; CHECK: [[FOR_COND16_LOOPEXIT:.*]]:
-; CHECK-NEXT: br label %[[FOR_COND16]]
-; CHECK: [[FOR_COND16]]:
-; CHECK-NEXT: br i1 [[CMP20]], label %[[FOR_COND23_PREHEADER:.*]], label %[[FOR_COND9_LOOPEXIT]]
-; CHECK: [[FOR_COND23_PREHEADER]]:
-; CHECK-NEXT: br label %[[FOR_COND23:.*]]
-; CHECK: [[FOR_COND23_LOOPEXIT:.*]]:
-; CHECK-NEXT: br label %[[FOR_COND23]]
-; CHECK: [[FOR_COND23]]:
-; CHECK-NEXT: br i1 [[CMP27]], label %[[FOR_COND30_PREHEADER:.*]], label %[[FOR_COND16_LOOPEXIT]]
-; CHECK: [[FOR_COND30_PREHEADER]]:
-; CHECK-NEXT: br label %[[FOR_COND30:.*]]
-; CHECK: [[FOR_COND30_LOOPEXIT_LOOPEXIT:.*]]:
-; CHECK-NEXT: br label %[[FOR_COND30_LOOPEXIT:.*]]
-; CHECK: [[FOR_COND30_LOOPEXIT]]:
-; CHECK-NEXT: br label %[[FOR_COND30]]
-; CHECK: [[FOR_COND30]]:
-; CHECK-NEXT: br i1 [[CMP34]], label %[[FOR_COND37_PREHEADER:.*]], label %[[FOR_COND23_LOOPEXIT]]
-; CHECK: [[FOR_COND37_PREHEADER]]:
-; CHECK-NEXT: br label %[[FOR_COND37_PEEL_BEGIN:.*]]
-; CHECK: [[FOR_COND37_PEEL_BEGIN]]:
-; CHECK-NEXT: br label %[[FOR_COND37_PEEL:.*]]
-; CHECK: [[FOR_COND37_PEEL]]:
-; CHECK-NEXT: br i1 [[CMP41]], label %[[FOR_BODY43_PEEL:.*]], label %[[FOR_COND30_LOOPEXIT]]
-; CHECK: [[FOR_BODY43_PEEL]]:
-; CHECK-NEXT: [[CONV45_PEEL:%.*]] = zext i32 0 to i64
-; CHECK-NEXT: [[CALL31_I_I_PEEL:%.*]] = load volatile i64, ptr null, align 8
-; CHECK-NEXT: [[MUL79_I_I_PEEL:%.*]] = mul i64 [[CALL31_I_I_PEEL]], [[INDVARS_IV]]
-; CHECK-NEXT: [[DOTIDX1_PEEL:%.*]] = add i64 [[CONV45_PEEL]], [[MUL79_I_I_PEEL]]
-; CHECK-NEXT: [[SUB_PTR_LHS_CAST_PEEL:%.*]] = shl i64 [[DOTIDX1_PEEL]], 2
-; CHECK-NEXT: [[SUB_PTR_DIV_PEEL:%.*]] = ashr exact i64 [[SUB_PTR_LHS_CAST_PEEL]], 1
-; CHECK-NEXT: [[CMP55_PEEL:%.*]] = icmp sgt i64 0, 0
-; CHECK-NEXT: call void @llvm.assume(i1 [[CMP55_PEEL]])
-; CHECK-NEXT: br label %[[FOR_COND37_PEEL_NEXT:.*]]
-; CHECK: [[FOR_COND37_PEEL_NEXT]]:
-; CHECK-NEXT: br label %[[FOR_COND37_PEEL_NEXT1:.*]]
-; CHECK: [[FOR_COND37_PEEL_NEXT1]]:
-; CHECK-NEXT: br label %[[FOR_COND37_PREHEADER_PEEL_NEWPH:.*]]
-; CHECK: [[FOR_COND37_PREHEADER_PEEL_NEWPH]]:
-; CHECK-NEXT: br label %[[FOR_COND37:.*]]
-; CHECK: [[FOR_COND37]]:
-; CHECK-NEXT: [[OFFSET_619:%.*]] = phi i64 [ [[SUB_PTR_DIV:%.*]], %[[FOR_BODY43:.*]] ], [ [[SUB_PTR_DIV_PEEL]], %[[FOR_COND37_PREHEADER_PEEL_NEWPH]] ]
-; CHECK-NEXT: br i1 [[CMP41]], label %[[FOR_BODY43]], label %[[FOR_COND30_LOOPEXIT_LOOPEXIT]]
-; CHECK: [[FOR_BODY43]]:
-; CHECK-NEXT: [[CALL31_I_I:%.*]] = load volatile i64, ptr null, align 8
-; CHECK-NEXT: [[ADD33_I_I:%.*]] = add i64 [[INDVARS_IV]], [[CALL31_I_I]]
-; CHECK-NEXT: [[MUL42_I_I:%.*]] = mul i64 [[TMP1]], [[ADD33_I_I]]
-; CHECK-NEXT: [[ADD43_I_I:%.*]] = add i64 [[MUL42_I_I]], 1
-; CHECK-NEXT: [[MUL52_I_I:%.*]] = mul i64 [[TMP1]], [[ADD43_I_I]]
-; CHECK-NEXT: [[ADD53_I_I:%.*]] = add i64 [[MUL52_I_I]], 1
-; CHECK-NEXT: [[MUL62_I_I:%.*]] = mul i64 [[TMP1]], [[ADD53_I_I]]
-; CHECK-NEXT: [[ADD63_I_I:%.*]] = add i64 [[MUL62_I_I]], 1
-; CHECK-NEXT: [[MUL72_I_I:%.*]] = mul i64 [[INDVARS_IV]], [[ADD63_I_I]]
-; CHECK-NEXT: [[MUL79_I_I:%.*]] = mul i64 [[CALL31_I_I]], [[MUL72_I_I]]
-; CHECK-NEXT: [[DOTIDX1:%.*]] = add i64 [[TMP1]], [[MUL79_I_I]]
-; CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = shl i64 [[DOTIDX1]], 2
-; CHECK-NEXT: [[SUB_PTR_DIV]] = ashr exact i64 [[SUB_PTR_LHS_CAST]], 1
-; CHECK-NEXT: [[CMP55:%.*]] = icmp sgt i64 [[OFFSET_619]], 0
-; CHECK-NEXT: call void @llvm.assume(i1 [[CMP55]])
-; CHECK-NEXT: br label %[[FOR_COND37]], !llvm.loop [[LOOP0:![0-9]+]]
-;
-entry:
- br label %for.cond
-
-for.cond: ; preds = %for.cond2, %entry
- br label %for.cond2
-
-for.cond2: ; preds = %for.cond.cleanup14, %for.cond
- %i5.0 = phi i32 [ 0, %for.cond ], [ %inc70, %for.cond.cleanup14 ]
- %cmp6 = icmp ult i32 %i5.0, %conv5
- br i1 %cmp6, label %for.cond9, label %for.cond
-
-for.cond9: ; preds = %for.cond16, %for.cond2
- br i1 %cmp13, label %for.cond16, label %for.cond.cleanup14
-
-for.cond.cleanup14: ; preds = %for.cond9
- %inc70 = add i32 %i5.0, 1
- br label %for.cond2
-
-for.cond16: ; preds = %for.cond23, %for.cond9
- br i1 %cmp20, label %for.cond23, label %for.cond9
-
-for.cond23: ; preds = %for.cond30, %for.cond16
- br i1 %cmp27, label %for.cond30, label %for.cond16
-
-for.cond30: ; preds = %for.cond37, %for.cond23
- br i1 %cmp34, label %for.cond37, label %for.cond23
-
-for.cond37: ; preds = %for.body43, %for.cond30
- %i0.018 = phi i32 [ %inc, %for.body43 ], [ 0, %for.cond30 ]
- %offset.619 = phi i64 [ %sub.ptr.div, %for.body43 ], [ 0, %for.cond30 ]
- br i1 %cmp41, label %for.body43, label %for.cond30
-
-for.body43: ; preds = %for.cond37
- %conv45 = zext i32 %i0.018 to i64
- %conv50 = zext i32 %i5.0 to i64
- %call31.i.i = load volatile i64, ptr null, align 8
- %add33.i.i = add i64 %conv50, %call31.i.i
- %mul42.i.i = mul i64 %conv45, %add33.i.i
- %add43.i.i = add i64 %mul42.i.i, 1
- %mul52.i.i = mul i64 %conv45, %add43.i.i
- %add53.i.i = add i64 %mul52.i.i, 1
- %mul62.i.i = mul i64 %conv45, %add53.i.i
- %add63.i.i = add i64 %mul62.i.i, 1
- %mul72.i.i = mul i64 %conv50, %add63.i.i
- %mul79.i.i = mul i64 %call31.i.i, %mul72.i.i
- %.idx1 = add i64 %conv45, %mul79.i.i
- %sub.ptr.lhs.cast = shl i64 %.idx1, 2
- %sub.ptr.div = ashr exact i64 %sub.ptr.lhs.cast, 1
- %cmp55 = icmp sgt i64 %offset.619, 0
- call void @llvm.assume(i1 %cmp55)
- %inc = add i32 %conv5, 1
- br label %for.cond37
-}
-
-declare void @llvm.assume(i1 noundef)
More information about the llvm-commits
mailing list