Skip to content

Commit b425b5a

Browse files
[Coroutines] Fix another crash related to CallGraph update
1 parent 92604cf commit b425b5a

File tree

2 files changed

+165
-3
lines changed

2 files changed

+165
-3
lines changed

llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,10 @@ PreservedAnalyses CoroAnnotationElidePass::run(LazyCallGraph::SCC &C,
146146
bool HasAttr = CB->hasFnAttr(llvm::Attribute::CoroElideSafe);
147147
if (IsCallerPresplitCoroutine && HasAttr) {
148148
auto *CallerN = CG.lookup(*Caller);
149-
auto *CallerC = CG.lookupSCC(*CallerN);
149+
auto *CallerC = CallerN ? CG.lookupSCC(*CallerN) : nullptr;
150+
// If CallerC is nullptr, it means LazyCallGraph hasn't visited Caller
151+
// yet. Skip the call graph update.
152+
auto ShouldUpdateCallGraph = !!CallerC;
150153
processCall(CB, Caller, NewCallee, FrameSize, FrameAlign);
151154

152155
ORE.emit([&]() {
@@ -158,8 +161,9 @@ PreservedAnalyses CoroAnnotationElidePass::run(LazyCallGraph::SCC &C,
158161

159162
FAM.invalidate(*Caller, PreservedAnalyses::none());
160163
Changed = true;
161-
updateCGAndAnalysisManagerForCGSCCPass(CG, *CallerC, *CallerN, AM, UR,
162-
FAM);
164+
if (ShouldUpdateCallGraph)
165+
updateCGAndAnalysisManagerForCGSCCPass(CG, *CallerC, *CallerN, AM, UR,
166+
FAM);
163167

164168
} else {
165169
ORE.emit([&]() {
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
; RUN: opt -passes="cgscc(coro-annotation-elide)" -S < %s | FileCheck %s
2+
3+
%foo.Frame = type { ptr, ptr, i1 }
4+
5+
@foo.resumers = private constant [3 x ptr] [ptr @foo.resume, ptr @foo.destroy, ptr @foo.cleanup]
6+
@foo.resumers.1 = private constant [4 x ptr] [ptr @foo.resume, ptr @foo.destroy, ptr @foo.cleanup, ptr @foo.noalloc]
7+
8+
; CHECK-LABEL: define void @foo
9+
define void @foo(ptr %agg.result, ptr %this) personality ptr null {
10+
entry:
11+
%0 = call token @llvm.coro.id(i32 0, ptr null, ptr nonnull @foo, ptr @foo.resumers.1)
12+
%1 = call noalias nonnull ptr @llvm.coro.begin(token %0, ptr null)
13+
%resume.addr = getelementptr inbounds nuw %foo.Frame, ptr %1, i32 0, i32 0
14+
store ptr @foo.resume, ptr %resume.addr, align 8
15+
%destroy.addr = getelementptr inbounds nuw %foo.Frame, ptr %1, i32 0, i32 1
16+
store ptr @foo.destroy, ptr %destroy.addr, align 8
17+
br label %AllocaSpillBB
18+
19+
AllocaSpillBB: ; preds = %entry
20+
br label %PostSpill
21+
22+
PostSpill: ; preds = %AllocaSpillBB
23+
br label %CoroSave
24+
25+
CoroSave: ; preds = %PostSpill
26+
%index.addr1 = getelementptr inbounds nuw %foo.Frame, ptr %1, i32 0, i32 2
27+
store i1 false, ptr %index.addr1, align 1
28+
br label %CoroSuspend
29+
30+
CoroSuspend: ; preds = %CoroSave
31+
br label %resume.0.landing
32+
33+
resume.0.landing: ; preds = %CoroSuspend
34+
br label %AfterCoroSuspend
35+
36+
AfterCoroSuspend: ; preds = %resume.0.landing
37+
ret void
38+
}
39+
40+
; CHECK-LABEL: define internal void @bar
41+
; Function Attrs: presplitcoroutine
42+
define internal void @bar() #0 personality ptr null {
43+
entry:
44+
; CHECK: %[[CALLEE_FRAME:.+]] = alloca [24 x i8], align 8
45+
%0 = call token @llvm.coro.id(i32 0, ptr null, ptr nonnull @bar, ptr null)
46+
%1 = call i1 @llvm.coro.alloc(token %0)
47+
call void @foo(ptr null, ptr null) #4
48+
; CHECK: %[[FOO_ID:.+]] = call token @llvm.coro.id(i32 0, ptr null, ptr nonnull @foo, ptr @foo.resumers)
49+
; CHECK-NEXT: store ptr @foo.resume, ptr %[[CALLEE_FRAME]], align 8
50+
; CHECK-NEXT: %[[DESTROY_ADDR:.+]] = getelementptr inbounds nuw %foo.Frame, ptr %[[CALLEE_FRAME]], i32 0, i32 1
51+
; CHECK-NEXT: store ptr @foo.destroy, ptr %[[DESTROY_ADDR]], align 8
52+
; CHECK-NEXT: %[[INDEX_ADDR:.+]] = getelementptr inbounds nuw %foo.Frame, ptr %[[CALLEE_FRAME]], i32 0, i32 2
53+
; CHECK-NEXT: store i1 false, ptr %[[INDEX_ADDR]], align 1
54+
; CHECK: ret void
55+
ret void
56+
}
57+
58+
; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: read)
59+
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
60+
61+
; Function Attrs: nounwind
62+
declare i1 @llvm.coro.alloc(token) #2
63+
64+
; Function Attrs: nounwind
65+
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
66+
67+
; Function Attrs: nomerge nounwind
68+
declare token @llvm.coro.save(ptr) #3
69+
70+
; Function Attrs: nounwind
71+
declare i8 @llvm.coro.suspend(token, i1) #2
72+
73+
define internal fastcc void @foo.resume(ptr noundef nonnull align 8 dereferenceable(24) %0) personality ptr null {
74+
entry.resume:
75+
br label %resume.entry
76+
77+
resume.0: ; preds = %resume.entry
78+
br label %resume.0.landing
79+
80+
resume.0.landing: ; preds = %resume.0
81+
br label %AfterCoroSuspend
82+
83+
AfterCoroSuspend: ; preds = %resume.0.landing
84+
unreachable
85+
86+
resume.entry: ; preds = %entry.resume
87+
br label %resume.0
88+
}
89+
90+
define internal fastcc void @foo.destroy(ptr noundef nonnull align 8 dereferenceable(24) %0) personality ptr null {
91+
entry.destroy:
92+
br label %resume.entry
93+
94+
resume.0: ; preds = %resume.entry
95+
br label %resume.0.landing
96+
97+
resume.0.landing: ; preds = %resume.0
98+
br label %AfterCoroSuspend
99+
100+
AfterCoroSuspend: ; preds = %resume.0.landing
101+
unreachable
102+
103+
resume.entry: ; preds = %entry.destroy
104+
br label %resume.0
105+
}
106+
107+
define internal fastcc void @foo.cleanup(ptr noundef nonnull align 8 dereferenceable(24) %0) personality ptr null {
108+
entry.cleanup:
109+
br label %resume.entry
110+
111+
resume.0: ; preds = %resume.entry
112+
br label %resume.0.landing
113+
114+
resume.0.landing: ; preds = %resume.0
115+
br label %AfterCoroSuspend
116+
117+
AfterCoroSuspend: ; preds = %resume.0.landing
118+
unreachable
119+
120+
resume.entry: ; preds = %entry.cleanup
121+
br label %resume.0
122+
}
123+
124+
define internal void @foo.noalloc(ptr %0, ptr %1, ptr noundef nonnull align 8 dereferenceable(24) %2) personality ptr null {
125+
entry:
126+
%3 = call token @llvm.coro.id(i32 0, ptr null, ptr nonnull @foo, ptr @foo.resumers)
127+
%resume.addr = getelementptr inbounds nuw %foo.Frame, ptr %2, i32 0, i32 0
128+
store ptr @foo.resume, ptr %resume.addr, align 8
129+
%destroy.addr = getelementptr inbounds nuw %foo.Frame, ptr %2, i32 0, i32 1
130+
store ptr @foo.destroy, ptr %destroy.addr, align 8
131+
br label %AllocaSpillBB
132+
133+
AllocaSpillBB: ; preds = %entry
134+
br label %PostSpill
135+
136+
PostSpill: ; preds = %AllocaSpillBB
137+
br label %CoroSave
138+
139+
CoroSave: ; preds = %PostSpill
140+
%index.addr1 = getelementptr inbounds nuw %foo.Frame, ptr %2, i32 0, i32 2
141+
store i1 false, ptr %index.addr1, align 1
142+
br label %CoroSuspend
143+
144+
CoroSuspend: ; preds = %CoroSave
145+
br label %resume.0.landing
146+
147+
resume.0.landing: ; preds = %CoroSuspend
148+
br label %AfterCoroSuspend
149+
150+
AfterCoroSuspend: ; preds = %resume.0.landing
151+
ret void
152+
}
153+
154+
attributes #0 = { presplitcoroutine }
155+
attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: read) }
156+
attributes #2 = { nounwind }
157+
attributes #3 = { nomerge nounwind }
158+
attributes #4 = { coro_elide_safe }

0 commit comments

Comments
 (0)