[llvm] [LSR] Reuse identical casts and instructions across fixups (PR #201839)

Timur Golubovich via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 8 03:40:29 PDT 2026


https://github.com/timurgol007 updated https://github.com/llvm/llvm-project/pull/201839

>From dd3c531ee6bbfb3a13aaeb658949464e0f4d4657 Mon Sep 17 00:00:00 2001
From: Timur Golubovich <timur.golubovich at intel.com>
Date: Mon, 8 Jun 2026 12:31:06 +0200
Subject: [PATCH 1/4] [Test] Fix icmp conditions to prevent trivial
 optimizations

---
 .../X86/reuse-existing-phi.ll                 |  6 +-
 .../Transforms/LoopStrengthReduce/funclet.ll  | 80 +++++++++----------
 2 files changed, 41 insertions(+), 45 deletions(-)

diff --git a/llvm/test/Transforms/LoopStrengthReduce/X86/reuse-existing-phi.ll b/llvm/test/Transforms/LoopStrengthReduce/X86/reuse-existing-phi.ll
index e7ec690577cb8..19f2a92e8ac28 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/X86/reuse-existing-phi.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/X86/reuse-existing-phi.ll
@@ -12,8 +12,8 @@ define void @reuse_existing_phi() {
 ; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 8
 ; CHECK-NEXT:    [[IV_INC:%.*]] = add i64 [[IV]], 1
 ; CHECK-NEXT:    [[USE:%.*]] = add i64 [[LSR_IV]], [[IV_INC]]
-; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], 8
-; CHECK-NEXT:    [[CHECK:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 108
+; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nuw nsw i64 [[LSR_IV]], 8
+; CHECK-NEXT:    [[CHECK:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 112
 ; CHECK-NEXT:    br i1 [[CHECK]], label %[[EXIT:.*]], label %[[LOOP]]
 ; CHECK:       [[EXIT]]:
 ; CHECK-NEXT:    ret void
@@ -26,7 +26,7 @@ loop:
   %iv.next = add i64 %iv, 8
   %iv.inc = add i64 %iv, 1
   %use = add i64 %iv.next, %iv.inc
-  %check = icmp eq i64 %iv.next, 100
+  %check = icmp eq i64 %iv.next, 104
   br i1 %check, label %exit, label %loop
 
 exit:
diff --git a/llvm/test/Transforms/LoopStrengthReduce/funclet.ll b/llvm/test/Transforms/LoopStrengthReduce/funclet.ll
index da5721a72a906..c2332c091a1fd 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/funclet.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/funclet.ll
@@ -10,15 +10,15 @@ declare i32 @__CxxFrameHandler3(...)
 declare void @external(ptr)
 declare void @reserve()
 
-define void @f() personality ptr @_except_handler3 {
+define void @f(ptr %start, ptr %end) personality ptr @_except_handler3 {
 ; CHECK-LABEL: @f(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[THROW:%.*]]
 ; CHECK:       throw:
 ; CHECK-NEXT:    invoke void @reserve()
-; CHECK-NEXT:    to label [[THROW]] unwind label [[PAD:%.*]]
+; CHECK-NEXT:            to label [[THROW]] unwind label [[PAD:%.*]]
 ; CHECK:       pad:
-; CHECK-NEXT:    [[CS:%.*]] = catchswitch within none [label %unreachable] unwind label [[BLAH2:%.*]]
+; CHECK-NEXT:    [[CS:%.*]] = catchswitch within none [label [[UNREACHABLE:%.*]]] unwind label [[BLAH2:%.*]]
 ; CHECK:       unreachable:
 ; CHECK-NEXT:    [[TMP0:%.*]] = catchpad within [[CS]] []
 ; CHECK-NEXT:    unreachable
@@ -26,10 +26,9 @@ define void @f() personality ptr @_except_handler3 {
 ; CHECK-NEXT:    [[CLEANUPPADI4_I_I_I:%.*]] = cleanuppad within none []
 ; CHECK-NEXT:    br label [[LOOP_BODY:%.*]]
 ; CHECK:       loop_body:
-; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[ITER:%.*]] ], [ 0, [[BLAH2]] ]
-; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], -1
-; CHECK-NEXT:    [[LSR_IV_NEXT1:%.*]] = inttoptr i32 [[LSR_IV_NEXT]] to ptr
-; CHECK-NEXT:    [[TMP100:%.*]] = icmp eq ptr [[LSR_IV_NEXT1]], null
+; CHECK-NEXT:    [[LSR_IV:%.*]] = phi ptr [ [[SCEVGEP:%.*]], [[ITER:%.*]] ], [ [[START:%.*]], [[BLAH2]] ]
+; CHECK-NEXT:    [[SCEVGEP]] = getelementptr i8, ptr [[LSR_IV]], i32 1
+; CHECK-NEXT:    [[TMP100:%.*]] = icmp eq ptr [[SCEVGEP]], [[END:%.*]]
 ; CHECK-NEXT:    br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
 ; CHECK:       iter:
 ; CHECK-NEXT:    br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
@@ -40,7 +39,7 @@ entry:
   br label %throw
 
 throw:                                            ; preds = %throw, %entry
-  %tmp96 = getelementptr inbounds i8, ptr undef, i32 1
+  %tmp96 = getelementptr inbounds i8, ptr %start, i32 1
   invoke void @reserve()
   to label %throw unwind label %pad
 
@@ -58,7 +57,7 @@ blah2:
 
 loop_body:                                        ; preds = %iter, %pad
   %tmp99 = phi ptr [ %tmp101, %iter ], [ %phi2, %blah2 ]
-  %tmp100 = icmp eq ptr %tmp99, undef
+  %tmp100 = icmp eq ptr %tmp99, %end
   br i1 %tmp100, label %unwind_out, label %iter
 
 iter:                                             ; preds = %loop_body
@@ -69,15 +68,15 @@ unwind_out:                                       ; preds = %iter, %loop_body
   cleanupret from %cleanuppadi4.i.i.i unwind to caller
 }
 
-define void @g() personality ptr @_except_handler3 {
+define void @g(ptr %start, ptr %end) personality ptr @_except_handler3 {
 ; CHECK-LABEL: @g(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[THROW:%.*]]
 ; CHECK:       throw:
 ; CHECK-NEXT:    invoke void @reserve()
-; CHECK-NEXT:    to label [[THROW]] unwind label [[PAD:%.*]]
+; CHECK-NEXT:            to label [[THROW]] unwind label [[PAD:%.*]]
 ; CHECK:       pad:
-; CHECK-NEXT:    [[CS:%.*]] = catchswitch within none [label [[UNREACHABLE:%.*]], label %blah] unwind to caller
+; CHECK-NEXT:    [[CS:%.*]] = catchswitch within none [label [[UNREACHABLE:%.*]], label [[BLAH:%.*]]] unwind to caller
 ; CHECK:       unreachable:
 ; CHECK-NEXT:    [[TMP0:%.*]] = catchpad within [[CS]] []
 ; CHECK-NEXT:    unreachable
@@ -89,10 +88,9 @@ define void @g() personality ptr @_except_handler3 {
 ; CHECK:       leave:
 ; CHECK-NEXT:    ret void
 ; CHECK:       loop_body:
-; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[ITER:%.*]] ], [ 0, [[BLAH:%.*]] ]
-; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], -1
-; CHECK-NEXT:    [[LSR_IV_NEXT1:%.*]] = inttoptr i32 [[LSR_IV_NEXT]] to ptr
-; CHECK-NEXT:    [[TMP100:%.*]] = icmp eq ptr [[LSR_IV_NEXT1]], null
+; CHECK-NEXT:    [[LSR_IV:%.*]] = phi ptr [ [[SCEVGEP:%.*]], [[ITER:%.*]] ], [ [[START:%.*]], [[BLAH]] ]
+; CHECK-NEXT:    [[SCEVGEP]] = getelementptr i8, ptr [[LSR_IV]], i32 1
+; CHECK-NEXT:    [[TMP100:%.*]] = icmp eq ptr [[SCEVGEP]], [[END:%.*]]
 ; CHECK-NEXT:    br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
 ; CHECK:       iter:
 ; CHECK-NEXT:    br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
@@ -101,7 +99,7 @@ entry:
   br label %throw
 
 throw:                                            ; preds = %throw, %entry
-  %tmp96 = getelementptr inbounds i8, ptr undef, i32 1
+  %tmp96 = getelementptr inbounds i8, ptr %start, i32 1
   invoke void @reserve()
   to label %throw unwind label %pad
 
@@ -125,7 +123,7 @@ leave:
 
 loop_body:                                        ; preds = %iter, %pad
   %tmp99 = phi ptr [ %tmp101, %iter ], [ %phi2, %blah ]
-  %tmp100 = icmp eq ptr %tmp99, undef
+  %tmp100 = icmp eq ptr %tmp99, %end
   br i1 %tmp100, label %unwind_out, label %iter
 
 iter:                                             ; preds = %loop_body
@@ -133,15 +131,15 @@ iter:                                             ; preds = %loop_body
   br i1 true, label %unwind_out, label %loop_body
 }
 
-define void @h() personality ptr @_except_handler3 {
+define void @h(ptr %start, ptr %end) personality ptr @_except_handler3 {
 ; CHECK-LABEL: @h(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[THROW:%.*]]
 ; CHECK:       throw:
 ; CHECK-NEXT:    invoke void @reserve()
-; CHECK-NEXT:    to label [[THROW]] unwind label [[PAD:%.*]]
+; CHECK-NEXT:            to label [[THROW]] unwind label [[PAD:%.*]]
 ; CHECK:       pad:
-; CHECK-NEXT:    [[CS:%.*]] = catchswitch within none [label [[UNREACHABLE:%.*]], label %blug] unwind to caller
+; CHECK-NEXT:    [[CS:%.*]] = catchswitch within none [label [[UNREACHABLE:%.*]], label [[BLUG:%.*]]] unwind to caller
 ; CHECK:       unreachable:
 ; CHECK-NEXT:    [[TMP0:%.*]] = catchpad within [[CS]] []
 ; CHECK-NEXT:    unreachable
@@ -153,10 +151,9 @@ define void @h() personality ptr @_except_handler3 {
 ; CHECK:       leave:
 ; CHECK-NEXT:    ret void
 ; CHECK:       loop_body:
-; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[ITER:%.*]] ], [ 0, [[BLUG:%.*]] ]
-; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], -1
-; CHECK-NEXT:    [[LSR_IV_NEXT1:%.*]] = inttoptr i32 [[LSR_IV_NEXT]] to ptr
-; CHECK-NEXT:    [[TMP100:%.*]] = icmp eq ptr [[LSR_IV_NEXT1]], null
+; CHECK-NEXT:    [[LSR_IV:%.*]] = phi ptr [ [[SCEVGEP:%.*]], [[ITER:%.*]] ], [ [[START:%.*]], [[BLUG]] ]
+; CHECK-NEXT:    [[SCEVGEP]] = getelementptr i8, ptr [[LSR_IV]], i32 1
+; CHECK-NEXT:    [[TMP100:%.*]] = icmp eq ptr [[SCEVGEP]], [[END:%.*]]
 ; CHECK-NEXT:    br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
 ; CHECK:       iter:
 ; CHECK-NEXT:    br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
@@ -165,7 +162,7 @@ entry:
   br label %throw
 
 throw:                                            ; preds = %throw, %entry
-  %tmp96 = getelementptr inbounds i8, ptr undef, i32 1
+  %tmp96 = getelementptr inbounds i8, ptr %start, i32 1
   invoke void @reserve()
   to label %throw unwind label %pad
 
@@ -189,7 +186,7 @@ leave:
 
 loop_body:                                        ; preds = %iter, %pad
   %tmp99 = phi ptr [ %tmp101, %iter ], [ %phi2, %blug ]
-  %tmp100 = icmp eq ptr %tmp99, undef
+  %tmp100 = icmp eq ptr %tmp99, %end
   br i1 %tmp100, label %unwind_out, label %iter
 
 iter:                                             ; preds = %loop_body
@@ -197,15 +194,15 @@ iter:                                             ; preds = %loop_body
   br i1 true, label %unwind_out, label %loop_body
 }
 
-define void @i() personality ptr @_except_handler3 {
+define void @i(ptr %start, ptr %end) personality ptr @_except_handler3 {
 ; CHECK-LABEL: @i(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[THROW:%.*]]
 ; CHECK:       throw:
 ; CHECK-NEXT:    invoke void @reserve()
-; CHECK-NEXT:    to label [[THROW]] unwind label [[CATCHPAD:%.*]]
+; CHECK-NEXT:            to label [[THROW]] unwind label [[CATCHPAD:%.*]]
 ; CHECK:       catchpad:
-; CHECK-NEXT:    [[CS:%.*]] = catchswitch within none [label %cp_body] unwind label [[CLEANUPPAD:%.*]]
+; CHECK-NEXT:    [[CS:%.*]] = catchswitch within none [label [[CP_BODY:%.*]]] unwind label [[CLEANUPPAD:%.*]]
 ; CHECK:       cp_body:
 ; CHECK-NEXT:    [[TMP0:%.*]] = catchpad within [[CS]] []
 ; CHECK-NEXT:    br label [[LOOP_HEAD:%.*]]
@@ -215,10 +212,9 @@ define void @i() personality ptr @_except_handler3 {
 ; CHECK:       loop_head:
 ; CHECK-NEXT:    br label [[LOOP_BODY:%.*]]
 ; CHECK:       loop_body:
-; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[ITER:%.*]] ], [ 0, [[LOOP_HEAD]] ]
-; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], -1
-; CHECK-NEXT:    [[LSR_IV_NEXT1:%.*]] = inttoptr i32 [[LSR_IV_NEXT]] to ptr
-; CHECK-NEXT:    [[TMP100:%.*]] = icmp eq ptr [[LSR_IV_NEXT1]], null
+; CHECK-NEXT:    [[LSR_IV:%.*]] = phi ptr [ [[SCEVGEP:%.*]], [[ITER:%.*]] ], [ [[START:%.*]], [[LOOP_HEAD]] ]
+; CHECK-NEXT:    [[SCEVGEP]] = getelementptr i8, ptr [[LSR_IV]], i32 1
+; CHECK-NEXT:    [[TMP100:%.*]] = icmp eq ptr [[SCEVGEP]], [[END:%.*]]
 ; CHECK-NEXT:    br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
 ; CHECK:       iter:
 ; CHECK-NEXT:    br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
@@ -229,7 +225,7 @@ entry:
   br label %throw
 
 throw:                                            ; preds = %throw, %entry
-  %tmp96 = getelementptr inbounds i8, ptr undef, i32 1
+  %tmp96 = getelementptr inbounds i8, ptr %start, i32 1
   invoke void @reserve()
   to label %throw unwind label %catchpad
 
@@ -250,7 +246,7 @@ loop_head:
 
 loop_body:                                        ; preds = %iter, %catchpad
   %tmp99 = phi ptr [ %tmp101, %iter ], [ %phi2, %loop_head ]
-  %tmp100 = icmp eq ptr %tmp99, undef
+  %tmp100 = icmp eq ptr %tmp99, %end
   br i1 %tmp100, label %unwind_out, label %iter
 
 iter:                                             ; preds = %loop_body
@@ -268,21 +264,21 @@ define void @test1(ptr %b, ptr %c) personality ptr @__CxxFrameHandler3 {
 ; CHECK:       for.cond:
 ; CHECK-NEXT:    [[D_0:%.*]] = phi ptr [ [[B:%.*]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR:%.*]], [[FOR_INC:%.*]] ]
 ; CHECK-NEXT:    invoke void @external(ptr [[D_0]])
-; CHECK-NEXT:    to label [[FOR_INC]] unwind label [[CATCH_DISPATCH:%.*]]
+; CHECK-NEXT:            to label [[FOR_INC]] unwind label [[CATCH_DISPATCH:%.*]]
 ; CHECK:       for.inc:
 ; CHECK-NEXT:    [[INCDEC_PTR]] = getelementptr inbounds i32, ptr [[D_0]], i32 1
 ; CHECK-NEXT:    br label [[FOR_COND]]
 ; CHECK:       catch.dispatch:
-; CHECK-NEXT:    [[CS:%.*]] = catchswitch within none [label %catch] unwind label [[CATCH_DISPATCH_2:%.*]]
+; CHECK-NEXT:    [[CS:%.*]] = catchswitch within none [label [[CATCH:%.*]]] unwind label [[CATCH_DISPATCH_2:%.*]]
 ; CHECK:       catch:
 ; CHECK-NEXT:    [[TMP0:%.*]] = catchpad within [[CS]] [ptr null, i32 64, ptr null]
 ; CHECK-NEXT:    catchret from [[TMP0]] to label [[TRY_CONT:%.*]]
 ; CHECK:       try.cont:
 ; CHECK-NEXT:    invoke void @external(ptr [[C:%.*]])
-; CHECK-NEXT:    to label [[TRY_CONT_7:%.*]] unwind label [[CATCH_DISPATCH_2]]
+; CHECK-NEXT:            to label [[TRY_CONT_7:%.*]] unwind label [[CATCH_DISPATCH_2]]
 ; CHECK:       catch.dispatch.2:
 ; CHECK-NEXT:    [[E_0:%.*]] = phi ptr [ [[C]], [[TRY_CONT]] ], [ [[B]], [[CATCH_DISPATCH]] ]
-; CHECK-NEXT:    [[CS2:%.*]] = catchswitch within none [label %catch.4] unwind to caller
+; CHECK-NEXT:    [[CS2:%.*]] = catchswitch within none [label [[CATCH_4:%.*]]] unwind to caller
 ; CHECK:       catch.4:
 ; CHECK-NEXT:    [[TMP1:%.*]] = catchpad within [[CS2]] [ptr null, i32 64, ptr null]
 ; CHECK-NEXT:    unreachable
@@ -331,9 +327,9 @@ define i32 @test2() personality ptr @_except_handler3 {
 ; CHECK:       for.body:
 ; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ]
 ; CHECK-NEXT:    invoke void @reserve()
-; CHECK-NEXT:    to label [[FOR_INC]] unwind label [[CATCH_DISPATCH:%.*]]
+; CHECK-NEXT:            to label [[FOR_INC]] unwind label [[CATCH_DISPATCH:%.*]]
 ; CHECK:       catch.dispatch:
-; CHECK-NEXT:    [[TMP18:%.*]] = catchswitch within none [label %catch.handler] unwind to caller
+; CHECK-NEXT:    [[TMP18:%.*]] = catchswitch within none [label [[CATCH_HANDLER:%.*]]] unwind to caller
 ; CHECK:       catch.handler:
 ; CHECK-NEXT:    [[PHI_LCSSA:%.*]] = phi i32 [ [[PHI]], [[CATCH_DISPATCH]] ]
 ; CHECK-NEXT:    [[TMP19:%.*]] = catchpad within [[TMP18]] [ptr null]

>From f0c1e4d9ebfc47a77ecfe6db654fa17cde994588 Mon Sep 17 00:00:00 2001
From: Timur Golubovich <timur.golubovich at intel.com>
Date: Tue, 19 May 2026 23:24:20 +0200
Subject: [PATCH 2/4] [LSR] Reuse identical casts and instructions across
 fixups

When multiple LSR fixups for the same use produce identical casts or
instructions (e.g., ICmpZero fixups sharing one IV), avoid creating
duplicates by reusing existing dominating instances.
---
 .../Transforms/Scalar/LoopStrengthReduce.cpp  | 113 ++++++++++++++++--
 .../LoopStrengthReduce/lsr-reuse-instrs.ll    |  63 ++++++++++
 2 files changed, 169 insertions(+), 7 deletions(-)
 create mode 100644 llvm/test/Transforms/LoopStrengthReduce/lsr-reuse-instrs.ll

diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index 444372ab2ddfc..7f1aae885812f 100644
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -2228,6 +2228,15 @@ class LSRInstance {
   // instructions to form LCSSA for them later.
   SmallSetVector<Instruction *, 4> InsertedNonLCSSAInsts;
 
+  // Track instructions rewritten by Rewrite() to CSE identical ones that arise
+  // when multiple fixups for the same LSRUse end up with the same operands
+  // (e.g. duplicate icmp instructions in ICmpZero fixups sharing one IV).
+  SmallVector<Instruction *, 8> RewrittenInsts;
+
+  // Track casts inserted during ImplementSolution so that getOrCreateCast()
+  // can reuse a dominating cast or become such one.
+  mutable DenseMap<Value *, SmallVector<CastInst *, 2>> InsertedCasts;
+
   void OptimizeShadowIV();
   bool FindIVUserForCond(Instruction *Cond, IVStrideUse *&CondUse);
   Instruction *OptimizeMax(ICmpInst *Cond, IVStrideUse *&CondUse);
@@ -2314,6 +2323,9 @@ class LSRInstance {
                                                      const LSRFixup &LF,
                                                      const LSRUse &LU) const;
 
+  CastInst *getOrCreateCast(Instruction::CastOps Op, Value *V, Type *Ty,
+                            const Twine &Name, BasicBlock::iterator IP) const;
+
   Value *Expand(const LSRUse &LU, const LSRFixup &LF, const Formula &F,
                 BasicBlock::iterator IP,
                 SmallVectorImpl<WeakTrackingVH> &DeadInsts) const;
@@ -5732,6 +5744,46 @@ BasicBlock::iterator LSRInstance::AdjustInsertPositionForExpand(
   return IP;
 }
 
+/// Return a cast of V to Ty with opcode Op inserted before IP, reusing a
+/// previously inserted cast when possible.  If an existing cast does not
+/// dominate IP but IP dominates the cast, the cast is moved earlier so it
+/// dominates both.  This deduplicates casts that arise when multiple ICmpZero
+/// fixups share the same IV value.
+CastInst *LSRInstance::getOrCreateCast(Instruction::CastOps Op, Value *V,
+                                       Type *Ty, const Twine &Name,
+                                       BasicBlock::iterator IP) const {
+  auto It = InsertedCasts.find(V);
+  if (It != InsertedCasts.end()) {
+    CastInst *MovableC = nullptr;
+    for (CastInst *C : It->second) {
+      if (C->getOpcode() != Op || C->getType() != Ty)
+        continue;
+      // Prefer a cast that already dominates - no move needed.
+      if (DT.dominates(C, &*IP)) {
+        LLVM_DEBUG(dbgs() << "getOrCreateCast reusing (" << *C << ")\n");
+        return C;
+      }
+      // Remember the first cast we could move to IP.
+      if (!MovableC && DT.dominates(&*IP, C))
+        MovableC = C;
+    }
+    // No dominating cast found - move the first movable one to IP.
+    if (MovableC) {
+      assert(
+          (!isa<Instruction>(V) || DT.dominates(cast<Instruction>(V), &*IP)) &&
+          "Cast operand must dominate the new insertion point");
+      MovableC->moveBefore(*IP->getParent(), IP);
+      LLVM_DEBUG(dbgs() << "getOrCreateCast moved and reusing (" << *MovableC
+                        << ")\n");
+      return MovableC;
+    }
+  }
+  CastInst *C = CastInst::Create(Op, V, Ty, Name, IP);
+  LLVM_DEBUG(dbgs() << "getOrCreateCast created (" << *C << ")\n");
+  InsertedCasts[V].push_back(C);
+  return C;
+}
+
 /// Emit instructions for the leading candidate expression for this LSRUse (this
 /// is called "expanding").
 Value *LSRInstance::Expand(const LSRUse &LU, const LSRFixup &LF,
@@ -5890,7 +5942,7 @@ Value *LSRInstance::Expand(const LSRUse &LU, const LSRFixup &LF,
                            "a scale at the same time!");
     if (F.Scale == -1) {
       if (ICmpScaledV->getType() != OpTy) {
-        Instruction *Cast = CastInst::Create(
+        Instruction *Cast = getOrCreateCast(
             CastInst::getCastOpcode(ICmpScaledV, false, OpTy, false),
             ICmpScaledV, OpTy, "tmp", CI->getIterator());
         ICmpScaledV = Cast;
@@ -5989,7 +6041,7 @@ void LSRInstance::RewriteForPHI(PHINode *PN, const LSRUse &LU,
         // If this is reuse-by-noop-cast, insert the noop cast.
         Type *OpTy = LF.OperandValToReplace->getType();
         if (FullV->getType() != OpTy)
-          FullV = CastInst::Create(
+          FullV = getOrCreateCast(
               CastInst::getCastOpcode(FullV, false, OpTy, false), FullV,
               LF.OperandValToReplace->getType(), "tmp",
               BB->getTerminator()->getIterator());
@@ -6062,8 +6114,8 @@ void LSRInstance::Rewrite(const LSRUse &LU, const LSRFixup &LF,
     Type *OpTy = LF.OperandValToReplace->getType();
     if (FullV->getType() != OpTy) {
       Instruction *Cast =
-          CastInst::Create(CastInst::getCastOpcode(FullV, false, OpTy, false),
-                           FullV, OpTy, "tmp", LF.UserInst->getIterator());
+          getOrCreateCast(CastInst::getCastOpcode(FullV, false, OpTy, false),
+                          FullV, OpTy, "tmp", LF.UserInst->getIterator());
       FullV = Cast;
     }
 
@@ -6076,6 +6128,28 @@ void LSRInstance::Rewrite(const LSRUse &LU, const LSRFixup &LF,
       LF.UserInst->setOperand(0, FullV);
     else
       LF.UserInst->replaceUsesOfWith(LF.OperandValToReplace, FullV);
+
+    // If this rewritten instruction is identical to one we already
+    // rewrote (same opcode and operands), replace it with the earlier one.
+    bool ReplacedWithPrev = false;
+    for (Instruction *Prev : RewrittenInsts) {
+      if (LU.Kind != LSRUse::ICmpZero && LU.Kind != LSRUse::Basic)
+        continue;
+
+      if (!LF.UserInst->isIdenticalTo(Prev) || !DT.dominates(Prev, LF.UserInst))
+        continue;
+
+      if (IVIncInsertPos == LF.UserInst)
+        IVIncInsertPos = Prev;
+      LLVM_DEBUG(dbgs() << "replaced (" << *LF.UserInst << ") with (" << *Prev
+                        << ")\n");
+      LF.UserInst->replaceAllUsesWith(Prev);
+      DeadInsts.emplace_back(LF.UserInst);
+      ReplacedWithPrev = true;
+      break;
+    }
+    if (!ReplacedWithPrev)
+      RewrittenInsts.push_back(LF.UserInst);
   }
 
   if (auto *OperandIsInstr = dyn_cast<Instruction>(LF.OperandValToReplace))
@@ -6152,9 +6226,6 @@ void LSRInstance::ImplementSolution(
   // instructions.
   Rewriter.clear();
 
-  Changed |= RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadInsts,
-                                                                  &TLI, MSSAU);
-
   // In our cost analysis above, we assume that each addrec consumes exactly
   // one register, and arrange to have increments inserted just before the
   // latch to maximimize the chance this is true.  However, if we reused
@@ -6197,7 +6268,35 @@ void LSRInstance::ImplementSolution(
     Changed = true;
   }
 
+  // Simplify only the rewritten instructions and their immediate users.
+  // Placed after IV inc hoisting to avoid erasing instructions still
+  // referenced by the hoisting logic.
+  SmallVector<Instruction *> Worklist;
+  llvm::copy_if(RewrittenInsts, std::back_inserter(Worklist),
+                [](Instruction *I) { return I->getParent(); });
 
+  SmallPtrSet<Instruction *, 16> Visited;
+  while (!Worklist.empty()) {
+    auto *I = cast<Instruction>(Worklist.pop_back_val());
+    if (!Visited.insert(I).second)
+      continue;
+
+    // Don't simplify instructions outside the loop.
+    if (!L->contains(I))
+      continue;
+
+    Value *Res = simplifyInstruction(I, {I->getDataLayout(), &TLI, &DT, &AC});
+    if (Res && LI.replacementPreservesLCSSAForm(I, Res)) {
+      for (User *U : I->users())
+        Worklist.push_back(cast<Instruction>(U));
+      I->replaceAllUsesWith(Res);
+      DeadInsts.emplace_back(I);
+      Changed = true;
+    }
+  }
+
+  Changed |= RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadInsts,
+                                                                  &TLI, MSSAU);
 }
 
 LSRInstance::LSRInstance(Loop *L, IVUsers &IU, ScalarEvolution &SE,
diff --git a/llvm/test/Transforms/LoopStrengthReduce/lsr-reuse-instrs.ll b/llvm/test/Transforms/LoopStrengthReduce/lsr-reuse-instrs.ll
new file mode 100644
index 0000000000000..8bbf615dd1a3a
--- /dev/null
+++ b/llvm/test/Transforms/LoopStrengthReduce/lsr-reuse-instrs.ll
@@ -0,0 +1,63 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=loop-reduce -S %s | FileCheck %s
+;
+; Verify that LSR's getOrCreateCast reuses/moves a single inttoptr cast when
+; multiple ICmpZero fixups in different blocks need the same cast, and that
+; identical icmp instructions produced by different fixups are CSE'd.
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @bfv_multiply(ptr %base1, ptr %base2, ptr %base3, i64 %n) {
+; CHECK-LABEL: @bfv_multiply(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = shl nsw i64 [[N:%.*]], 3
+; CHECK-NEXT:    [[TMP1:%.*]] = inttoptr i64 [[TMP0]] to ptr
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[LOOP_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[BASE1:%.*]], i64 [[LSR_IV]]
+; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[BASE3:%.*]], i64 [[LSR_IV]]
+; CHECK-NEXT:    [[TMP:%.*]] = inttoptr i64 [[LSR_IV]] to ptr
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq ptr [[TMP1]], [[TMP]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[LOOP_CHECK:%.*]], label [[LOOP_BODY]]
+; CHECK:       loop.check:
+; CHECK-NEXT:    br i1 false, label [[LOOP_BODY]], label [[EXIT:%.*]]
+; CHECK:       loop.body:
+; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[SCEVGEP]], align 8
+; CHECK-NEXT:    store i64 [[VAL]], ptr [[SCEVGEP1]], align 8
+; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], 8
+; CHECK-NEXT:    br label [[LOOP]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %limit1 = getelementptr inbounds i64, ptr %base1, i64 %n
+  %limit2 = getelementptr inbounds i64, ptr %base2, i64 %n
+  %limit3 = getelementptr inbounds i64, ptr %base3, i64 %n
+  br label %loop
+
+loop:
+  %iv1 = phi ptr [ %base1, %entry ], [ %iv1.next, %loop.body ]
+  %iv2 = phi ptr [ %base2, %entry ], [ %iv2.next, %loop.body ]
+  %iv3 = phi ptr [ %base3, %entry ], [ %iv3.next, %loop.body ]
+  %cmp1 = icmp eq ptr %iv2, %limit2
+  br i1 %cmp1, label %loop.check, label %loop.body
+
+loop.check:
+  %cmp2 = icmp ne ptr %iv1, %limit1
+  %cmp3 = icmp ne ptr %iv3, %limit3
+  %or = select i1 %cmp2, i1 true, i1 %cmp3
+  br i1 %or, label %loop.body, label %exit
+
+loop.body:
+  %val = load i64, ptr %iv1, align 8
+  store i64 %val, ptr %iv3, align 8
+  %iv1.next = getelementptr inbounds i64, ptr %iv1, i64 1
+  %iv2.next = getelementptr inbounds i64, ptr %iv2, i64 1
+  %iv3.next = getelementptr inbounds i64, ptr %iv3, i64 1
+  br label %loop
+
+exit:
+  ret void
+}

>From 6509f66b51cc4533b95b93b2b1e7a8421137cb86 Mon Sep 17 00:00:00 2001
From: Timur Golubovich <timur.golubovich at intel.com>
Date: Wed, 3 Jun 2026 21:06:58 +0200
Subject: [PATCH 3/4] [LSR] Updated X86 and middle-end tests

---
 .../test/CodeGen/X86/apx/check-nf-in-suppress-reloc-pass.ll | 4 +---
 .../Transforms/LoopStrengthReduce/X86/2012-01-13-phielim.ll | 6 +-----
 .../Transforms/LoopStrengthReduce/lsr-rewrite-to-add-one.ll | 3 +--
 .../LoopStrengthReduce/post-increment-insertion.ll          | 4 ++--
 .../test/Transforms/LoopStrengthReduce/wrong-hoisting-iv.ll | 2 --
 5 files changed, 5 insertions(+), 14 deletions(-)

diff --git a/llvm/test/CodeGen/X86/apx/check-nf-in-suppress-reloc-pass.ll b/llvm/test/CodeGen/X86/apx/check-nf-in-suppress-reloc-pass.ll
index 3a2c954e37077..0f816aae8e0e2 100644
--- a/llvm/test/CodeGen/X86/apx/check-nf-in-suppress-reloc-pass.ll
+++ b/llvm/test/CodeGen/X86/apx/check-nf-in-suppress-reloc-pass.ll
@@ -38,10 +38,8 @@ define fastcc void @foo(i32 %0, i1 %or.cond) nounwind {
 ; CHECK-NEXT:    je .LBB0_3
 ; CHECK-NEXT:  # %bb.2: # %if.then37
 ; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    movq %r15, %rax
-; CHECK-NEXT:    addq %rbp, %rax
 ; CHECK-NEXT:    movq 0, %rax
-; CHECK-NEXT:    {nf} addq %r15, %rax
+; CHECK-NEXT:    addq %r15, %rax
 ; CHECK-NEXT:    movb $0, (%rbp,%rax)
 ; CHECK-NEXT:    jmp .LBB0_3
 entry:
diff --git a/llvm/test/Transforms/LoopStrengthReduce/X86/2012-01-13-phielim.ll b/llvm/test/Transforms/LoopStrengthReduce/X86/2012-01-13-phielim.ll
index f780bee7874cf..6d49ab7927154 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/X86/2012-01-13-phielim.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/X86/2012-01-13-phielim.ll
@@ -156,10 +156,8 @@ define fastcc void @test3(ptr nocapture %u, i1 %arg) nounwind uwtable ssp {
 ; CHECK:       for.inc8.us.i:
 ; CHECK-NEXT:    br i1 [[ARG]], label [[MESHBB1_LOOPEXIT:%.*]], label [[MESHBB:%.*]]
 ; CHECK:       for.body3.us.i:
-; CHECK-NEXT:    [[TMP:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[MESHBB]] ], [ [[TMP3:%.*]], [[FOR_BODY3_LR_PH_US_I:%.*]] ]
-; CHECK-NEXT:    [[SCEVGEP:%.*]] = phi ptr [ [[SCEVGEP1:%.*]], [[MESHBB]] ], [ [[U:%.*]], [[FOR_BODY3_LR_PH_US_I]] ]
+; CHECK-NEXT:    [[SCEVGEP:%.*]] = phi ptr [ [[SCEVGEP1:%.*]], [[MESHBB]] ], [ [[U:%.*]], [[FOR_BODY3_LR_PH_US_I:%.*]] ]
 ; CHECK-NEXT:    [[OPQ_SA_CALC12:%.*]] = sub i32 undef, 227
-; CHECK-NEXT:    [[MUL_I_US_I:%.*]] = mul nsw i32 0, [[TMP]]
 ; CHECK-NEXT:    [[TMP2:%.*]] = load double, ptr [[SCEVGEP]], align 8
 ; CHECK-NEXT:    br i1 [[ARG]], label [[FOR_INC8_US_I:%.*]], label [[MESHBB]]
 ; CHECK:       for.body3.lr.ph.us.i.loopexit:
@@ -168,7 +166,6 @@ define fastcc void @test3(ptr nocapture %u, i1 %arg) nounwind uwtable ssp {
 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ undef, [[MESHBB1]] ], [ [[INDVARS_IV8_I_SV_PHI24:%.*]], [[FOR_BODY3_LR_PH_US_I_LOOPEXIT:%.*]] ]
 ; CHECK-NEXT:    [[ARRAYIDX_US_I:%.*]] = getelementptr inbounds double, ptr undef, i64 [[LSR_IV]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[LSR_IV]], 1
-; CHECK-NEXT:    [[TMP3]] = trunc i64 [[LSR_IV]] to i32
 ; CHECK-NEXT:    br label [[FOR_BODY3_US_I:%.*]]
 ; CHECK:       for.inc8.us.i2:
 ; CHECK-NEXT:    unreachable
@@ -178,7 +175,6 @@ define fastcc void @test3(ptr nocapture %u, i1 %arg) nounwind uwtable ssp {
 ; CHECK-NEXT:    [[INDVARS_IV8_I_SV_PHI24]] = phi i64 [ undef, [[FOR_BODY3_US_I]] ], [ [[TMP1]], [[FOR_INC8_US_I]] ]
 ; CHECK-NEXT:    [[MESHSTACKVARIABLE_PHI:%.*]] = phi i32 [ [[OPQ_SA_CALC12]], [[FOR_BODY3_US_I]] ], [ undef, [[FOR_INC8_US_I]] ]
 ; CHECK-NEXT:    [[SCEVGEP1]] = getelementptr i8, ptr [[SCEVGEP]], i64 8
-; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i32 [[TMP]], 1
 ; CHECK-NEXT:    br i1 [[ARG]], label [[FOR_BODY3_LR_PH_US_I_LOOPEXIT]], label [[FOR_BODY3_US_I]]
 ; CHECK:       meshBB1.loopexit:
 ; CHECK-NEXT:    br label [[MESHBB1]]
diff --git a/llvm/test/Transforms/LoopStrengthReduce/lsr-rewrite-to-add-one.ll b/llvm/test/Transforms/LoopStrengthReduce/lsr-rewrite-to-add-one.ll
index d66905ae26f14..e5145eaa0443e 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/lsr-rewrite-to-add-one.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/lsr-rewrite-to-add-one.ll
@@ -20,8 +20,7 @@ define i32 @test(i1 %c.1, ptr %src) {
 ; CHECK-NEXT:    [[OR:%.*]] = or i1 [[P]], [[T]]
 ; CHECK-NEXT:    [[ZEXT_OR:%.*]] = zext i1 [[OR]] to i32
 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nuw i32 [[LSR_IV]], 1
-; CHECK-NEXT:    [[LOOP_HEADER_TERMCOND:%.*]] = icmp sgt i32 [[LSR_IV]], -1050
-; CHECK-NEXT:    br i1 [[LOOP_HEADER_TERMCOND]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
+; CHECK-NEXT:    br i1 [[T]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    [[ZEXT_OR_LCSSA:%.*]] = phi i32 [ [[ZEXT_OR]], [[LOOP_LATCH]] ]
 ; CHECK-NEXT:    ret i32 [[ZEXT_OR_LCSSA]]
diff --git a/llvm/test/Transforms/LoopStrengthReduce/post-increment-insertion.ll b/llvm/test/Transforms/LoopStrengthReduce/post-increment-insertion.ll
index d8861f44cabfd..a431e028fa9c9 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/post-increment-insertion.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/post-increment-insertion.ll
@@ -13,6 +13,7 @@ define i32 @test_01(ptr %p, i64 %len, i32 %x) {
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], -1
 ; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
 ; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
 ; CHECK:       backedge:
@@ -20,7 +21,6 @@ define i32 @test_01(ptr %p, i64 %len, i32 %x) {
 ; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[SCEVGEP]], i64 [[TMP0]]
 ; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, ptr [[SCEVGEP1]] unordered, align 4
 ; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
-; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], -1
 ; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret i32 -1
@@ -148,6 +148,7 @@ define i32 @test_04(ptr %p, i64 %len, i32 %x) {
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[IV_NEXT]] = sub i64 [[IV]], 1
 ; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
 ; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
 ; CHECK:       backedge:
@@ -155,7 +156,6 @@ define i32 @test_04(ptr %p, i64 %len, i32 %x) {
 ; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[SCEVGEP]], i64 [[TMP0]]
 ; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, ptr [[SCEVGEP1]] unordered, align 4
 ; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
-; CHECK-NEXT:    [[IV_NEXT]] = sub i64 [[IV]], 1
 ; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret i32 -1
diff --git a/llvm/test/Transforms/LoopStrengthReduce/wrong-hoisting-iv.ll b/llvm/test/Transforms/LoopStrengthReduce/wrong-hoisting-iv.ll
index 007d84f9120e3..e48d405ea3804 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/wrong-hoisting-iv.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/wrong-hoisting-iv.ll
@@ -199,9 +199,7 @@ define void @test2() {
 ; CHECK:       bb11:
 ; CHECK-NEXT:    unreachable
 ; CHECK:       bb12:
-; CHECK-NEXT:    [[VAL14:%.*]] = add i32 [[VAL8]], [[VAL1]]
 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[VAL1]], [[VAL8]]
-; CHECK-NEXT:    [[VAL15:%.*]] = select i1 false, i32 [[VAL14]], i32 [[VAL8]]
 ; CHECK-NEXT:    [[VAL16]] = add i32 [[TMP0]], 1
 ; CHECK-NEXT:    [[VAL17:%.*]] = fcmp olt double 0.000000e+00, 2.270000e+02
 ; CHECK-NEXT:    br i1 [[VAL17]], label [[BB6]], label [[BB4:%.*]]

>From 49f3957a1ebd23947a15190437dba756bf535439 Mon Sep 17 00:00:00 2001
From: Timur Golubovich <timur.golubovich at intel.com>
Date: Fri, 5 Jun 2026 14:56:32 +0200
Subject: [PATCH 4/4] [LSR] Updated rest of tests

---
 llvm/test/CodeGen/ARM/mbp.ll                  |  8 +-
 llvm/test/CodeGen/AVR/bug-81911.ll            | 39 ++++----
 llvm/test/CodeGen/Hexagon/loop_correctness.ll | 12 ---
 llvm/test/CodeGen/RISCV/memset-pattern.ll     | 90 +++++++------------
 llvm/test/CodeGen/WebAssembly/cfg-stackify.ll | 15 +---
 5 files changed, 57 insertions(+), 107 deletions(-)

diff --git a/llvm/test/CodeGen/ARM/mbp.ll b/llvm/test/CodeGen/ARM/mbp.ll
index 4f96029e06b95..1204bd9e8f87e 100644
--- a/llvm/test/CodeGen/ARM/mbp.ll
+++ b/llvm/test/CodeGen/ARM/mbp.ll
@@ -40,14 +40,14 @@ define i1 @foo(ptr %ha, i32 %he) !prof !39 {
 ; CHECK-NEXT:  .LBB0_5: @ %for.cond.i
 ; CHECK-NEXT:    @ Parent Loop BB0_3 Depth=1
 ; CHECK-NEXT:    @ => This Inner Loop Header: Depth=2
-; CHECK-NEXT:    cmp r3, #1
+; CHECK-NEXT:    subs.w lr, r3, #1
 ; CHECK-NEXT:    blt .LBB0_2
 ; CHECK-NEXT:  @ %bb.6: @ %for.body.i
 ; CHECK-NEXT:    @ in Loop: Header=BB0_5 Depth=2
-; CHECK-NEXT:    ldr.w lr, [r12, r3, lsl #2]
-; CHECK-NEXT:    subs r3, #1
+; CHECK-NEXT:    ldr.w r3, [r12, r3, lsl #2]
 ; CHECK-NEXT:    movs r0, #1
-; CHECK-NEXT:    cmp lr, r1
+; CHECK-NEXT:    cmp r3, r1
+; CHECK-NEXT:    mov r3, lr
 ; CHECK-NEXT:    bne .LBB0_5
 ; CHECK-NEXT:  @ %bb.7:
 ; CHECK-NEXT:    pop {r7, pc}
diff --git a/llvm/test/CodeGen/AVR/bug-81911.ll b/llvm/test/CodeGen/AVR/bug-81911.ll
index 2a22666a1ff92..36af379467bf3 100644
--- a/llvm/test/CodeGen/AVR/bug-81911.ll
+++ b/llvm/test/CodeGen/AVR/bug-81911.ll
@@ -24,7 +24,7 @@ define internal i8 @main() {
 ; CHECK-NEXT:    push r29
 ; CHECK-NEXT:    in r28, 61
 ; CHECK-NEXT:    in r29, 62
-; CHECK-NEXT:    sbiw r28, 13
+; CHECK-NEXT:    sbiw r28, 12
 ; CHECK-NEXT:    in r0, 63
 ; CHECK-NEXT:    cli
 ; CHECK-NEXT:    out 62, r29
@@ -32,13 +32,12 @@ define internal i8 @main() {
 ; CHECK-NEXT:    out 61, r28
 ; CHECK-NEXT:    ldi r16, 0
 ; CHECK-NEXT:    ldi r17, 0
-; CHECK-NEXT:    ldi r18, -1
 ; CHECK-NEXT:    ;APP
 ; CHECK-NEXT:    ldi r24, 123
 ; CHECK-NEXT:    ;NO_APP
 ; CHECK-NEXT:    std Y+1, r24 ; 1-byte Folded Spill
 ; CHECK-NEXT:    movw r24, r28
-; CHECK-NEXT:    adiw r24, 6
+; CHECK-NEXT:    adiw r24, 5
 ; CHECK-NEXT:    std Y+3, r25 ; 2-byte Folded Spill
 ; CHECK-NEXT:    std Y+2, r24 ; 2-byte Folded Spill
 ; CHECK-NEXT:    movw r8, r16
@@ -49,37 +48,33 @@ define internal i8 @main() {
 ; CHECK-NEXT:  .LBB0_1: ; %bb1
 ; CHECK-NEXT:    ; in Loop: Header=BB0_2 Depth=1
 ; CHECK-NEXT:    andi r30, 1
-; CHECK-NEXT:    ldd r31, Y+4 ; 1-byte Folded Reload
-; CHECK-NEXT:    dec r31
 ; CHECK-NEXT:    cpi r30, 0
 ; CHECK-NEXT:    movw r8, r18
 ; CHECK-NEXT:    movw r6, r20
 ; CHECK-NEXT:    movw r4, r22
 ; CHECK-NEXT:    movw r2, r24
-; CHECK-NEXT:    mov r18, r31
 ; CHECK-NEXT:    brne .LBB0_2
 ; CHECK-NEXT:    rjmp .LBB0_4
 ; CHECK-NEXT:  .LBB0_2: ; %bb1
 ; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
-; CHECK-NEXT:    std Y+4, r18 ; 1-byte Folded Spill
 ; CHECK-NEXT:    movw r18, r8
 ; CHECK-NEXT:    movw r20, r6
 ; CHECK-NEXT:    movw r22, r4
 ; CHECK-NEXT:    movw r24, r2
-; CHECK-NEXT:    ldi r26, 10
-; CHECK-NEXT:    ldi r27, 0
-; CHECK-NEXT:    movw r10, r26
+; CHECK-NEXT:    ldi r30, 10
+; CHECK-NEXT:    ldi r31, 0
+; CHECK-NEXT:    movw r10, r30
 ; CHECK-NEXT:    movw r12, r16
 ; CHECK-NEXT:    movw r14, r16
 ; CHECK-NEXT:    call __udivdi3
-; CHECK-NEXT:    std Y+13, r25
-; CHECK-NEXT:    std Y+12, r24
-; CHECK-NEXT:    std Y+11, r23
-; CHECK-NEXT:    std Y+10, r22
-; CHECK-NEXT:    std Y+9, r21
-; CHECK-NEXT:    std Y+8, r20
-; CHECK-NEXT:    std Y+7, r19
-; CHECK-NEXT:    std Y+6, r18
+; CHECK-NEXT:    std Y+12, r25
+; CHECK-NEXT:    std Y+11, r24
+; CHECK-NEXT:    std Y+10, r23
+; CHECK-NEXT:    std Y+9, r22
+; CHECK-NEXT:    std Y+8, r21
+; CHECK-NEXT:    std Y+7, r20
+; CHECK-NEXT:    std Y+6, r19
+; CHECK-NEXT:    std Y+5, r18
 ; CHECK-NEXT:    ldd r30, Y+2 ; 2-byte Folded Reload
 ; CHECK-NEXT:    ldd r31, Y+3 ; 2-byte Folded Reload
 ; CHECK-NEXT:    ;APP
@@ -101,13 +96,13 @@ define internal i8 @main() {
 ; CHECK-NEXT:    rjmp .LBB0_1
 ; CHECK-NEXT:  .LBB0_4: ; %bb3
 ; CHECK-NEXT:    ldd r24, Y+1 ; 1-byte Folded Reload
-; CHECK-NEXT:    std Y+5, r24
+; CHECK-NEXT:    std Y+4, r24
 ; CHECK-NEXT:    movw r24, r28
-; CHECK-NEXT:    adiw r24, 5
+; CHECK-NEXT:    adiw r24, 4
 ; CHECK-NEXT:    ;APP
 ; CHECK-NEXT:    ;NO_APP
-; CHECK-NEXT:    ldd r24, Y+5
-; CHECK-NEXT:    adiw r28, 13
+; CHECK-NEXT:    ldd r24, Y+4
+; CHECK-NEXT:    adiw r28, 12
 ; CHECK-NEXT:    in r0, 63
 ; CHECK-NEXT:    cli
 ; CHECK-NEXT:    out 62, r29
diff --git a/llvm/test/CodeGen/Hexagon/loop_correctness.ll b/llvm/test/CodeGen/Hexagon/loop_correctness.ll
index 08e563942fd20..14cfeae49528a 100644
--- a/llvm/test/CodeGen/Hexagon/loop_correctness.ll
+++ b/llvm/test/CodeGen/Hexagon/loop_correctness.ll
@@ -73,18 +73,6 @@ define void @f2(ptr nocapture %a0, i32 %a1, i32 %a2) #0 {
 ; CHECK-LABEL: f2:
 ; CHECK:       // %bb.0: // %b0
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     loop0(.LBB2_1,#1)
-; CHECK-NEXT:    }
-; CHECK-NEXT:    .p2align 4
-; CHECK-NEXT:  .LBB2_1: // Block address taken
-; CHECK-NEXT:    // %b2
-; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
-; CHECK-NEXT:    {
-; CHECK-NEXT:     nop
-; CHECK-NEXT:     nop
-; CHECK-NEXT:    } :endloop0
-; CHECK-NEXT:  // %bb.2: // %b3
-; CHECK-NEXT:    {
 ; CHECK-NEXT:     jumpr r31
 ; CHECK-NEXT:    }
 b0:
diff --git a/llvm/test/CodeGen/RISCV/memset-pattern.ll b/llvm/test/CodeGen/RISCV/memset-pattern.ll
index cfc61144634b1..778b2d6c9ee05 100644
--- a/llvm/test/CodeGen/RISCV/memset-pattern.ll
+++ b/llvm/test/CodeGen/RISCV/memset-pattern.ll
@@ -37,15 +37,9 @@ define void @memset_1(ptr %a, i128 %value) nounwind {
 ; RV32-BOTH-NEXT:    ret
 ;
 ; RV64-BOTH-LABEL: memset_1:
-; RV64-BOTH:       # %bb.0:
-; RV64-BOTH-NEXT:    addi a3, a0, 16
-; RV64-BOTH-NEXT:  .LBB0_1: # %memset.pattern-expansion-main-body
-; RV64-BOTH-NEXT:    # =>This Inner Loop Header: Depth=1
+; RV64-BOTH:       # %bb.0: # %memset.pattern-expansion-main-body
 ; RV64-BOTH-NEXT:    sd a1, 0(a0)
 ; RV64-BOTH-NEXT:    sd a2, 8(a0)
-; RV64-BOTH-NEXT:    addi a0, a0, 16
-; RV64-BOTH-NEXT:    bne a0, a3, .LBB0_1
-; RV64-BOTH-NEXT:  # %bb.2: # %memset.pattern-post-expansion
 ; RV64-BOTH-NEXT:    ret
   tail call void @llvm.experimental.memset.pattern(ptr align 8 %a, i128 %value, i64 1, i1 0)
   ret void
@@ -115,51 +109,37 @@ define void @memset_1_noalign(ptr %a, i128 %value) nounwind {
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: memset_1_noalign:
-; RV64:       # %bb.0:
-; RV64-NEXT:    addi sp, sp, -32
-; RV64-NEXT:    sd s0, 24(sp) # 8-byte Folded Spill
-; RV64-NEXT:    sd s1, 16(sp) # 8-byte Folded Spill
-; RV64-NEXT:    sd s2, 8(sp) # 8-byte Folded Spill
-; RV64-NEXT:    addi a3, a0, 16
-; RV64-NEXT:    srli a4, a1, 56
-; RV64-NEXT:    srli a5, a1, 48
-; RV64-NEXT:    srli a6, a1, 40
-; RV64-NEXT:    srli a7, a1, 32
-; RV64-NEXT:    srli t0, a1, 24
-; RV64-NEXT:    srli t1, a1, 16
-; RV64-NEXT:    srli t2, a1, 8
-; RV64-NEXT:    srli t3, a2, 56
-; RV64-NEXT:    srli t4, a2, 48
-; RV64-NEXT:    srli t5, a2, 40
-; RV64-NEXT:    srli t6, a2, 32
-; RV64-NEXT:    srli s0, a2, 24
-; RV64-NEXT:    srli s1, a2, 16
-; RV64-NEXT:    srli s2, a2, 8
-; RV64-NEXT:  .LBB1_1: # %memset.pattern-expansion-main-body
-; RV64-NEXT:    # =>This Inner Loop Header: Depth=1
-; RV64-NEXT:    sb a7, 4(a0)
-; RV64-NEXT:    sb a6, 5(a0)
-; RV64-NEXT:    sb a5, 6(a0)
-; RV64-NEXT:    sb a4, 7(a0)
-; RV64-NEXT:    sb a1, 0(a0)
-; RV64-NEXT:    sb t2, 1(a0)
-; RV64-NEXT:    sb t1, 2(a0)
-; RV64-NEXT:    sb t0, 3(a0)
-; RV64-NEXT:    sb t6, 12(a0)
-; RV64-NEXT:    sb t5, 13(a0)
-; RV64-NEXT:    sb t4, 14(a0)
-; RV64-NEXT:    sb t3, 15(a0)
+; RV64:       # %bb.0: # %memset.pattern-expansion-main-body
+; RV64-NEXT:    srli a3, a2, 56
+; RV64-NEXT:    srli a4, a2, 48
+; RV64-NEXT:    srli a5, a2, 40
+; RV64-NEXT:    srli a6, a2, 32
+; RV64-NEXT:    srli a7, a2, 24
+; RV64-NEXT:    srli t0, a2, 16
+; RV64-NEXT:    srli t1, a2, 8
+; RV64-NEXT:    srli t2, a1, 56
+; RV64-NEXT:    srli t3, a1, 48
+; RV64-NEXT:    srli t4, a1, 40
+; RV64-NEXT:    srli t5, a1, 32
+; RV64-NEXT:    sb a6, 12(a0)
+; RV64-NEXT:    sb a5, 13(a0)
+; RV64-NEXT:    sb a4, 14(a0)
+; RV64-NEXT:    sb a3, 15(a0)
+; RV64-NEXT:    srli a3, a1, 24
 ; RV64-NEXT:    sb a2, 8(a0)
-; RV64-NEXT:    sb s2, 9(a0)
-; RV64-NEXT:    sb s1, 10(a0)
-; RV64-NEXT:    sb s0, 11(a0)
-; RV64-NEXT:    addi a0, a0, 16
-; RV64-NEXT:    bne a0, a3, .LBB1_1
-; RV64-NEXT:  # %bb.2: # %memset.pattern-post-expansion
-; RV64-NEXT:    ld s0, 24(sp) # 8-byte Folded Reload
-; RV64-NEXT:    ld s1, 16(sp) # 8-byte Folded Reload
-; RV64-NEXT:    ld s2, 8(sp) # 8-byte Folded Reload
-; RV64-NEXT:    addi sp, sp, 32
+; RV64-NEXT:    sb t1, 9(a0)
+; RV64-NEXT:    sb t0, 10(a0)
+; RV64-NEXT:    sb a7, 11(a0)
+; RV64-NEXT:    srli a2, a1, 16
+; RV64-NEXT:    sb t5, 4(a0)
+; RV64-NEXT:    sb t4, 5(a0)
+; RV64-NEXT:    sb t3, 6(a0)
+; RV64-NEXT:    sb t2, 7(a0)
+; RV64-NEXT:    srli a4, a1, 8
+; RV64-NEXT:    sb a1, 0(a0)
+; RV64-NEXT:    sb a4, 1(a0)
+; RV64-NEXT:    sb a2, 2(a0)
+; RV64-NEXT:    sb a3, 3(a0)
 ; RV64-NEXT:    ret
 ;
 ; RV32-FAST-LABEL: memset_1_noalign:
@@ -187,15 +167,9 @@ define void @memset_1_noalign(ptr %a, i128 %value) nounwind {
 ; RV32-FAST-NEXT:    ret
 ;
 ; RV64-FAST-LABEL: memset_1_noalign:
-; RV64-FAST:       # %bb.0:
-; RV64-FAST-NEXT:    addi a3, a0, 16
-; RV64-FAST-NEXT:  .LBB1_1: # %memset.pattern-expansion-main-body
-; RV64-FAST-NEXT:    # =>This Inner Loop Header: Depth=1
+; RV64-FAST:       # %bb.0: # %memset.pattern-expansion-main-body
 ; RV64-FAST-NEXT:    sd a1, 0(a0)
 ; RV64-FAST-NEXT:    sd a2, 8(a0)
-; RV64-FAST-NEXT:    addi a0, a0, 16
-; RV64-FAST-NEXT:    bne a0, a3, .LBB1_1
-; RV64-FAST-NEXT:  # %bb.2: # %memset.pattern-post-expansion
 ; RV64-FAST-NEXT:    ret
   tail call void @llvm.experimental.memset.pattern(ptr %a, i128 %value, i64 1, i1 0)
   ret void
diff --git a/llvm/test/CodeGen/WebAssembly/cfg-stackify.ll b/llvm/test/CodeGen/WebAssembly/cfg-stackify.ll
index c443c4ddb4729..5826899ade134 100644
--- a/llvm/test/CodeGen/WebAssembly/cfg-stackify.ll
+++ b/llvm/test/CodeGen/WebAssembly/cfg-stackify.ll
@@ -906,22 +906,15 @@ bb50:
 ; CHECK:        block
 ; CHECK-NEXT:   block
 ; CHECK:        br_if       0, $pop{{.*}}{{$}}
-; CHECK:        .LBB{{[0-9]+}}_2:
-; CHECK-NEXT:   block   {{$}}
-; CHECK-NEXT:   block   {{$}}
+; CHECK:        .LBB{{[0-9]+}}_1:
 ; CHECK-NEXT:   loop    {{$}}
-; CHECK:        br_if       1, $pop{{.*}}{{$}}
-; CHECK:        br_if       0, ${{.*}}{{$}}
-; CHECK-NEXT:   br          2{{$}}
-; CHECK-NEXT:   .LBB{{[0-9]+}}_4:
+; CHECK:        br_if       0, $pop{{.*}}{{$}}
 ; CHECK-NEXT:   end_loop{{$}}
-; CHECK:        .LBB{{[0-9]+}}_5:
-; CHECK-NEXT:   end_block{{$}}
 ; CHECK:        br_if       1, $pop{{.*}}{{$}}
 ; CHECK:        return{{$}}
-; CHECK:        .LBB{{[0-9]+}}_7:
+; CHECK:        .LBB{{[0-9]+}}_4:
 ; CHECK-NEXT:   end_block{{$}}
-; CHECK:        .LBB{{[0-9]+}}_8:
+; CHECK:        .LBB{{[0-9]+}}_5:
 ; CHECK-NEXT:   end_block{{$}}
 ; CHECK-NEXT:   return{{$}}
 %0 = type { i8, i32 }



More information about the llvm-commits mailing list