| ; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/coroutine.perfscript --binary=%S/Inputs/coroutine.perfbin --output=%t |
| ; RUN: FileCheck %s --input-file %t --check-prefix=CHECK |
| |
| ; Check that the head sample count for ticker is 0. |
| ; CHECK: _Z6tickeri:67:0 |
| ; CHECK-NOT: _Z6tickeri.resume |
| |
| |
| /* |
| * Inputs/coroutine.perfbin is generated by compiling the following source code: |
| * clang++ coroutine.cpp -std=c++2a -g2 -o coroutine |
| */ |
| |
| #include <cstdint> |
| #include <cstdlib> |
| #include <ctime> |
| #include <experimental/coroutine> |
| #include <iostream> |
| |
| struct task { |
| struct promise_type { |
| task get_return_object() { return {}; } |
| std::experimental::suspend_never initial_suspend() { return {}; } |
| std::experimental::suspend_never final_suspend() noexcept { return {}; } |
| void return_void() {} |
| void unhandled_exception() {} |
| }; |
| }; |
| |
| template <typename T> |
| struct generator { |
| struct promise_type; |
| using handle = std::experimental::coroutine_handle<promise_type>; |
| struct promise_type { |
| int current_value; |
| static auto get_return_object_on_allocation_failure() { return generator{nullptr}; } |
| auto get_return_object() { return generator{handle::from_promise(*this)}; } |
| auto initial_suspend() { return std::experimental::suspend_always{}; } |
| auto final_suspend() { return std::experimental::suspend_always{}; } |
| void unhandled_exception() { std::terminate(); } |
| void return_void() {} |
| auto yield_value(int value) { |
| current_value = value; |
| return std::experimental::suspend_always{}; |
| } |
| }; |
| bool move_next() { return coro ? (coro.resume(), !coro.done()) : false; } |
| int current_value() { return coro.promise().current_value; } |
| generator(generator const &) = delete; |
| generator(generator &&rhs) : coro(rhs.coro) { rhs.coro = nullptr; } |
| ~generator() { |
| if (coro) |
| coro.destroy(); |
| } |
| |
| private: |
| generator(handle h) : coro(h) {} |
| handle coro; |
| }; |
| |
| generator<int> ticker(int count) { |
| for (int i = 0; i < count; ++i) { |
| srand(time(NULL)); |
| uint32_t a = rand() % 10 + 1; |
| uint32_t b = rand() % 10 + 1; |
| uint64_t c = 0; |
| for (int i = 0; i < 1500; ++i) { |
| c = ((uint64_t)a) + b; |
| a = b; |
| b = c % 2147483648ULL; |
| } |
| co_yield a; |
| } |
| } |
| |
| int main() { |
| auto g = ticker(500000); |
| uint64_t ans = 0; |
| while (g.move_next()) { |
| ans += g.current_value(); |
| } |
| std::cout << ans << "\n"; |
| } |