Skip to content

Commit fb632ed

Browse files
authored
[GVN] Handle provenance when propagating assume equality (#151953)
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.
1 parent fcae1ba commit fb632ed

File tree

3 files changed

+49
-5
lines changed

3 files changed

+49
-5
lines changed

llvm/lib/Transforms/Scalar/GVN.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2499,11 +2499,11 @@ void GVNPass::assignBlockRPONumber(Function &F) {
24992499
bool GVNPass::replaceOperandsForInBlockEquality(Instruction *Instr) const {
25002500
bool Changed = false;
25012501
for (unsigned OpNum = 0; OpNum < Instr->getNumOperands(); ++OpNum) {
2502-
Value *Operand = Instr->getOperand(OpNum);
2503-
auto It = ReplaceOperandsWithMap.find(Operand);
2502+
Use &Operand = Instr->getOperandUse(OpNum);
2503+
auto It = ReplaceOperandsWithMap.find(Operand.get());
25042504
if (It != ReplaceOperandsWithMap.end()) {
2505-
// Do not replace lifetime alloca argument with something else.
2506-
if (Instr->isLifetimeStartOrEnd())
2505+
const DataLayout &DL = Instr->getDataLayout();
2506+
if (!canReplacePointersInUseIfEqual(Operand, It->second, DL))
25072507
continue;
25082508

25092509
LLVM_DEBUG(dbgs() << "GVN replacing: " << *Operand << " with "

llvm/test/Transforms/GVN/assume-equal.ll

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,50 @@ meh:
343343
ret i1 %k
344344
}
345345

346+
define i8 @assume_ptr_eq_different_prov_matters(ptr %p, ptr %p2) {
347+
; CHECK-LABEL: define i8 @assume_ptr_eq_different_prov_matters(
348+
; CHECK-SAME: ptr [[P:%.*]], ptr [[P2:%.*]]) {
349+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P2]]
350+
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
351+
; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[P2]], align 1
352+
; CHECK-NEXT: ret i8 [[V]]
353+
;
354+
%cmp = icmp eq ptr %p, %p2
355+
call void @llvm.assume(i1 %cmp)
356+
%v = load i8, ptr %p2
357+
ret i8 %v
358+
}
359+
360+
define i1 @assume_ptr_eq_different_prov_does_not_matter(ptr %p, ptr %p2) {
361+
; CHECK-LABEL: define i1 @assume_ptr_eq_different_prov_does_not_matter(
362+
; CHECK-SAME: ptr [[P:%.*]], ptr [[P2:%.*]]) {
363+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P2]]
364+
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
365+
; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P]], null
366+
; CHECK-NEXT: ret i1 [[C]]
367+
;
368+
%cmp = icmp eq ptr %p, %p2
369+
call void @llvm.assume(i1 %cmp)
370+
%c = icmp eq ptr %p2, null
371+
ret i1 %c
372+
}
373+
374+
define i8 @assume_ptr_eq_same_prov(ptr %p, i64 %x) {
375+
; CHECK-LABEL: define i8 @assume_ptr_eq_same_prov(
376+
; CHECK-SAME: ptr [[P:%.*]], i64 [[X:%.*]]) {
377+
; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 [[X]]
378+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], [[P2]]
379+
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
380+
; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[P]], align 1
381+
; CHECK-NEXT: ret i8 [[V]]
382+
;
383+
%p2 = getelementptr i8, ptr %p, i64 %x
384+
%cmp = icmp eq ptr %p, %p2
385+
call void @llvm.assume(i1 %cmp)
386+
%v = load i8, ptr %p2
387+
ret i8 %v
388+
}
389+
346390
declare noalias ptr @_Znwm(i64)
347391
declare void @_ZN1AC1Ev(ptr)
348392
declare void @llvm.assume(i1)

llvm/test/Transforms/GVN/lifetime-simple.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ define void @assume_eq_arg(ptr %arg) {
2929
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[ALLOCA]], [[ARG]]
3030
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
3131
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[ALLOCA]])
32-
; CHECK-NEXT: store volatile i32 0, ptr [[ARG]], align 4
32+
; CHECK-NEXT: store volatile i32 0, ptr [[ALLOCA]], align 4
3333
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[ALLOCA]])
3434
; CHECK-NEXT: ret void
3535
;

0 commit comments

Comments
 (0)