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