[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