Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions llvm/include/llvm/Analysis/ScalarEvolution.h
Original file line number Diff line number Diff line change
Expand Up @@ -1502,12 +1502,6 @@ class ScalarEvolution {
/// Mark predicate values currently being processed by isImpliedCond.
SmallPtrSet<const Value *, 6> PendingLoopPredicates;

/// Mark SCEVUnknown Phis currently being processed by getRangeRef.
SmallPtrSet<const PHINode *, 6> PendingPhiRanges;

/// Mark SCEVUnknown Phis currently being processed by getRangeRefIter.
SmallPtrSet<const PHINode *, 6> PendingPhiRangesIter;

// Mark SCEVUnknown Phis currently being processed by isImpliedViaMerge.
SmallPtrSet<const PHINode *, 6> PendingMerges;

Expand Down
141 changes: 109 additions & 32 deletions llvm/lib/Analysis/ScalarEvolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6000,7 +6000,9 @@ static bool BrPHIToSelect(DominatorTree &DT, BranchInst *BI, PHINode *Merge,
return false;
}

const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
static bool getOperandsForSelectLikePHI(DominatorTree &DT, PHINode *PN,
Value *&Cond, Value *&LHS,
Value *&RHS) {
auto IsReachable =
[&](BasicBlock *BB) { return DT.isReachableFromEntry(BB); };
if (PN->getNumIncomingValues() == 2 && all_of(PN->blocks(), IsReachable)) {
Expand All @@ -6020,29 +6022,23 @@ const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
assert(IDom && "At least the entry block should dominate PN");

auto *BI = dyn_cast<BranchInst>(IDom->getTerminator());
Value *Cond = nullptr, *LHS = nullptr, *RHS = nullptr;

if (BI && BI->isConditional() &&
BrPHIToSelect(DT, BI, PN, Cond, LHS, RHS) &&
properlyDominates(getSCEV(LHS), PN->getParent()) &&
properlyDominates(getSCEV(RHS), PN->getParent()))
return createNodeForSelectOrPHI(PN, Cond, LHS, RHS);
return BI && BI->isConditional() &&
BrPHIToSelect(DT, BI, PN, Cond, LHS, RHS);
}
return false;
}

const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
Value *Cond = nullptr, *LHS = nullptr, *RHS = nullptr;
if (getOperandsForSelectLikePHI(DT, PN, Cond, LHS, RHS) &&
properlyDominates(getSCEV(LHS), PN->getParent()) &&
properlyDominates(getSCEV(RHS), PN->getParent()))
return createNodeForSelectOrPHI(PN, Cond, LHS, RHS);

return nullptr;
}

/// Returns SCEV for the first operand of a phi if all phi operands have
/// identical opcodes and operands
/// eg.
/// a: %add = %a + %b
/// br %c
/// b: %add1 = %a + %b
/// br %c
/// c: %phi = phi [%add, a], [%add1, b]
/// scev(%phi) => scev(%add)
const SCEV *
ScalarEvolution::createNodeForPHIWithIdenticalOperands(PHINode *PN) {
static BinaryOperator *getCommonInstForPHI(PHINode *PN) {
BinaryOperator *CommonInst = nullptr;
// Check if instructions are identical.
for (Value *Incoming : PN->incoming_values()) {
Expand All @@ -6057,6 +6053,21 @@ ScalarEvolution::createNodeForPHIWithIdenticalOperands(PHINode *PN) {
CommonInst = IncomingInst;
}
}
return CommonInst;
}

/// Returns SCEV for the first operand of a phi if all phi operands have
/// identical opcodes and operands
/// eg.
/// a: %add = %a + %b
/// br %c
/// b: %add1 = %a + %b
/// br %c
/// c: %phi = phi [%add, a], [%add1, b]
/// scev(%phi) => scev(%add)
const SCEV *
ScalarEvolution::createNodeForPHIWithIdenticalOperands(PHINode *PN) {
BinaryOperator *CommonInst = getCommonInstForPHI(PN);
if (!CommonInst)
return nullptr;

Expand Down Expand Up @@ -6581,6 +6592,28 @@ getRangeForUnknownRecurrence(const SCEVUnknown *U) {
return FullSet;
}

// The goal of this function is to check if recursively visiting the operands
// of this PHI might lead to an infinite loop. If we do see such a loop,
// there's no good way to break it, so we avoid analyzing such cases.
//
// getRangeRef previously used a visited set to avoid infinite loops, but this
// caused other issues: the result was dependent on the order of getRangeRef
// calls, and the interaction with createSCEVIter could cause a stack overflow
// in some cases (see issue #148253).
//
// FIXME: The way this is implemented is overly conservative.
static bool RangeRefPHIAllowedOperands(DominatorTree &DT, PHINode *PH) {
Value *Cond = nullptr, *LHS = nullptr, *RHS = nullptr;
if (getOperandsForSelectLikePHI(DT, PH, Cond, LHS, RHS))
return true;

if (all_of(PH->operands(),
[&](Value *Operand) { return DT.dominates(Operand, PH); }))
return true;

return false;
}

const ConstantRange &
ScalarEvolution::getRangeRefIter(const SCEV *S,
ScalarEvolution::RangeSignHint SignHint) {
Expand Down Expand Up @@ -6636,8 +6669,8 @@ ScalarEvolution::getRangeRefIter(const SCEV *S,
continue;
}
// `SCEVUnknown`'s require special treatment.
if (const PHINode *P = dyn_cast<PHINode>(UnknownS->getValue())) {
if (!PendingPhiRangesIter.insert(P).second)
if (PHINode *P = dyn_cast<PHINode>(UnknownS->getValue())) {
if (!RangeRefPHIAllowedOperands(DT, P))
continue;
for (auto &Op : reverse(P->operands()))
AddToWorklist(getSCEV(Op));
Expand All @@ -6650,10 +6683,6 @@ ScalarEvolution::getRangeRefIter(const SCEV *S,
// their users in most cases.
for (const SCEV *P : reverse(drop_begin(WorkList))) {
getRangeRef(P, SignHint);

if (auto *UnknownS = dyn_cast<SCEVUnknown>(P))
if (const PHINode *P = dyn_cast<PHINode>(UnknownS->getValue()))
PendingPhiRangesIter.erase(P);
}
}

Expand Down Expand Up @@ -6963,8 +6992,13 @@ const ConstantRange &ScalarEvolution::getRangeRef(

// A range of Phi is a subset of union of all ranges of its input.
if (PHINode *Phi = dyn_cast<PHINode>(V)) {
// SCEVExpander sometimes creates SCEVUnknowns that are secretly
// AddRecs; return the range for the corresponding AddRec.
if (auto *AR = dyn_cast<SCEVAddRecExpr>(getSCEV(V)))
return getRangeRef(AR, SignHint, Depth + 1);

// Make sure that we do not run over cycled Phis.
if (PendingPhiRanges.insert(Phi).second) {
if (RangeRefPHIAllowedOperands(DT, Phi)) {
ConstantRange RangeFromOps(BitWidth, /*isFullSet=*/false);

for (const auto &Op : Phi->operands()) {
Expand All @@ -6976,9 +7010,6 @@ const ConstantRange &ScalarEvolution::getRangeRef(
}
ConservativeResult =
ConservativeResult.intersectWith(RangeFromOps, RangeType);
bool Erased = PendingPhiRanges.erase(Phi);
assert(Erased && "Failed to erase Phi properly?");
(void)Erased;
}
}

Expand Down Expand Up @@ -7657,7 +7688,55 @@ ScalarEvolution::getOperandsToCreate(Value *V, SmallVectorImpl<Value *> &Ops) {
return getUnknown(V);

case Instruction::PHI:
// Keep constructing SCEVs' for phis recursively for now.
// getNodeForPHI has four ways to turn a PHI into a SCEV; retrieve the
// relevant nodes for each of them.
//
// The first is just to call simplifyInstruction, and get something back
// that isn't a PHI.
if (Value *V = simplifyInstruction(
cast<PHINode>(U),
{getDataLayout(), &TLI, &DT, &AC, /*CtxI=*/nullptr,
/*UseInstrInfo=*/true, /*CanUseUndef=*/false})) {
assert(V);
Ops.push_back(V);
return nullptr;
}
// The second is createNodeForPHIWithIdenticalOperands: this looks for
// operands which all perform the same operation, but haven't been
// CSE'ed for whatever reason.
if (BinaryOperator *BO = getCommonInstForPHI(cast<PHINode>(U))) {
assert(BO);
Ops.push_back(BO);
return nullptr;
}
// The third is createNodeFromSelectLikePHI; this takes a PHI which
// is equivalent to a select, and analyzes it like a select.
{
Value *Cond = nullptr, *LHS = nullptr, *RHS = nullptr;
if (getOperandsForSelectLikePHI(DT, cast<PHINode>(U), Cond, LHS, RHS)) {
assert(Cond);
assert(LHS);
assert(RHS);
if (auto *CondICmp = dyn_cast<ICmpInst>(Cond)) {
Ops.push_back(CondICmp->getOperand(0));
Ops.push_back(CondICmp->getOperand(1));
}
Ops.push_back(Cond);
Ops.push_back(LHS);
Ops.push_back(RHS);
return nullptr;
}
}
// The fourth way is createAddRecFromPHI. It's complicated to handle here,
// so just construct it recursively.
//
// In addition to getNodeForPHI, also construct nodes which might be needed
// by getRangeRef.
if (RangeRefPHIAllowedOperands(DT, cast<PHINode>(U))) {
for (Value *V : cast<PHINode>(U)->operands())
Ops.push_back(V);
return nullptr;
}
return nullptr;

case Instruction::Select: {
Expand Down Expand Up @@ -13728,7 +13807,6 @@ ScalarEvolution::ScalarEvolution(ScalarEvolution &&Arg)
DT(Arg.DT), LI(Arg.LI), CouldNotCompute(std::move(Arg.CouldNotCompute)),
ValueExprMap(std::move(Arg.ValueExprMap)),
PendingLoopPredicates(std::move(Arg.PendingLoopPredicates)),
PendingPhiRanges(std::move(Arg.PendingPhiRanges)),
PendingMerges(std::move(Arg.PendingMerges)),
ConstantMultipleCache(std::move(Arg.ConstantMultipleCache)),
BackedgeTakenCounts(std::move(Arg.BackedgeTakenCounts)),
Expand Down Expand Up @@ -13771,7 +13849,6 @@ ScalarEvolution::~ScalarEvolution() {
PredicatedBackedgeTakenCounts.clear();

assert(PendingLoopPredicates.empty() && "isImpliedCond garbage");
assert(PendingPhiRanges.empty() && "getRangeRef garbage");
assert(PendingMerges.empty() && "isImpliedViaMerge garbage");
assert(!WalkingBEDominatingConds && "isLoopBackedgeGuardedByCond garbage!");
assert(!ProvingSplitPredicate && "ProvingSplitPredicate garbage!");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ define void @test(ptr %p) {
; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
; CHECK-NEXT: --> %iv U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop.header: Variant, %loop2: Invariant, %loop3: Invariant }
; CHECK-NEXT: %iv2 = phi i32 [ %iv, %loop.header ], [ %iv2.next, %loop2 ]
; CHECK-NEXT: --> {%iv,+,1}<%loop2> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Computable, %loop.header: Variant }
; CHECK-NEXT: --> {%iv,+,1}<nsw><%loop2> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Computable, %loop.header: Variant }
; CHECK-NEXT: %iv2.next = add i32 %iv2, 1
; CHECK-NEXT: --> {(1 + %iv),+,1}<%loop2> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Computable, %loop.header: Variant }
; CHECK-NEXT: --> {(1 + %iv),+,1}<nw><%loop2> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Computable, %loop.header: Variant }
; CHECK-NEXT: %v = load i32, ptr %p, align 4
; CHECK-NEXT: --> %v U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Variant, %loop.header: Variant }
; CHECK-NEXT: %iv2.ext = sext i32 %iv2 to i64
; CHECK-NEXT: --> (sext i32 {%iv,+,1}<%loop2> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) Exits: <<Unknown>> LoopDispositions: { %loop.header: Variant, %loop2: Computable, %loop3: Invariant }
; CHECK-NEXT: --> {(sext i32 %iv to i64),+,1}<nsw><%loop2> U: [-2147483648,6442450943) S: [-2147483648,6442450943) Exits: <<Unknown>> LoopDispositions: { %loop.header: Variant, %loop2: Computable, %loop3: Invariant }
; CHECK-NEXT: %iv3 = phi i64 [ %iv2.ext, %loop2.end ], [ %iv3.next, %loop3 ]
; CHECK-NEXT: --> {(sext i32 {%iv,+,1}<%loop2> to i64),+,1}<nsw><%loop3> U: [-2147483648,2147483648) S: [-2147483648,2147483648) Exits: (sext i32 {%iv,+,1}<%loop2> to i64) LoopDispositions: { %loop3: Computable, %loop.header: Variant }
; CHECK-NEXT: --> {{\{\{}}(sext i32 %iv to i64),+,1}<nsw><%loop2>,+,1}<nsw><%loop3> U: [-2147483648,6442450943) S: [-2147483648,6442450943) Exits: {(sext i32 %iv to i64),+,1}<nsw><%loop2> LoopDispositions: { %loop3: Computable, %loop.header: Variant }
; CHECK-NEXT: %iv3.next = add nsw i64 %iv3, 1
; CHECK-NEXT: --> {(1 + (sext i32 {%iv,+,1}<%loop2> to i64))<nsw>,+,1}<nsw><%loop3> U: [-2147483647,2147483649) S: [-2147483647,2147483649) Exits: (1 + (sext i32 {%iv,+,1}<%loop2> to i64))<nsw> LoopDispositions: { %loop3: Computable, %loop.header: Variant }
; CHECK-NEXT: --> {{\{\{}}(1 + (sext i32 %iv to i64))<nsw>,+,1}<nsw><%loop2>,+,1}<nsw><%loop3> U: [-2147483647,6442450944) S: [-2147483647,6442450944) Exits: {(1 + (sext i32 %iv to i64))<nsw>,+,1}<nsw><%loop2> LoopDispositions: { %loop3: Computable, %loop.header: Variant }
; CHECK-NEXT: %iv.next = trunc i64 %iv3 to i32
; CHECK-NEXT: --> {{\{\{}}%iv,+,1}<%loop2>,+,1}<%loop3> U: full-set S: full-set --> {%iv,+,1}<%loop2> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop.header: Variant, %loop2: Variant, %loop3: Computable }
; CHECK-NEXT: --> {{\{\{}}%iv,+,1}<nsw><%loop2>,+,1}<%loop3> U: full-set S: full-set --> {%iv,+,1}<nsw><%loop2> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop.header: Variant, %loop2: Variant, %loop3: Computable }
; CHECK-NEXT: Determining loop execution counts for: @test
; CHECK-NEXT: Loop %loop2: Unpredictable backedge-taken count.
; CHECK-NEXT: Loop %loop2: constant max backedge-taken count is i32 -1
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Analysis/ScalarEvolution/outer_phi.ll
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ define i32 @test_01(i32 %a, i32 %b) {
; CHECK-LABEL: 'test_01'
; CHECK-NEXT: Classifying expressions for: @test_01
; CHECK-NEXT: %outer.iv = phi i32 [ 0, %entry ], [ %iv.next, %outer.backedge ]
; CHECK-NEXT: --> %outer.iv U: [0,-2147483647) S: [0,-2147483647) Exits: <<Unknown>> LoopDispositions: { %outer: Variant, %inner: Invariant }
; CHECK-NEXT: --> %outer.iv U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %outer: Variant, %inner: Invariant }
; CHECK-NEXT: %iv = phi i32 [ 0, %outer ], [ %iv.next, %inner.backedge ]
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%inner> U: [0,-2147483648) S: [0,-2147483648) Exits: <<Unknown>> LoopDispositions: { %inner: Computable, %outer: Variant }
; CHECK-NEXT: %iv.next = add nuw nsw i32 %iv, 1
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Analysis/ScalarEvolution/pr123550.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ define i32 @test() {
; CHECK-LABEL: 'test'
; CHECK-NEXT: Classifying expressions for: @test
; CHECK-NEXT: %phi = phi i32 [ -173, %bb ], [ %sub, %loop ]
; CHECK-NEXT: --> %phi U: [-173,1) S: [-173,1) Exits: -173 LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> %phi U: [-256,256) S: [-256,256) Exits: -173 LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %iv2 = phi i32 [ 1, %bb ], [ %iv2.inc, %loop ]
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,2) S: [1,2) Exits: 1 LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %srem = srem i32 729259140, %phi
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Analysis/ScalarEvolution/pr49856.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ define void @test() {
; CHECK-LABEL: 'test'
; CHECK-NEXT: Classifying expressions for: @test
; CHECK-NEXT: %tmp = phi i32 [ 2, %bb ], [ %tmp2, %bb3 ]
; CHECK-NEXT: --> %tmp U: [1,-2147483648) S: [0,-2147483648)
; CHECK-NEXT: --> %tmp U: [0,-2147483648) S: [0,-2147483648)
; CHECK-NEXT: %tmp2 = add nuw nsw i32 %tmp, 1
; CHECK-NEXT: --> (1 + %tmp)<nuw> U: [1,-2147483647) S: [1,-2147483647)
; CHECK-NEXT: Determining loop execution counts for: @test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ define i32 @pr58402_large_number_of_zext(ptr %dst) {
; CHECK-LABEL: 'pr58402_large_number_of_zext'
; CHECK-NEXT: Classifying expressions for: @pr58402_large_number_of_zext
; CHECK-NEXT: %d.0 = phi i32 [ 0, %entry ], [ %add7.15, %header ]
; CHECK-NEXT: --> %d.0 U: [0,65) S: [0,65) Exits: <<Unknown>> LoopDispositions: { %header: Variant }
; CHECK-NEXT: --> %d.0 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %header: Variant }
; CHECK-NEXT: %b.0 = phi i32 [ 59, %entry ], [ %b.0, %header ]
; CHECK-NEXT: --> 59 U: [59,60) S: [59,60) Exits: 59 LoopDispositions: { %header: Invariant }
; CHECK-NEXT: %conv.neg = sext i1 %cmp to i32
Expand Down
10 changes: 5 additions & 5 deletions llvm/test/Analysis/ScalarEvolution/ranges.ll
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ define void @mul_6(i32 %n) {
; CHECK-LABEL: 'mul_6'
; CHECK-NEXT: Classifying expressions for: @mul_6
; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
; CHECK-NEXT: --> %iv U: [0,-1) S: [-2147483648,2147483645) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> %iv U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %iv.inc = mul nuw i32 %iv, 6
; CHECK-NEXT: --> (6 * %iv) U: [0,-3) S: [-2147483648,2147483645) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @mul_6
Expand Down Expand Up @@ -358,7 +358,7 @@ define void @mul_8(i32 %n) {
; CHECK-LABEL: 'mul_8'
; CHECK-NEXT: Classifying expressions for: @mul_8
; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
; CHECK-NEXT: --> %iv U: [0,-7) S: [-2147483648,2147483585) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> %iv U: [0,-7) S: [-2147483648,2147483641) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %iv.inc = mul nuw i32 %iv, 8
; CHECK-NEXT: --> (8 * %iv) U: [0,-63) S: [-2147483648,2147483585) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @mul_8
Expand Down Expand Up @@ -408,7 +408,7 @@ define void @mul_10(i32 %n) {
; CHECK-LABEL: 'mul_10'
; CHECK-NEXT: Classifying expressions for: @mul_10
; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
; CHECK-NEXT: --> %iv U: [0,-1) S: [-2147483648,2147483645) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> %iv U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %iv.inc = mul nuw i32 %iv, 10
; CHECK-NEXT: --> (10 * %iv) U: [0,-3) S: [-2147483648,2147483645) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @mul_10
Expand All @@ -433,7 +433,7 @@ define void @mul_8_wrap(i32 %n) {
; CHECK-LABEL: 'mul_8_wrap'
; CHECK-NEXT: Classifying expressions for: @mul_8_wrap
; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
; CHECK-NEXT: --> %iv U: [0,-7) S: [-2147483648,2147483585) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> %iv U: [0,-7) S: [-2147483648,2147483641) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %iv.inc = mul i32 %iv, 8
; CHECK-NEXT: --> (8 * %iv) U: [0,-63) S: [-2147483648,2147483585) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @mul_8_wrap
Expand All @@ -458,7 +458,7 @@ define void @mul_10_wrap(i32 %n) {
; CHECK-LABEL: 'mul_10_wrap'
; CHECK-NEXT: Classifying expressions for: @mul_10_wrap
; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
; CHECK-NEXT: --> %iv U: [0,-1) S: [-2147483648,2147483645) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> %iv U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %iv.inc = mul i32 %iv, 10
; CHECK-NEXT: --> (10 * %iv) U: [0,-3) S: [-2147483648,2147483645) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @mul_10_wrap
Expand Down
Loading
Loading