[PATCH] D88210: [IndVars] Use knowledge about execution on last iteration when removing checks

Max Kazantsev via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 29 22:00:10 PDT 2020


mkazantsev updated this revision to Diff 295172.

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

https://reviews.llvm.org/D88210

Files:
  llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
  llvm/test/Transforms/IndVarSimplify/predicated_ranges.ll


Index: llvm/test/Transforms/IndVarSimplify/predicated_ranges.ll
===================================================================
--- llvm/test/Transforms/IndVarSimplify/predicated_ranges.ll
+++ llvm/test/Transforms/IndVarSimplify/predicated_ranges.ll
@@ -21,8 +21,7 @@
 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
 ; CHECK:       range_check_block:
 ; CHECK-NEXT:    [[IV_NEXT]] = sub i32 [[IV]], 1
-; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ult i32 [[IV_NEXT]], [[LEN]]
-; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]]
+; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]]
 ; CHECK:       backedge:
 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[P]], i32 [[IV]]
 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
Index: llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -2332,7 +2332,8 @@
 // Returns true if the condition of \p BI being checked is invariant and can be
 // proved to be trivially true during at least first \p MaxIter iterations.
 static bool isTrivialCond(const Loop *L, BranchInst *BI, ScalarEvolution *SE,
-                          bool ProvingLoopExit, const SCEV *MaxIter) {
+                          bool ProvingLoopExit, const SCEV *MaxIter,
+                          bool SkipLastIter) {
   ICmpInst::Predicate Pred;
   Value *LHS, *RHS;
   using namespace PatternMatch;
@@ -2388,6 +2389,10 @@
   if (AR->getType() != MaxIter->getType())
     return false;
 
+
+  if (SkipLastIter)
+    MaxIter = SE->getMinusSCEV(MaxIter, One, SCEV::FlagNUW);
+
   // First, check the predicate on the 1st iteration.
   const SCEV *Start = AR->getStart();
   if (!SE->isKnownPredicateAt(Pred, Start, RHSS, BI))
@@ -2485,13 +2490,14 @@
   };
 
   bool Changed = false;
+  bool SkipLastIter = false;
   SmallSet<const SCEV*, 8> DominatingExitCounts;
   for (BasicBlock *ExitingBB : ExitingBlocks) {
     const SCEV *ExitCount = SE->getExitCount(L, ExitingBB);
     if (isa<SCEVCouldNotCompute>(ExitCount)) {
       auto *BI = cast<BranchInst>(ExitingBB->getTerminator());
-      auto OptimizeCond = [&](bool Inverted, const SCEV *MaxIter) {
-        if (isTrivialCond(L, BI, SE, Inverted, MaxIter)) {
+      auto OptimizeCond = [&](bool Inverted, bool SkipLastIter) {
+        if (isTrivialCond(L, BI, SE, Inverted, MaxExitCount, SkipLastIter)) {
           FoldExit(ExitingBB, Inverted);
           return true;
         }
@@ -2499,13 +2505,40 @@
       };
       // Okay, we do not know the exit count here. Can we at least prove that it
       // will remain the same within iteration space?
-      if (OptimizeCond(false, MaxExitCount))
+      if (OptimizeCond(false, false))
         Changed = true;
-      else if (OptimizeCond(true, MaxExitCount))
+      else if (OptimizeCond(true, false))
         Changed = true;
+      else if (SkipLastIter) {
+        // If we cannot prove it on the last loop iteration, try to benefit
+        // from the fact that this check will not be executed on the last
+        // iteration.
+        // TODO: What we really want is to query with (MaxExitCount - 1),
+        // and the check should only check the condition on pre-last iteration
+        // if the backedge was taken at least once. Consider loop:
+        //
+        //   for (i = len; i != 0; i--) { ... check (i ult X) ... }
+        //
+        // If len = 0 then MaxExitCount = 0, and the pre-last iteration will
+        // not be executed at all. But SCEV does not always recognize this and
+        // may start thinking that i on the iteration (MaxExitCount - 1) is a
+        // huge value. So we just query this separately.
+        //
+        // The checks against MaxExitCount above can be removed once we find a
+        // good way to resolve this problem.
+        if (OptimizeCond(false, true))
+          Changed = true;
+        else if (OptimizeCond(true, true))
+          Changed = true;
+      }
       continue;
     }
 
+    if (MaxExitCount == ExitCount)
+      // If the loop has more than 1 iteration, all further checks will be
+      // executed 1 iteration less.
+      SkipLastIter = true;
+
     // If we know we'd exit on the first iteration, rewrite the exit to
     // reflect this.  This does not imply the loop must exit through this
     // exit; there may be an earlier one taken on the first iteration.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D88210.295172.patch
Type: text/x-patch
Size: 4555 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200930/fb1735b1/attachment.bin>


More information about the llvm-commits mailing list