[clang] 268c065 - [fatlto] Add coroutine passes when using FatLTO with ThinLTO (#134434)

via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 7 08:41:53 PDT 2025


Author: Paul Kirth
Date: 2025-04-07T08:41:49-07:00
New Revision: 268c065eab06b81a0d7256ac62c0865b3781e236

URL: https://github.com/llvm/llvm-project/commit/268c065eab06b81a0d7256ac62c0865b3781e236
DIFF: https://github.com/llvm/llvm-project/commit/268c065eab06b81a0d7256ac62c0865b3781e236.diff

LOG: [fatlto] Add coroutine passes when using FatLTO with ThinLTO (#134434)

When coroutines are used w/ both -ffat-lto-objects and -flto=thin,
the coroutine passes are not added to the optimization pipelines.
Ensure they are added before ModuleOptimization to generate a
working ELF object.

Fixes #134409.

Added: 
    clang/test/CodeGenCoroutines/pr134409.cpp

Modified: 
    llvm/lib/Passes/PassBuilderPipelines.cpp

Removed: 
    


################################################################################
diff  --git a/clang/test/CodeGenCoroutines/pr134409.cpp b/clang/test/CodeGenCoroutines/pr134409.cpp
new file mode 100644
index 0000000000000..142962d44ede4
--- /dev/null
+++ b/clang/test/CodeGenCoroutines/pr134409.cpp
@@ -0,0 +1,43 @@
+// An end-to-end test to make sure coroutine passes are added for thinlto.
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 -ffat-lto-objects -flto=thin -emit-llvm %s -O3 -o - \
+// RUN:  | FileCheck %s
+
+#include "Inputs/coroutine.h"
+
+class BasicCoroutine {
+public:
+    struct Promise {
+        BasicCoroutine get_return_object() { return BasicCoroutine {}; }
+
+        void unhandled_exception() noexcept { }
+
+        void return_void() noexcept { }
+
+        std::suspend_never initial_suspend() noexcept { return {}; }
+        std::suspend_never final_suspend() noexcept { return {}; }
+    };
+    using promise_type = Promise;
+};
+
+// COM: match the embedded module, so we don't match something in it by accident.
+// CHECK: @llvm.embedded.object = {{.*}}
+// CHECK: @llvm.compiler.used = {{.*}}
+
+BasicCoroutine coro() {
+// CHECK: define {{.*}} void @_Z4corov() {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+    co_return;
+}
+
+int main() {
+// CHECK: define {{.*}} i32 @main() {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: tail call void @_Z4corov()
+// CHECK-NEXT: ret i32 0
+// CHECK-NEXT: }
+    coro();
+}
+

diff  --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index a18b36ba40754..f222dbede7da7 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -1692,6 +1692,19 @@ PassBuilder::buildFatLTODefaultPipeline(OptimizationLevel Level, bool ThinLTO,
   if (ThinLTO && PGOOpt && PGOOpt->Action == PGOOptions::SampleUse)
     MPM.addPass(buildThinLTODefaultPipeline(Level, /*ImportSummary=*/nullptr));
   else {
+    // ModuleSimplification does not run the coroutine passes for
+    // ThinLTOPreLink, so we need the coroutine passes to run for ThinLTO
+    // builds, otherwise they will miscompile.
+    if (ThinLTO) {
+      // TODO: replace w/ buildCoroWrapper() when it takes phase and level into
+      // consideration.
+      CGSCCPassManager CGPM;
+      CGPM.addPass(CoroSplitPass(Level != OptimizationLevel::O0));
+      CGPM.addPass(CoroAnnotationElidePass());
+      MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
+      MPM.addPass(CoroCleanupPass());
+    }
+
     // otherwise, just use module optimization
     MPM.addPass(
         buildModuleOptimizationPipeline(Level, ThinOrFullLTOPhase::None));


        


More information about the cfe-commits mailing list