[llvm] [SCEV] Avoid unnecessary call to getExitingBlock() in computeExitLimit() (PR #96188)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 20 06:28:05 PDT 2024


https://github.com/Enna1 created https://github.com/llvm/llvm-project/pull/96188

In `computeExitLimit()`, we use `getExitingBlock()` to check if loop has exactly one exiting block.
Since `computeExitLimit()` is only used in `computeBackedgeTakenCount()`, and `getExitingBlocks()` is called to get all exiting blocks in `computeBackedgeTakenCount()`, we can simply check if loop has exactly one exiting block by checking if the number of exiting blocks equals 1 in `computeBackedgeTakenCount()` and pass it as an argument to `computeExitLimit()`.

This change helps to improve the compile time for files containing large loops.

>From ad57d93d8ccc8bc1a81f56ce182628f25546d7a7 Mon Sep 17 00:00:00 2001
From: "xumingjie.enna1" <xumingjie.enna1 at bytedance.com>
Date: Thu, 20 Jun 2024 20:48:20 +0800
Subject: [PATCH] [SCEV] Avoid unnecessary call to getExitingBlock() in
 computeExitLimit()

In `computeExitLimit()`, we use `getExitingBlock()` to check if loop has exactly
one exiting block.
Since `computeExitLimit()` is only used in `computeBackedgeTakenCount()`,
and `getExitingBlocks()` is called to get all exiting blocks in
`computeBackedgeTakenCount()`, we can simply check if loop has exactly one
exiting block by checking if the number of exiting blocks equals 1 in
`computeBackedgeTakenCount()` and pass it as an argument to `computeExitLimit()`.

This change helps to improve the compile time for files containing large loops.
---
 llvm/include/llvm/Analysis/ScalarEvolution.h |  1 +
 llvm/lib/Analysis/ScalarEvolution.cpp        | 13 +++++--------
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index b273d118c4c76..67260ac4d8a9c 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -1766,6 +1766,7 @@ class ScalarEvolution {
   /// this call will try to use a minimal set of SCEV predicates in order to
   /// return an exact answer.
   ExitLimit computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
+                             bool ControlsOnlyExit,
                              bool AllowPredicates = false);
 
   // Helper functions for computeExitLimitFromCond to avoid exponential time
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 7d3e3f4fcd45d..2d88e35e67823 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -8775,6 +8775,7 @@ ScalarEvolution::computeBackedgeTakenCount(const Loop *L,
   const SCEV *MustExitMaxBECount = nullptr;
   const SCEV *MayExitMaxBECount = nullptr;
   bool MustExitMaxOrZero = false;
+  bool IsOnlyExit = ExitingBlocks.size() == 1;
 
   // Compute the ExitLimit for each loop exit. Use this to populate ExitCounts
   // and compute maxBECount.
@@ -8792,7 +8793,7 @@ ScalarEvolution::computeBackedgeTakenCount(const Loop *L,
           continue;
       }
 
-    ExitLimit EL = computeExitLimit(L, ExitBB, AllowPredicates);
+    ExitLimit EL = computeExitLimit(L, ExitBB, IsOnlyExit, AllowPredicates);
 
     assert((AllowPredicates || EL.Predicates.empty()) &&
            "Predicated exit limit when predicates are not allowed!");
@@ -8867,7 +8868,7 @@ ScalarEvolution::computeBackedgeTakenCount(const Loop *L,
 
 ScalarEvolution::ExitLimit
 ScalarEvolution::computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
-                                      bool AllowPredicates) {
+                                  bool ControlsOnlyExit, bool AllowPredicates) {
   assert(L->contains(ExitingBlock) && "Exit count for non-loop block?");
   // If our exiting block does not dominate the latch, then its connection with
   // loop's exit limit may be far from trivial.
@@ -8875,7 +8876,6 @@ ScalarEvolution::computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
   if (!Latch || !DT.dominates(ExitingBlock, Latch))
     return getCouldNotCompute();
 
-  bool IsOnlyExit = (L->getExitingBlock() != nullptr);
   Instruction *Term = ExitingBlock->getTerminator();
   if (BranchInst *BI = dyn_cast<BranchInst>(Term)) {
     assert(BI->isConditional() && "If unconditional, it can't be in loop!");
@@ -8884,8 +8884,7 @@ ScalarEvolution::computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
            "It should have one successor in loop and one exit block!");
     // Proceed to the next level to examine the exit condition expression.
     return computeExitLimitFromCond(L, BI->getCondition(), ExitIfTrue,
-                                    /*ControlsOnlyExit=*/IsOnlyExit,
-                                    AllowPredicates);
+                                    ControlsOnlyExit, AllowPredicates);
   }
 
   if (SwitchInst *SI = dyn_cast<SwitchInst>(Term)) {
@@ -8898,9 +8897,7 @@ ScalarEvolution::computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
         Exit = SBB;
       }
     assert(Exit && "Exiting block must have at least one exit");
-    return computeExitLimitFromSingleExitSwitch(
-        L, SI, Exit,
-        /*ControlsOnlyExit=*/IsOnlyExit);
+    return computeExitLimitFromSingleExitSwitch(L, SI, Exit, ControlsOnlyExit);
   }
 
   return getCouldNotCompute();



More information about the llvm-commits mailing list