[llvm-bugs] [Bug 39806] New: coroutines generator optimization

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Nov 27 03:29:20 PST 2018


https://bugs.llvm.org/show_bug.cgi?id=39806

            Bug ID: 39806
           Summary: coroutines generator optimization
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Common Code Generator Code
          Assignee: unassignedbugs at nondot.org
          Reporter: trass3r at gmail.com
                CC: llvm-bugs at lists.llvm.org

Just saw this code: https://arbmind.github.io/2018-cogen-en/#61.1
https://godbolt.org/z/dT5KBO

#include <experimental/coroutine>
namespace coro = std::experimental;

template<class T>
struct Generator {
    using element_type = T;
    struct Promise;
    using promise_type = Promise;
    using Handle = coro::coroutine_handle<Promise>;

    struct Promise {
        T current_m;

        auto get_return_object() noexcept {
            return Generator{Handle::from_promise(*this)};
        }

        auto initial_suspend() noexcept {
            return coro::suspend_always{};
        }
        auto final_suspend() noexcept {
            return coro::suspend_always{};
        }

        auto yield_value(T value) noexcept {
            current_m = std::move(value);
            return coro::suspend_always{};
        }
        auto return_void() noexcept {}
        auto unhandled_exception() noexcept {}
    };

    auto operator*() const -> const T & {
        return h.promise().current_m;
    }
    auto operator-> () const -> const T * {
        return &h.promise().current_m;
    }
    auto move() -> T {
        return std::move(h.promise().current_m);
    }

    operator bool() const { return h && !h.done(); }
    auto operator++() -> Generator & {
        if (h) h.resume();
        return *this;
    }

    struct End {};
    static auto end() -> End { return {}; }

    auto begin() {
        struct Iterator {
            using iterator_category =
                std::input_iterator_tag;
            using difference_type = ptrdiff_t;
            using value_type = T;
            using reference = T const &;
            using pointer = T const *;

            Generator &gen;

            auto operator*() const -> const T & {
                return *gen;
            }
            auto operator++() -> Iterator & {
                ++gen;
                return *this;
            }
            bool operator==(End) const { return !gen; }
            bool operator!=(End) const { return gen; }
        };
        return Iterator{++(*this)};
    }
    ~Generator() {
        if (h) h.destroy();
    }
    Generator() = delete;
    Generator(const Generator &) = delete;
    Generator(Generator &&o) noexcept
        : h(o.h) {
        o.h = {};
    }
    auto operator=(const Generator &) = delete;
    auto operator=(Generator &&) = delete;

private:
    Generator(Handle h)
        : h(h) {}

private:
    Handle h;
};

inline auto iota(size_t n) -> Generator<size_t> {
    for (auto i = 0u; i < n; ++i)
        co_yield i;
}

template<size_t N>
auto fixedSum() {
    auto sum = 0u;
    for (auto v : iota(N + 1)) sum += v;
    return sum;
}

auto test() {
    return fixedSum<100>();
}

auto dynSum(size_t n) {
    auto sum = 0u;
    for (auto v : iota(n + 1))
        sum += v;
    return sum;
}

auto simpleSum(size_t n) {
    auto sum = 0u;
    for (auto v = 0; v <= n; ++v)
        sum += v;
    return sum;
}



# clang -std=c++2a -O3 -stdlib=libc++ -fcoroutines-ts

test():                               # @test()
        mov     eax, 5050
        ret
dynSum(unsigned long):                             # @dynSum(unsigned long)
        add     rdi, 1
        sete    cl
        je      .LBB1_1
        xor     eax, eax
        xor     esi, esi
.LBB1_4:                                # =>This Inner Loop Header: Depth=1
        mov     edx, esi
        add     eax, esi
        mov     esi, 0
        test    cl, 1
        mov     ecx, 0
        jne     .LBB1_4
        add     edx, 1
        xor     ecx, ecx
        mov     esi, edx
        cmp     rdi, rdx
        ja      .LBB1_4
        ret
.LBB1_1:
        xor     eax, eax
        ret
simpleSum(unsigned long):                          # @simpleSum(unsigned long)
        mov     rax, rdi
        lea     rcx, [rdi - 1]
        imul    rcx, rdi
        shr     rcx
        add     eax, ecx
        ret

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20181127/7c43bdc5/attachment.html>


More information about the llvm-bugs mailing list