[llvm] [SCCP] Consider provenance when propagating constant ptrs (PR #160083)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 22 05:15:53 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-analysis

Author: Antonio Frighetto (antoniofrighetto)

<details>
<summary>Changes</summary>

Similarly to what it is being already done in GVN (fb632ed2377d280b581b8d4653b855e60d611f77), make sure pointers equalities derived via PredicatedInfo may be propagated, taking into account their provenance as well.

Fixes: https://github.com/llvm/llvm-project/issues/159565.

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


4 Files Affected:

- (modified) llvm/lib/Analysis/Loads.cpp (+2-2) 
- (modified) llvm/lib/Transforms/Utils/SCCPSolver.cpp (+22-1) 
- (modified) llvm/test/Transforms/SCCP/assume.ll (+11) 
- (modified) llvm/test/Transforms/SCCP/replace-dereferenceable-ptr-with-undereferenceable.ll (+2-2) 


``````````diff
diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp
index 0c4e3a2e3b233..bb8724d8af9d1 100644
--- a/llvm/lib/Analysis/Loads.cpp
+++ b/llvm/lib/Analysis/Loads.cpp
@@ -799,7 +799,7 @@ Value *llvm::FindAvailableLoadedValue(LoadInst *Load, BatchAAResults &AA,
 
 // Returns true if a use is either in an ICmp/PtrToInt or a Phi/Select that only
 // feeds into them.
-static bool isPointerUseReplacable(const Use &U) {
+static bool isPointerUseReplaceable(const Use &U) {
   unsigned Limit = 40;
   SmallVector<const User *> Worklist({U.getUser()});
   SmallPtrSet<const User *, 8> Visited;
@@ -847,7 +847,7 @@ bool llvm::canReplacePointersInUseIfEqual(const Use &U, const Value *To,
 
   if (isPointerAlwaysReplaceable(&*U, To, DL))
     return true;
-  return isPointerUseReplacable(U);
+  return isPointerUseReplaceable(U);
 }
 
 bool llvm::canReplacePointersIfEqual(const Value *From, const Value *To,
diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
index af216cd9214bf..27e285fd74bf6 100644
--- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp
+++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
@@ -16,6 +16,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/Analysis/InstructionSimplify.h"
+#include "llvm/Analysis/Loads.h"
 #include "llvm/Analysis/ValueLattice.h"
 #include "llvm/Analysis/ValueLatticeUtils.h"
 #include "llvm/Analysis/ValueTracking.h"
@@ -82,6 +83,26 @@ bool SCCPSolver::tryToReplaceWithConstant(Value *V) {
     return false;
   }
 
+  // Perform constant pointer propagation as long as assuming PredicateInfo
+  // derived equality between the two holds, and their provenance is the same.
+  if (auto *I = dyn_cast<Instruction>(V); I && I->getType()->isPointerTy()) {
+    if (getPredicateInfoFor(I)) {
+      bool MadeChange = false;
+      const auto &DL = I->getDataLayout();
+
+      I->replaceUsesWithIf(Const, [&](Use &U) {
+        bool CanReplace = canReplacePointersInUseIfEqual(U, Const, DL);
+        if (CanReplace)
+          LLVM_DEBUG(dbgs() << "  Constant pointer: " << *Const << " = " << *V
+                            << '\n');
+
+        MadeChange |= CanReplace;
+        return CanReplace;
+      });
+      return MadeChange;
+    }
+  }
+
   LLVM_DEBUG(dbgs() << "  Constant: " << *Const << " = " << *V << '\n');
 
   // Replaces all of the uses of a variable with uses of the constant.
@@ -350,7 +371,7 @@ bool SCCPSolver::simplifyInstsInBlock(BasicBlock &BB,
     if (Inst.getType()->isVoidTy())
       continue;
     if (tryToReplaceWithConstant(&Inst)) {
-      if (wouldInstructionBeTriviallyDead(&Inst))
+      if (isInstructionTriviallyDead(&Inst))
         Inst.eraseFromParent();
 
       MadeChanges = true;
diff --git a/llvm/test/Transforms/SCCP/assume.ll b/llvm/test/Transforms/SCCP/assume.ll
index 9beee934bb509..28df0cc6ce5f1 100644
--- a/llvm/test/Transforms/SCCP/assume.ll
+++ b/llvm/test/Transforms/SCCP/assume.ll
@@ -119,3 +119,14 @@ define void @neg_trunc(i8 %v) {
   call void @use(i1 %c4)
   ret void
 }
+
+define ptr @assume_pointers_equality_maybe_different_provenance(ptr %x) {
+; CHECK-LABEL: @assume_pointers_equality_maybe_different_provenance(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[X:%.*]], inttoptr (i64 12345678 to ptr)
+; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT:    ret ptr [[X]]
+;
+  %cmp = icmp eq ptr %x, inttoptr (i64 12345678 to ptr)
+  call void @llvm.assume(i1 %cmp)
+  ret ptr %x
+}
diff --git a/llvm/test/Transforms/SCCP/replace-dereferenceable-ptr-with-undereferenceable.ll b/llvm/test/Transforms/SCCP/replace-dereferenceable-ptr-with-undereferenceable.ll
index 39af513a4506c..f336fcbe70c77 100644
--- a/llvm/test/Transforms/SCCP/replace-dereferenceable-ptr-with-undereferenceable.ll
+++ b/llvm/test/Transforms/SCCP/replace-dereferenceable-ptr-with-undereferenceable.ll
@@ -11,7 +11,7 @@ define i32 @eq_undereferenceable(ptr %p) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[P:%.*]], getelementptr inbounds (i32, ptr @x, i64 1)
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
 ; CHECK:       if.then:
-; CHECK-NEXT:    store i32 2, ptr getelementptr inbounds (i32, ptr @x, i64 1), align 4
+; CHECK-NEXT:    store i32 2, ptr [[P]], align 4
 ; CHECK-NEXT:    br label [[IF_END]]
 ; CHECK:       if.end:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr @y, align 4
@@ -65,7 +65,7 @@ define i1 @eq_undereferenceable_cmp_simp(ptr %p) {
 ; CHECK-NEXT:    [[CMP_0:%.*]] = icmp eq ptr [[P:%.*]], getelementptr inbounds (i32, ptr @x, i64 1)
 ; CHECK-NEXT:    br i1 [[CMP_0]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
 ; CHECK:       if.then:
-; CHECK-NEXT:    store i32 2, ptr getelementptr inbounds (i32, ptr @x, i64 1), align 4
+; CHECK-NEXT:    store i32 2, ptr [[P]], align 4
 ; CHECK-NEXT:    ret i1 true
 ; CHECK:       if.end:
 ; CHECK-NEXT:    ret i1 false

``````````

</details>


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


More information about the llvm-commits mailing list