[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