[llvm] [ConstantFolding] Support ptrtoaddr in ConstantFoldCompareInstOperands (PR #162653)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 9 06:31:35 PDT 2025


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/162653

This folds `icmp (ptrtoaddr x, ptrtoaddr y)` to `icmp (x, y)`, matching the existing ptrtoint fold. Notably, this fold is not generally correct for the case where the address size and the pointer size differ, as the ptrtoaddr variant will only compare the address bits, while the icmp will compare all bits.

Both of the examples here *can* still be folded, but not through the logic we currently use. We'd have to add dedicated folds for that. For now add fixmes.

Related discussion: https://discourse.llvm.org/t/clarifiying-the-semantics-of-ptrtoint/83987/60?u=nikic

>From aef0993259628aa19d1592d840b3b8ad92df5609 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Thu, 9 Oct 2025 15:26:20 +0200
Subject: [PATCH] [ConstantFolding] Support ptrtoaddr in
 ConstantFoldCompareInstOperands

This folds `icmp (ptrtoaddr x, ptrtoaddr y)` to `icmp (x, y)`,
matching the existing ptrtoint fold. Notably, this fold is not
generally correct for the case where the address size and the
pointer size differ, as the ptrtoaddr variant will only compare
the address bits, while the icmp will compare all bits.

Both of the examples here *can* still be folded, but not through
the logic we currently use. We'd have to add dedicated folds for
that. For now add fixmes.

Related discussion:
https://discourse.llvm.org/t/clarifiying-the-semantics-of-ptrtoint/83987/60?u=nikic
---
 llvm/lib/Analysis/ConstantFolding.cpp         |  6 ++--
 llvm/test/Transforms/InstCombine/ptrtoaddr.ll | 36 +++++++++++++++++++
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 45c889cef8e2c..689e2e01610e2 100755
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1225,7 +1225,8 @@ Constant *llvm::ConstantFoldCompareInstOperands(
 
       // Only do this transformation if the int is intptrty in size, otherwise
       // there is a truncation or extension that we aren't modeling.
-      if (CE0->getOpcode() == Instruction::PtrToInt) {
+      if (CE0->getOpcode() == Instruction::PtrToInt ||
+          CE0->getOpcode() == Instruction::PtrToAddr) {
         Type *IntPtrTy = DL.getIntPtrType(CE0->getOperand(0)->getType());
         if (CE0->getType() == IntPtrTy) {
           Constant *C = CE0->getOperand(0);
@@ -1252,7 +1253,8 @@ Constant *llvm::ConstantFoldCompareInstOperands(
 
         // Only do this transformation if the int is intptrty in size, otherwise
         // there is a truncation or extension that we aren't modeling.
-        if (CE0->getOpcode() == Instruction::PtrToInt) {
+        if (CE0->getOpcode() == Instruction::PtrToInt ||
+            CE0->getOpcode() == Instruction::PtrToAddr) {
           Type *IntPtrTy = DL.getIntPtrType(CE0->getOperand(0)->getType());
           if (CE0->getType() == IntPtrTy &&
               CE0->getOperand(0)->getType() == CE1->getOperand(0)->getType()) {
diff --git a/llvm/test/Transforms/InstCombine/ptrtoaddr.ll b/llvm/test/Transforms/InstCombine/ptrtoaddr.ll
index 5211fbd8b897a..2e688d8b7872c 100644
--- a/llvm/test/Transforms/InstCombine/ptrtoaddr.ll
+++ b/llvm/test/Transforms/InstCombine/ptrtoaddr.ll
@@ -130,3 +130,39 @@ define i32 @ptrtoaddr_sub_consts_offset_addrsize() {
 ;
   ret i32 sub (i32 ptrtoaddr (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) @g.as1, i32 42) to i32), i32 ptrtoaddr (ptr addrspace(1) @g.as1 to i32))
 }
+
+define i1 @icmp_ptrtoaddr_0() {
+; CHECK-LABEL: define i1 @icmp_ptrtoaddr_0() {
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp ne i64 ptrtoaddr (ptr @g to i64), 0
+  ret i1 %cmp
+}
+
+; FIXME: This can still fold, but not by converting to pointer comparison.
+define i1 @icmp_ptrtoaddr_0_addrsize() {
+; CHECK-LABEL: define i1 @icmp_ptrtoaddr_0_addrsize() {
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 ptrtoaddr (ptr addrspace(1) @g.as1 to i32), 0
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %cmp = icmp ne i32 ptrtoaddr (ptr addrspace(1) @g.as1 to i32), 0
+  ret i1 %cmp
+}
+
+define i1 @icmp_ptrtoaddr_ptrtoaddr() {
+; CHECK-LABEL: define i1 @icmp_ptrtoaddr_ptrtoaddr() {
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp ne i64 ptrtoaddr (ptr @g to i64), ptrtoaddr (ptr @g2 to i64)
+  ret i1 %cmp
+}
+
+; FIXME: This can still fold, but not by converting to pointer comparison.
+define i1 @icmp_ptrtoaddr_ptrtoaddr_addrsize() {
+; CHECK-LABEL: define i1 @icmp_ptrtoaddr_ptrtoaddr_addrsize() {
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 ptrtoaddr (ptr addrspace(1) @g.as1 to i32), ptrtoaddr (ptr addrspace(1) @g2.as1 to i32)
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %cmp = icmp ne i32 ptrtoaddr (ptr addrspace(1) @g.as1 to i32), ptrtoaddr (ptr addrspace(1) @g2.as1 to i32)
+  ret i1 %cmp
+}



More information about the llvm-commits mailing list