[PATCH] D103189: [SCEV] Compute trip multiple for multiple exit loops

Philip Reames via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 26 11:03:48 PDT 2021


reames created this revision.
reames added reviewers: nikic, mkazantsev.
Herald added subscribers: bollu, hiraditya, mcrosier.
reames requested review of this revision.
Herald added a project: LLVM.

This patch implements getSmallConstantTripCount(L) correctly for multiple exit loops.  The previous implementation was both imprecise, and violated the specified behavior of the method.  This was fine in practice, because it turns out the function was both dead in real code, and not tested for the multiple exit case.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D103189

Files:
  llvm/include/llvm/Analysis/ScalarEvolution.h
  llvm/lib/Analysis/ScalarEvolution.cpp
  llvm/test/Analysis/ScalarEvolution/tripmultiple_calculation.ll


Index: llvm/test/Analysis/ScalarEvolution/tripmultiple_calculation.ll
===================================================================
--- llvm/test/Analysis/ScalarEvolution/tripmultiple_calculation.ll
+++ llvm/test/Analysis/ScalarEvolution/tripmultiple_calculation.ll
@@ -124,3 +124,27 @@
   ret i32 0
 }
 
+; If there are multiple exits, the result is the GCD of the multiples
+; of each individual exit (since we don't know which is taken).
+
+; CHECK: Loop %l4: Trip multiple is 50
+
+define i32 @foo5(i32 %n) {
+entry:
+  br label %l4
+
+l4:
+  %x.0 = phi i32 [ 0, %entry ], [ %inc, %l4-latch ]
+  call void @f()
+  %inc = add i32 %x.0, 1
+  %earlycond = icmp eq i32 %inc, 150
+  br i1 %earlycond, label %exit, label %l4-latch
+
+l4-latch:
+  %exitcond = icmp eq i32 %inc, 200
+  br i1 %exitcond, label %exit, label %l4
+
+exit:
+  ret i32 0
+}
+
Index: llvm/lib/Analysis/ScalarEvolution.cpp
===================================================================
--- llvm/lib/Analysis/ScalarEvolution.cpp
+++ llvm/lib/Analysis/ScalarEvolution.cpp
@@ -6973,11 +6973,19 @@
 }
 
 unsigned ScalarEvolution::getSmallConstantTripMultiple(const Loop *L) {
-  if (BasicBlock *ExitingBB = L->getExitingBlock())
-    return getSmallConstantTripMultiple(L, ExitingBB);
+  SmallVector<BasicBlock *, 8> ExitingBlocks;
+  L->getExitingBlocks(ExitingBlocks);
 
-  // No trip multiple information for multiple exits.
-  return 0;
+  Optional<unsigned> Res = None;
+  for (auto *ExitingBB : ExitingBlocks) {
+    unsigned Multiple = getSmallConstantTripMultiple(L, ExitingBB);
+    if (!Res)
+      Res = Multiple;
+    Res = (unsigned)GreatestCommonDivisor64(*Res, Multiple);
+  }
+  if (!Res)
+    return 1;
+  return *Res;
 }
 
 unsigned ScalarEvolution::getSmallConstantTripMultiple(const Loop *L,
Index: llvm/include/llvm/Analysis/ScalarEvolution.h
===================================================================
--- llvm/include/llvm/Analysis/ScalarEvolution.h
+++ llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -744,11 +744,8 @@
                                         const SCEV *ExitCount);
 
   /// Returns the largest constant divisor of the trip count of the
-  /// loop if it is a single-exit loop and we can compute a small maximum for
-  /// that loop.
-  ///
-  /// Implemented in terms of the \c getSmallConstantTripMultiple overload with
-  /// the single exiting block passed to it. See that routine for details.
+  /// loop.  Will return 1 if no trip count could be computed, or if a
+  /// divisor could not be found.
   unsigned getSmallConstantTripMultiple(const Loop *L);
 
   /// Returns the largest constant divisor of the trip count of this loop as a


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D103189.348022.patch
Type: text/x-patch
Size: 2672 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210526/0bf507a7/attachment.bin>


More information about the llvm-commits mailing list