Skip to content

Commit cd68d7b

Browse files
authored
[Pipelines] Do not run CoroSplit and CoroCleanup in LTO pre-link pipeline (#90310)
Skip CoroSplit and CoroCleanup in LTO pre-link pipeline so that CoroElide can happen after callee coroutine is imported into caller's module in ThinLTO.
1 parent fe3f6c6 commit cd68d7b

File tree

6 files changed

+88
-12
lines changed

6 files changed

+88
-12
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// This tests that the coroutine elide optimization could happen succesfully with ThinLTO.
2+
// This test is adapted from coro-elide.cpp and splits functions into two files.
3+
//
4+
// RUN: split-file %s %t
5+
// RUN: %clang --target=x86_64-linux -std=c++20 -O2 -flto=thin -I %S -c %t/coro-elide-callee.cpp -o coro-elide-callee.o
6+
// RUN: %clang --target=x86_64-linux -std=c++20 -O2 -flto=thin -I %S -c %t/coro-elide-caller.cpp -o coro-elide-caller.o
7+
// RUN: llvm-lto -thinlto coro-elide-callee.o coro-elide-caller.o -o summary
8+
// RUN: %clang_cc1 -O2 -x ir coro-elide-caller.o -fthinlto-index=summary.thinlto.bc -emit-llvm -o - | FileCheck %s
9+
10+
//--- coro-elide-task.h
11+
#pragma once
12+
#include "Inputs/coroutine.h"
13+
14+
struct Task {
15+
struct promise_type {
16+
struct FinalAwaiter {
17+
bool await_ready() const noexcept { return false; }
18+
template <typename PromiseType>
19+
std::coroutine_handle<> await_suspend(std::coroutine_handle<PromiseType> h) noexcept {
20+
if (!h)
21+
return std::noop_coroutine();
22+
return h.promise().continuation;
23+
}
24+
void await_resume() noexcept {}
25+
};
26+
Task get_return_object() noexcept {
27+
return std::coroutine_handle<promise_type>::from_promise(*this);
28+
}
29+
std::suspend_always initial_suspend() noexcept { return {}; }
30+
FinalAwaiter final_suspend() noexcept { return {}; }
31+
void unhandled_exception() noexcept {}
32+
void return_value(int x) noexcept {
33+
_value = x;
34+
}
35+
std::coroutine_handle<> continuation;
36+
int _value;
37+
};
38+
39+
Task(std::coroutine_handle<promise_type> handle) : handle(handle) {}
40+
~Task() {
41+
if (handle)
42+
handle.destroy();
43+
}
44+
45+
struct Awaiter {
46+
bool await_ready() const noexcept { return false; }
47+
void await_suspend(std::coroutine_handle<void> continuation) noexcept {}
48+
int await_resume() noexcept {
49+
return 43;
50+
}
51+
};
52+
53+
auto operator co_await() {
54+
return Awaiter{};
55+
}
56+
57+
private:
58+
std::coroutine_handle<promise_type> handle;
59+
};
60+
61+
//--- coro-elide-callee.cpp
62+
#include "coro-elide-task.h"
63+
Task task0() {
64+
co_return 43;
65+
}
66+
67+
//--- coro-elide-caller.cpp
68+
#include "coro-elide-task.h"
69+
70+
Task task0();
71+
72+
Task task1() {
73+
co_return co_await task0();
74+
}
75+
76+
// CHECK-LABEL: define{{.*}} void @_Z5task1v.resume
77+
// CHECK-NOT: {{.*}}_Znwm

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,8 @@ PassBuilder::buildInlinerPipeline(OptimizationLevel Level,
963963
MainCGPipeline.addPass(createCGSCCToFunctionPassAdaptor(
964964
RequireAnalysisPass<ShouldNotRunFunctionPassesAnalysis, Function>()));
965965

966-
MainCGPipeline.addPass(CoroSplitPass(Level != OptimizationLevel::O0));
966+
if (!isLTOPreLink(Phase))
967+
MainCGPipeline.addPass(CoroSplitPass(Level != OptimizationLevel::O0));
967968

968969
// Make sure we don't affect potential future NoRerun CGSCC adaptors.
969970
MIWP.addLateModulePass(createModuleToFunctionPassAdaptor(
@@ -1005,8 +1006,9 @@ PassBuilder::buildModuleInlinerPipeline(OptimizationLevel Level,
10051006
buildFunctionSimplificationPipeline(Level, Phase),
10061007
PTO.EagerlyInvalidateAnalyses));
10071008

1008-
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
1009-
CoroSplitPass(Level != OptimizationLevel::O0)));
1009+
if (!isLTOPreLink(Phase))
1010+
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
1011+
CoroSplitPass(Level != OptimizationLevel::O0)));
10101012

10111013
return MPM;
10121014
}
@@ -1183,7 +1185,8 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
11831185
// and argument promotion.
11841186
MPM.addPass(DeadArgumentEliminationPass());
11851187

1186-
MPM.addPass(CoroCleanupPass());
1188+
if (!isLTOPreLink(Phase))
1189+
MPM.addPass(CoroCleanupPass());
11871190

11881191
// Optimize globals now that functions are fully simplified.
11891192
MPM.addPass(GlobalOptPass());

llvm/test/Other/new-pm-defaults.ll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,14 @@
224224
; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass
225225
; CHECK-O-NEXT: Running pass: RequireAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis
226226
; CHECK-O-NEXT: Running analysis: ShouldNotRunFunctionPassesAnalysis
227-
; CHECK-O-NEXT: Running pass: CoroSplitPass
227+
; CHECK-DEFAULT-NEXT: Running pass: CoroSplitPass
228+
; CHECK-LTO-NOT: Running pass: CoroSplitPass
228229
; CHECK-O-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis
229230
; CHECK-O-NEXT: Invalidating analysis: ShouldNotRunFunctionPassesAnalysis
230231
; CHECK-O-NEXT: Invalidating analysis: InlineAdvisorAnalysis
231232
; CHECK-O-NEXT: Running pass: DeadArgumentEliminationPass
232-
; CHECK-O-NEXT: Running pass: CoroCleanupPass
233+
; CHECK-DEFAULT-NEXT: Running pass: CoroCleanupPass
234+
; CHECK-LTO-NOT: Running pass: CoroCleanupPass
233235
; CHECK-O-NEXT: Running pass: GlobalOptPass
234236
; CHECK-O-NEXT: Running pass: GlobalDCEPass
235237
; CHECK-DEFAULT-NEXT: Running pass: EliminateAvailableExternallyPass

llvm/test/Other/new-pm-thinlto-prelink-defaults.ll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,10 @@
183183
; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass
184184
; CHECK-O-NEXT: Running pass: RequireAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis
185185
; CHECK-O-NEXT: Running analysis: ShouldNotRunFunctionPassesAnalysis
186-
; CHECK-O-NEXT: Running pass: CoroSplitPass
187186
; CHECK-O-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis
188187
; CHECK-O-NEXT: Invalidating analysis: ShouldNotRunFunctionPassesAnalysis
189188
; CHECK-O-NEXT: Invalidating analysis: InlineAdvisorAnalysis
190189
; CHECK-O-NEXT: Running pass: DeadArgumentEliminationPass
191-
; CHECK-O-NEXT: Running pass: CoroCleanupPass
192190
; CHECK-O-NEXT: Running pass: GlobalOptPass
193191
; CHECK-O-NEXT: Running pass: GlobalDCEPass
194192
; CHECK-EXT: Running pass: {{.*}}::Bye

llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,10 @@
182182
; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass
183183
; CHECK-O-NEXT: Running pass: RequireAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis
184184
; CHECK-O-NEXT: Running analysis: ShouldNotRunFunctionPassesAnalysis
185-
; CHECK-O-NEXT: Running pass: CoroSplitPass
186185
; CHECK-O-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis
187186
; CHECK-O-NEXT: Invalidating analysis: ShouldNotRunFunctionPassesAnalysis
188187
; CHECK-O-NEXT: Invalidating analysis: InlineAdvisorAnalysis
189188
; CHECK-O-NEXT: Running pass: DeadArgumentEliminationPass
190-
; CHECK-O-NEXT: Running pass: CoroCleanupPass
191189
; CHECK-O-NEXT: Running pass: GlobalOptPass
192190
; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis on bar
193191
; CHECK-O-NEXT: Running pass: GlobalDCEPass

llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,10 @@
147147
; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass
148148
; CHECK-O-NEXT: Running pass: RequireAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis
149149
; CHECK-O-NEXT: Running analysis: ShouldNotRunFunctionPassesAnalysis
150-
; CHECK-O-NEXT: Running pass: CoroSplitPass
151150
; CHECK-O-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis
152151
; CHECK-O-NEXT: Invalidating analysis: ShouldNotRunFunctionPassesAnalysis
153152
; CHECK-O-NEXT: Invalidating analysis: InlineAdvisorAnalysis
154153
; CHECK-O-NEXT: Running pass: DeadArgumentEliminationPass
155-
; CHECK-O-NEXT: Running pass: CoroCleanupPass
156154
; CHECK-O-NEXT: Running pass: GlobalOptPass
157155
; CHECK-O-NEXT: Running pass: GlobalDCEPass
158156
; CHECK-O-NEXT: Running pass: AnnotationRemarksPass on foo

0 commit comments

Comments
 (0)