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

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 3 07:42:00 PDT 2024


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

>From d1a22f3b0f8979e8dbdf4b177685be16f6ffb8d2 Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Thu, 27 Jun 2024 00:15:46 +0200
Subject: [PATCH 1/8] [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/Transforms/Utils/SimplifyIndVar.h    | 11 ++-
 llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 11 ++-
 llvm/lib/Transforms/Utils/SimplifyIndVar.cpp  | 76 +++++++++++--------
 3 files changed, 60 insertions(+), 38 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h b/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h
index bd1718dd8cad7..dbf2bdd18467d 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 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 dd7c89034ca09..ea0f7a986e4b9 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -124,6 +124,12 @@ 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> 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 {
 
 class IndVarSimplify {
@@ -624,8 +630,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,
+                            MaxDepthOutOfLoop, &Visitor);
 
       Changed |= C;
       RunUnswitching |= U;
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 74af0ef40fe7f..a3c1134cd7d64 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -62,13 +62,18 @@ namespace {
     bool Changed = false;
     bool RunUnswitching = false;
 
+    // When following the def-use chains, it can go outside the loop.
+    // 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)
+                   SmallVectorImpl<WeakTrackingVH> &Dead,
+                   unsigned MaxDepthOutOfLoop = 1)
         : L(Loop), LI(LI), SE(SE), DT(DT), TTI(TTI), Rewriter(Rewriter),
-          DeadInsts(Dead) {
+          DeadInsts(Dead), MaxDepthOutOfLoop(MaxDepthOutOfLoop) {
       assert(LI && "IV simplification requires LoopInfo");
     }
 
@@ -80,10 +85,11 @@ namespace {
     /// all simplifications to users of an IV.
     void simplifyUsers(PHINode *CurrIV, IVVisitor *V = nullptr);
 
-    void pushIVUsers(Instruction *Def,
-                     SmallPtrSet<Instruction *, 16> &Simplified,
-                     SmallVectorImpl<std::pair<Instruction *, Instruction *>>
-                         &SimpleIVUsers);
+    void pushIVUsers(
+        Instruction *Def, SmallPtrSet<Instruction *, 16> &Simplified,
+        SmallVectorImpl<std::tuple<Instruction *, Instruction *, unsigned>>
+            &SimpleIVUsers,
+        unsigned OutOfLoopChainCounter);
 
     Value *foldIVUser(Instruction *UseInst, Instruction *IVOperand);
 
@@ -514,8 +520,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?");
+    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;
@@ -846,7 +852,9 @@ bool SimplifyIndvar::strengthenRightShift(BinaryOperator *BO,
 /// Add all uses of Def to the current IV's worklist.
 void SimplifyIndvar::pushIVUsers(
     Instruction *Def, SmallPtrSet<Instruction *, 16> &Simplified,
-    SmallVectorImpl<std::pair<Instruction *, Instruction *>> &SimpleIVUsers) {
+    SmallVectorImpl<std::tuple<Instruction *, Instruction *, unsigned>>
+        &SimpleIVUsers,
+    unsigned OutOfLoopChainCounter) {
   for (User *U : Def->users()) {
     Instruction *UI = cast<Instruction>(U);
 
@@ -857,16 +865,23 @@ void SimplifyIndvar::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.
     if (!Simplified.insert(UI).second)
       continue;
 
-    SimpleIVUsers.push_back(std::make_pair(UI, Def));
+    unsigned Counter =
+        L->contains(UI)
+            ? 0 // reset depth if we go back inside the loop.
+            : OutOfLoopChainCounter + (UI->getParent() != Def->getParent());
+
+    if (!MaxDepthOutOfLoop || Counter < MaxDepthOutOfLoop) {
+      SimpleIVUsers.push_back(std::make_tuple(UI, Def, Counter));
+    }
   }
 }
 
@@ -911,17 +926,17 @@ 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, Simplified, SimpleIVUsers);
+  pushIVUsers(CurrIV, Simplified, SimpleIVUsers, 0);
 
   while (!SimpleIVUsers.empty()) {
-    std::pair<Instruction*, Instruction*> UseOper =
-      SimpleIVUsers.pop_back_val();
-    Instruction *UseInst = UseOper.first;
+    auto [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
@@ -945,11 +960,11 @@ 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
       }
 
-    Instruction *IVOperand = UseOper.second;
     for (unsigned N = 0; IVOperand; ++N) {
       assert(N <= Simplified.size() && "runaway iteration");
       (void) N;
@@ -963,7 +978,7 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
       continue;
 
     if (eliminateIVUser(UseInst, IVOperand)) {
-      pushIVUsers(IVOperand, Simplified, SimpleIVUsers);
+      pushIVUsers(IVOperand, Simplified, SimpleIVUsers, OutOfLoopChainCounter);
       continue;
     }
 
@@ -971,14 +986,15 @@ 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, Simplified, SimpleIVUsers);
+        pushIVUsers(IVOperand, Simplified, SimpleIVUsers,
+                    OutOfLoopChainCounter);
       }
     }
 
     // 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, Simplified, SimpleIVUsers);
+      pushIVUsers(IVOperand, Simplified, SimpleIVUsers, OutOfLoopChainCounter);
       continue;
     }
 
@@ -988,7 +1004,7 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
       continue;
     }
     if (isSimpleIVUser(UseInst, L, SE)) {
-      pushIVUsers(UseInst, Simplified, SimpleIVUsers);
+      pushIVUsers(UseInst, Simplified, SimpleIVUsers, OutOfLoopChainCounter);
     }
   }
 }
@@ -1002,13 +1018,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 MaxDepthOutOfLoop, IVVisitor *V) {
   SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), SE, DT, LI, TTI,
-                     Rewriter, Dead);
+                     Rewriter, Dead, MaxDepthOutOfLoop);
   SIV.simplifyUsers(CurrIV, V);
   return {SIV.hasChanged(), SIV.runUnswitching()};
 }

>From e0d9d0083efe7efe03b95d4c890087f9217caa57 Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Wed, 26 Jun 2024 23:38:48 +0200
Subject: [PATCH 2/8] Add simple tests

---
 .../simplify-indvars-post-loop.ll             | 112 ++++++++++++++++++
 1 file changed, 112 insertions(+)
 create mode 100644 llvm/test/Transforms/IndVarSimplify/simplify-indvars-post-loop.ll

diff --git a/llvm/test/Transforms/IndVarSimplify/simplify-indvars-post-loop.ll b/llvm/test/Transforms/IndVarSimplify/simplify-indvars-post-loop.ll
new file mode 100644
index 0000000000000..20da68f946345
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/simplify-indvars-post-loop.ll
@@ -0,0 +1,112 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -S -passes=indvars --indvars-max-depth-out-of-loop=0 | FileCheck %s
+
+define dso_local i1 @ugt_add_rec_iv(ptr nocapture noundef readonly %s) local_unnamed_addr #0 {
+; CHECK-LABEL: define dso_local i1 @ugt_add_rec_iv(
+; CHECK-SAME: ptr nocapture noundef readonly [[S:%.*]]) local_unnamed_addr {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[WHILE_COND:.*]]
+; CHECK:       [[WHILE_COND]]:
+; CHECK-NEXT:    [[I_0:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[ADD:%.*]], %[[WHILE_BODY:.*]] ]
+; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp ugt i64 [[I_0]], 1234
+; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[WHILE_END:.*]], label %[[WHILE_BODY]]
+; CHECK:       [[WHILE_BODY]]:
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 [[I_0]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[TMP0]], -48
+; CHECK-NEXT:    [[OR_COND:%.*]] = icmp ult i8 [[TMP1]], 10
+; CHECK-NEXT:    [[ADD]] = add nuw nsw i64 [[I_0]], 1
+; CHECK-NEXT:    br i1 [[OR_COND]], label %[[WHILE_COND]], label %[[WHILE_END]]
+; CHECK:       [[WHILE_END]]:
+; CHECK-NEXT:    ret i1 true
+;
+entry:
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.body, %entry
+  %i.0 = phi i64 [ 0, %entry ], [ %add, %while.body ]
+  %exitcond.not = icmp ugt i64 %i.0, 1234
+  br i1 %exitcond.not, label %while.end, label %while.body
+
+while.body:                                       ; preds = %while.cond
+  %arrayidx = getelementptr inbounds i8, ptr %s, i64 %i.0
+  %0 = load i8, ptr %arrayidx, align 1
+  %1 = add i8 %0, -48
+  %or.cond = icmp ult i8 %1, 10
+  %add = add nuw nsw i64 %i.0, 1
+  br i1 %or.cond, label %while.cond, label %while.end
+
+while.end:                                        ; preds = %while.body, %while.cond
+  %cmp6 = icmp ule i64 %i.0, 1235
+  ret i1 %cmp6
+}
+
+define dso_local i1 @ne_add_rec_iv(ptr nocapture noundef readonly %s) local_unnamed_addr #0 {
+; CHECK-LABEL: define dso_local i1 @ne_add_rec_iv(
+; CHECK-SAME: ptr nocapture noundef readonly [[S:%.*]]) local_unnamed_addr {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[WHILE_COND:.*]]
+; CHECK:       [[WHILE_COND]]:
+; CHECK-NEXT:    [[I_0:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[ADD:%.*]], %[[WHILE_BODY:.*]] ]
+; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[I_0]], 1235
+; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[WHILE_END:.*]], label %[[WHILE_BODY]]
+; CHECK:       [[WHILE_BODY]]:
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 [[I_0]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[TMP0]], -48
+; CHECK-NEXT:    [[OR_COND:%.*]] = icmp ult i8 [[TMP1]], 10
+; CHECK-NEXT:    [[ADD]] = add nuw nsw i64 [[I_0]], 1
+; CHECK-NEXT:    br i1 [[OR_COND]], label %[[WHILE_COND]], label %[[WHILE_END]]
+; CHECK:       [[WHILE_END]]:
+; CHECK-NEXT:    ret i1 true
+;
+entry:
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.body, %entry
+  %i.0 = phi i64 [ 0, %entry ], [ %add, %while.body ]
+  %exitcond.not = icmp eq i64 %i.0, 1235
+  br i1 %exitcond.not, label %while.end, label %while.body
+
+while.body:                                       ; preds = %while.cond
+  %arrayidx = getelementptr inbounds i8, ptr %s, i64 %i.0
+  %0 = load i8, ptr %arrayidx, align 1
+  %1 = add i8 %0, -48
+  %or.cond = icmp ult i8 %1, 10
+  %add = add nuw nsw i64 %i.0, 1
+  br i1 %or.cond, label %while.cond, label %while.end
+
+while.end:                                        ; preds = %while.body, %while.cond
+  %cmp6 = icmp ule i64 %i.0, 1235
+  ret i1 %cmp6
+}
+
+; sanity check to verify there is no simplification of outer loop phis.
+define dso_local i32 @nested_loop(i32 noundef %0, i32 noundef %1) local_unnamed_addr #0 {
+  %3 = icmp eq i32 %0, 0
+  br i1 %3, label %18, label %4
+
+4:                                                ; preds = %2, %15
+  %5 = phi i32 [ %16, %15 ], [ 0, %2 ]
+  %6 = phi i32 [ %13, %15 ], [ 1, %2 ]
+  %7 = urem i32 %5, %1
+  br label %8
+
+8:                                                ; preds = %4, %8
+  %9 = phi i32 [ %7, %4 ], [ %11, %8 ]
+  %10 = phi i32 [ %6, %4 ], [ %13, %8 ]
+  %11 = add i32 %9, 1
+  %12 = mul i32 %11, %9
+  %13 = add i32 %12, %10
+  %14 = icmp ult i32 %11, %1
+  br i1 %14, label %8, label %15
+
+15:                                               ; preds = %8
+  %16 = add i32 %11, %5
+  %17 = icmp ult i32 %16, %0
+  br i1 %17, label %4, label %18
+
+18:                                               ; preds = %15, %2
+  %19 = phi i32 [ 1, %2 ], [ %13, %15 ]
+  ret i32 %19
+}

>From 3511e43aeb58522b5fde2f9b588f2501f557b63b Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Wed, 26 Jun 2024 23:41:19 +0200
Subject: [PATCH 3/8] Default to enable full traversal (it shoud be changed
 before merge)

---
 llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index ea0f7a986e4b9..c270841835672 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -125,7 +125,7 @@ AllowIVWidening("indvars-widen-indvars", cl::Hidden, cl::init(true),
                 cl::desc("Allow widening of indvars to eliminate s/zext"));
 
 static cl::opt<unsigned> MaxDepthOutOfLoop(
-    "indvars-max-depth-out-of-loop", cl::Hidden, cl::init(1),
+    "indvars-max-depth-out-of-loop", cl::Hidden, cl::init(0),
     cl::desc(
         "Strict upper bound for the number of successive out-of-loop blocks "
         "when traversing use-def chains. 0 enables full traversal"));

>From aeac9e850e55c3c81942eaf13e05db52b05a3185 Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Thu, 27 Jun 2024 00:18:29 +0200
Subject: [PATCH 4/8] typo

---
 llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index a3c1134cd7d64..05b28d91587b3 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -866,7 +866,7 @@ void SimplifyIndvar::pushIVUsers(
       continue;
 
     // Avoid adding Defs that SCEV expand to themselves, e.g. the LoopPhis
-    // of the outter loops.
+    // of the outer loops.
     if (!DT->dominates(L->getHeader(), UI->getParent()))
       continue;
 
@@ -879,9 +879,8 @@ void SimplifyIndvar::pushIVUsers(
             ? 0 // reset depth if we go back inside the loop.
             : OutOfLoopChainCounter + (UI->getParent() != Def->getParent());
 
-    if (!MaxDepthOutOfLoop || Counter < MaxDepthOutOfLoop) {
+    if (!MaxDepthOutOfLoop || Counter < MaxDepthOutOfLoop)
       SimpleIVUsers.push_back(std::make_tuple(UI, Def, Counter));
-    }
   }
 }
 

>From 06970c7e2717e10064266f58dfd8ef1b19795f4c Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Thu, 27 Jun 2024 08:53:51 +0200
Subject: [PATCH 5/8] Update tests

---
 .../Transforms/IndVarSimplify/X86/pr57187.ll  |  7 +------
 .../IndVarSimplify/lcssa-preservation.ll      |  2 --
 .../IndVarSimplify/no-iv-rewrite.ll           |  5 -----
 .../test/Transforms/IndVarSimplify/pr25578.ll |  2 --
 .../rewrite-loop-exit-values-phi.ll           |  4 ----
 .../Transforms/IndVarSimplify/rlev-add-me.ll  |  5 ++---
 .../scev-expander-preserve-lcssa.ll           | 20 ++++---------------
 .../Transforms/IndVarSimplify/sentinel.ll     |  3 +--
 8 files changed, 8 insertions(+), 40 deletions(-)

diff --git a/llvm/test/Transforms/IndVarSimplify/X86/pr57187.ll b/llvm/test/Transforms/IndVarSimplify/X86/pr57187.ll
index 620b0adaebfe5..f4aa186d87e78 100644
--- a/llvm/test/Transforms/IndVarSimplify/X86/pr57187.ll
+++ b/llvm/test/Transforms/IndVarSimplify/X86/pr57187.ll
@@ -9,23 +9,18 @@ define void @test(i32 %start) {
 ; CHECK-LABEL: @test(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[START:%.*]], -1
-; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[START]] to i64
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       backedge:
 ; CHECK-NEXT:    br label [[LOOP]]
 ; CHECK:       loop:
-; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP1]], [[ENTRY:%.*]] ]
-; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
-; CHECK-NEXT:    [[INDVARS:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
 ; CHECK-NEXT:    [[LOOP_EXIT_COND:%.*]] = icmp slt i32 [[TMP0]], 11
 ; CHECK-NEXT:    br i1 [[LOOP_EXIT_COND]], label [[EXIT:%.*]], label [[STUCK_PREHEADER:%.*]]
 ; CHECK:       stuck.preheader:
 ; CHECK-NEXT:    br label [[STUCK:%.*]]
 ; CHECK:       exit:
-; CHECK-NEXT:    [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[INDVARS]], [[LOOP]] ]
 ; CHECK-NEXT:    ret void
 ; CHECK:       stuck:
-; CHECK-NEXT:    br i1 false, label [[BACKEDGE]], label [[STUCK]]
+; CHECK-NEXT:    br i1 false, label [[BACKEDGE:%.*]], label [[STUCK]]
 ;
 entry:
   br label %loop
diff --git a/llvm/test/Transforms/IndVarSimplify/lcssa-preservation.ll b/llvm/test/Transforms/IndVarSimplify/lcssa-preservation.ll
index f00a111aa6a6d..e12b89a53204a 100644
--- a/llvm/test/Transforms/IndVarSimplify/lcssa-preservation.ll
+++ b/llvm/test/Transforms/IndVarSimplify/lcssa-preservation.ll
@@ -17,12 +17,10 @@ define void @PR18642(i32 %x) {
 ; CHECK:       outer.latch:
 ; CHECK-NEXT:    br i1 false, label [[OUTER_HEADER]], label [[EXIT_LOOPEXIT1:%.*]]
 ; CHECK:       exit.loopexit:
-; CHECK-NEXT:    [[INC_LCSSA:%.*]] = phi i32 [ -2147483648, [[INNER_LATCH]] ]
 ; CHECK-NEXT:    br label [[EXIT:%.*]]
 ; CHECK:       exit.loopexit1:
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
-; CHECK-NEXT:    [[EXIT_PHI:%.*]] = phi i32 [ [[INC_LCSSA]], [[EXIT_LOOPEXIT]] ], [ undef, [[EXIT_LOOPEXIT1]] ]
 ; CHECK-NEXT:    ret void
 ;
 entry:
diff --git a/llvm/test/Transforms/IndVarSimplify/no-iv-rewrite.ll b/llvm/test/Transforms/IndVarSimplify/no-iv-rewrite.ll
index 579b8536cedf0..c5e751257ce2c 100644
--- a/llvm/test/Transforms/IndVarSimplify/no-iv-rewrite.ll
+++ b/llvm/test/Transforms/IndVarSimplify/no-iv-rewrite.ll
@@ -380,18 +380,13 @@ define i32 @isomorphic(i32 %init, i32 %step, i32 %lim) nounwind {
 ; CHECK-NEXT:    [[J:%.*]] = phi i32 [ [[INIT]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ]
 ; CHECK-NEXT:    [[II_NEXT]] = add i32 [[II]], [[STEP1]]
 ; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], [[STEP1]]
-; CHECK-NEXT:    [[L_STEP:%.*]] = add i32 [[J]], [[STEP]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[II_NEXT]], [[LIM:%.*]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[RETURN:%.*]]
 ; CHECK:       return:
 ; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[J]], [[LOOP]] ]
 ; CHECK-NEXT:    [[J_NEXT_LCSSA:%.*]] = phi i32 [ [[J_NEXT]], [[LOOP]] ]
-; CHECK-NEXT:    [[K_NEXT_LCSSA:%.*]] = phi i32 [ [[II_NEXT]], [[LOOP]] ]
-; CHECK-NEXT:    [[L_STEP_LCSSA:%.*]] = phi i32 [ [[L_STEP]], [[LOOP]] ]
 ; CHECK-NEXT:    [[L_NEXT_LCSSA:%.*]] = phi i32 [ [[J_NEXT]], [[LOOP]] ]
 ; CHECK-NEXT:    [[SUM1:%.*]] = add i32 [[I_LCSSA]], [[J_NEXT_LCSSA]]
-; CHECK-NEXT:    [[SUM2:%.*]] = add i32 [[SUM1]], [[K_NEXT_LCSSA]]
-; CHECK-NEXT:    [[SUM3:%.*]] = add i32 [[SUM1]], [[L_STEP_LCSSA]]
 ; CHECK-NEXT:    [[SUM4:%.*]] = add i32 [[SUM1]], [[L_NEXT_LCSSA]]
 ; CHECK-NEXT:    ret i32 [[SUM4]]
 ;
diff --git a/llvm/test/Transforms/IndVarSimplify/pr25578.ll b/llvm/test/Transforms/IndVarSimplify/pr25578.ll
index 380e8171798b0..3dc5639abf753 100644
--- a/llvm/test/Transforms/IndVarSimplify/pr25578.ll
+++ b/llvm/test/Transforms/IndVarSimplify/pr25578.ll
@@ -13,7 +13,6 @@ L1_header:
 
 ; CHECK: L2_header:
 ; CHECK: %[[INDVAR:.*]] = phi i64
-; CHECK: %[[TRUNC:.*]] = trunc nuw nsw i64 %[[INDVAR]] to i32
 L2_header:
   %i = phi i32 [ 0, %L1_header ], [ %i_next, %L2_latch ]
   %i_prom = sext i32 %i to i64
@@ -38,7 +37,6 @@ L2_latch:
 
 L1_latch:
 ; CHECK: L1_latch:
-; CHECK: %i_lcssa = phi i32 [ %[[TRUNC]], %L2_exiting_1 ], [ %[[TRUNC]], %L2_exiting_2 ]
 
   %i_lcssa = phi i32 [ %i, %L2_exiting_1 ], [ %i, %L2_exiting_2 ]
   br i1 undef, label %exit, label %L1_header
diff --git a/llvm/test/Transforms/IndVarSimplify/rewrite-loop-exit-values-phi.ll b/llvm/test/Transforms/IndVarSimplify/rewrite-loop-exit-values-phi.ll
index 63f3da7af46ec..8362d083bd3c6 100644
--- a/llvm/test/Transforms/IndVarSimplify/rewrite-loop-exit-values-phi.ll
+++ b/llvm/test/Transforms/IndVarSimplify/rewrite-loop-exit-values-phi.ll
@@ -22,16 +22,12 @@ define dso_local void @hoge() local_unnamed_addr {
 ; CHECK:       inner.preheader:
 ; CHECK-NEXT:    br label [[INNER:%.*]]
 ; CHECK:       inner:
-; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[INNER]] ], [ 0, [[INNER_PREHEADER]] ]
 ; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[J_NEXT:%.*]], [[INNER]] ], [ [[N]], [[INNER_PREHEADER]] ]
-; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i64 [[I]], 1
 ; CHECK-NEXT:    [[J_NEXT]] = add nsw i64 [[J]], 1
 ; CHECK-NEXT:    store i64 undef, ptr @ptr, align 8
 ; CHECK-NEXT:    [[COND1:%.*]] = icmp slt i64 [[J]], [[IDX]]
 ; CHECK-NEXT:    br i1 [[COND1]], label [[INNER]], label [[INNER_EXIT:%.*]]
 ; CHECK:       inner_exit:
-; CHECK-NEXT:    [[INDVAR:%.*]] = phi i64 [ [[I_NEXT]], [[INNER]] ]
-; CHECK-NEXT:    [[INDVAR_USE:%.*]] = add i64 [[INDVAR]], 1
 ; CHECK-NEXT:    br label [[LATCH]]
 ; CHECK:       latch:
 ; CHECK-NEXT:    [[IDX_NEXT]] = add nsw i64 [[IDX]], -1
diff --git a/llvm/test/Transforms/IndVarSimplify/rlev-add-me.ll b/llvm/test/Transforms/IndVarSimplify/rlev-add-me.ll
index 9ae7d0af2a43e..22378db12ac3f 100644
--- a/llvm/test/Transforms/IndVarSimplify/rlev-add-me.ll
+++ b/llvm/test/Transforms/IndVarSimplify/rlev-add-me.ll
@@ -88,7 +88,7 @@ define i32 @neg_wrong_loop(i32 %n) {
 ; CHECK:       wrong_loop:
 ; CHECK-NEXT:    [[IV2:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV2_NEXT:%.*]], [[WRONG_LOOP]] ]
 ; CHECK-NEXT:    [[IV2_NEXT]] = add i32 [[IV2]], 1
-; CHECK-NEXT:    [[UNKNOWN:%.*]] = load volatile i32, ptr @G
+; CHECK-NEXT:    [[UNKNOWN:%.*]] = load volatile i32, ptr @G, align 4
 ; CHECK-NEXT:    [[CMP_UNK:%.*]] = icmp eq i32 [[UNKNOWN]], 0
 ; CHECK-NEXT:    br i1 [[CMP_UNK]], label [[HEADER_PREHEADER:%.*]], label [[WRONG_LOOP]]
 ; CHECK:       header.preheader:
@@ -108,8 +108,7 @@ define i32 @neg_wrong_loop(i32 %n) {
 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[HEADER]] ]
 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
 ; CHECK:       exit2:
-; CHECK-NEXT:    [[EXITVAL:%.*]] = phi i32 [ [[IV2_LCSSA]], [[LATCH]] ]
-; CHECK-NEXT:    ret i32 [[EXITVAL]]
+; CHECK-NEXT:    ret i32 [[IV2_LCSSA]]
 ;
 entry:
   br label %wrong_loop
diff --git a/llvm/test/Transforms/IndVarSimplify/scev-expander-preserve-lcssa.ll b/llvm/test/Transforms/IndVarSimplify/scev-expander-preserve-lcssa.ll
index 14e06fe06b412..968d5107c0901 100644
--- a/llvm/test/Transforms/IndVarSimplify/scev-expander-preserve-lcssa.ll
+++ b/llvm/test/Transforms/IndVarSimplify/scev-expander-preserve-lcssa.ll
@@ -107,16 +107,14 @@ define void @test2(i16 %x)  {
 ; CHECK-NEXT:    i16 43, label [[FOR_COND]]
 ; CHECK-NEXT:    ]
 ; CHECK:       for.end:
-; CHECK-NEXT:    [[I_0_LCSSA2:%.*]] = phi i32 [ 0, [[FOR_COND]] ]
-; CHECK-NEXT:    [[CMP8243:%.*]] = icmp sgt i32 [[I_0_LCSSA2]], 0
-; CHECK-NEXT:    br i1 [[CMP8243]], label [[FOR_BODY84_PREHEADER:%.*]], label [[RETURN]]
+; CHECK-NEXT:    br i1 false, label [[FOR_BODY84_PREHEADER:%.*]], label [[RETURN]]
 ; CHECK:       for.body84.preheader:
 ; CHECK-NEXT:    br label [[FOR_BODY84:%.*]]
 ; CHECK:       for.body84:
 ; CHECK-NEXT:    [[C_2:%.*]] = call i1 @cond()
 ; CHECK-NEXT:    br i1 [[C_2]], label [[IF_END106:%.*]], label [[RETURN_LOOPEXIT:%.*]]
 ; CHECK:       if.end106:
-; CHECK-NEXT:    br i1 false, label [[FOR_BODY84]], label [[RETURN_LOOPEXIT]]
+; CHECK-NEXT:    br i1 true, label [[FOR_BODY84]], label [[RETURN_LOOPEXIT]]
 ; CHECK:       return.loopexit:
 ; CHECK-NEXT:    br label [[RETURN]]
 ; CHECK:       return.loopexit1:
@@ -228,8 +226,7 @@ define void @test4(ptr %ptr) {
 ; CHECK:       for.body1208.lr.ph:
 ; CHECK-NEXT:    br label [[FOR_BODY1208:%.*]]
 ; CHECK:       for.body1208:
-; CHECK-NEXT:    [[TMP0:%.*]] = phi i32 [ 0, [[FOR_BODY1208_LR_PH]] ], [ [[TMP1:%.*]], [[FOR_INC1498:%.*]] ]
-; CHECK-NEXT:    [[M_0804:%.*]] = phi i32 [ 1, [[FOR_BODY1208_LR_PH]] ], [ [[INC1499:%.*]], [[FOR_INC1498]] ]
+; CHECK-NEXT:    [[M_0804:%.*]] = phi i32 [ 1, [[FOR_BODY1208_LR_PH]] ], [ [[INC1499:%.*]], [[FOR_INC1498:%.*]] ]
 ; CHECK-NEXT:    [[IDXPROM1212:%.*]] = zext i32 [[M_0804]] to i64
 ; CHECK-NEXT:    [[V:%.*]] = call i32 @get.i32()
 ; CHECK-NEXT:    [[CMP1215:%.*]] = icmp eq i32 0, [[V]]
@@ -256,13 +253,9 @@ define void @test4(ptr %ptr) {
 ; CHECK-NEXT:    [[CMP1358:%.*]] = icmp eq i32 [[V_2]], 0
 ; CHECK-NEXT:    br i1 [[CMP1358]], label [[IF_THEN1360:%.*]], label [[FOR_INC1498]]
 ; CHECK:       if.then1360:
-; CHECK-NEXT:    [[DOTLCSSA2:%.*]] = phi i32 [ [[TMP0]], [[IF_ELSE1351]] ]
-; CHECK-NEXT:    [[M_0804_LCSSA1:%.*]] = phi i32 [ [[M_0804]], [[IF_ELSE1351]] ]
-; CHECK-NEXT:    [[CMP1392:%.*]] = icmp slt i32 [[M_0804_LCSSA1]], [[DOTLCSSA2]]
 ; CHECK-NEXT:    unreachable
 ; CHECK:       for.inc1498:
 ; CHECK-NEXT:    [[INC1499]] = add nuw nsw i32 [[M_0804]], 1
-; CHECK-NEXT:    [[TMP1]] = load i32, ptr [[PTR]], align 8
 ; CHECK-NEXT:    br label [[FOR_BODY1208]]
 ; CHECK:       if.then1504:
 ; CHECK-NEXT:    unreachable
@@ -495,17 +488,13 @@ define void @test7(ptr %ptr) {
 ; CHECK:       while.body:
 ; CHECK-NEXT:    br label [[FOR_BODY1208:%.*]]
 ; CHECK:       for.body1208:
-; CHECK-NEXT:    [[TMP0:%.*]] = phi i32 [ undef, [[WHILE_BODY]] ], [ [[TMP1:%.*]], [[FOR_INC1498:%.*]] ]
-; CHECK-NEXT:    [[M_048:%.*]] = phi i32 [ 1, [[WHILE_BODY]] ], [ [[INC1499:%.*]], [[FOR_INC1498]] ]
+; CHECK-NEXT:    [[M_048:%.*]] = phi i32 [ 1, [[WHILE_BODY]] ], [ [[INC1499:%.*]], [[FOR_INC1498:%.*]] ]
 ; CHECK-NEXT:    [[IDXPROM1212:%.*]] = zext i32 [[M_048]] to i64
 ; CHECK-NEXT:    [[XPOS1214:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 [[IDXPROM1212]]
 ; CHECK-NEXT:    [[V_1:%.*]] = call i32 @get.i32()
 ; CHECK-NEXT:    [[CMP1215:%.*]] = icmp eq i32 0, [[V_1]]
 ; CHECK-NEXT:    br i1 [[CMP1215]], label [[IF_THEN1217:%.*]], label [[IF_ELSE1351:%.*]]
 ; CHECK:       if.then1217:
-; CHECK-NEXT:    [[DOTLCSSA:%.*]] = phi i32 [ [[TMP0]], [[FOR_BODY1208]] ]
-; CHECK-NEXT:    [[M_048_LCSSA:%.*]] = phi i32 [ [[M_048]], [[FOR_BODY1208]] ]
-; CHECK-NEXT:    [[CMP1249_NOT_NOT:%.*]] = icmp slt i32 [[M_048_LCSSA]], [[DOTLCSSA]]
 ; CHECK-NEXT:    unreachable
 ; CHECK:       if.else1351:
 ; CHECK-NEXT:    [[CMP1358:%.*]] = icmp eq i32 0, undef
@@ -526,7 +515,6 @@ define void @test7(ptr %ptr) {
 ; CHECK-NEXT:    br label [[IF_END1824:%.*]]
 ; CHECK:       for.inc1498:
 ; CHECK-NEXT:    [[INC1499]] = add nuw nsw i32 [[M_048]], 1
-; CHECK-NEXT:    [[TMP1]] = load i32, ptr undef, align 8
 ; CHECK-NEXT:    br label [[FOR_BODY1208]]
 ; CHECK:       if.end1824:
 ; CHECK-NEXT:    br label [[WHILE_BODY]]
diff --git a/llvm/test/Transforms/IndVarSimplify/sentinel.ll b/llvm/test/Transforms/IndVarSimplify/sentinel.ll
index f9ee4a61f4862..fcb010d31f8a0 100644
--- a/llvm/test/Transforms/IndVarSimplify/sentinel.ll
+++ b/llvm/test/Transforms/IndVarSimplify/sentinel.ll
@@ -11,7 +11,6 @@ define void @test() personality ptr @snork {
 ; CHECK:       bb1:
 ; CHECK-NEXT:    br i1 true, label [[BB2:%.*]], label [[BB4]]
 ; CHECK:       bb2:
-; CHECK-NEXT:    [[TMP3:%.*]] = phi i32 [ undef, [[BB1:%.*]] ]
 ; CHECK-NEXT:    ret void
 ; CHECK:       bb4:
 ; CHECK-NEXT:    [[TMP6:%.*]] = invoke i32 @quux() [ "deopt"(i32 0, i32 0, i32 0, i32 180, i32 0, i32 25, i32 0, i32 7, ptr null, i32 7, ptr null, i32 7, ptr null, i32 3, i32 undef, i32 3, i32 undef, i32 7, ptr null, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 3, i32 undef, i32 4, double undef, i32 7, ptr null, i32 4, i64 undef, i32 7, ptr null, i32 0, ptr addrspace(1) undef, i32 3, i32 undef, i32 0, ptr addrspace(1) undef, i32 0, ptr addrspace(1) undef, i32 0, ptr addrspace(1) undef, i32 0, ptr addrspace(1) undef, i32 0, ptr addrspace(1) undef, i32 0, ptr addrspace(1) undef, i32 0, ptr addrspace(1) undef, i32 0, ptr addrspace(1) undef, i32 7, ptr null) ]
@@ -19,7 +18,7 @@ define void @test() personality ptr @snork {
 ; CHECK:       bb7:
 ; CHECK-NEXT:    br label [[BB9:%.*]]
 ; CHECK:       bb9:
-; CHECK-NEXT:    br i1 true, label [[BB1]], label [[BB9]]
+; CHECK-NEXT:    br i1 true, label [[BB1:%.*]], label [[BB9]]
 ; CHECK:       bb15:
 ; CHECK-NEXT:    [[TMP16:%.*]] = landingpad { ptr, i32 }
 ; CHECK-NEXT:    cleanup

>From 522ba6e4f344ef03f196e3e13e1f5a6d23cc5d3e Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Thu, 27 Jun 2024 18:23:27 +0200
Subject: [PATCH 6/8] Update test for LoopDeletion/LoopVectorize

---
 llvm/test/Transforms/LoopDeletion/pr53969.ll                 | 5 ++---
 .../pr54413-select-interleave-count-loop-with-cost-zero.ll   | 2 --
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/llvm/test/Transforms/LoopDeletion/pr53969.ll b/llvm/test/Transforms/LoopDeletion/pr53969.ll
index f9b9dc3373b5e..94de823a9d8ab 100644
--- a/llvm/test/Transforms/LoopDeletion/pr53969.ll
+++ b/llvm/test/Transforms/LoopDeletion/pr53969.ll
@@ -31,17 +31,16 @@ define void @test() {
 ; CHECK:       bb32:
 ; CHECK-NEXT:    ret void
 ; CHECK:       bb33.loopexit:
-; CHECK-NEXT:    [[TMP2_LCSSA9:%.*]] = phi i32 [ [[TMP2_LCSSA12]], [[BB11:%.*]] ]
 ; CHECK-NEXT:    br label [[BB33:%.*]]
 ; CHECK:       bb33.loopexit1:
 ; CHECK-NEXT:    [[TMP2_LCSSA:%.*]] = phi i32 [ 11, [[BB1]] ]
 ; CHECK-NEXT:    br label [[BB33]]
 ; CHECK:       bb33:
-; CHECK-NEXT:    [[TMP210:%.*]] = phi i32 [ [[TMP2_LCSSA]], [[BB33_LOOPEXIT1]] ], [ [[TMP2_LCSSA9]], [[BB33_LOOPEXIT]] ]
+; CHECK-NEXT:    [[TMP210:%.*]] = phi i32 [ [[TMP2_LCSSA]], [[BB33_LOOPEXIT1]] ], [ [[TMP2_LCSSA12]], [[BB33_LOOPEXIT]] ]
 ; CHECK-NEXT:    call void @use(i32 [[TMP210]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       bb34:
-; CHECK-NEXT:    br i1 false, label [[BB11]], label [[BB12:%.*]]
+; CHECK-NEXT:    br i1 false, label [[BB11:%.*]], label [[BB12:%.*]]
 ; CHECK:       bb42:
 ; CHECK-NEXT:    [[TMP24_LCSSA:%.*]] = phi i32 [ undef, [[BB22]] ]
 ; CHECK-NEXT:    [[TMP18_LCSSA4:%.*]] = phi i64 [ 0, [[BB22]] ]
diff --git a/llvm/test/Transforms/LoopVectorize/X86/pr54413-select-interleave-count-loop-with-cost-zero.ll b/llvm/test/Transforms/LoopVectorize/X86/pr54413-select-interleave-count-loop-with-cost-zero.ll
index ecab2e6bf4aec..d65b1aa97778a 100644
--- a/llvm/test/Transforms/LoopVectorize/X86/pr54413-select-interleave-count-loop-with-cost-zero.ll
+++ b/llvm/test/Transforms/LoopVectorize/X86/pr54413-select-interleave-count-loop-with-cost-zero.ll
@@ -15,10 +15,8 @@ define void @pr54413(ptr %ptr.base) {
 ; CHECK:       loop2.preheader:
 ; CHECK-NEXT:    br label [[LOOP2:%.*]]
 ; CHECK:       loop2:
-; CHECK-NEXT:    [[PTR_NEXT:%.*]] = getelementptr inbounds i64, ptr [[PTR_BASE:%.*]], i64 1
 ; CHECK-NEXT:    br i1 true, label [[LOOP2_EXIT:%.*]], label [[LOOP2]]
 ; CHECK:       loop2.exit:
-; CHECK-NEXT:    [[PTR_NEXT_LCSSA:%.*]] = phi ptr [ [[PTR_NEXT]], [[LOOP2]] ]
 ; CHECK-NEXT:    br label [[LOOP1_LATCH]]
 ; CHECK:       loop1.latch:
 ; CHECK-NEXT:    br label [[LOOP1]]

>From db8fb22c231ae3500d91004397c3a8ca6c22f83d Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Wed, 3 Jul 2024 14:45:59 +0200
Subject: [PATCH 7/8] pre-commit test eliminateTrunc miscompile

---
 .../out_of_loop_eliminate_truncate.ll         | 127 ++++++++++++++++++
 1 file changed, 127 insertions(+)
 create mode 100644 llvm/test/Transforms/IndVarSimplify/out_of_loop_eliminate_truncate.ll

diff --git a/llvm/test/Transforms/IndVarSimplify/out_of_loop_eliminate_truncate.ll b/llvm/test/Transforms/IndVarSimplify/out_of_loop_eliminate_truncate.ll
new file mode 100644
index 0000000000000..432117daa1c64
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/out_of_loop_eliminate_truncate.ll
@@ -0,0 +1,127 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=indvars -S | FileCheck %s
+
+target datalayout = "n8:16:32:64"
+
+; This test is inspired by a miscompilation of llvm by itself in
+; ``ValueTracking.cpp matchSimpleReccurence``.
+; Because of that, the assignment ``Start = R;`` was not emitted
+; although ``true`` was returned.
+
+define dso_local noundef zeroext i1 @matchSimpleRecurrence(
+; CHECK-LABEL: define dso_local noundef zeroext i1 @matchSimpleRecurrence(
+; CHECK-SAME: ptr nocapture noundef readonly [[P:%.*]], ptr nocapture noundef nonnull writeonly align 8 dereferenceable(8) [[START:%.*]], ptr nocapture noundef nonnull writeonly align 8 dereferenceable(8) [[STEP:%.*]]) local_unnamed_addr {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[FOR_BODY:.*]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[FOR_INC:.*]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT:    [[CMP_NOT17:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ [[CMP_NOT:%.*]], %[[FOR_INC]] ]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[P]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8
+; CHECK-NEXT:    [[TOBOOL3_NOT:%.*]] = icmp eq ptr [[TMP0]], null
+; CHECK-NEXT:    br i1 [[TOBOOL3_NOT]], label %[[FOR_INC]], label %[[IF_THEN:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    [[CMP_NOT17_LCSSA:%.*]] = phi i1 [ [[CMP_NOT17]], %[[FOR_BODY]] ]
+; CHECK-NEXT:    [[I_016_LCSSA_WIDE:%.*]] = phi i64 [ [[INDVARS_IV]], %[[FOR_BODY]] ]
+; CHECK-NEXT:    [[DOTLCSSA:%.*]] = phi ptr [ [[TMP0]], %[[FOR_BODY]] ]
+; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 poison to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[I_016_LCSSA_WIDE]], [[ZEXT]]
+; CHECK-NEXT:    [[IDXPROM1:%.*]] = zext i1 [[TMP1]] to i64
+; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds ptr, ptr [[P]], i64 [[IDXPROM1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX2]], align 8
+; CHECK-NEXT:    store ptr [[TMP2]], ptr [[START]], align 8
+; CHECK-NEXT:    store ptr [[DOTLCSSA]], ptr [[STEP]], align 8
+; CHECK-NEXT:    br label %[[CLEANUP5:.*]]
+; CHECK:       [[FOR_INC]]:
+; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[CMP_NOT]] = icmp ne i64 [[INDVARS_IV_NEXT]], 2
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label %[[FOR_BODY]], label %[[CLEANUP5_LOOPEXIT:.*]]
+; CHECK:       [[CLEANUP5_LOOPEXIT]]:
+; CHECK-NEXT:    [[CMP_NOT_LCSSA:%.*]] = phi i1 [ [[CMP_NOT]], %[[FOR_INC]] ]
+; CHECK-NEXT:    br label %[[CLEANUP5]]
+; CHECK:       [[CLEANUP5]]:
+; CHECK-NEXT:    [[CMP_NOT14:%.*]] = phi i1 [ [[CMP_NOT17_LCSSA]], %[[IF_THEN]] ], [ [[CMP_NOT_LCSSA]], %[[CLEANUP5_LOOPEXIT]] ]
+; CHECK-NEXT:    ret i1 [[CMP_NOT14]]
+;
+  ptr nocapture noundef readonly %P,
+  ptr nocapture noundef nonnull writeonly align 8 dereferenceable(8) %Start,
+  ptr nocapture noundef nonnull writeonly align 8 dereferenceable(8) %Step
+) local_unnamed_addr {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.inc
+  %cmp.not17 = phi i1 [ true, %entry ], [ %cmp.not, %for.inc ]
+  %i.016 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %idxprom = zext nneg i32 %i.016 to i64
+  %arrayidx = getelementptr inbounds ptr, ptr %P, i64 %idxprom
+  %0 = load ptr, ptr %arrayidx, align 8
+  %tobool3.not = icmp eq ptr %0, null
+  br i1 %tobool3.not, label %for.inc, label %if.then
+
+if.then:                                          ; preds = %for.body
+  %tobool.not = icmp eq i32 %i.016, 0
+  %idxprom1 = zext i1 %tobool.not to i64
+  %arrayidx2 = getelementptr inbounds ptr, ptr %P, i64 %idxprom1
+  %1 = load ptr, ptr %arrayidx2, align 8
+  store ptr %1, ptr %Start, align 8
+  store ptr %0, ptr %Step, align 8
+  br label %cleanup5
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nuw nsw i32 %i.016, 1
+  %cmp.not = icmp ne i32 %inc, 2
+  br i1 %cmp.not, label %for.body, label %cleanup5.loopexit
+
+cleanup5.loopexit:                                ; preds = %for.inc
+  br label %cleanup5
+
+cleanup5:                                         ; preds = %cleanup5.loopexit, %if.then
+  %cmp.not14 = phi i1 [ %cmp.not17, %if.then ], [ %cmp.not, %cleanup5.loopexit ]
+  ret i1 %cmp.not14
+}
+
+
+define i1 @check_size_str(ptr %str, i32 %str.size, i32 %n) {
+; CHECK-LABEL: define i1 @check_size_str(
+; CHECK-SAME: ptr [[STR:%.*]], i32 [[STR_SIZE:%.*]], i32 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[I:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[I_INC:%.*]], %[[LOOP]] ]
+; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
+; CHECK-NEXT:    [[STR_I:%.*]] = getelementptr i8, ptr [[STR]], i64 [[I]]
+; CHECK-NEXT:    [[CHAR:%.*]] = load i8, ptr [[STR_I]], align 1
+; CHECK-NEXT:    [[CMP_CHAR:%.*]] = icmp eq i8 [[CHAR]], 0
+; CHECK-NEXT:    [[STR_SIZE_64:%.*]] = zext i32 [[STR_SIZE]] to i64
+; CHECK-NEXT:    [[CMP_I:%.*]] = icmp eq i64 [[I]], [[STR_SIZE_64]]
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP_I]], [[CMP_CHAR]]
+; CHECK-NEXT:    br i1 [[OR]], label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i64 [ [[I]], %[[LOOP]] ]
+; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 poison to i64
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[I_LCSSA]], [[ZEXT]]
+; CHECK-NEXT:    ret i1 [[TMP0]]
+;
+entry:
+  br label %loop
+
+loop:
+  %i = phi i64 [0, %entry], [%i.inc, %loop]
+  %i.inc = add nuw nsw i64 %i, 1
+
+  %str.i = getelementptr i8, ptr %str, i64 %i
+  %char = load i8, ptr %str.i, align 1
+  %cmp.char = icmp eq i8 %char, 0
+
+  %str.size.64 = zext i32 %str.size to i64
+  %cmp.i = icmp eq i64 %i, %str.size.64
+
+  %or = or i1 %cmp.i, %cmp.char
+  br i1 %or, label %exit, label %loop
+
+exit:
+  %i.32 = trunc nuw nsw i64 %i to i32
+  %cmp.i.32 = icmp eq i32 %i.32, %n
+  ret i1 %cmp.i.32
+}

>From 8a92def57b05e3e759c057666fdb7c650c7f7d5d Mon Sep 17 00:00:00 2001
From: v01dxyz <v01dxyz at v01d.xyz>
Date: Tue, 2 Jul 2024 17:54:54 +0200
Subject: [PATCH 8/8] Fix eliminateTrunc

Out of loop, an IV user is loop invariant. Using L->isLoopInvariant is
no more valid to distinguish which operand is the loop-constant one from
the IV user.
---
 llvm/lib/Transforms/Utils/SimplifyIndVar.cpp                 | 2 +-
 .../IndVarSimplify/out_of_loop_eliminate_truncate.ll         | 5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 05b28d91587b3..325633a5848c2 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -554,7 +554,7 @@ bool SimplifyIndvar::eliminateTrunc(TruncInst *TI) {
   };
   // Replace all comparisons against trunc with comparisons against IV.
   for (auto *ICI : ICmpUsers) {
-    bool IsSwapped = L->isLoopInvariant(ICI->getOperand(0));
+    bool IsSwapped = ICI->getOperand(0) != TI;
     auto *Op1 = IsSwapped ? ICI->getOperand(0) : ICI->getOperand(1);
     IRBuilder<> Builder(ICI);
     Value *Ext = nullptr;
diff --git a/llvm/test/Transforms/IndVarSimplify/out_of_loop_eliminate_truncate.ll b/llvm/test/Transforms/IndVarSimplify/out_of_loop_eliminate_truncate.ll
index 432117daa1c64..61ede96d0d356 100644
--- a/llvm/test/Transforms/IndVarSimplify/out_of_loop_eliminate_truncate.ll
+++ b/llvm/test/Transforms/IndVarSimplify/out_of_loop_eliminate_truncate.ll
@@ -24,8 +24,7 @@ define dso_local noundef zeroext i1 @matchSimpleRecurrence(
 ; CHECK-NEXT:    [[CMP_NOT17_LCSSA:%.*]] = phi i1 [ [[CMP_NOT17]], %[[FOR_BODY]] ]
 ; CHECK-NEXT:    [[I_016_LCSSA_WIDE:%.*]] = phi i64 [ [[INDVARS_IV]], %[[FOR_BODY]] ]
 ; CHECK-NEXT:    [[DOTLCSSA:%.*]] = phi ptr [ [[TMP0]], %[[FOR_BODY]] ]
-; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 poison to i64
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[I_016_LCSSA_WIDE]], [[ZEXT]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[I_016_LCSSA_WIDE]], 0
 ; CHECK-NEXT:    [[IDXPROM1:%.*]] = zext i1 [[TMP1]] to i64
 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds ptr, ptr [[P]], i64 [[IDXPROM1]]
 ; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX2]], align 8
@@ -99,7 +98,7 @@ define i1 @check_size_str(ptr %str, i32 %str.size, i32 %n) {
 ; CHECK-NEXT:    br i1 [[OR]], label %[[EXIT:.*]], label %[[LOOP]]
 ; CHECK:       [[EXIT]]:
 ; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i64 [ [[I]], %[[LOOP]] ]
-; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 poison to i64
+; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[N]] to i64
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[I_LCSSA]], [[ZEXT]]
 ; CHECK-NEXT:    ret i1 [[TMP0]]
 ;



More information about the llvm-commits mailing list