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
