[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