Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGenCoroutines / coro-awaiter-noinline-suspend.cpp
blobf95286faf46ec8ddc317723e72d104401406e004
1 // Tests that we can mark await-suspend as noinline correctly.
2 //
3 // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s \
4 // RUN: -O1 -disable-llvm-passes | FileCheck %s
6 #include "Inputs/coroutine.h"
8 struct Task {
9 struct promise_type {
10 struct FinalAwaiter {
11 bool await_ready() const noexcept { return false; }
12 template <typename PromiseType>
13 std::coroutine_handle<> await_suspend(std::coroutine_handle<PromiseType> h) noexcept {
14 return h.promise().continuation;
16 void await_resume() noexcept {}
19 Task get_return_object() noexcept {
20 return std::coroutine_handle<promise_type>::from_promise(*this);
23 std::suspend_always initial_suspend() noexcept { return {}; }
24 FinalAwaiter final_suspend() noexcept { return {}; }
25 void unhandled_exception() noexcept {}
26 void return_void() noexcept {}
28 std::coroutine_handle<> continuation;
31 Task(std::coroutine_handle<promise_type> handle);
32 ~Task();
34 private:
35 std::coroutine_handle<promise_type> handle;
38 struct StatefulAwaiter {
39 int value;
40 bool await_ready() const noexcept { return false; }
41 template <typename PromiseType>
42 void await_suspend(std::coroutine_handle<PromiseType> h) noexcept {}
43 void await_resume() noexcept {}
46 typedef std::suspend_always NoStateAwaiter;
47 using AnotherStatefulAwaiter = StatefulAwaiter;
49 template <class T>
50 struct TemplatedAwaiter {
51 T value;
52 bool await_ready() const noexcept { return false; }
53 template <typename PromiseType>
54 void await_suspend(std::coroutine_handle<PromiseType> h) noexcept {}
55 void await_resume() noexcept {}
59 class Awaitable {};
60 StatefulAwaiter operator co_await(Awaitable) {
61 return StatefulAwaiter{};
64 StatefulAwaiter GlobalAwaiter;
65 class Awaitable2 {};
66 StatefulAwaiter& operator co_await(Awaitable2) {
67 return GlobalAwaiter;
70 struct AlwaysInlineStatefulAwaiter {
71 void* value;
72 bool await_ready() const noexcept { return false; }
74 template <typename PromiseType>
75 __attribute__((always_inline))
76 void await_suspend(std::coroutine_handle<PromiseType> h) noexcept {}
78 void await_resume() noexcept {}
81 Task testing() {
82 co_await std::suspend_always{};
83 co_await StatefulAwaiter{};
84 co_await AnotherStatefulAwaiter{};
86 // Test lvalue case.
87 StatefulAwaiter awaiter;
88 co_await awaiter;
90 // The explicit call to await_suspend is not considered suspended.
91 awaiter.await_suspend(std::coroutine_handle<void>::from_address(nullptr));
93 co_await TemplatedAwaiter<int>{};
94 TemplatedAwaiter<int> TemplatedAwaiterInstace;
95 co_await TemplatedAwaiterInstace;
97 co_await Awaitable{};
98 co_await Awaitable2{};
100 co_await AlwaysInlineStatefulAwaiter{};
103 struct AwaitTransformTask {
104 struct promise_type {
105 struct FinalAwaiter {
106 bool await_ready() const noexcept { return false; }
107 template <typename PromiseType>
108 std::coroutine_handle<> await_suspend(std::coroutine_handle<PromiseType> h) noexcept {
109 return h.promise().continuation;
111 void await_resume() noexcept {}
114 AwaitTransformTask get_return_object() noexcept {
115 return std::coroutine_handle<promise_type>::from_promise(*this);
118 std::suspend_always initial_suspend() noexcept { return {}; }
119 FinalAwaiter final_suspend() noexcept { return {}; }
120 void unhandled_exception() noexcept {}
121 void return_void() noexcept {}
123 template <typename Awaitable>
124 auto await_transform(Awaitable &&awaitable) {
125 return awaitable;
128 std::coroutine_handle<> continuation;
131 AwaitTransformTask(std::coroutine_handle<promise_type> handle);
132 ~AwaitTransformTask();
134 private:
135 std::coroutine_handle<promise_type> handle;
138 struct awaitableWithGetAwaiter {
139 bool await_ready() const noexcept { return false; }
140 template <typename PromiseType>
141 void await_suspend(std::coroutine_handle<PromiseType> h) noexcept {}
142 void await_resume() noexcept {}
145 AwaitTransformTask testingWithAwaitTransform() {
146 co_await awaitableWithGetAwaiter{};
149 // CHECK: define{{.*}}@_ZNSt14suspend_always13await_suspendESt16coroutine_handleIvE{{.*}}#[[NORMAL_ATTR:[0-9]+]]
151 // CHECK: define{{.*}}@_ZN15StatefulAwaiter13await_suspendIN4Task12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[NOINLINE_ATTR:[0-9]+]]
153 // CHECK: define{{.*}}@_ZN15StatefulAwaiter13await_suspendIvEEvSt16coroutine_handleIT_E{{.*}}#[[NORMAL_ATTR]]
155 // CHECK: define{{.*}}@_ZN16TemplatedAwaiterIiE13await_suspendIN4Task12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[NOINLINE_ATTR]]
157 // CHECK: define{{.*}}@_ZN27AlwaysInlineStatefulAwaiter13await_suspendIN4Task12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[ALWAYS_INLINE_ATTR:[0-9]+]]
159 // CHECK: define{{.*}}@_ZN4Task12promise_type12FinalAwaiter13await_suspendIS0_EESt16coroutine_handleIvES3_IT_E{{.*}}#[[NORMAL_ATTR]]
161 // CHECK: define{{.*}}@_ZN23awaitableWithGetAwaiter13await_suspendIN18AwaitTransformTask12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[NORMAL_ATTR]]
163 // CHECK: define{{.*}}@_ZN18AwaitTransformTask12promise_type12FinalAwaiter13await_suspendIS0_EESt16coroutine_handleIvES3_IT_E{{.*}}#[[NORMAL_ATTR]]
165 // CHECK-NOT: attributes #[[NORMAL_ATTR]] = noinline
166 // CHECK: attributes #[[NOINLINE_ATTR]] = {{.*}}noinline
167 // CHECK-NOT: attributes #[[ALWAYS_INLINE_ATTR]] = {{.*}}noinline
168 // CHECK: attributes #[[ALWAYS_INLINE_ATTR]] = {{.*}}alwaysinline