[llvm] 2755ffc - [InstCombine] Fold icmp ptrtoaddr x, ptrtoaddr y -> icmp x, y (#211991)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 25 02:11:23 PDT 2026


Author: Alexis Engelke
Date: 2026-07-25T09:11:19Z
New Revision: 2755ffcabdce740c65d773155c659f505ac6c74e

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

LOG: [InstCombine] Fold icmp ptrtoaddr x, ptrtoaddr y -> icmp x, y (#211991)

Similar to the existing ptrtoint fold; this is valid, because icmp only
compares address bits. This addresses optimization regressions when
generating ptrtoaddr for pointer subtractions.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/test/Transforms/InstCombine/cast_ptr.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 094d53363082e..6c4f8d08031dd 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6548,6 +6548,8 @@ Instruction *InstCombinerImpl::foldICmpWithCastOp(ICmpInst &ICmp) {
 
   // Turn icmp (ptrtoint x), (ptrtoint/c) into a compare of the input if the
   // integer type is the same size as the pointer type.
+  // TODO: for icmp (ptrtoaddr), (ptrtoaddr), we don't need this check;
+  // currently it is always false if the pointer has non-address bits.
   auto CompatibleSizes = [&](Type *PtrTy, Type *IntTy) {
     if (isa<VectorType>(PtrTy)) {
       PtrTy = cast<VectorType>(PtrTy)->getElementType();
@@ -6555,13 +6557,18 @@ Instruction *InstCombinerImpl::foldICmpWithCastOp(ICmpInst &ICmp) {
     }
     return DL.getPointerTypeSizeInBits(PtrTy) == IntTy->getIntegerBitWidth();
   };
-  if (CastOp0->getOpcode() == Instruction::PtrToInt &&
+  if (isa<PtrToIntInst, PtrToAddrInst>(CastOp0) &&
       CompatibleSizes(SrcTy, DestTy)) {
     Value *NewOp1 = nullptr;
     if (auto *PtrToIntOp1 = dyn_cast<PtrToIntOperator>(ICmp.getOperand(1))) {
       Value *PtrSrc = PtrToIntOp1->getOperand(0);
       if (PtrSrc->getType() == Op0Src->getType())
         NewOp1 = PtrToIntOp1->getOperand(0);
+    } else if (auto *PtrToAddrOp1 =
+                   dyn_cast<PtrToAddrOperator>(ICmp.getOperand(1))) {
+      Value *PtrSrc = PtrToAddrOp1->getOperand(0);
+      if (PtrSrc->getType() == Op0Src->getType())
+        NewOp1 = PtrToAddrOp1->getOperand(0);
     } else if (auto *RHSC = dyn_cast<Constant>(ICmp.getOperand(1))) {
       NewOp1 = ConstantExpr::getIntToPtr(RHSC, SrcTy);
     }

diff  --git a/llvm/test/Transforms/InstCombine/cast_ptr.ll b/llvm/test/Transforms/InstCombine/cast_ptr.ll
index c42add1bcd071..c80a32868640f 100644
--- a/llvm/test/Transforms/InstCombine/cast_ptr.ll
+++ b/llvm/test/Transforms/InstCombine/cast_ptr.ll
@@ -36,6 +36,28 @@ define i1 @test2(ptr %a, ptr %b) {
   ret i1 %r
 }
 
+define i1 @test2_ptrtoaddr(ptr %a, ptr %b) {
+; CHECK-LABEL: @test2_ptrtoaddr(
+; CHECK-NEXT:    [[R:%.*]] = icmp eq ptr [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %ta = ptrtoaddr ptr %a to i32
+  %tb = ptrtoaddr ptr %b to i32
+  %r = icmp eq i32 %ta, %tb
+  ret i1 %r
+}
+
+define i1 @test2_ptrtoaddr_ptrtoint(ptr %a, ptr %b) {
+; CHECK-LABEL: @test2_ptrtoaddr_ptrtoint(
+; CHECK-NEXT:    [[R:%.*]] = icmp eq ptr [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %ta = ptrtoint ptr %a to i32
+  %tb = ptrtoaddr ptr %b to i32
+  %r = icmp eq i32 %ta, %tb
+  ret i1 %r
+}
+
 ; These casts should be folded away.
 
 define i1 @test2_as2_same_int(ptr addrspace(2) %a, ptr addrspace(2) %b) {
@@ -49,6 +71,28 @@ define i1 @test2_as2_same_int(ptr addrspace(2) %a, ptr addrspace(2) %b) {
   ret i1 %r
 }
 
+define i1 @test2_as2_same_int_ptrtoaddr(ptr addrspace(2) %a, ptr addrspace(2) %b) {
+; CHECK-LABEL: @test2_as2_same_int_ptrtoaddr(
+; CHECK-NEXT:    [[R:%.*]] = icmp eq ptr addrspace(2) [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %ta = ptrtoaddr ptr addrspace(2) %a to i16
+  %tb = ptrtoaddr ptr addrspace(2) %b to i16
+  %r = icmp eq i16 %ta, %tb
+  ret i1 %r
+}
+
+define i1 @test2_as2_same_int_ptrtoint(ptr addrspace(2) %a, ptr addrspace(2) %b) {
+; CHECK-LABEL: @test2_as2_same_int_ptrtoint(
+; CHECK-NEXT:    [[R:%.*]] = icmp eq ptr addrspace(2) [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %ta = ptrtoaddr ptr addrspace(2) %a to i16
+  %tb = ptrtoint ptr addrspace(2) %b to i16
+  %r = icmp eq i16 %ta, %tb
+  ret i1 %r
+}
+
 ; These casts should be folded away.
 
 define i1 @test2_as2_larger(ptr addrspace(2) %a, ptr addrspace(2) %b) {
@@ -77,6 +121,32 @@ define i1 @test2_
diff _as(ptr %p, ptr addrspace(1) %q) {
   ret i1 %r0
 }
 
+define i1 @test2_
diff _as_ptrtoaddr(ptr %p, ptr addrspace(1) %q) {
+; CHECK-LABEL: @test2_
diff _as_ptrtoaddr(
+; CHECK-NEXT:    [[I0:%.*]] = ptrtoaddr ptr [[P:%.*]] to i32
+; CHECK-NEXT:    [[I1:%.*]] = ptrtoaddr ptr addrspace(1) [[Q:%.*]] to i32
+; CHECK-NEXT:    [[R0:%.*]] = icmp sge i32 [[I0]], [[I1]]
+; CHECK-NEXT:    ret i1 [[R0]]
+;
+  %i0 = ptrtoaddr ptr %p to i32
+  %i1 = ptrtoaddr ptr addrspace(1) %q to i32
+  %r0 = icmp sge i32 %i0, %i1
+  ret i1 %r0
+}
+
+define i1 @test2_
diff _as_ptrtoaddr_ptrtoint(ptr %p, ptr addrspace(1) %q) {
+; CHECK-LABEL: @test2_
diff _as_ptrtoaddr_ptrtoint(
+; CHECK-NEXT:    [[I0:%.*]] = ptrtoint ptr [[P:%.*]] to i32
+; CHECK-NEXT:    [[I1:%.*]] = ptrtoaddr ptr addrspace(1) [[Q:%.*]] to i32
+; CHECK-NEXT:    [[R0:%.*]] = icmp sge i32 [[I0]], [[I1]]
+; CHECK-NEXT:    ret i1 [[R0]]
+;
+  %i0 = ptrtoint ptr %p to i32
+  %i1 = ptrtoaddr ptr addrspace(1) %q to i32
+  %r0 = icmp sge i32 %i0, %i1
+  ret i1 %r0
+}
+
 ; These casts should not be folded away.
 
 define i1 @test2_
diff _as_global(ptr addrspace(1) %q) {
@@ -91,6 +161,30 @@ define i1 @test2_
diff _as_global(ptr addrspace(1) %q) {
   ret i1 %r0
 }
 
+define i1 @test2_
diff _as_global_ptrtoaddr(ptr addrspace(1) %q) {
+; CHECK-LABEL: @test2_
diff _as_global_ptrtoaddr(
+; CHECK-NEXT:    [[I1:%.*]] = ptrtoaddr ptr addrspace(1) [[Q:%.*]] to i32
+; CHECK-NEXT:    [[R0:%.*]] = icmp sge i32 [[I1]], ptrtoaddr (ptr @global to i32)
+; CHECK-NEXT:    ret i1 [[R0]]
+;
+  %i0 = ptrtoaddr ptr @global to i32
+  %i1 = ptrtoaddr ptr addrspace(1) %q to i32
+  %r0 = icmp sge i32 %i1, %i0
+  ret i1 %r0
+}
+
+define i1 @test2_
diff _as_global_ptrtoaddr_ptrtoint(ptr addrspace(1) %q) {
+; CHECK-LABEL: @test2_
diff _as_global_ptrtoaddr_ptrtoint(
+; CHECK-NEXT:    [[I1:%.*]] = ptrtoint ptr addrspace(1) [[Q:%.*]] to i32
+; CHECK-NEXT:    [[R0:%.*]] = icmp sge i32 [[I1]], ptrtoaddr (ptr @global to i32)
+; CHECK-NEXT:    ret i1 [[R0]]
+;
+  %i0 = ptrtoaddr ptr @global to i32
+  %i1 = ptrtoint ptr addrspace(1) %q to i32
+  %r0 = icmp sge i32 %i1, %i0
+  ret i1 %r0
+}
+
 ; These casts should also be folded away.
 
 define i1 @test3(ptr %a) {
@@ -103,6 +197,26 @@ define i1 @test3(ptr %a) {
   ret i1 %r
 }
 
+define i1 @test3_ptrtoaddr(ptr %a) {
+; CHECK-LABEL: @test3_ptrtoaddr(
+; CHECK-NEXT:    [[R:%.*]] = icmp eq ptr [[A:%.*]], @global
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %ta = ptrtoaddr ptr %a to i32
+  %r = icmp eq i32 %ta, ptrtoaddr (ptr @global to i32)
+  ret i1 %r
+}
+
+define i1 @test3_ptrtoaddr_ptrtoint(ptr %a) {
+; CHECK-LABEL: @test3_ptrtoaddr_ptrtoint(
+; CHECK-NEXT:    [[R:%.*]] = icmp eq ptr [[A:%.*]], @global
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %ta = ptrtoaddr ptr %a to i32
+  %r = icmp eq i32 %ta, ptrtoint (ptr @global to i32)
+  ret i1 %r
+}
+
 define i1 @test4(i32 %A) {
 ; CHECK-LABEL: @test4(
 ; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[A:%.*]], 0


        


More information about the llvm-commits mailing list