xref: /llvm-project/llvm/test/tools/llvm-profgen/coroutine.test (revision 484a569eea7ba294d84b9a700e6fcc2f97626320)
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