[llvm] (Draft) [SimplifyIndVar] Push more users to worklist for simplifyUsers (PR #93598)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 5 00:14:27 PDT 2024


https://github.com/v01dXYZ updated https://github.com/llvm/llvm-project/pull/93598

>From 4306f3b479701ce410ce2fb9b990fe80ebff3f8d Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Mon, 27 May 2024 11:31:21 +0200
Subject: [PATCH 1/6] (Draft) [SimplifyIndVar] Push more users to worklist for
 simplifyUsers

Instead of considering only users that are inside the loop,
consider all the users with parent dominated by the loop header.
---
 llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 22 ++++++++++----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 912c02c2ed3ae..decdf27125f58 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -840,9 +840,9 @@ bool SimplifyIndvar::strengthenRightShift(BinaryOperator *BO,
 
 /// Add all uses of Def to the current IV's worklist.
 static void pushIVUsers(
-  Instruction *Def, Loop *L,
-  SmallPtrSet<Instruction*,16> &Simplified,
-  SmallVectorImpl< std::pair<Instruction*,Instruction*> > &SimpleIVUsers) {
+    Instruction *Def, Loop *L, DominatorTree *DT,
+    SmallPtrSet<Instruction *, 16> &Simplified,
+    SmallVectorImpl<std::pair<Instruction *, Instruction *>> &SimpleIVUsers) {
 
   for (User *U : Def->users()) {
     Instruction *UI = cast<Instruction>(U);
@@ -854,9 +854,9 @@ static void pushIVUsers(
     if (UI == Def)
       continue;
 
-    // Only change the current Loop, do not change the other parts (e.g. other
-    // Loops).
-    if (!L->contains(UI))
+    // Avoid adding Defs that SCEV expand to themselves, e.g. the LoopPhis
+    // of the outter loops.
+    if (!DT->dominates(L->getHeader(), UI->getParent()))
       continue;
 
     // Do not push the same instruction more than once.
@@ -913,7 +913,7 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
   // Push users of the current LoopPhi. In rare cases, pushIVUsers may be
   // called multiple times for the same LoopPhi. This is the proper thing to
   // do for loop header phis that use each other.
-  pushIVUsers(CurrIV, L, Simplified, SimpleIVUsers);
+  pushIVUsers(CurrIV, L, DT, Simplified, SimpleIVUsers);
 
   while (!SimpleIVUsers.empty()) {
     std::pair<Instruction*, Instruction*> UseOper =
@@ -960,7 +960,7 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
       continue;
 
     if (eliminateIVUser(UseInst, IVOperand)) {
-      pushIVUsers(IVOperand, L, Simplified, SimpleIVUsers);
+      pushIVUsers(IVOperand, L, DT, Simplified, SimpleIVUsers);
       continue;
     }
 
@@ -968,14 +968,14 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
       if (strengthenBinaryOp(BO, IVOperand)) {
         // re-queue uses of the now modified binary operator and fall
         // through to the checks that remain.
-        pushIVUsers(IVOperand, L, Simplified, SimpleIVUsers);
+        pushIVUsers(IVOperand, L, DT, Simplified, SimpleIVUsers);
       }
     }
 
     // Try to use integer induction for FPToSI of float induction directly.
     if (replaceFloatIVWithIntegerIV(UseInst)) {
       // Re-queue the potentially new direct uses of IVOperand.
-      pushIVUsers(IVOperand, L, Simplified, SimpleIVUsers);
+      pushIVUsers(IVOperand, L, DT, Simplified, SimpleIVUsers);
       continue;
     }
 
@@ -985,7 +985,7 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
       continue;
     }
     if (isSimpleIVUser(UseInst, L, SE)) {
-      pushIVUsers(UseInst, L, Simplified, SimpleIVUsers);
+      pushIVUsers(UseInst, L, DT, Simplified, SimpleIVUsers);
     }
   }
 }

>From c55695b44b98640c7c5eaf04b7895c2888407b13 Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Fri, 31 May 2024 00:22:58 +0200
Subject: [PATCH 2/6] (Draft) [SimplifyIndvar] Dirty fixes to allow out of loop
 Users

---
 llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index decdf27125f58..18257373d678f 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -511,6 +511,7 @@ bool SimplifyIndvar::eliminateTrunc(TruncInst *TI) {
     ICmpInst *ICI = dyn_cast<ICmpInst>(U);
     if (!ICI) return false;
     assert(L->contains(ICI->getParent()) && "LCSSA form broken?");
+    //    assert(L->contains(ICI->getParent()) && "LCSSA form broken?");
     if (!(ICI->getOperand(0) == TI && L->isLoopInvariant(ICI->getOperand(1))) &&
         !(ICI->getOperand(1) == TI && L->isLoopInvariant(ICI->getOperand(0))))
       return false;
@@ -942,7 +943,8 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
     if ((isa<PtrToIntInst>(UseInst)) || (isa<TruncInst>(UseInst)))
       for (Use &U : UseInst->uses()) {
         Instruction *User = cast<Instruction>(U.getUser());
-        if (replaceIVUserWithLoopInvariant(User))
+        if (DT->dominates(L->getHeader(), User->getParent()) &&
+            replaceIVUserWithLoopInvariant(User))
           break; // done replacing
       }
 

>From 6ae58f1e0c0c86b870f49035be1686b87c80554a Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Mon, 3 Jun 2024 10:27:55 +0200
Subject: [PATCH 3/6] (Draft) [SimplifyIndvar] Add a parameter to limit
 processing out-of-loop users

---
 llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 52 ++++++++++++++------
 1 file changed, 37 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 18257373d678f..7023b2f01696c 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -62,6 +62,12 @@ namespace {
     bool Changed = false;
     bool RunUnswitching = false;
 
+    // When following the def-use chains, it can go outside the loop.
+    // Stop processing the chain if it encounters
+    // MaxSuccessiveOutOfLoop successive out-of-loop users.
+    // If null, traverse the full chain.
+    std::optional<unsigned> MaxSuccessiveOutOfLoop = 0;
+
   public:
     SimplifyIndvar(Loop *Loop, ScalarEvolution *SE, DominatorTree *DT,
                    LoopInfo *LI, const TargetTransformInfo *TTI,
@@ -840,10 +846,13 @@ bool SimplifyIndvar::strengthenRightShift(BinaryOperator *BO,
 }
 
 /// Add all uses of Def to the current IV's worklist.
-static void pushIVUsers(
-    Instruction *Def, Loop *L, DominatorTree *DT,
-    SmallPtrSet<Instruction *, 16> &Simplified,
-    SmallVectorImpl<std::pair<Instruction *, Instruction *>> &SimpleIVUsers) {
+static void
+pushIVUsers(Instruction *Def, Loop *L, DominatorTree *DT,
+            SmallPtrSet<Instruction *, 16> &Simplified,
+            SmallVectorImpl<std::tuple<Instruction *, Instruction *, unsigned>>
+                &SimpleIVUsers,
+            unsigned OutOfLoopChainCounter,
+            std::optional<unsigned> MaxSuccessiveOutOfLoop) {
 
   for (User *U : Def->users()) {
     Instruction *UI = cast<Instruction>(U);
@@ -864,7 +873,13 @@ static void pushIVUsers(
     if (!Simplified.insert(UI).second)
       continue;
 
-    SimpleIVUsers.push_back(std::make_pair(UI, Def));
+    // reset depth if we go back inside the loop.
+    if (L->contains(UI) || !MaxSuccessiveOutOfLoop) {
+      SimpleIVUsers.push_back(std::make_tuple(UI, Def, 0));
+    } else if (OutOfLoopChainCounter + 1 <= *MaxSuccessiveOutOfLoop) {
+      SimpleIVUsers.push_back(
+          std::make_tuple(UI, Def, OutOfLoopChainCounter + 1));
+    }
   }
 }
 
@@ -909,17 +924,21 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
   SmallPtrSet<Instruction*,16> Simplified;
 
   // Use-def pairs if IV users waiting to be processed for CurrIV.
-  SmallVector<std::pair<Instruction*, Instruction*>, 8> SimpleIVUsers;
+  SmallVector<std::tuple<Instruction *, Instruction *, unsigned>, 8>
+      SimpleIVUsers;
 
   // Push users of the current LoopPhi. In rare cases, pushIVUsers may be
   // called multiple times for the same LoopPhi. This is the proper thing to
   // do for loop header phis that use each other.
-  pushIVUsers(CurrIV, L, DT, Simplified, SimpleIVUsers);
+  pushIVUsers(CurrIV, L, DT, Simplified, SimpleIVUsers, 0,
+              MaxSuccessiveOutOfLoop);
 
   while (!SimpleIVUsers.empty()) {
-    std::pair<Instruction*, Instruction*> UseOper =
-      SimpleIVUsers.pop_back_val();
-    Instruction *UseInst = UseOper.first;
+    Instruction *UseInst, *IVOperand;
+    unsigned OutOfLoopChainCounter;
+
+    std::tie(UseInst, IVOperand, OutOfLoopChainCounter) =
+        SimpleIVUsers.pop_back_val();
 
     // If a user of the IndVar is trivially dead, we prefer just to mark it dead
     // rather than try to do some complex analysis or transformation (such as
@@ -948,7 +967,6 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
           break; // done replacing
       }
 
-    Instruction *IVOperand = UseOper.second;
     for (unsigned N = 0; IVOperand; ++N) {
       assert(N <= Simplified.size() && "runaway iteration");
       (void) N;
@@ -962,7 +980,8 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
       continue;
 
     if (eliminateIVUser(UseInst, IVOperand)) {
-      pushIVUsers(IVOperand, L, DT, Simplified, SimpleIVUsers);
+      pushIVUsers(IVOperand, L, DT, Simplified, SimpleIVUsers,
+                  OutOfLoopChainCounter, MaxSuccessiveOutOfLoop);
       continue;
     }
 
@@ -970,14 +989,16 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
       if (strengthenBinaryOp(BO, IVOperand)) {
         // re-queue uses of the now modified binary operator and fall
         // through to the checks that remain.
-        pushIVUsers(IVOperand, L, DT, Simplified, SimpleIVUsers);
+        pushIVUsers(IVOperand, L, DT, Simplified, SimpleIVUsers,
+                    OutOfLoopChainCounter, MaxSuccessiveOutOfLoop);
       }
     }
 
     // Try to use integer induction for FPToSI of float induction directly.
     if (replaceFloatIVWithIntegerIV(UseInst)) {
       // Re-queue the potentially new direct uses of IVOperand.
-      pushIVUsers(IVOperand, L, DT, Simplified, SimpleIVUsers);
+      pushIVUsers(IVOperand, L, DT, Simplified, SimpleIVUsers,
+                  OutOfLoopChainCounter, MaxSuccessiveOutOfLoop);
       continue;
     }
 
@@ -987,7 +1008,8 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
       continue;
     }
     if (isSimpleIVUser(UseInst, L, SE)) {
-      pushIVUsers(UseInst, L, DT, Simplified, SimpleIVUsers);
+      pushIVUsers(UseInst, L, DT, Simplified, SimpleIVUsers,
+                  OutOfLoopChainCounter, MaxSuccessiveOutOfLoop);
     }
   }
 }

>From ddcf5916b6e1f86f2a333a0f3454aee7d30f83b5 Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Mon, 3 Jun 2024 13:43:47 +0200
Subject: [PATCH 4/6] (Draft) TMP Add MaxSuccessiveOutOfLoop to IndVarSimplify

to squash
---
 .../llvm/Transforms/Utils/SimplifyIndVar.h    | 11 ++++----
 llvm/lib/Transforms/Scalar/IndVarSimplify.cpp |  9 +++++--
 llvm/lib/Transforms/Utils/SimplifyIndVar.cpp  | 27 ++++++++++---------
 3 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h b/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h
index bd1718dd8cad7..2fdd9fefd3980 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h
@@ -52,12 +52,11 @@ class IVVisitor {
 /// where the first entry indicates that the function makes changes and the
 /// second entry indicates that it introduced new opportunities for loop
 /// unswitching.
-std::pair<bool, bool> simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE,
-                                        DominatorTree *DT, LoopInfo *LI,
-                                        const TargetTransformInfo *TTI,
-                                        SmallVectorImpl<WeakTrackingVH> &Dead,
-                                        SCEVExpander &Rewriter,
-                                        IVVisitor *V = nullptr);
+std::pair<bool, bool>
+simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, DominatorTree *DT,
+                  LoopInfo *LI, const TargetTransformInfo *TTI,
+                  SmallVectorImpl<WeakTrackingVH> &Dead, SCEVExpander &Rewriter,
+                  unsigned MaxSuccessiveOutOfLoop = 1, IVVisitor *V = nullptr);
 
 /// SimplifyLoopIVs - Simplify users of induction variables within this
 /// loop. This does not actually change or add IVs.
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index dd7c89034ca09..0d62d0c1dc4d9 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -124,6 +124,10 @@ static cl::opt<bool>
 AllowIVWidening("indvars-widen-indvars", cl::Hidden, cl::init(true),
                 cl::desc("Allow widening of indvars to eliminate s/zext"));
 
+static cl::opt<unsigned> MaxSuccessiveOutOfLoop(
+    "indvars-max-successive-out-of-loop", cl::Hidden, cl::init(1),
+    cl::desc("Number of successive out-of-loop users before stopping"));
+
 namespace {
 
 class IndVarSimplify {
@@ -624,8 +628,9 @@ bool IndVarSimplify::simplifyAndExtend(Loop *L,
       // Information about sign/zero extensions of CurrIV.
       IndVarSimplifyVisitor Visitor(CurrIV, SE, TTI, DT);
 
-      const auto &[C, U] = simplifyUsersOfIV(CurrIV, SE, DT, LI, TTI, DeadInsts,
-                                             Rewriter, &Visitor);
+      const auto &[C, U] =
+          simplifyUsersOfIV(CurrIV, SE, DT, LI, TTI, DeadInsts, Rewriter,
+                            MaxSuccessiveOutOfLoop, &Visitor);
 
       Changed |= C;
       RunUnswitching |= U;
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 7023b2f01696c..4a5a153b1041a 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -66,15 +66,16 @@ namespace {
     // Stop processing the chain if it encounters
     // MaxSuccessiveOutOfLoop successive out-of-loop users.
     // If null, traverse the full chain.
-    std::optional<unsigned> MaxSuccessiveOutOfLoop = 0;
+    unsigned MaxSuccessiveOutOfLoop;
 
   public:
     SimplifyIndvar(Loop *Loop, ScalarEvolution *SE, DominatorTree *DT,
                    LoopInfo *LI, const TargetTransformInfo *TTI,
                    SCEVExpander &Rewriter,
-                   SmallVectorImpl<WeakTrackingVH> &Dead)
+                   SmallVectorImpl<WeakTrackingVH> &Dead,
+                   unsigned MaxSuccessiveOutOfLoop = 1)
         : L(Loop), LI(LI), SE(SE), DT(DT), TTI(TTI), Rewriter(Rewriter),
-          DeadInsts(Dead) {
+          DeadInsts(Dead), MaxSuccessiveOutOfLoop(MaxSuccessiveOutOfLoop) {
       assert(LI && "IV simplification requires LoopInfo");
     }
 
@@ -851,8 +852,7 @@ pushIVUsers(Instruction *Def, Loop *L, DominatorTree *DT,
             SmallPtrSet<Instruction *, 16> &Simplified,
             SmallVectorImpl<std::tuple<Instruction *, Instruction *, unsigned>>
                 &SimpleIVUsers,
-            unsigned OutOfLoopChainCounter,
-            std::optional<unsigned> MaxSuccessiveOutOfLoop) {
+            unsigned OutOfLoopChainCounter, unsigned MaxSuccessiveOutOfLoop) {
 
   for (User *U : Def->users()) {
     Instruction *UI = cast<Instruction>(U);
@@ -874,9 +874,10 @@ pushIVUsers(Instruction *Def, Loop *L, DominatorTree *DT,
       continue;
 
     // reset depth if we go back inside the loop.
-    if (L->contains(UI) || !MaxSuccessiveOutOfLoop) {
+    if (L->contains(UI)) {
       SimpleIVUsers.push_back(std::make_tuple(UI, Def, 0));
-    } else if (OutOfLoopChainCounter + 1 <= *MaxSuccessiveOutOfLoop) {
+    } else if (!MaxSuccessiveOutOfLoop ||
+               OutOfLoopChainCounter + 1 < MaxSuccessiveOutOfLoop) {
       SimpleIVUsers.push_back(
           std::make_tuple(UI, Def, OutOfLoopChainCounter + 1));
     }
@@ -1023,13 +1024,13 @@ void IVVisitor::anchor() { }
 ///  Returns a pair where the first entry indicates that the function makes
 ///  changes and the second entry indicates that it introduced new opportunities
 ///  for loop unswitching.
-std::pair<bool, bool> simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE,
-                                        DominatorTree *DT, LoopInfo *LI,
-                                        const TargetTransformInfo *TTI,
-                                        SmallVectorImpl<WeakTrackingVH> &Dead,
-                                        SCEVExpander &Rewriter, IVVisitor *V) {
+std::pair<bool, bool>
+simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, DominatorTree *DT,
+                  LoopInfo *LI, const TargetTransformInfo *TTI,
+                  SmallVectorImpl<WeakTrackingVH> &Dead, SCEVExpander &Rewriter,
+                  unsigned MaxSuccessiveOutOfLoop, IVVisitor *V) {
   SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), SE, DT, LI, TTI,
-                     Rewriter, Dead);
+                     Rewriter, Dead, MaxSuccessiveOutOfLoop);
   SIV.simplifyUsers(CurrIV, V);
   return {SIV.hasChanged(), SIV.runUnswitching()};
 }

>From 6787cdb2aec57a313c1b7d9e5d66c73928f09ac7 Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Mon, 3 Jun 2024 15:03:53 +0200
Subject: [PATCH 5/6] (Draft) TMP Depth with block instead of instruction

to squash
---
 .../llvm/Transforms/Utils/SimplifyIndVar.h    |  2 +-
 llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 10 ++--
 llvm/lib/Transforms/Utils/SimplifyIndVar.cpp  | 49 +++++++++----------
 3 files changed, 30 insertions(+), 31 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h b/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h
index 2fdd9fefd3980..dbf2bdd18467d 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h
@@ -56,7 +56,7 @@ std::pair<bool, bool>
 simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, DominatorTree *DT,
                   LoopInfo *LI, const TargetTransformInfo *TTI,
                   SmallVectorImpl<WeakTrackingVH> &Dead, SCEVExpander &Rewriter,
-                  unsigned MaxSuccessiveOutOfLoop = 1, IVVisitor *V = nullptr);
+                  unsigned MaxDepthOutOfLoop = 1, IVVisitor *V = nullptr);
 
 /// SimplifyLoopIVs - Simplify users of induction variables within this
 /// loop. This does not actually change or add IVs.
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index 0d62d0c1dc4d9..ea0f7a986e4b9 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -124,9 +124,11 @@ static cl::opt<bool>
 AllowIVWidening("indvars-widen-indvars", cl::Hidden, cl::init(true),
                 cl::desc("Allow widening of indvars to eliminate s/zext"));
 
-static cl::opt<unsigned> MaxSuccessiveOutOfLoop(
-    "indvars-max-successive-out-of-loop", cl::Hidden, cl::init(1),
-    cl::desc("Number of successive out-of-loop users before stopping"));
+static cl::opt<unsigned> MaxDepthOutOfLoop(
+    "indvars-max-depth-out-of-loop", cl::Hidden, cl::init(1),
+    cl::desc(
+        "Strict upper bound for the number of successive out-of-loop blocks "
+        "when traversing use-def chains. 0 enables full traversal"));
 
 namespace {
 
@@ -630,7 +632,7 @@ bool IndVarSimplify::simplifyAndExtend(Loop *L,
 
       const auto &[C, U] =
           simplifyUsersOfIV(CurrIV, SE, DT, LI, TTI, DeadInsts, Rewriter,
-                            MaxSuccessiveOutOfLoop, &Visitor);
+                            MaxDepthOutOfLoop, &Visitor);
 
       Changed |= C;
       RunUnswitching |= U;
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 4a5a153b1041a..c840491f5b7df 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -63,19 +63,17 @@ namespace {
     bool RunUnswitching = false;
 
     // When following the def-use chains, it can go outside the loop.
-    // Stop processing the chain if it encounters
-    // MaxSuccessiveOutOfLoop successive out-of-loop users.
-    // If null, traverse the full chain.
-    unsigned MaxSuccessiveOutOfLoop;
+    // Strict upper bound on number of traversed out-of-loop blocks.
+    unsigned MaxDepthOutOfLoop;
 
   public:
     SimplifyIndvar(Loop *Loop, ScalarEvolution *SE, DominatorTree *DT,
                    LoopInfo *LI, const TargetTransformInfo *TTI,
                    SCEVExpander &Rewriter,
                    SmallVectorImpl<WeakTrackingVH> &Dead,
-                   unsigned MaxSuccessiveOutOfLoop = 1)
+                   unsigned MaxDepthOutOfLoop = 1)
         : L(Loop), LI(LI), SE(SE), DT(DT), TTI(TTI), Rewriter(Rewriter),
-          DeadInsts(Dead), MaxSuccessiveOutOfLoop(MaxSuccessiveOutOfLoop) {
+          DeadInsts(Dead), MaxDepthOutOfLoop(MaxDepthOutOfLoop) {
       assert(LI && "IV simplification requires LoopInfo");
     }
 
@@ -852,7 +850,7 @@ pushIVUsers(Instruction *Def, Loop *L, DominatorTree *DT,
             SmallPtrSet<Instruction *, 16> &Simplified,
             SmallVectorImpl<std::tuple<Instruction *, Instruction *, unsigned>>
                 &SimpleIVUsers,
-            unsigned OutOfLoopChainCounter, unsigned MaxSuccessiveOutOfLoop) {
+            unsigned OutOfLoopChainCounter) {
 
   for (User *U : Def->users()) {
     Instruction *UI = cast<Instruction>(U);
@@ -874,13 +872,11 @@ pushIVUsers(Instruction *Def, Loop *L, DominatorTree *DT,
       continue;
 
     // reset depth if we go back inside the loop.
-    if (L->contains(UI)) {
-      SimpleIVUsers.push_back(std::make_tuple(UI, Def, 0));
-    } else if (!MaxSuccessiveOutOfLoop ||
-               OutOfLoopChainCounter + 1 < MaxSuccessiveOutOfLoop) {
-      SimpleIVUsers.push_back(
-          std::make_tuple(UI, Def, OutOfLoopChainCounter + 1));
-    }
+    SimpleIVUsers.push_back(std::make_tuple(
+        UI, Def,
+        L->contains(UI)
+            ? 0
+            : OutOfLoopChainCounter + (UI->getParent() != Def->getParent())));
   }
 }
 
@@ -931,8 +927,7 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
   // Push users of the current LoopPhi. In rare cases, pushIVUsers may be
   // called multiple times for the same LoopPhi. This is the proper thing to
   // do for loop header phis that use each other.
-  pushIVUsers(CurrIV, L, DT, Simplified, SimpleIVUsers, 0,
-              MaxSuccessiveOutOfLoop);
+  pushIVUsers(CurrIV, L, DT, Simplified, SimpleIVUsers, 0);
 
   while (!SimpleIVUsers.empty()) {
     Instruction *UseInst, *IVOperand;
@@ -980,26 +975,28 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
     if (!IVOperand)
       continue;
 
-    if (eliminateIVUser(UseInst, IVOperand)) {
+    bool IsLowerMaxOutOfLoop =
+        !MaxDepthOutOfLoop || (OutOfLoopChainCounter < MaxDepthOutOfLoop);
+    if (eliminateIVUser(UseInst, IVOperand) && IsLowerMaxOutOfLoop) {
       pushIVUsers(IVOperand, L, DT, Simplified, SimpleIVUsers,
-                  OutOfLoopChainCounter, MaxSuccessiveOutOfLoop);
+                  OutOfLoopChainCounter);
       continue;
     }
 
     if (BinaryOperator *BO = dyn_cast<BinaryOperator>(UseInst)) {
-      if (strengthenBinaryOp(BO, IVOperand)) {
+      if (strengthenBinaryOp(BO, IVOperand) && IsLowerMaxOutOfLoop) {
         // re-queue uses of the now modified binary operator and fall
         // through to the checks that remain.
         pushIVUsers(IVOperand, L, DT, Simplified, SimpleIVUsers,
-                    OutOfLoopChainCounter, MaxSuccessiveOutOfLoop);
+                    OutOfLoopChainCounter);
       }
     }
 
     // Try to use integer induction for FPToSI of float induction directly.
-    if (replaceFloatIVWithIntegerIV(UseInst)) {
+    if (replaceFloatIVWithIntegerIV(UseInst) && IsLowerMaxOutOfLoop) {
       // Re-queue the potentially new direct uses of IVOperand.
       pushIVUsers(IVOperand, L, DT, Simplified, SimpleIVUsers,
-                  OutOfLoopChainCounter, MaxSuccessiveOutOfLoop);
+                  OutOfLoopChainCounter);
       continue;
     }
 
@@ -1008,9 +1005,9 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
       V->visitCast(Cast);
       continue;
     }
-    if (isSimpleIVUser(UseInst, L, SE)) {
+    if (IsLowerMaxOutOfLoop && isSimpleIVUser(UseInst, L, SE)) {
       pushIVUsers(UseInst, L, DT, Simplified, SimpleIVUsers,
-                  OutOfLoopChainCounter, MaxSuccessiveOutOfLoop);
+                  OutOfLoopChainCounter);
     }
   }
 }
@@ -1028,9 +1025,9 @@ std::pair<bool, bool>
 simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, DominatorTree *DT,
                   LoopInfo *LI, const TargetTransformInfo *TTI,
                   SmallVectorImpl<WeakTrackingVH> &Dead, SCEVExpander &Rewriter,
-                  unsigned MaxSuccessiveOutOfLoop, IVVisitor *V) {
+                  unsigned MaxDepthOutOfLoop, IVVisitor *V) {
   SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), SE, DT, LI, TTI,
-                     Rewriter, Dead, MaxSuccessiveOutOfLoop);
+                     Rewriter, Dead, MaxDepthOutOfLoop);
   SIV.simplifyUsers(CurrIV, V);
   return {SIV.hasChanged(), SIV.runUnswitching()};
 }

>From 165ef0d5e429b5301497445b732d82ff6bcaad07 Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Wed, 5 Jun 2024 09:11:37 +0200
Subject: [PATCH 6/6] (Draft) TMP Typo, style consistency

to squash
---
 llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index c840491f5b7df..9fcdc1a502676 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -514,9 +514,8 @@ bool SimplifyIndvar::eliminateTrunc(TruncInst *TI) {
         !DT->isReachableFromEntry(cast<Instruction>(U)->getParent()))
       continue;
     ICmpInst *ICI = dyn_cast<ICmpInst>(U);
-    if (!ICI) return false;
-    assert(L->contains(ICI->getParent()) && "LCSSA form broken?");
-    //    assert(L->contains(ICI->getParent()) && "LCSSA form broken?");
+    if (!ICI)
+      return false;
     if (!(ICI->getOperand(0) == TI && L->isLoopInvariant(ICI->getOperand(1))) &&
         !(ICI->getOperand(1) == TI && L->isLoopInvariant(ICI->getOperand(0))))
       return false;
@@ -930,10 +929,7 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
   pushIVUsers(CurrIV, L, DT, Simplified, SimpleIVUsers, 0);
 
   while (!SimpleIVUsers.empty()) {
-    Instruction *UseInst, *IVOperand;
-    unsigned OutOfLoopChainCounter;
-
-    std::tie(UseInst, IVOperand, OutOfLoopChainCounter) =
+    const auto &[UseInst, IVOperand, OutOfLoopChainCounter] =
         SimpleIVUsers.pop_back_val();
 
     // If a user of the IndVar is trivially dead, we prefer just to mark it dead



More information about the llvm-commits mailing list