105 lines · cpp
1// This tests that the coroutine heap allocation elision optimization could happen succesfully.2// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O2 -emit-llvm %s -o - | FileCheck %s3// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O2 -emit-llvm %s \4// RUN: -fcxx-exceptions -fexceptions -o - | FileCheck %s5 6#include "Inputs/coroutine.h"7#include "Inputs/numeric.h"8 9template <typename T> struct generator {10 struct promise_type {11 T current_value;12 std::suspend_always yield_value(T value) {13 this->current_value = value;14 return {};15 }16 std::suspend_always initial_suspend() { return {}; }17 std::suspend_always final_suspend() noexcept { return {}; }18 generator get_return_object() { return generator{this}; };19 void unhandled_exception() {}20 void return_void() {}21 };22 23 struct iterator {24 std::coroutine_handle<promise_type> _Coro;25 bool _Done;26 27 iterator(std::coroutine_handle<promise_type> Coro, bool Done)28 : _Coro(Coro), _Done(Done) {}29 30 iterator &operator++() {31 _Coro.resume();32 _Done = _Coro.done();33 return *this;34 }35 36 bool operator==(iterator const &_Right) const {37 return _Done == _Right._Done;38 }39 40 bool operator!=(iterator const &_Right) const { return !(*this == _Right); }41 T const &operator*() const { return _Coro.promise().current_value; }42 T const *operator->() const { return &(operator*()); }43 };44 45 iterator begin() {46 p.resume();47 return {p, p.done()};48 }49 50 iterator end() { return {p, true}; }51 52 generator(generator const &) = delete;53 generator(generator &&rhs) : p(rhs.p) { rhs.p = nullptr; }54 55 ~generator() {56 if (p)57 p.destroy();58 }59 60private:61 explicit generator(promise_type *p)62 : p(std::coroutine_handle<promise_type>::from_promise(*p)) {}63 64 std::coroutine_handle<promise_type> p;65};66 67template <typename T>68generator<T> seq() {69 for (T i = {};; ++i)70 co_yield i;71}72 73template <typename T>74generator<T> take_until(generator<T> &g, T limit) {75 for (auto &&v : g)76 if (v < limit)77 co_yield v;78 else79 break;80}81 82template <typename T>83generator<T> multiply(generator<T> &g, T factor) {84 for (auto &&v : g)85 co_yield v *factor;86}87 88template <typename T>89generator<T> add(generator<T> &g, T adder) {90 for (auto &&v : g)91 co_yield v + adder;92}93 94int main() {95 auto s = seq<int>();96 auto t = take_until(s, 10);97 auto m = multiply(t, 2);98 auto a = add(m, 110);99 return std::accumulate(a.begin(), a.end(), 0);100}101 102// CHECK-LABEL: define{{.*}} i32 @main(103// CHECK: ret i32 1190104// CHECK-NOT: call{{.*}}_Znwm105