1b1a45c62Swlei; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/coroutine.perfscript --binary=%S/Inputs/coroutine.perfbin --output=%t 2b1a45c62Swlei; RUN: FileCheck %s --input-file %t --check-prefix=CHECK 3b1a45c62Swlei 4b1a45c62Swlei; Check that the head sample count for ticker is 0. 5*484a569eSwlei; CHECK: _Z6tickeri:1566:0 6b1a45c62Swlei; CHECK-NOT: _Z6tickeri.resume 7b1a45c62Swlei 8b1a45c62Swlei 9b1a45c62Swlei/* 10b1a45c62Swlei * Inputs/coroutine.perfbin is generated by compiling the following source code: 11b1a45c62Swlei * clang++ coroutine.cpp -std=c++2a -g2 -o coroutine 12b1a45c62Swlei */ 13b1a45c62Swlei 14b1a45c62Swlei#include <cstdint> 15b1a45c62Swlei#include <cstdlib> 16b1a45c62Swlei#include <ctime> 17b1a45c62Swlei#include <experimental/coroutine> 18b1a45c62Swlei#include <iostream> 19b1a45c62Swlei 20b1a45c62Swleistruct task { 21b1a45c62Swlei struct promise_type { 22b1a45c62Swlei task get_return_object() { return {}; } 23b1a45c62Swlei std::experimental::suspend_never initial_suspend() { return {}; } 24b1a45c62Swlei std::experimental::suspend_never final_suspend() noexcept { return {}; } 25b1a45c62Swlei void return_void() {} 26b1a45c62Swlei void unhandled_exception() {} 27b1a45c62Swlei }; 28b1a45c62Swlei}; 29b1a45c62Swlei 30b1a45c62Swleitemplate <typename T> 31b1a45c62Swleistruct generator { 32b1a45c62Swlei struct promise_type; 33b1a45c62Swlei using handle = std::experimental::coroutine_handle<promise_type>; 34b1a45c62Swlei struct promise_type { 35b1a45c62Swlei int current_value; 36b1a45c62Swlei static auto get_return_object_on_allocation_failure() { return generator{nullptr}; } 37b1a45c62Swlei auto get_return_object() { return generator{handle::from_promise(*this)}; } 38b1a45c62Swlei auto initial_suspend() { return std::experimental::suspend_always{}; } 39b1a45c62Swlei auto final_suspend() { return std::experimental::suspend_always{}; } 40b1a45c62Swlei void unhandled_exception() { std::terminate(); } 41b1a45c62Swlei void return_void() {} 42b1a45c62Swlei auto yield_value(int value) { 43b1a45c62Swlei current_value = value; 44b1a45c62Swlei return std::experimental::suspend_always{}; 45b1a45c62Swlei } 46b1a45c62Swlei }; 47b1a45c62Swlei bool move_next() { return coro ? (coro.resume(), !coro.done()) : false; } 48b1a45c62Swlei int current_value() { return coro.promise().current_value; } 49b1a45c62Swlei generator(generator const &) = delete; 50b1a45c62Swlei generator(generator &&rhs) : coro(rhs.coro) { rhs.coro = nullptr; } 51b1a45c62Swlei ~generator() { 52b1a45c62Swlei if (coro) 53b1a45c62Swlei coro.destroy(); 54b1a45c62Swlei } 55b1a45c62Swlei 56b1a45c62Swleiprivate: 57b1a45c62Swlei generator(handle h) : coro(h) {} 58b1a45c62Swlei handle coro; 59b1a45c62Swlei}; 60b1a45c62Swlei 61b1a45c62Swleigenerator<int> ticker(int count) { 62b1a45c62Swlei for (int i = 0; i < count; ++i) { 63b1a45c62Swlei srand(time(NULL)); 64b1a45c62Swlei uint32_t a = rand() % 10 + 1; 65b1a45c62Swlei uint32_t b = rand() % 10 + 1; 66b1a45c62Swlei uint64_t c = 0; 67b1a45c62Swlei for (int i = 0; i < 1500; ++i) { 68b1a45c62Swlei c = ((uint64_t)a) + b; 69b1a45c62Swlei a = b; 70b1a45c62Swlei b = c % 2147483648ULL; 71b1a45c62Swlei } 72b1a45c62Swlei co_yield a; 73b1a45c62Swlei } 74b1a45c62Swlei} 75b1a45c62Swlei 76b1a45c62Swleiint main() { 77b1a45c62Swlei auto g = ticker(500000); 78b1a45c62Swlei uint64_t ans = 0; 79b1a45c62Swlei while (g.move_next()) { 80b1a45c62Swlei ans += g.current_value(); 81b1a45c62Swlei } 82b1a45c62Swlei std::cout << ans << "\n"; 83b1a45c62Swlei} 84