[llvm] e04f5dd - [LSR] Fix ICmpZero type mismatch with mixed-width pointers (#206193)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 29 04:03:59 PDT 2026


Author: Timur Golubovich
Date: 2026-06-29T11:03:53Z
New Revision: e04f5dd223c9e69c339f87c0af04e7fb4c77ebdc

URL: https://github.com/llvm/llvm-project/commit/e04f5dd223c9e69c339f87c0af04e7fb4c77ebdc
DIFF: https://github.com/llvm/llvm-project/commit/e04f5dd223c9e69c339f87c0af04e7fb4c77ebdc.diff

LOG: [LSR] Fix ICmpZero type mismatch with mixed-width pointers (#206193)

Fix regression from 85ed098a6d5d where ICmpZero produced a
type-mismatched icmp (i64 vs i32) when the loop has pointer IVs of
different widths. Move the pointer-to-integer override after IntTy is
computed so both icmp operands match the IV.

Added: 
    llvm/test/Transforms/LoopStrengthReduce/AMDGPU/lsr-icmpzero-mixed-ptr-width.ll

Modified: 
    llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index 4aeb32bfd3b4b..d382a22da6782 100644
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -5833,10 +5833,6 @@ 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)
@@ -5847,6 +5843,14 @@ Value *LSRInstance::Expand(const LSRUse &LU, const LSRFixup &LF,
     Ty = OpTy;
   // This is the type to do integer arithmetic in.
   Type *IntTy = SE.getEffectiveSCEVType(Ty);
+  // For ICmpZero with pointer-typed operands, keep the comparison in the
+  // integer domain to avoid generating inttoptr casts. Use IntTy (the
+  // formula's arithmetic width) so that both icmp operands match even when
+  // the IV is wider than the pointer.
+  if (LU.Kind == LSRUse::ICmpZero && OpTy->isPointerTy()) {
+    OpTy = IntTy;
+    Ty = IntTy;
+  }
 
   // Build up a list of operands to add together to form the full base.
   SmallVector<SCEVUse, 8> Ops;

diff  --git a/llvm/test/Transforms/LoopStrengthReduce/AMDGPU/lsr-icmpzero-mixed-ptr-width.ll b/llvm/test/Transforms/LoopStrengthReduce/AMDGPU/lsr-icmpzero-mixed-ptr-width.ll
new file mode 100644
index 0000000000000..5418b6d10c5cb
--- /dev/null
+++ b/llvm/test/Transforms/LoopStrengthReduce/AMDGPU/lsr-icmpzero-mixed-ptr-width.ll
@@ -0,0 +1,61 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=loop-reduce -S -mcpu=gfx942 %s | FileCheck %s
+;
+; Verify that LSR produces well-typed icmp operands when ICmpZero uses a
+; pointer-typed operand from a narrow address space (addrspace(5), 32-bit)
+; but the chosen IV is wider (i64, from flat-pointer address uses).
+
+target triple = "amdgcn-amd-amdhsa"
+
+define amdgpu_kernel void @icmpzero_mixed_ptr_width(ptr addrspace(5) %scratch) {
+; CHECK-LABEL: define amdgpu_kernel void @icmpzero_mixed_ptr_width(
+; CHECK-SAME: ptr addrspace(5) [[SCRATCH:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT:    [[DST:%.*]] = phi ptr addrspace(5) [ [[SCRATCH]], %[[ENTRY]] ], [ [[DST_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT:    [[SCEVGEP4:%.*]] = getelementptr i8, ptr null, i64 [[LSR_IV]]
+; CHECK-NEXT:    [[D0:%.*]] = load double, ptr addrspace(5) [[DST]], align 8
+; CHECK-NEXT:    [[S0:%.*]] = load double, ptr [[SCEVGEP4]], align 8
+; CHECK-NEXT:    [[DST_1:%.*]] = getelementptr i8, ptr addrspace(5) [[DST]], i32 8
+; CHECK-NEXT:    [[D1:%.*]] = load double, ptr addrspace(5) [[DST_1]], align 8
+; CHECK-NEXT:    [[SCEVGEP2:%.*]] = getelementptr i8, ptr null, i64 [[LSR_IV]]
+; CHECK-NEXT:    [[SCEVGEP3:%.*]] = getelementptr i8, ptr [[SCEVGEP2]], i64 8
+; CHECK-NEXT:    [[S1:%.*]] = load double, ptr [[SCEVGEP3]], align 8
+; CHECK-NEXT:    [[DST_2:%.*]] = getelementptr i8, ptr addrspace(5) [[DST]], i32 16
+; CHECK-NEXT:    [[D2:%.*]] = load double, ptr addrspace(5) [[DST_2]], align 8
+; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr null, i64 [[LSR_IV]]
+; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[SCEVGEP]], i64 16
+; CHECK-NEXT:    [[S2:%.*]] = load double, ptr [[SCEVGEP1]], align 8
+; CHECK-NEXT:    [[DST_NEXT]] = getelementptr i8, ptr addrspace(5) [[DST]], i32 96
+; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nuw nsw i64 [[LSR_IV]], 96
+; CHECK-NEXT:    [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 96
+; CHECK-NEXT:    br i1 [[DONE]], label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop
+
+loop:
+  %src = phi ptr [ null, %entry ], [ %src.next, %loop ]
+  %dst = phi ptr addrspace(5) [ %scratch, %entry ], [ %dst.next, %loop ]
+  %d0 = load double, ptr addrspace(5) %dst, align 8
+  %s0 = load double, ptr %src, align 8
+  %dst.1 = getelementptr i8, ptr addrspace(5) %dst, i32 8
+  %d1 = load double, ptr addrspace(5) %dst.1, align 8
+  %src.1 = getelementptr i8, ptr %src, i64 8
+  %s1 = load double, ptr %src.1, align 8
+  %dst.2 = getelementptr i8, ptr addrspace(5) %dst, i32 16
+  %d2 = load double, ptr addrspace(5) %dst.2, align 8
+  %src.2 = getelementptr i8, ptr %src, i64 16
+  %s2 = load double, ptr %src.2, align 8
+  %dst.next = getelementptr i8, ptr addrspace(5) %dst, i32 96
+  %src.next = getelementptr i8, ptr %src, i64 96
+  %done = icmp eq ptr addrspace(5) %dst, %scratch
+  br i1 %done, label %exit, label %loop
+
+exit:
+  ret void
+}


        


More information about the llvm-commits mailing list