[PATCH] D104140: [SCEV] Allow negative steps for LT exit count computation

Philip Reames via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 19 15:49:01 PDT 2021


reames updated this revision to Diff 359947.
reames added a comment.

Address Eli's review comment which isn't covered by D106197 <https://reviews.llvm.org/D106197>.

I'm going to land some tests for this case and probably split this patch since this appears to be a flaw in the existing logic for potentially zero strides.


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

https://reviews.llvm.org/D104140

Files:
  llvm/lib/Analysis/ScalarEvolution.cpp
  llvm/test/Analysis/ScalarEvolution/trip-count-negative-stride.ll


Index: llvm/test/Analysis/ScalarEvolution/trip-count-negative-stride.ll
===================================================================
--- llvm/test/Analysis/ScalarEvolution/trip-count-negative-stride.ll
+++ llvm/test/Analysis/ScalarEvolution/trip-count-negative-stride.ll
@@ -85,8 +85,8 @@
 }
 
 ; CHECK-LABEL: Determining loop execution counts for: @ult_129_unknown_start
-; CHECK: Loop %for.body: Unpredictable backedge-taken count
-; CHECK: Loop %for.body: Unpredictable max backedge-taken count
+; CHECK: Loop %for.body: backedge-taken count is ((-1 + (-1 * %start) + (-128 umax (-127 + %start))) /u -127)
+; CHECK: Loop %for.body: max backedge-taken count is -128
 
 define void @ult_129_unknown_start(i8 %start) mustprogress {
 entry:
@@ -308,8 +308,8 @@
 }
 
 ; CHECK-LABEL: Determining loop execution counts for: @slt_129_unknown_start
-; CHECK: Loop %for.body: Unpredictable backedge-taken count
-; CHECK: Loop %for.body: Unpredictable max backedge-taken count
+; CHECK: Loop %for.body: backedge-taken count is ((-1 + (-1 * %start) + (0 smax (-127 + %start))) /u -127)
+; CHECK: Loop %for.body: max backedge-taken count is -128
 
 define void @slt_129_unknown_start(i8 %start) mustprogress {
 entry:
Index: llvm/lib/Analysis/ScalarEvolution.cpp
===================================================================
--- llvm/lib/Analysis/ScalarEvolution.cpp
+++ llvm/lib/Analysis/ScalarEvolution.cpp
@@ -11530,8 +11530,6 @@
                                                     unsigned BitWidth,
                                                     bool IsSigned) {
 
-  assert(!isKnownNonPositive(Stride) &&
-         "Stride is expected strictly positive!");
   // Calculate the maximum backedge count based on the range of values
   // permitted by Start, End, and Stride.
   const SCEV *MaxBECount;
@@ -11625,32 +11623,28 @@
     //
     // a) IV is either nuw or nsw depending upon signedness (indicated by the
     //    NoWrap flag).
-    // b) loop is single exit with no side effects.
+    // b) loop is single exit with no side effects and mustprogress.
     //
     //
     // Precondition a) implies that if the stride is negative, this is a single
     // trip loop. The backedge taken count formula reduces to zero in this case.
     //
-    // Precondition b) implies that the unknown stride cannot be zero otherwise
-    // we have UB.
+    // Precondition b) implies that if the stride is zero and rhs is invariant,
+    // this is a single trip loop.  The backedge taken count formula reduces
+    // to zero in this case.
     //
     // The positive stride case is the same as isKnownPositive(Stride) returning
     // true (original behavior of the function).
-    //
-    // We want to make sure that the stride is truly unknown as there are edge
-    // cases where ScalarEvolution propagates no wrap flags to the
-    // post-increment/decrement IV even though the increment/decrement operation
-    // itself is wrapping. The computed backedge taken count may be wrong in
-    // such cases. This is prevented by checking that the stride is not known to
-    // be either positive or non-positive. For example, no wrap flags are
-    // propagated to the post-increment IV of this loop with a trip count of 2 -
-    //
-    // unsigned char i;
-    // for(i=127; i<128; i+=129)
-    //   A[i] = i;
-    //
-    if (PredicatedIV || !NoWrap || isKnownNonPositive(Stride) ||
-        !loopIsFiniteByAssumption(L))
+    if (PredicatedIV || !NoWrap || !loopIsFiniteByAssumption(L))
+      return getCouldNotCompute();
+
+    // If we have a potentially zero step, and RHS isn't invariant in L, we
+    // don't know if it might eventually be greater than start.  The overflow
+    // fact does still imply an upper bound if we wanted to use that.  We
+    // could also try to prove start < end which would prove stride != 0 as
+    // a zero stride would be provably infinite and thus a contradition.
+    const bool StrideNonZero = isKnownNonZero(Stride);
+    if (!StrideNonZero && !isLoopInvariant(RHS, L))
       return getCouldNotCompute();
 
     // We allow a potentially zero stride, but we need to divide by stride
@@ -11679,7 +11673,7 @@
       auto *StartIfZero = getMinusSCEV(IV->getStart(), Stride);
       return isLoopEntryGuardedByCond(L, Cond, StartIfZero, RHS);
     };
-    if (!isKnownNonZero(Stride) && !wouldZeroStrideBeUB()) {
+    if (!StrideNonZero && !wouldZeroStrideBeUB()) {
       Stride = getUMaxExpr(Stride, getOne(Stride->getType()));
     }
   } else if (!Stride->isOne() && !NoWrap) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D104140.359947.patch
Type: text/x-patch
Size: 4552 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210719/c6c46295/attachment.bin>


More information about the llvm-commits mailing list