[llvm] ff08c34 - [SCEV] Compute trip multiple for multiple exit loops

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Wed May 26 11:52:33 PDT 2021


Author: Philip Reames
Date: 2021-05-26T11:52:25-07:00
New Revision: ff08c3468fa4ba25384104206255f3648fd21fe9

URL: https://github.com/llvm/llvm-project/commit/ff08c3468fa4ba25384104206255f3648fd21fe9
DIFF: https://github.com/llvm/llvm-project/commit/ff08c3468fa4ba25384104206255f3648fd21fe9.diff

LOG: [SCEV] Compute trip multiple for multiple exit loops

This patch implements getSmallConstantTripMultiple(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.

Differential Revision: https://reviews.llvm.org/D103189

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 57a091d7d7f9..a33621170c02 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -745,11 +745,8 @@ class ScalarEvolution {
                                         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

diff  --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 3acaecde1351..872c515fd909 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -6970,11 +6970,17 @@ unsigned ScalarEvolution::getSmallConstantMaxTripCount(const Loop *L) {
 }
 
 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);
+  }
+  return Res.getValueOr(1);
 }
 
 unsigned ScalarEvolution::getSmallConstantTripMultiple(const Loop *L,

diff  --git a/llvm/test/Analysis/ScalarEvolution/tripmultiple_calculation.ll b/llvm/test/Analysis/ScalarEvolution/tripmultiple_calculation.ll
index f57ab3dbdad3..34a07aa70a48 100644
--- a/llvm/test/Analysis/ScalarEvolution/tripmultiple_calculation.ll
+++ b/llvm/test/Analysis/ScalarEvolution/tripmultiple_calculation.ll
@@ -124,3 +124,27 @@ exit:
   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
+}
+


        


More information about the llvm-commits mailing list