https://github.com/apolloww updated https://github.com/llvm/llvm-project/pull/100205
>From 041670dc6a8e9f6a86af152567f0705034db6ad2 Mon Sep 17 00:00:00 2001 From: Wei Wang <apollo.mobil...@gmail.com> Date: Mon, 29 Apr 2024 10:24:53 -0700 Subject: [PATCH 1/2] [Pipelines] Do not run CoroSplit and CoroCleanup in ThinLTO pre-link pipeline Skip CoroSplit and CoroCleanup in ThinLTO pre-link pipeline so that CoroElide can happen after callee coroutine is imported into caller's module in ThinLTO. --- .../CodeGenCoroutines/coro-elide-thinlto.cpp | 84 +++++++++++++++++++ llvm/lib/Passes/PassBuilderPipelines.cpp | 11 ++- .../Other/new-pm-thinlto-prelink-defaults.ll | 2 - .../new-pm-thinlto-prelink-pgo-defaults.ll | 2 - ...w-pm-thinlto-prelink-samplepgo-defaults.ll | 2 - 5 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 clang/test/CodeGenCoroutines/coro-elide-thinlto.cpp diff --git a/clang/test/CodeGenCoroutines/coro-elide-thinlto.cpp b/clang/test/CodeGenCoroutines/coro-elide-thinlto.cpp new file mode 100644 index 0000000000000..16bee64df9a11 --- /dev/null +++ b/clang/test/CodeGenCoroutines/coro-elide-thinlto.cpp @@ -0,0 +1,84 @@ +// REQUIRES: x86_64-linux +// This tests that the coroutine elide optimization could happen succesfully with ThinLTO. +// This test is adapted from coro-elide.cpp and splits functions into two files. +// +// RUN: split-file %s %t +// RUN: %clang --target=x86_64-linux -std=c++20 -O2 -flto=thin -I %S -c %t/coro-elide-callee.cpp -o coro-elide-callee.bc +// RUN: %clang --target=x86_64-linux -std=c++20 -O2 -flto=thin -I %S -c %t/coro-elide-caller.cpp -o coro-elide-caller.bc +// RUN: llvm-lto --thinlto coro-elide-callee.bc coro-elide-caller.bc -o summary +// RUN: %clang_cc1 -O2 -x ir coro-elide-caller.bc -fthinlto-index=summary.thinlto.bc -emit-llvm -o - | FileCheck %s +// +// Run asan +// RUN: %clang --target=x86_64-linux -std=c++20 -O2 -flto=thin -fsanitize=address -I %S -c %t/coro-elide-callee.cpp -o coro-elide-callee.bc +// RUN: %clang --target=x86_64-linux -std=c++20 -O2 -flto=thin -fsanitize=address -I %S -c %t/coro-elide-caller.cpp -o coro-elide-caller.bc +// RUN: llvm-lto --thinlto coro-elide-callee.bc coro-elide-caller.bc -o summary +// RUN: %clang_cc1 -O2 -x ir coro-elide-caller.bc -fthinlto-index=summary.thinlto.bc -emit-llvm -o - | FileCheck %s + +//--- coro-elide-task.h +#pragma once +#include "Inputs/coroutine.h" + +struct Task { + struct promise_type { + struct FinalAwaiter { + bool await_ready() const noexcept { return false; } + template <typename PromiseType> + std::coroutine_handle<> await_suspend(std::coroutine_handle<PromiseType> h) noexcept { + if (!h) + return std::noop_coroutine(); + return h.promise().continuation; + } + void await_resume() noexcept {} + }; + Task get_return_object() noexcept { + return std::coroutine_handle<promise_type>::from_promise(*this); + } + std::suspend_always initial_suspend() noexcept { return {}; } + FinalAwaiter final_suspend() noexcept { return {}; } + void unhandled_exception() noexcept {} + void return_value(int x) noexcept { + _value = x; + } + std::coroutine_handle<> continuation; + int _value; + }; + + Task(std::coroutine_handle<promise_type> handle) : handle(handle) {} + ~Task() { + if (handle) + handle.destroy(); + } + + struct Awaiter { + bool await_ready() const noexcept { return false; } + void await_suspend(std::coroutine_handle<void> continuation) noexcept {} + int await_resume() noexcept { + return 43; + } + }; + + auto operator co_await() { + return Awaiter{}; + } + +private: + std::coroutine_handle<promise_type> handle; +}; + +//--- coro-elide-callee.cpp +#include "coro-elide-task.h" +Task task0() { + co_return 43; +} + +//--- coro-elide-caller.cpp +#include "coro-elide-task.h" + +Task task0(); + +Task task1() { + co_return co_await task0(); +} + +// CHECK-LABEL: define{{.*}} void @_Z5task1v.resume +// CHECK-NOT: {{.*}}_Znwm diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index 757b20dcd6693..a6118726945e8 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -979,7 +979,8 @@ PassBuilder::buildInlinerPipeline(OptimizationLevel Level, MainCGPipeline.addPass(createCGSCCToFunctionPassAdaptor( RequireAnalysisPass<ShouldNotRunFunctionPassesAnalysis, Function>())); - MainCGPipeline.addPass(CoroSplitPass(Level != OptimizationLevel::O0)); + if (Phase != ThinOrFullLTOPhase::ThinLTOPreLink) + MainCGPipeline.addPass(CoroSplitPass(Level != OptimizationLevel::O0)); // Make sure we don't affect potential future NoRerun CGSCC adaptors. MIWP.addLateModulePass(createModuleToFunctionPassAdaptor( @@ -1021,8 +1022,9 @@ PassBuilder::buildModuleInlinerPipeline(OptimizationLevel Level, buildFunctionSimplificationPipeline(Level, Phase), PTO.EagerlyInvalidateAnalyses)); - MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor( - CoroSplitPass(Level != OptimizationLevel::O0))); + if (Phase != ThinOrFullLTOPhase::ThinLTOPreLink) + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor( + CoroSplitPass(Level != OptimizationLevel::O0))); return MPM; } @@ -1219,7 +1221,8 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, // and argument promotion. MPM.addPass(DeadArgumentEliminationPass()); - MPM.addPass(CoroCleanupPass()); + if (Phase != ThinOrFullLTOPhase::ThinLTOPreLink) + MPM.addPass(CoroCleanupPass()); // Optimize globals now that functions are fully simplified. MPM.addPass(GlobalOptPass()); diff --git a/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll index 42ef49f8f7c7e..ab04f80abc572 100644 --- a/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll @@ -184,12 +184,10 @@ ; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass ; CHECK-O-NEXT: Running pass: RequireAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis ; CHECK-O-NEXT: Running analysis: ShouldNotRunFunctionPassesAnalysis -; CHECK-O-NEXT: Running pass: CoroSplitPass ; CHECK-O-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis ; CHECK-O-NEXT: Invalidating analysis: ShouldNotRunFunctionPassesAnalysis ; CHECK-O-NEXT: Invalidating analysis: InlineAdvisorAnalysis ; CHECK-O-NEXT: Running pass: DeadArgumentEliminationPass -; CHECK-O-NEXT: Running pass: CoroCleanupPass ; CHECK-O-NEXT: Running pass: GlobalOptPass ; CHECK-O-NEXT: Running pass: GlobalDCEPass ; CHECK-EXT: Running pass: {{.*}}::Bye diff --git a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll index e74f88c1a3bf9..cb49cbd22d60c 100644 --- a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll @@ -183,12 +183,10 @@ ; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass ; CHECK-O-NEXT: Running pass: RequireAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis ; CHECK-O-NEXT: Running analysis: ShouldNotRunFunctionPassesAnalysis -; CHECK-O-NEXT: Running pass: CoroSplitPass ; CHECK-O-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis ; CHECK-O-NEXT: Invalidating analysis: ShouldNotRunFunctionPassesAnalysis ; CHECK-O-NEXT: Invalidating analysis: InlineAdvisorAnalysis ; CHECK-O-NEXT: Running pass: DeadArgumentEliminationPass -; CHECK-O-NEXT: Running pass: CoroCleanupPass ; CHECK-O-NEXT: Running pass: GlobalOptPass ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis on bar ; CHECK-O-NEXT: Running pass: GlobalDCEPass diff --git a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll index 0bb26330d000a..96e8349350442 100644 --- a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll @@ -148,12 +148,10 @@ ; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass ; CHECK-O-NEXT: Running pass: RequireAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis ; CHECK-O-NEXT: Running analysis: ShouldNotRunFunctionPassesAnalysis -; CHECK-O-NEXT: Running pass: CoroSplitPass ; CHECK-O-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}ShouldNotRunFunctionPassesAnalysis ; CHECK-O-NEXT: Invalidating analysis: ShouldNotRunFunctionPassesAnalysis ; CHECK-O-NEXT: Invalidating analysis: InlineAdvisorAnalysis ; CHECK-O-NEXT: Running pass: DeadArgumentEliminationPass -; CHECK-O-NEXT: Running pass: CoroCleanupPass ; CHECK-O-NEXT: Running pass: GlobalOptPass ; CHECK-O-NEXT: Running pass: GlobalDCEPass ; CHECK-O-NEXT: Running pass: AnnotationRemarksPass on foo >From 991168c402fbfd6f8026bcb88ca331d359fada42 Mon Sep 17 00:00:00 2001 From: Wei Wang <wang...@meta.com> Date: Mon, 29 Jul 2024 13:59:09 -0700 Subject: [PATCH 2/2] update test. --- clang/test/CodeGenCoroutines/coro-elide-thinlto.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/clang/test/CodeGenCoroutines/coro-elide-thinlto.cpp b/clang/test/CodeGenCoroutines/coro-elide-thinlto.cpp index 16bee64df9a11..77a4dc3ad4257 100644 --- a/clang/test/CodeGenCoroutines/coro-elide-thinlto.cpp +++ b/clang/test/CodeGenCoroutines/coro-elide-thinlto.cpp @@ -7,12 +7,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.bc // RUN: llvm-lto --thinlto coro-elide-callee.bc coro-elide-caller.bc -o summary // RUN: %clang_cc1 -O2 -x ir coro-elide-caller.bc -fthinlto-index=summary.thinlto.bc -emit-llvm -o - | FileCheck %s -// -// Run asan -// RUN: %clang --target=x86_64-linux -std=c++20 -O2 -flto=thin -fsanitize=address -I %S -c %t/coro-elide-callee.cpp -o coro-elide-callee.bc -// RUN: %clang --target=x86_64-linux -std=c++20 -O2 -flto=thin -fsanitize=address -I %S -c %t/coro-elide-caller.cpp -o coro-elide-caller.bc -// RUN: llvm-lto --thinlto coro-elide-callee.bc coro-elide-caller.bc -o summary -// RUN: %clang_cc1 -O2 -x ir coro-elide-caller.bc -fthinlto-index=summary.thinlto.bc -emit-llvm -o - | FileCheck %s //--- coro-elide-task.h #pragma once _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits