Index: llvm/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/lib/Analysis/ScalarEvolution.cpp +++ llvm/lib/Analysis/ScalarEvolution.cpp @@ -10148,8 +10148,21 @@ // We want to avoid hurting the compile time with analysis of too big trees. if (Depth > MaxSCEVOperationsImplicationDepth) return false; + + if (ICmpInst::isUnsigned(Pred)) + // We can replace unsigned predicate with its signed counterpart if all + // involved values are non-negative. + // TODO: We could have better support for unsigned. + if (isKnownNonNegative(FoundLHS) && isKnownNonNegative(FoundRHS)) { + const SCEV *MinusOne = getNegativeSCEV(getOne(LHS->getType())); + if (isImpliedCondOperands(ICmpInst::ICMP_SGT, LHS, MinusOne, FoundLHS, + FoundRHS) && + isImpliedCondOperands(ICmpInst::ICMP_SGT, RHS, MinusOne, FoundLHS, + FoundRHS)) + Pred = ICmpInst::getSignedPredicate(Pred); + } + // We only want to work with ICMP_SGT comparison so far. - // TODO: Extend to ICMP_UGT? if (Pred == ICmpInst::ICMP_SLT) { Pred = ICmpInst::ICMP_SGT; std::swap(LHS, RHS); Index: llvm/unittests/Analysis/ScalarEvolutionTest.cpp =================================================================== --- llvm/unittests/Analysis/ScalarEvolutionTest.cpp +++ llvm/unittests/Analysis/ScalarEvolutionTest.cpp @@ -1186,4 +1186,35 @@ }); } +TEST_F(ScalarEvolutionsTest, UnsignedIsImpliedViaOperations) { + LLVMContext C; + SMDiagnostic Err; + std::unique_ptr M = + parseAssemblyString("define void @foo(i32* %p) { " + "entry: " + " %x = load i32, i32* %p, !range !0 " + " %cond = icmp ne i32 %x, 0 " + " br i1 %cond, label %loop, label %exit " + "loop: " + " %y = add i32 %x, -1 " + " br label %loop " + "exit:" + " ret void " + "} " + "!0 = !{i32 0, i32 2147483647}", + 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(getInstructionByName(F, "x")); + auto *Y = SE.getSCEV(getInstructionByName(F, "y")); + auto *Loop = LI.getLoopFor(getInstructionByName(F, "y")->getParent()); + ASSERT_TRUE(Loop); + EXPECT_TRUE(SE.isLoopEntryGuardedByCond(Loop, ICmpInst::ICMP_UGT, X, Y)); + EXPECT_TRUE(SE.isLoopEntryGuardedByCond(Loop, ICmpInst::ICMP_ULT, Y, X)); + }); +} + } // end namespace llvm