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 @@ -5593,6 +5593,14 @@ ConservativeResult.intersectWith(X, RangeType)); } + if (const SCEVUMinExpr *UMin = dyn_cast(S)) { + ConstantRange X = getRangeRef(UMin->getOperand(0), SignHint); + for (unsigned i = 1, e = UMin->getNumOperands(); i != e; ++i) + X = X.umin(getRangeRef(UMin->getOperand(i), SignHint)); + return setRange(UMin, SignHint, + ConservativeResult.intersectWith(X, RangeType)); + } + if (const SCEVUDivExpr *UDiv = dyn_cast(S)) { ConstantRange X = getRangeRef(UDiv->getLHS(), SignHint); ConstantRange Y = getRangeRef(UDiv->getRHS(), SignHint); diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp --- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp +++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp @@ -1757,8 +1757,7 @@ std::unique_ptr M = parseAssemblyString( "define void @foo(i32 %i) { " "entry: " - " %cmp3 = icmp ult i32 %i, 16 " - " br i1 %cmp3, label %loop.body, label %exit " + " br label %loop.body " "loop.body: " " %iv = phi i32 [ %iv.next, %loop.body ], [ %i, %entry ] " " %iv.next = add nsw i32 %iv, 1 " @@ -1790,4 +1789,41 @@ cast(ScevIV)->getStepRecurrence(SE)); }); } + +TEST_F(ScalarEvolutionsTest, SCEVgetRanges) { + LLVMContext C; + SMDiagnostic Err; + std::unique_ptr M = parseAssemblyString( + "define void @foo(i32 %i) { " + "entry: " + " br label %loop.body " + "loop.body: " + " %iv = phi i32 [ %iv.next, %loop.body ], [ 0, %entry ] " + " %iv.next = add nsw i32 %iv, 1 " + " %cmp = icmp eq i32 %iv.next, 16 " + " br i1 %cmp, label %exit, label %loop.body " + "exit: " + " ret void " + "} ", + Err, C); + + ASSERT_TRUE(M && "Could not parse module?"); + ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!"); + + runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) { + auto *ScevIV = SE.getSCEV(getInstructionByName(F, "iv")); // {0,+,1} + auto *ScevI = SE.getSCEV(getArgByName(F, "i")); + EXPECT_EQ(SE.getUnsignedRange(ScevIV).getLower(), 0); + EXPECT_EQ(SE.getUnsignedRange(ScevIV).getUpper(), 16); + + auto *Add = SE.getAddExpr(ScevI, ScevIV); + ValueToSCEVMapTy RewriteMap; + RewriteMap[cast(ScevI)->getValue()] = + SE.getUMinExpr(ScevI, SE.getConstant(ScevI->getType(), 17)); + auto *AddWithUMin = SCEVParameterRewriter::rewrite(Add, SE, RewriteMap); + EXPECT_EQ(SE.getUnsignedRange(AddWithUMin).getLower(), 0); + EXPECT_EQ(SE.getUnsignedRange(AddWithUMin).getUpper(), 33); + }); +} + } // end namespace llvm