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 @@ -9314,6 +9314,24 @@ if (MatchBinaryAddToConst(LHS, RHS, C, SCEV::FlagNSW) && C.isNegative()) return true; break; + + case ICmpInst::ICMP_UGE: + std::swap(LHS, RHS); + LLVM_FALLTHROUGH; + case ICmpInst::ICMP_ULE: + // X u<= (X + C) for any C + if (MatchBinaryAddToConst(RHS, LHS, C, SCEV::FlagNUW)) + return true; + break; + + case ICmpInst::ICMP_UGT: + std::swap(LHS, RHS); + LLVM_FALLTHROUGH; + case ICmpInst::ICMP_ULT: + // X u< (X + C) if C != 0 + if (MatchBinaryAddToConst(RHS, LHS, C, SCEV::FlagNUW) && !C.isNullValue()) + return true; + break; } return false; 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 @@ -1165,4 +1165,25 @@ cast(ScevIV)->getStepRecurrence(SE)); }); } + +TEST_F(ScalarEvolutionsTest, SCEVAddNUW) { + LLVMContext C; + SMDiagnostic Err; + std::unique_ptr M = parseAssemblyString("define void @foo(i32 %x) { " + " 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 *X = SE.getSCEV(getArgByName(F, "x")); + auto *One = SE.getOne(X->getType()); + auto *Sum = SE.getAddExpr(X, One, SCEV::FlagNUW); + EXPECT_TRUE(SE.isKnownPredicate(ICmpInst::ICMP_UGE, Sum, X)); + EXPECT_TRUE(SE.isKnownPredicate(ICmpInst::ICMP_UGT, Sum, X)); + }); +} + } // end namespace llvm