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

Timur Golubovich via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 9 04:03:54 PDT 2026


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

>From a740f51193a3b3f4da9c3c1532ceb8cb0f0e140a Mon Sep 17 00:00:00 2001
From: Timur Golubovich <timur.golubovich at intel.com>
Date: Sat, 6 Jun 2026 02:12:26 +0200
Subject: [PATCH 1/4] [LSR] Keep ICmpZero comparisons in integer domain to
 avoid inttoptr casts

When LSR expands ICmpZero fixups with pointer-typed operands, override OpTy
to the integer type so both icmp sides stay in the integer domain, eliminating
redundant inttoptr casts.
---
 .../Transforms/Scalar/LoopStrengthReduce.cpp  |  9 ++-
 llvm/test/CodeGen/X86/conditional-tailcall.ll | 15 ++--
 .../X86/lsr-icmpzero-no-inttoptr.ll           | 76 +++++++++++++++++++
 .../Transforms/LoopStrengthReduce/funclet.ll  | 44 +++++------
 .../LoopStrengthReduce/post-inc-icmpzero.ll   |  3 +-
 .../Transforms/LoopStrengthReduce/pr25541.ll  |  3 +-
 .../Transforms/LoopStrengthReduce/pr27056.ll  |  7 +-
 7 files changed, 115 insertions(+), 42 deletions(-)
 create mode 100644 llvm/test/Transforms/LoopStrengthReduce/X86/lsr-icmpzero-no-inttoptr.ll

diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index 444372ab2ddfc..ca37d33d865d6 100644
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -5751,6 +5751,10 @@ Value *LSRInstance::Expand(const LSRUse &LU, const LSRFixup &LF,
 
   // This is the type that the user actually needs.
   Type *OpTy = LF.OperandValToReplace->getType();
+  // For ICmpZero with pointer-typed operands, keep the comparison in the
+  // integer domain to avoid generating inttoptr casts.
+  if (LU.Kind == LSRUse::ICmpZero && OpTy->isPointerTy())
+    OpTy = SE.getEffectiveSCEVType(OpTy);
   // This will be the type that we'll initially expand to.
   Type *Ty = F.getType();
   if (!Ty)
@@ -6059,8 +6063,11 @@ void LSRInstance::Rewrite(const LSRUse &LU, const LSRFixup &LF,
     Value *FullV = Expand(LU, LF, F, LF.UserInst->getIterator(), DeadInsts);
 
     // If this is reuse-by-noop-cast, insert the noop cast.
+    // For ICmpZero with pointer operands, Expand() already set both operands
+    // in integer domain, so no cast is needed here.
     Type *OpTy = LF.OperandValToReplace->getType();
-    if (FullV->getType() != OpTy) {
+    if (FullV->getType() != OpTy &&
+        !(LU.Kind == LSRUse::ICmpZero && OpTy->isPointerTy())) {
       Instruction *Cast =
           CastInst::Create(CastInst::getCastOpcode(FullV, false, OpTy, false),
                            FullV, OpTy, "tmp", LF.UserInst->getIterator());
diff --git a/llvm/test/CodeGen/X86/conditional-tailcall.ll b/llvm/test/CodeGen/X86/conditional-tailcall.ll
index 2859a87db3d56..34f11af756ad0 100644
--- a/llvm/test/CodeGen/X86/conditional-tailcall.ll
+++ b/llvm/test/CodeGen/X86/conditional-tailcall.ll
@@ -261,8 +261,8 @@ define zeroext i1 @pr31257(ptr nocapture readonly dereferenceable(8) %s) minsize
 ; CHECK32-NEXT:    incl %edi # encoding: [0x47]
 ; CHECK32-NEXT:  .LBB3_1: # %for.cond
 ; CHECK32-NEXT:    # =>This Inner Loop Header: Depth=1
-; CHECK32-NEXT:    testl %edx, %edx # encoding: [0x85,0xd2]
-; CHECK32-NEXT:    je .LBB3_14 # encoding: [0x74,A]
+; CHECK32-NEXT:    subl $1, %edx # encoding: [0x83,0xea,0x01]
+; CHECK32-NEXT:    jb .LBB3_14 # encoding: [0x72,A]
 ; CHECK32-NEXT:    # fixup A - offset: 1, value: .LBB3_14, kind: FK_PCRel_1
 ; CHECK32-NEXT:  # %bb.2: # %for.body
 ; CHECK32-NEXT:    # in Loop: Header=BB3_1 Depth=1
@@ -321,7 +321,6 @@ define zeroext i1 @pr31257(ptr nocapture readonly dereferenceable(8) %s) minsize
 ; CHECK32-NEXT:  .LBB3_11: # %for.inc
 ; CHECK32-NEXT:    # in Loop: Header=BB3_1 Depth=1
 ; CHECK32-NEXT:    incl %eax # encoding: [0x40]
-; CHECK32-NEXT:    decl %edx # encoding: [0x4a]
 ; CHECK32-NEXT:    jmp .LBB3_1 # encoding: [0xeb,A]
 ; CHECK32-NEXT:    # fixup A - offset: 1, value: .LBB3_1, kind: FK_PCRel_1
 ; CHECK32-NEXT:  .LBB3_14:
@@ -376,8 +375,8 @@ define zeroext i1 @pr31257(ptr nocapture readonly dereferenceable(8) %s) minsize
 ; CHECK64-NEXT:    .cfi_adjust_cfa_offset -8
 ; CHECK64-NEXT:  .LBB3_1: # %for.cond
 ; CHECK64-NEXT:    # =>This Inner Loop Header: Depth=1
-; CHECK64-NEXT:    testq %rax, %rax # encoding: [0x48,0x85,0xc0]
-; CHECK64-NEXT:    je .LBB3_12 # encoding: [0x74,A]
+; CHECK64-NEXT:    subq $1, %rax # encoding: [0x48,0x83,0xe8,0x01]
+; CHECK64-NEXT:    jb .LBB3_12 # encoding: [0x72,A]
 ; CHECK64-NEXT:    # fixup A - offset: 1, value: .LBB3_12, kind: FK_PCRel_1
 ; CHECK64-NEXT:  # %bb.2: # %for.body
 ; CHECK64-NEXT:    # in Loop: Header=BB3_1 Depth=1
@@ -437,7 +436,6 @@ define zeroext i1 @pr31257(ptr nocapture readonly dereferenceable(8) %s) minsize
 ; CHECK64-NEXT:  .LBB3_11: # %for.inc
 ; CHECK64-NEXT:    # in Loop: Header=BB3_1 Depth=1
 ; CHECK64-NEXT:    incq %rdi # encoding: [0x48,0xff,0xc7]
-; CHECK64-NEXT:    decq %rax # encoding: [0x48,0xff,0xc8]
 ; CHECK64-NEXT:    jmp .LBB3_1 # encoding: [0xeb,A]
 ; CHECK64-NEXT:    # fixup A - offset: 1, value: .LBB3_1, kind: FK_PCRel_1
 ; CHECK64-NEXT:  .LBB3_12:
@@ -458,8 +456,8 @@ define zeroext i1 @pr31257(ptr nocapture readonly dereferenceable(8) %s) minsize
 ; WIN64-NEXT:    xorl %r8d, %r8d # encoding: [0x45,0x31,0xc0]
 ; WIN64-NEXT:  .LBB3_1: # %for.cond
 ; WIN64-NEXT:    # =>This Inner Loop Header: Depth=1
-; WIN64-NEXT:    testq %rax, %rax # encoding: [0x48,0x85,0xc0]
-; WIN64-NEXT:    je .LBB3_11 # encoding: [0x74,A]
+; WIN64-NEXT:    subq $1, %rax # encoding: [0x48,0x83,0xe8,0x01]
+; WIN64-NEXT:    jb .LBB3_11 # encoding: [0x72,A]
 ; WIN64-NEXT:    # fixup A - offset: 1, value: .LBB3_11, kind: FK_PCRel_1
 ; WIN64-NEXT:  # %bb.2: # %for.body
 ; WIN64-NEXT:    # in Loop: Header=BB3_1 Depth=1
@@ -514,7 +512,6 @@ define zeroext i1 @pr31257(ptr nocapture readonly dereferenceable(8) %s) minsize
 ; WIN64-NEXT:  .LBB3_10: # %for.inc
 ; WIN64-NEXT:    # in Loop: Header=BB3_1 Depth=1
 ; WIN64-NEXT:    incq %rcx # encoding: [0x48,0xff,0xc1]
-; WIN64-NEXT:    decq %rax # encoding: [0x48,0xff,0xc8]
 ; WIN64-NEXT:    jmp .LBB3_1 # encoding: [0xeb,A]
 ; WIN64-NEXT:    # fixup A - offset: 1, value: .LBB3_1, kind: FK_PCRel_1
 ; WIN64-NEXT:  .LBB3_11:
diff --git a/llvm/test/Transforms/LoopStrengthReduce/X86/lsr-icmpzero-no-inttoptr.ll b/llvm/test/Transforms/LoopStrengthReduce/X86/lsr-icmpzero-no-inttoptr.ll
new file mode 100644
index 0000000000000..0d6a374f86692
--- /dev/null
+++ b/llvm/test/Transforms/LoopStrengthReduce/X86/lsr-icmpzero-no-inttoptr.ll
@@ -0,0 +1,76 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=loop-reduce -S %s | FileCheck %s
+;
+; Verify that LSR keeps ICmpZero comparisons in the integer domain when the
+; original operands are pointers, avoiding inttoptr casts entirely. The loop
+; has three pointer IVs sharing the same stride; LSR should produce a single
+; integer IV and compare it directly against the precomputed bound.
+; Target-dependent because TTI must report that scaled addressing is legal.
+
+target triple = "x86_64-unknown-linux-gnu"
+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"
+
+define void @test_no_inttoptr_casts(ptr %base1, ptr %base2, ptr %base3, i64 %n) {
+; CHECK-LABEL: @test_no_inttoptr_casts(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = shl i64 [[N:%.*]], 3
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[BASE1:%.*]], i64 [[LSR_IV]]
+; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[BASE2:%.*]], i64 [[LSR_IV]]
+; CHECK-NEXT:    [[SCEVGEP2:%.*]] = getelementptr i8, ptr [[BASE3:%.*]], i64 [[LSR_IV]]
+; CHECK-NEXT:    [[CMP_EXIT:%.*]] = icmp eq i64 [[TMP0]], [[LSR_IV]]
+; CHECK-NEXT:    br i1 [[CMP_EXIT]], label [[CHECK:%.*]], label [[BODY:%.*]]
+; CHECK:       check:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i64 [[TMP0]], [[LSR_IV]]
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp ne i64 [[TMP0]], [[LSR_IV]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP3]]
+; CHECK-NEXT:    br i1 [[SEL]], label [[BODY]], label [[EXIT:%.*]]
+; CHECK:       body:
+; CHECK-NEXT:    [[V1:%.*]] = load i64, ptr [[SCEVGEP]], align 8
+; CHECK-NEXT:    [[V2:%.*]] = load i64, ptr [[SCEVGEP1]], align 8
+; CHECK-NEXT:    [[SUM:%.*]] = add i64 [[V1]], [[V2]]
+; CHECK-NEXT:    store i64 [[SUM]], ptr [[SCEVGEP2]], align 8
+; CHECK-NEXT:    br label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], 8
+; CHECK-NEXT:    br label [[LOOP]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %bound1 = getelementptr i64, ptr %base1, i64 %n
+  %bound2 = getelementptr i64, ptr %base2, i64 %n
+  %bound3 = getelementptr i64, ptr %base3, i64 %n
+  br label %loop
+
+loop:
+  %p1 = phi ptr [ %base1, %entry ], [ %p1.next, %loop.latch ]
+  %p2 = phi ptr [ %base2, %entry ], [ %p2.next, %loop.latch ]
+  %p3 = phi ptr [ %base3, %entry ], [ %p3.next, %loop.latch ]
+  %cmp.exit = icmp eq ptr %p2, %bound2
+  br i1 %cmp.exit, label %check, label %body
+
+check:
+  %cmp1 = icmp ne ptr %p1, %bound1
+  %cmp3 = icmp ne ptr %p3, %bound3
+  %sel = select i1 %cmp1, i1 true, i1 %cmp3
+  br i1 %sel, label %body, label %exit
+
+body:
+  %v1 = load i64, ptr %p1, align 8
+  %v2 = load i64, ptr %p2, align 8
+  %sum = add i64 %v1, %v2
+  store i64 %sum, ptr %p3, align 8
+  br label %loop.latch
+
+loop.latch:
+  %p1.next = getelementptr inbounds i8, ptr %p1, i64 8
+  %p2.next = getelementptr inbounds i8, ptr %p2, i64 8
+  %p3.next = getelementptr inbounds i8, ptr %p3, i64 8
+  br label %loop
+
+exit:
+  ret void
+}
diff --git a/llvm/test/Transforms/LoopStrengthReduce/funclet.ll b/llvm/test/Transforms/LoopStrengthReduce/funclet.ll
index da5721a72a906..bbcb00ccf8ba9 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/funclet.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/funclet.ll
@@ -16,9 +16,9 @@ define void @f() personality ptr @_except_handler3 {
 ; 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
@@ -28,8 +28,7 @@ define void @f() personality ptr @_except_handler3 {
 ; 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:    [[TMP100:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 0
 ; CHECK-NEXT:    br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
 ; CHECK:       iter:
 ; CHECK-NEXT:    br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
@@ -75,9 +74,9 @@ define void @g() personality ptr @_except_handler3 {
 ; 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:%.*]] = 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:    [[TMP100:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 0
 ; CHECK-NEXT:    br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
 ; CHECK:       iter:
 ; CHECK-NEXT:    br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
@@ -139,9 +137,9 @@ define void @h() personality ptr @_except_handler3 {
 ; 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:%.*]] = 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:    [[TMP100:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 0
 ; CHECK-NEXT:    br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
 ; CHECK:       iter:
 ; CHECK-NEXT:    br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
@@ -203,9 +200,9 @@ define void @i() personality ptr @_except_handler3 {
 ; 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:%.*]]
@@ -217,8 +214,7 @@ define void @i() personality ptr @_except_handler3 {
 ; 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:    [[TMP100:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 0
 ; CHECK-NEXT:    br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
 ; CHECK:       iter:
 ; CHECK-NEXT:    br i1 true, label [[UNWIND_OUT]], label [[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]
diff --git a/llvm/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll b/llvm/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll
index d0a910a0758a9..24b8b0a2417df 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll
@@ -62,9 +62,8 @@ define void @_Z15IntegerToStringjjR7Vector2(i32 %i, i32 %radix, ptr nocapture %r
 ; CHECK-NEXT:    [[INST29:%.*]] = load i16, ptr [[LSR_IV6]], align 2
 ; CHECK-NEXT:    store i16 [[INST29]], ptr [[SCEVGEP1]], align 2
 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], 2
-; CHECK-NEXT:    [[LSR_IV_NEXT2:%.*]] = inttoptr i64 [[LSR_IV_NEXT]] to ptr
 ; CHECK-NEXT:    [[SCEVGEP7]] = getelementptr i8, ptr [[LSR_IV6]], i64 2
-; CHECK-NEXT:    [[CMP27:%.*]] = icmp eq ptr [[LSR_IV_NEXT2]], null
+; CHECK-NEXT:    [[CMP27:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
 ; CHECK-NEXT:    br i1 [[CMP27]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
 ; CHECK:       for.end.loopexit:
 ; CHECK-NEXT:    br label [[FOR_END]]
diff --git a/llvm/test/Transforms/LoopStrengthReduce/pr25541.ll b/llvm/test/Transforms/LoopStrengthReduce/pr25541.ll
index 1995b8be179ae..84ec3054b3858 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/pr25541.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/pr25541.ll
@@ -12,14 +12,13 @@ define void @f() personality ptr @__CxxFrameHandler3 {
 ; CHECK-NEXT:    br label %[[FOR_COND_I:.*]]
 ; CHECK:       [[FOR_COND_I]]:
 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], %[[FOR_INC_I:.*]] ], [ 0, %[[ENTRY]] ]
-; CHECK-NEXT:    [[LSR_IV_LCSSA1:%.*]] = inttoptr i64 [[LSR_IV]] to ptr
 ; CHECK-NEXT:    invoke void @g()
 ; CHECK-NEXT:            to label %[[FOR_INC_I]] unwind label %[[CATCH_DISPATCH_I:.*]]
 ; CHECK:       [[CATCH_DISPATCH_I]]:
 ; CHECK-NEXT:    [[CS:%.*]] = catchswitch within none [label %[[FOR_COND_1_PREHEADER_I:.*]]] unwind to caller
 ; CHECK:       [[FOR_COND_1_PREHEADER_I]]:
 ; CHECK-NEXT:    [[TMP0:%.*]] = catchpad within [[CS]] [ptr null, i32 64, ptr null]
-; CHECK-NEXT:    [[CMP_I:%.*]] = icmp eq ptr [[LSR_IV_LCSSA1]], null
+; CHECK-NEXT:    [[CMP_I:%.*]] = icmp eq i64 [[LSR_IV]], 0
 ; CHECK-NEXT:    br label %[[FOR_COND_1_I:.*]]
 ; CHECK:       [[FOR_COND_1_I]]:
 ; CHECK-NEXT:    br i1 [[CMP_I]], label %[[FOR_END_I:.*]], label %[[FOR_BODY_I:.*]]
diff --git a/llvm/test/Transforms/LoopStrengthReduce/pr27056.ll b/llvm/test/Transforms/LoopStrengthReduce/pr27056.ll
index 5f082dae7cf7b..51c409ca2380d 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/pr27056.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/pr27056.ll
@@ -17,17 +17,16 @@ define void @b_copy_ctor() personality ptr @__CxxFrameHandler3 {
 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
 ; CHECK:       for.cond:
 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[CALL_I_NOEXC:%.*]] ], [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    [[LSR_IV2:%.*]] = inttoptr i64 [[LSR_IV]] to ptr
 ; CHECK-NEXT:    invoke void @a_copy_ctor()
-; CHECK-NEXT:    to label [[CALL_I_NOEXC]] unwind label [[CATCH_DISPATCH:%.*]]
+; CHECK-NEXT:            to label [[CALL_I_NOEXC]] unwind label [[CATCH_DISPATCH:%.*]]
 ; CHECK:       call.i.noexc:
 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -16
 ; CHECK-NEXT:    br label [[FOR_COND]]
 ; CHECK:       catch.dispatch:
-; CHECK-NEXT:    [[TMP2:%.*]] = catchswitch within none [label %catch] unwind to caller
+; CHECK-NEXT:    [[TMP2:%.*]] = catchswitch within none [label [[CATCH:%.*]]] unwind to caller
 ; CHECK:       catch:
 ; CHECK-NEXT:    [[TMP3:%.*]] = catchpad within [[TMP2]] [ptr null, i32 64, ptr null]
-; CHECK-NEXT:    [[CMP16:%.*]] = icmp eq ptr [[LSR_IV2]], null
+; CHECK-NEXT:    [[CMP16:%.*]] = icmp eq i64 [[LSR_IV]], 0
 ; CHECK-NEXT:    [[TMP4:%.*]] = mul i64 [[LSR_IV]], -1
 ; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[TMP0]], i64 [[TMP4]]
 ; CHECK-NEXT:    br i1 [[CMP16]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]

>From 6db482341e03a6eade2d4e04e758941a676d3432 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 2/4] [Test] Fix LSR tests to prevent trivial simplification of
 icmp with undef

Replace undef operands in funclet.ll with function parameters and adjust
the loop bound in reuse-existing-phi.ll so the new simplification pass
does not fold away the comparisons these tests are meant to exercise.
---
 .../X86/reuse-existing-phi.ll                 |  6 +--
 .../Transforms/LoopStrengthReduce/funclet.ll  | 48 +++++++++----------
 2 files changed, 27 insertions(+), 27 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 bbcb00ccf8ba9..c2332c091a1fd 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/funclet.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/funclet.ll
@@ -10,7 +10,7 @@ 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:%.*]]
@@ -26,9 +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:    [[TMP100:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 0
+; 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]]
@@ -39,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
 
@@ -57,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
@@ -68,7 +68,7 @@ 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:%.*]]
@@ -88,9 +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:    [[TMP100:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 0
+; 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]]
@@ -99,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
 
@@ -123,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
@@ -131,7 +131,7 @@ 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:%.*]]
@@ -151,9 +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:    [[TMP100:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 0
+; 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]]
@@ -162,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
 
@@ -186,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
@@ -194,7 +194,7 @@ 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:%.*]]
@@ -212,9 +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:    [[TMP100:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 0
+; 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]]
@@ -225,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
 
@@ -246,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

>From 1f2238dfd7a21aeaefc3d4e8b850020e4f2476f0 Mon Sep 17 00:00:00 2001
From: Timur Golubovich <timur.golubovich at intel.com>
Date: Tue, 9 Jun 2026 12:52:59 +0200
Subject: [PATCH 3/4] [LSR] CSE duplicate instructions produced by multiple
 fixups in Rewrite

Track rewritten instructions and replace subsequent identical ones when
dominance holds, eliminating redundant icmps from shared-IV fixups.
---
 .../Transforms/Scalar/LoopStrengthReduce.cpp  | 27 +++++++++++++++++++
 .../X86/lsr-icmpzero-no-inttoptr.ll           |  3 +--
 .../lsr-rewrite-to-add-one.ll                 |  3 +--
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index ca37d33d865d6..26da4b3c346d7 100644
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -2228,6 +2228,11 @@ 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;
+
   void OptimizeShadowIV();
   bool FindIVUserForCond(Instruction *Cond, IVStrideUse *&CondUse);
   Instruction *OptimizeMax(ICmpInst *Cond, IVStrideUse *&CondUse);
@@ -6083,6 +6088,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))
diff --git a/llvm/test/Transforms/LoopStrengthReduce/X86/lsr-icmpzero-no-inttoptr.ll b/llvm/test/Transforms/LoopStrengthReduce/X86/lsr-icmpzero-no-inttoptr.ll
index 0d6a374f86692..e9f79956c3f2b 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/X86/lsr-icmpzero-no-inttoptr.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/X86/lsr-icmpzero-no-inttoptr.ll
@@ -23,9 +23,8 @@ define void @test_no_inttoptr_casts(ptr %base1, ptr %base2, ptr %base3, i64 %n)
 ; CHECK-NEXT:    [[CMP_EXIT:%.*]] = icmp eq i64 [[TMP0]], [[LSR_IV]]
 ; CHECK-NEXT:    br i1 [[CMP_EXIT]], label [[CHECK:%.*]], label [[BODY:%.*]]
 ; CHECK:       check:
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i64 [[TMP0]], [[LSR_IV]]
 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp ne i64 [[TMP0]], [[LSR_IV]]
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP3]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP3]], i1 true, i1 [[CMP3]]
 ; CHECK-NEXT:    br i1 [[SEL]], label [[BODY]], label [[EXIT:%.*]]
 ; CHECK:       body:
 ; CHECK-NEXT:    [[V1:%.*]] = load i64, ptr [[SCEVGEP]], align 8
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]]

>From cb3d5981225cca6246bfd90821d0be7b0186fc86 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 4/4] [LSR] Simplify rewritten instructions after IV increment
 hoisting

Run simplifyInstruction() over rewritten instructions and their users
after IV hoisting, folding trivially redundant compares and arithmetic.
Move dead-instruction cleanup to the end to avoid use-after-free.
---
 .../Transforms/Scalar/LoopStrengthReduce.cpp  | 31 ++++++-
 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 +---
 .../apx/check-nf-in-suppress-reloc-pass.ll    |  4 +-
 .../X86/2012-01-13-phielim.ll                 |  6 +-
 .../X86/lsr-icmpzero-no-inttoptr.ll           |  4 +-
 .../post-increment-insertion.ll               |  4 +-
 .../LoopStrengthReduce/wrong-hoisting-iv.ll   |  2 -
 11 files changed, 90 insertions(+), 125 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index 26da4b3c346d7..b307f73ac30fa 100644
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -6186,9 +6186,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
@@ -6231,7 +6228,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/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 }
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/X86/lsr-icmpzero-no-inttoptr.ll b/llvm/test/Transforms/LoopStrengthReduce/X86/lsr-icmpzero-no-inttoptr.ll
index e9f79956c3f2b..0f26d384fc11d 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/X86/lsr-icmpzero-no-inttoptr.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/X86/lsr-icmpzero-no-inttoptr.ll
@@ -23,9 +23,7 @@ define void @test_no_inttoptr_casts(ptr %base1, ptr %base2, ptr %base3, i64 %n)
 ; CHECK-NEXT:    [[CMP_EXIT:%.*]] = icmp eq i64 [[TMP0]], [[LSR_IV]]
 ; CHECK-NEXT:    br i1 [[CMP_EXIT]], label [[CHECK:%.*]], label [[BODY:%.*]]
 ; CHECK:       check:
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp ne i64 [[TMP0]], [[LSR_IV]]
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP3]], i1 true, i1 [[CMP3]]
-; CHECK-NEXT:    br i1 [[SEL]], label [[BODY]], label [[EXIT:%.*]]
+; CHECK-NEXT:    br i1 false, label [[BODY]], label [[EXIT:%.*]]
 ; CHECK:       body:
 ; CHECK-NEXT:    [[V1:%.*]] = load i64, ptr [[SCEVGEP]], align 8
 ; CHECK-NEXT:    [[V2:%.*]] = load i64, ptr [[SCEVGEP1]], align 8
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:%.*]]



More information about the llvm-commits mailing list