Author: Weibo He
Date: 2026-04-03T02:06:10Z
New Revision: bc11c85b6b16f1daabfc9e8b326c9568c3318cb9

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

LOG: [clang][CodeGen] Emit coro.dead intrinsic to improve coroutine allocation 
elision (#190295)

Part 4/4: Implement HALO for coroutines that flow off final suspend.
Parent PR: #185336

Added: 
    

Modified: 
    clang/lib/CodeGen/CGCoroutine.cpp
    clang/test/CodeGenCoroutines/coro-elide.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGCoroutine.cpp 
b/clang/lib/CodeGen/CGCoroutine.cpp
index 7282c42420657..9d9d2450c3d68 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -643,6 +643,9 @@ struct CallCoroDelete final : public EHScopeStack::Cleanup {
     // No longer need old terminator.
     InsertPt->eraseFromParent();
     CGF.Builder.SetInsertPoint(AfterFreeBB);
+
+    auto *CoroDeadFn = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_dead);
+    CGF.Builder.CreateCall(CoroDeadFn, {CGF.CurCoro.Data->CoroBegin});
   }
   explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}
 };

diff  --git a/clang/test/CodeGenCoroutines/coro-elide.cpp 
b/clang/test/CodeGenCoroutines/coro-elide.cpp
index d7569c3b4d087..1902dd64b5e5a 100644
--- a/clang/test/CodeGenCoroutines/coro-elide.cpp
+++ b/clang/test/CodeGenCoroutines/coro-elide.cpp
@@ -1,8 +1,32 @@
-// This tests that the coroutine elide optimization could happen succesfully.
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O2 -emit-llvm 
%s -o - | FileCheck %s
 
 #include "Inputs/coroutine.h"
 
+namespace {
+struct coro {
+    using promise_type = coro;
+
+    auto get_return_object() noexcept { return 
coro{std::coroutine_handle<coro>::from_promise(*this)}; }
+    std::suspend_never initial_suspend() noexcept { return {}; }
+    std::suspend_never final_suspend() noexcept { return {}; }
+    void return_void() noexcept {}
+    void unhandled_exception() {}
+
+    std::coroutine_handle<> handle;
+};
+}
+
+void flowoff() {
+  []() -> coro {
+    co_await std::suspend_always{};
+  }().handle.resume();
+}
+
+// Tests that the coroutine elide optimization could happen if control flows 
off the end of the coroutine
+// CHECK-LABEL: define{{.*}} void @_Z7flowoffv
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret void
+
 struct Task {
   struct promise_type {
     struct FinalAwaiter {
@@ -58,5 +82,6 @@ Task task1() {
   co_return co_await task0();
 }
 
+// Tests that the coroutine elide optimization could happen if 
handle.destroy() is invoked
 // CHECK-LABEL: define{{.*}} void @_Z5task1v.resume
 // CHECK-NOT: call{{.*}}_Znwm


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to