[PATCH] D88087: [SCEV] Limited support for unsigned preds in isImpliedViaOperations

Max Kazantsev via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 1 01:26:52 PDT 2020


mkazantsev updated this revision to Diff 295486.
mkazantsev added a comment.

- Simplified code, making it crystal clear that it only works for ULT/UGT;
- Simplified test to show what we are trying to prove without redundant entities;
- Checks with `isKnownNonNegative(LHS/RHS)` do not work, because if these facts are known, we never reach this code and prove the required fact with other means. But in most cases, it is just not known even in simplest cases. For example, for `%x = load ... {1, SINT_MAX}`, it cannot prove that `add(x, -1)` is non-negative. We could fix that, but it's a problem which has nothing to do with what I am trying to achieve here.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D88087/new/

https://reviews.llvm.org/D88087

Files:
  llvm/lib/Analysis/ScalarEvolution.cpp
  llvm/unittests/Analysis/ScalarEvolutionTest.cpp


Index: llvm/unittests/Analysis/ScalarEvolutionTest.cpp
===================================================================
--- llvm/unittests/Analysis/ScalarEvolutionTest.cpp
+++ llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -1251,4 +1251,35 @@
   });
 }
 
+TEST_F(ScalarEvolutionsTest, UnsignedIsImpliedViaOperations) {
+  LLVMContext C;
+  SMDiagnostic Err;
+  std::unique_ptr<Module> M =
+      parseAssemblyString("define void @foo(i32* %p1, i32* %p2) { "
+                          "entry: "
+                          "  %x = load i32, i32* %p1, !range !0 "
+                          "  %cond = icmp ne i32 %x, 0 "
+                          "  br i1 %cond, label %guarded, label %exit "
+                          "guarded: "
+                          "  %y = add i32 %x, -1 "
+                          "  ret void "
+                          "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 *Guarded = getInstructionByName(F, "y")->getParent();
+    ASSERT_TRUE(Guarded);
+    EXPECT_TRUE(SE.isBasicBlockEntryGuardedByCond(Guarded, ICmpInst::ICMP_ULT, Y, X));
+    EXPECT_TRUE(SE.isBasicBlockEntryGuardedByCond(Guarded, ICmpInst::ICMP_UGT, X, Y));
+  });
+}
+
 }  // end namespace llvm
Index: llvm/lib/Analysis/ScalarEvolution.cpp
===================================================================
--- llvm/lib/Analysis/ScalarEvolution.cpp
+++ llvm/lib/Analysis/ScalarEvolution.cpp
@@ -10185,13 +10185,32 @@
   // We want to avoid hurting the compile time with analysis of too big trees.
   if (Depth > MaxSCEVOperationsImplicationDepth)
     return false;
-  // 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;
+
+  // We only want to work with GT comparison so far.
+  if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_SLT) {
+    Pred = CmpInst::getSwappedPredicate(Pred);
     std::swap(LHS, RHS);
     std::swap(FoundLHS, FoundRHS);
   }
+
+  // For unsigned, try to reduce it to corresponding signed comparison.
+  if (Pred == ICmpInst::ICMP_UGT)
+    // 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)) {
+      // Knowing that both FoundLHS and FoundRHS are non-negative, and knowing
+      // FoundLHS >u FoundRHS, we also know that FoundLHS >s FoundRHS. Let us
+      // use this fact to prove that LHS and RHS are non-negative.
+      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::ICMP_SGT;
+    }
+
+
   if (Pred != ICmpInst::ICMP_SGT)
     return false;
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D88087.295486.patch
Type: text/x-patch
Size: 3426 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20201001/248d727c/attachment.bin>


More information about the llvm-commits mailing list