[llvm] [GVN] Reuse dominating PtrToInt for PtrToAddr. (PR #209164)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 13 05:43:30 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Florian Hahn (fhahn)

<details>
<summary>Changes</summary>

A ptrtoaddr and a ptrtoint of the same pointer compute the same value
when the address width equals the pointer representation width. Reuse
a dominating ptrtoint in place of a ptrtoaddr.

This fixes a few end-to-end regressions with
https://github.com/llvm/llvm-project/pull/180244.

I am not sure if there's a better way to implement this. Initially I
tried to use the same numbering for PtrToInt and PtrToAddr, but then
there are multiple places where we need to check the direction is
correct, which seemed a bit more fragile.

---
Full diff: https://github.com/llvm/llvm-project/pull/209164.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/Scalar/GVN.cpp (+24) 
- (modified) llvm/test/Transforms/GVN/ptrtoaddr.ll (+46-2) 


``````````diff
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index 517d33bfba103..91939bb965a5c 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -3400,6 +3400,30 @@ bool GVNPass::processInstruction(Instruction *I) {
     return false;
   }
 
+  // A ptrtoaddr and a ptrtoint of the same pointer compute the same value when
+  // the address width equals the pointer representation width. Reuse a
+  // dominating ptrtoint in place of a ptrtoaddr.
+  if (auto *PTA = dyn_cast<PtrToAddrInst>(I)) {
+    const DataLayout &DL = I->getDataLayout();
+    unsigned AS = PTA->getPointerAddressSpace();
+    Value *Ptr = PTA->getPointerOperand();
+    if (DL.getAddressSizeInBits(AS) == DL.getPointerSizeInBits(AS) &&
+        !DL.hasUnstableRepresentation(AS) && Ptr->hasUseList()) {
+      unsigned Scanned = 0;
+      for (User *U : Ptr->users()) {
+        if (++Scanned >= ScanUsersLimit)
+          break;
+        auto *PTI = dyn_cast<PtrToIntInst>(U);
+        if (PTI && PTI->getType() == I->getType() && PTI != I &&
+            DT->dominates(PTI, I)) {
+          patchAndReplaceAllUsesWith(I, PTI);
+          salvageAndRemoveInstruction(I);
+          return true;
+        }
+      }
+    }
+  }
+
   // If the number we were assigned was a brand new VN, then we don't
   // need to do a lookup to see if the number already exists
   // somewhere in the domtree: it can't!
diff --git a/llvm/test/Transforms/GVN/ptrtoaddr.ll b/llvm/test/Transforms/GVN/ptrtoaddr.ll
index a731ef433741a..c96961762194e 100644
--- a/llvm/test/Transforms/GVN/ptrtoaddr.ll
+++ b/llvm/test/Transforms/GVN/ptrtoaddr.ll
@@ -33,8 +33,7 @@ define i64 @ptrtoaddr_reuses_dominating_ptrtoint(ptr %p) {
 ; CHECK-LABEL: define i64 @ptrtoaddr_reuses_dominating_ptrtoint(
 ; CHECK-SAME: ptr [[P:%.*]]) {
 ; CHECK-NEXT:    [[I:%.*]] = ptrtoint ptr [[P]] to i64
-; CHECK-NEXT:    [[A:%.*]] = ptrtoaddr ptr [[P]] to i64
-; CHECK-NEXT:    [[R:%.*]] = add i64 [[I]], [[A]]
+; CHECK-NEXT:    [[R:%.*]] = add i64 [[I]], [[I]]
 ; CHECK-NEXT:    ret i64 [[R]]
 ;
   %i = ptrtoint ptr %p to i64
@@ -74,3 +73,48 @@ define i64 @ptrtoaddr_wrong_type(ptr %p) {
   %r = add i64 %z, %a
   ret i64 %r
 }
+
+define i64 @ptrtoint_not_pred_from_ptrtoaddr(ptr %p, i1 %c) {
+; CHECK-LABEL: define i64 @ptrtoint_not_pred_from_ptrtoaddr(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = ptrtoaddr ptr [[P]] to i64
+; CHECK-NEXT:    br i1 [[C]], label %[[THEN:.*]], label %[[ELSE:.*]]
+; CHECK:       [[THEN]]:
+; CHECK-NEXT:    br label %[[MERGE:.*]]
+; CHECK:       [[ELSE]]:
+; CHECK-NEXT:    br label %[[MERGE]]
+; CHECK:       [[MERGE]]:
+; CHECK-NEXT:    [[I:%.*]] = ptrtoint ptr [[P]] to i64
+; CHECK-NEXT:    ret i64 [[I]]
+;
+  %a = ptrtoaddr ptr %p to i64
+  br i1 %c, label %then, label %else
+
+then:
+  br label %merge
+
+else:
+  br label %merge
+
+merge:
+  %i = ptrtoint ptr %p to i64
+  ret i64 %i
+}
+
+define i64 @no_transitive_merge_of_ptrtoint_and_ptrtoaddr(ptr %p) {
+; CHECK-LABEL: define i64 @no_transitive_merge_of_ptrtoint_and_ptrtoaddr(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = ptrtoaddr ptr [[P]] to i64
+; CHECK-NEXT:    [[ADDA:%.*]] = add i64 [[A]], 7
+; CHECK-NEXT:    [[I:%.*]] = ptrtoint ptr [[P]] to i64
+; CHECK-NEXT:    [[ADDI:%.*]] = add i64 [[I]], 7
+; CHECK-NEXT:    [[R:%.*]] = add i64 [[ADDA]], [[ADDI]]
+; CHECK-NEXT:    ret i64 [[R]]
+;
+  %a = ptrtoaddr ptr %p to i64
+  %adda = add i64 %a, 7
+  %i = ptrtoint ptr %p to i64
+  %addi = add i64 %i, 7
+  %r = add i64 %adda, %addi
+  ret i64 %r
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/209164


More information about the llvm-commits mailing list