Skip to content

Commit 4b5b36e

Browse files
committed
[GVN] Avoid creating lifetime of non-alloca
There is a larger problem here in that we should not be performing arbitrary pointer replacements for assumes. This is handled for branches, but assume goes through a different code path. Fixes #151785.
1 parent 1feed44 commit 4b5b36e

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

llvm/lib/Analysis/Loads.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,10 @@ bool llvm::canReplacePointersInUseIfEqual(const Use &U, const Value *To,
833833
if (!To->getType()->isPointerTy())
834834
return true;
835835

836+
// Do not perform replacements in lifetime intrinsic arguments.
837+
if (isa<LifetimeIntrinsic>(U.getUser()))
838+
return false;
839+
836840
if (isPointerAlwaysReplaceable(&*U, To, DL))
837841
return true;
838842
return isPointerUseReplacable(U);

llvm/lib/Transforms/Scalar/GVN.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2502,6 +2502,10 @@ bool GVNPass::replaceOperandsForInBlockEquality(Instruction *Instr) const {
25022502
Value *Operand = Instr->getOperand(OpNum);
25032503
auto It = ReplaceOperandsWithMap.find(Operand);
25042504
if (It != ReplaceOperandsWithMap.end()) {
2505+
// Do not replace lifetime alloca argument with something else.
2506+
if (Instr->isLifetimeStartOrEnd())
2507+
continue;
2508+
25052509
LLVM_DEBUG(dbgs() << "GVN replacing: " << *Operand << " with "
25062510
<< *It->second << " in instruction " << *Instr << '\n');
25072511
Instr->setOperand(OpNum, It->second);

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

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,71 @@ entry:
2222
ret i8 %1
2323
}
2424

25+
define void @assume_eq_arg(ptr %arg) {
26+
; CHECK-LABEL: define void @assume_eq_arg(
27+
; CHECK-SAME: ptr [[ARG:%.*]]) {
28+
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i32, align 4
29+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[ALLOCA]], [[ARG]]
30+
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
31+
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[ALLOCA]])
32+
; CHECK-NEXT: store volatile i32 0, ptr [[ARG]], align 4
33+
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[ALLOCA]])
34+
; CHECK-NEXT: ret void
35+
;
36+
%alloca = alloca i32
37+
%cmp = icmp eq ptr %alloca, %arg
38+
call void @llvm.assume(i1 %cmp)
39+
call void @llvm.lifetime.start.p0(i64 4, ptr %alloca)
40+
store volatile i32 0, ptr %alloca
41+
call void @llvm.lifetime.end.p0(i64 4, ptr %alloca)
42+
ret void
43+
}
44+
45+
define void @assume_eq_null() {
46+
; CHECK-LABEL: define void @assume_eq_null() {
47+
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i32, align 4, addrspace(1)
48+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr addrspace(1) [[ALLOCA]], null
49+
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
50+
; CHECK-NEXT: call void @llvm.lifetime.start.p1(i64 4, ptr addrspace(1) [[ALLOCA]])
51+
; CHECK-NEXT: store volatile i32 0, ptr addrspace(1) null, align 4
52+
; CHECK-NEXT: call void @llvm.lifetime.end.p1(i64 4, ptr addrspace(1) [[ALLOCA]])
53+
; CHECK-NEXT: ret void
54+
;
55+
%alloca = alloca i32, addrspace(1)
56+
%cmp = icmp eq ptr addrspace(1) %alloca, null
57+
call void @llvm.assume(i1 %cmp)
58+
call void @llvm.lifetime.start.p1(i64 4, ptr addrspace(1) %alloca)
59+
store volatile i32 0, ptr addrspace(1) %alloca
60+
call void @llvm.lifetime.end.p1(i64 4, ptr addrspace(1) %alloca)
61+
ret void
62+
}
63+
64+
define void @dom_eq_null() {
65+
; CHECK-LABEL: define void @dom_eq_null() {
66+
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i32, align 4, addrspace(1)
67+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr addrspace(1) [[ALLOCA]], null
68+
; CHECK-NEXT: br i1 [[CMP]], label %[[IF:.*]], label %[[ELSE:.*]]
69+
; CHECK: [[IF]]:
70+
; CHECK-NEXT: call void @llvm.lifetime.start.p1(i64 4, ptr addrspace(1) [[ALLOCA]])
71+
; CHECK-NEXT: store volatile i32 0, ptr addrspace(1) null, align 4
72+
; CHECK-NEXT: call void @llvm.lifetime.end.p1(i64 4, ptr addrspace(1) [[ALLOCA]])
73+
; CHECK-NEXT: ret void
74+
; CHECK: [[ELSE]]:
75+
; CHECK-NEXT: ret void
76+
;
77+
%alloca = alloca i32, addrspace(1)
78+
%cmp = icmp eq ptr addrspace(1) %alloca, null
79+
br i1 %cmp, label %if, label %else
80+
81+
if:
82+
call void @llvm.lifetime.start.p1(i64 4, ptr addrspace(1) %alloca)
83+
store volatile i32 0, ptr addrspace(1) %alloca
84+
call void @llvm.lifetime.end.p1(i64 4, ptr addrspace(1) %alloca)
85+
ret void
86+
87+
else:
88+
ret void
89+
}
90+
2591
declare void @llvm.lifetime.start.p0(i64 %S, ptr nocapture %P) readonly
2692
declare void @llvm.lifetime.end.p0(i64 %S, ptr nocapture %P)

0 commit comments

Comments
 (0)