[llvm] [GVN] Handle provenance when propagating assume equality (PR #151953)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 4 06:27:01 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Nikita Popov (nikic)
<details>
<summary>Changes</summary>
If we have a known `p == p2` equality, we cannot replace `p2` with `p` unless they are known to have the same provenance. GVN handles this when propagating equalities from conditions, but not for assumes, as these go through a different code path for uses in the same block.
Call canReplacePointersInUseIfEqual() before performing the replacement. This is subject to the usual approximations (e.g. that we always allow replacement with a dereferenceable constant and null).
This restriction does not appear to have any impact in practice.
---
Full diff: https://github.com/llvm/llvm-project/pull/151953.diff
3 Files Affected:
- (modified) llvm/lib/Transforms/Scalar/GVN.cpp (+4-4)
- (modified) llvm/test/Transforms/GVN/assume-equal.ll (+44)
- (modified) llvm/test/Transforms/GVN/lifetime-simple.ll (+1-1)
``````````diff
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index fa6ee95d33d10..d6f55bbea7abe 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -2499,11 +2499,11 @@ void GVNPass::assignBlockRPONumber(Function &F) {
bool GVNPass::replaceOperandsForInBlockEquality(Instruction *Instr) const {
bool Changed = false;
for (unsigned OpNum = 0; OpNum < Instr->getNumOperands(); ++OpNum) {
- Value *Operand = Instr->getOperand(OpNum);
- auto It = ReplaceOperandsWithMap.find(Operand);
+ Use &Operand = Instr->getOperandUse(OpNum);
+ auto It = ReplaceOperandsWithMap.find(Operand.get());
if (It != ReplaceOperandsWithMap.end()) {
- // Do not replace lifetime alloca argument with something else.
- if (Instr->isLifetimeStartOrEnd())
+ const DataLayout &DL = Instr->getDataLayout();
+ if (!canReplacePointersInUseIfEqual(Operand, It->second, DL))
continue;
LLVM_DEBUG(dbgs() << "GVN replacing: " << *Operand << " with "
diff --git a/llvm/test/Transforms/GVN/assume-equal.ll b/llvm/test/Transforms/GVN/assume-equal.ll
index a27b0e45bf9e1..0c922daf82b32 100644
--- a/llvm/test/Transforms/GVN/assume-equal.ll
+++ b/llvm/test/Transforms/GVN/assume-equal.ll
@@ -343,6 +343,50 @@ meh:
ret i1 %k
}
+define i8 @assume_ptr_eq_different_prov_matters(ptr %p, ptr %p2) {
+; CHECK-LABEL: define i8 @assume_ptr_eq_different_prov_matters(
+; CHECK-SAME: ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P2]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[P2]], align 1
+; CHECK-NEXT: ret i8 [[V]]
+;
+ %cmp = icmp eq ptr %p, %p2
+ call void @llvm.assume(i1 %cmp)
+ %v = load i8, ptr %p2
+ ret i8 %v
+}
+
+define i1 @assume_ptr_eq_different_prov_does_not_matter(ptr %p, ptr %p2) {
+; CHECK-LABEL: define i1 @assume_ptr_eq_different_prov_does_not_matter(
+; CHECK-SAME: ptr [[P:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P2]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P]], null
+; CHECK-NEXT: ret i1 [[C]]
+;
+ %cmp = icmp eq ptr %p, %p2
+ call void @llvm.assume(i1 %cmp)
+ %c = icmp eq ptr %p2, null
+ ret i1 %c
+}
+
+define i8 @assume_ptr_eq_same_prov(ptr %p, i64 %x) {
+; CHECK-LABEL: define i8 @assume_ptr_eq_same_prov(
+; CHECK-SAME: ptr [[P:%.*]], i64 [[X:%.*]]) {
+; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 [[X]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P2]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[P]], align 1
+; CHECK-NEXT: ret i8 [[V]]
+;
+ %p2 = getelementptr i8, ptr %p, i64 %x
+ %cmp = icmp eq ptr %p, %p2
+ call void @llvm.assume(i1 %cmp)
+ %v = load i8, ptr %p2
+ ret i8 %v
+}
+
declare noalias ptr @_Znwm(i64)
declare void @_ZN1AC1Ev(ptr)
declare void @llvm.assume(i1)
diff --git a/llvm/test/Transforms/GVN/lifetime-simple.ll b/llvm/test/Transforms/GVN/lifetime-simple.ll
index 30883bd9dc6d3..89ca127a47fda 100644
--- a/llvm/test/Transforms/GVN/lifetime-simple.ll
+++ b/llvm/test/Transforms/GVN/lifetime-simple.ll
@@ -29,7 +29,7 @@ define void @assume_eq_arg(ptr %arg) {
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[ALLOCA]], [[ARG]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[ALLOCA]])
-; CHECK-NEXT: store volatile i32 0, ptr [[ARG]], align 4
+; CHECK-NEXT: store volatile i32 0, ptr [[ALLOCA]], align 4
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[ALLOCA]])
; CHECK-NEXT: ret void
;
``````````
</details>
https://github.com/llvm/llvm-project/pull/151953
More information about the llvm-commits
mailing list