[llvm] [InstCombine] Handle icmp+ptrtoint/addr folds for non-int ptrs (PR #212101)
Alexis Engelke via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 26 01:13:35 PDT 2026
https://github.com/aengelke created https://github.com/llvm/llvm-project/pull/212101
Followup of #211991. icmp ptrtoint, ptrtoint cannot be folded away for
non-integral pointers, this is only possible with ptrtoaddr.
>From fe248b37e3ac89ee9170d728e7654dedbe9c3a5f Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Sun, 26 Jul 2026 08:12:54 +0000
Subject: [PATCH] [spr] initial version
Created using spr 1.3.8-wip
---
.../InstCombine/InstCombineCompares.cpp | 40 +++++++-------
llvm/test/Transforms/InstCombine/cast_ptr.ll | 55 +++++++++++++++++++
2 files changed, 75 insertions(+), 20 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 6c4f8d08031dd..9b3ec370876d1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6537,6 +6537,7 @@ Instruction *InstCombinerImpl::foldICmpWithCastOp(ICmpInst &ICmp) {
SimplifiedOp1 ? SimplifiedOp1 : ICmp.getOperand(1));
auto *CastOp0 = dyn_cast<CastInst>(ICmp.getOperand(0));
+ Value *Op1 = ICmp.getOperand(1);
if (!CastOp0)
return nullptr;
if (!isa<Constant>(ICmp.getOperand(1)) && !isa<CastInst>(ICmp.getOperand(1)))
@@ -6548,33 +6549,32 @@ 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();
- IntTy = cast<VectorType>(IntTy)->getElementType();
- }
- return DL.getPointerTypeSizeInBits(PtrTy) == IntTy->getIntegerBitWidth();
+ unsigned IntWidth = IntTy->getScalarType()->getIntegerBitWidth();
+ PtrTy = PtrTy->getScalarType();
+ unsigned IndexWidth = DL.getAddressSizeInBits(PtrTy);
+ unsigned PtrWidth = DL.getPointerTypeSizeInBits(PtrTy);
+ // For ptrtoint/inttoptr, we must check that IntWidth == IndexWidth and also
+ // IndexWidth == PtrWidth to (not) handle non-integral pointers.
+ return IntWidth == IndexWidth && IndexWidth == PtrWidth;
};
- if (isa<PtrToIntInst, PtrToAddrInst>(CastOp0) &&
- CompatibleSizes(SrcTy, DestTy)) {
+ if (isa<PtrToIntInst, PtrToAddrInst>(CastOp0)) {
+ bool HasPtrToInt = isa<PtrToIntInst>(CastOp0);
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);
+ if (auto *PtrToIntOp1 = dyn_cast<PtrToIntOperator>(Op1)) {
+ NewOp1 = PtrToIntOp1->getOperand(0);
+ HasPtrToInt = true;
+ } else if (auto *PtrToAddrOp1 = dyn_cast<PtrToAddrOperator>(Op1)) {
+ NewOp1 = PtrToAddrOp1->getOperand(0);
} else if (auto *RHSC = dyn_cast<Constant>(ICmp.getOperand(1))) {
NewOp1 = ConstantExpr::getIntToPtr(RHSC, SrcTy);
}
- if (NewOp1)
- return new ICmpInst(ICmp.getPredicate(), Op0Src, NewOp1);
+ // For ptrtoaddr, IntWidth == IndexWidth is implied and we don't need to
+ // check PtrWidth.
+ if (!HasPtrToInt || CompatibleSizes(SrcTy, DestTy))
+ if (NewOp1 && NewOp1->getType() == Op0Src->getType())
+ return new ICmpInst(ICmp.getPredicate(), Op0Src, NewOp1);
}
// Do the same in the other direction for icmp (inttoptr x), (inttoptr/c).
diff --git a/llvm/test/Transforms/InstCombine/cast_ptr.ll b/llvm/test/Transforms/InstCombine/cast_ptr.ll
index c80a32868640f..5319f1352b368 100644
--- a/llvm/test/Transforms/InstCombine/cast_ptr.ll
+++ b/llvm/test/Transforms/InstCombine/cast_ptr.ll
@@ -106,6 +106,61 @@ define i1 @test2_as2_larger(ptr addrspace(2) %a, ptr addrspace(2) %b) {
ret i1 %r
}
+; These casts on a non-integral ptr type should not be folded away for ptrtoint.
+
+define i1 @test3_as3_same_int(ptr addrspace(3) %a, ptr addrspace(3) %b) {
+; CHECK-LABEL: @test3_as3_same_int(
+; CHECK-NEXT: [[TA:%.*]] = ptrtoint ptr addrspace(3) [[A:%.*]] to i32
+; CHECK-NEXT: [[TB:%.*]] = ptrtoint ptr addrspace(3) [[B:%.*]] to i32
+; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TA]], [[TB]]
+; CHECK-NEXT: ret i1 [[R]]
+;
+ %ta = ptrtoint ptr addrspace(3) %a to i32
+ %tb = ptrtoint ptr addrspace(3) %b to i32
+ %r = icmp eq i32 %ta, %tb
+ ret i1 %r
+}
+
+define i1 @test3_as3_same_int_ptrtoaddr(ptr addrspace(3) %a, ptr addrspace(3) %b) {
+; CHECK-LABEL: @test3_as3_same_int_ptrtoaddr(
+; CHECK-NEXT: [[R:%.*]] = icmp eq ptr addrspace(3) [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: ret i1 [[R]]
+;
+ %ta = ptrtoaddr ptr addrspace(3) %a to i16
+ %tb = ptrtoaddr ptr addrspace(3) %b to i16
+ %r = icmp eq i16 %ta, %tb
+ ret i1 %r
+}
+
+define i1 @test3_as3_same_int_ptrtoint(ptr addrspace(3) %a, ptr addrspace(3) %b) {
+; CHECK-LABEL: @test3_as3_same_int_ptrtoint(
+; CHECK-NEXT: [[TA:%.*]] = ptrtoaddr ptr addrspace(3) [[A:%.*]] to i16
+; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr addrspace(3) [[B:%.*]] to i32
+; CHECK-NEXT: [[TB:%.*]] = trunc i32 [[TMP1]] to i16
+; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[TA]], [[TB]]
+; CHECK-NEXT: ret i1 [[R]]
+;
+ %ta = ptrtoaddr ptr addrspace(3) %a to i16
+ %tb = ptrtoint ptr addrspace(3) %b to i16
+ %r = icmp eq i16 %ta, %tb
+ ret i1 %r
+}
+
+; These casts should not be folded away.
+
+define i1 @test3_as3_larger(ptr addrspace(3) %a, ptr addrspace(3) %b) {
+; CHECK-LABEL: @test3_as3_larger(
+; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr addrspace(3) [[A:%.*]] to i32
+; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr addrspace(3) [[B:%.*]] to i32
+; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: ret i1 [[R]]
+;
+ %ta = ptrtoint ptr addrspace(3) %a to i33
+ %tb = ptrtoint ptr addrspace(3) %b to i33
+ %r = icmp eq i33 %ta, %tb
+ ret i1 %r
+}
+
; These casts should not be folded away.
define i1 @test2_diff_as(ptr %p, ptr addrspace(1) %q) {
More information about the llvm-commits
mailing list