|
| 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 |
0 commit comments