diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h --- a/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -1199,7 +1199,8 @@ /// controls the exit of a loop known to have a finite number of iterations. bool SimplifyICmpOperands(ICmpInst::Predicate &Pred, const SCEV *&LHS, const SCEV *&RHS, unsigned Depth = 0, - bool ControllingFiniteLoop = false); + bool ControllingFiniteLoop = false, + const Loop *L = nullptr); /// Return the "disposition" of the given SCEV with respect to the given /// loop. diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -9186,9 +9186,9 @@ bool ControllingFiniteLoop = ControlsExit && loopHasNoAbnormalExits(L) && loopIsFiniteByAssumption(L); // Simplify the operands before analyzing them. - (void)SimplifyICmpOperands(Pred, LHS, RHS, /*Depth=*/0, - (EnableFiniteLoopControl ? ControllingFiniteLoop - : false)); + (void)SimplifyICmpOperands( + Pred, LHS, RHS, /*Depth=*/0, + (EnableFiniteLoopControl ? ControllingFiniteLoop : false), L); // If we have a comparison of a chrec against a constant, try to use value // ranges to answer this query. @@ -10655,7 +10655,8 @@ bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred, const SCEV *&LHS, const SCEV *&RHS, unsigned Depth, - bool ControllingFiniteLoop) { + bool ControllingFiniteLoop, + const Loop *L) { bool Changed = false; // Simplifies ICMP to trivial true or false by turning it into '0 == 0' or // '0 != 0'. @@ -10783,6 +10784,12 @@ return TrivialCase(false); } + bool IsRHSOuterLoopInvariant = false; + if (L) { + const Loop *Parent = L->getOutermostLoop(); + IsRHSOuterLoopInvariant = Parent != L ? isLoopInvariant(RHS, Parent) : true; + } + // If possible, canonicalize GE/LE comparisons to GT/LT comparisons, by // adding or subtracting 1 from one of the operands. This can be done for // one of two reasons: @@ -10818,7 +10825,8 @@ } break; case ICmpInst::ICMP_ULE: - if (ControllingFiniteLoop || !getUnsignedRangeMax(RHS).isMaxValue()) { + if ((ControllingFiniteLoop && IsRHSOuterLoopInvariant) || + !getUnsignedRangeMax(RHS).isMaxValue()) { RHS = getAddExpr(getConstant(RHS->getType(), 1, true), RHS, SCEV::FlagNUW); Pred = ICmpInst::ICMP_ULT; diff --git a/llvm/test/Transforms/IndVarSimplify/pr60944.ll b/llvm/test/Transforms/IndVarSimplify/pr60944.ll --- a/llvm/test/Transforms/IndVarSimplify/pr60944.ll +++ b/llvm/test/Transforms/IndVarSimplify/pr60944.ll @@ -32,7 +32,8 @@ ; CHECK-NEXT: [[TMP5:%.*]] = load i16, ptr @a, align 4 ; CHECK-NEXT: [[CONV5_I:%.*]] = sext i16 [[TMP5]] to i32 ; CHECK-NEXT: [[DIV_I]] = sdiv i32 [[CONV5_I]], [[DIV11_I]] -; CHECK-NEXT: br i1 false, label [[E_EXIT:%.*]], label [[WHILE_BODY_I]] +; CHECK-NEXT: [[CMP6_NOT_I:%.*]] = icmp eq i32 [[DIV11_I]], -1 +; CHECK-NEXT: br i1 [[CMP6_NOT_I]], label [[E_EXIT:%.*]], label [[WHILE_BODY_I]] ; CHECK: while.body4.i.preheader: ; CHECK-NEXT: br label [[WHILE_BODY4_I]] ; CHECK: while.end.i.loopexit: