[llvm] [Coroutines] Drop dead instructions more aggressively in addMustTailToCoroResumes() (PR #85271)

Chuanqi Xu via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 19 22:38:04 PDT 2024


ChuanqiXu9 wrote:

> My test case does come from a C++ program. Here is a reasonably small reproducer:
> 
> ```
> $ cat /tmp/b.cc
> #include <coroutine>
> struct Task {
>   struct promise_type {
>     Task get_return_object() { return Task(std::coroutine_handle<promise_type>::from_promise(*this)); }
>     std::suspend_always initial_suspend() { return {}; }
>     struct FinalAwaiter {
>       bool await_ready() noexcept { return false; }
>       std::coroutine_handle<> await_suspend(std::coroutine_handle<promise_type> handle) {
>         return handle.promise().continuation_;
>       }
>       void await_resume() noexcept {}
>     };
>     FinalAwaiter final_suspend() noexcept { return {}; }
>     void return_void() {}
>     void unhandled_exception() { }
> 
>     std::coroutine_handle<> continuation_;
>   };
> 
>   explicit Task(std::coroutine_handle<promise_type> handle) : handle_(handle) {}
> 
>   std::coroutine_handle<promise_type> handle_;
>   int x = 42;
> };
> 
> void g();
> extern "C" Task foo() {
>   g();
>   co_return;
> }
> 
> $ build/bin/clang++ -c -fno-exceptions /tmp/b.cc -std=c++20 -O1 -mllvm -print-after=coro-split -mllvm -filter-print-funcs=foo.resume -o /dev/null -w
> ; *** IR Dump After CoroSplitPass on (foo.resume) ***
> ; Function Attrs: mustprogress nounwind uwtable
> define internal fastcc void @foo.resume(ptr nocapture noundef nonnull align 8 dereferenceable(32) %0) #0 {
> entry.resume:
>   %__promise.reload.addr = getelementptr inbounds i8, ptr %0, i64 16
>   call void @_Z1gv() #2
>   store ptr null, ptr %0, align 8
>   %retval.sroa.0.0.copyload.i.i = load ptr, ptr %__promise.reload.addr, align 8, !tbaa !5
>   %1 = call ptr @llvm.coro.subfn.addr(ptr %retval.sroa.0.0.copyload.i.i, i8 0)
>   call fastcc void %1(ptr %retval.sroa.0.0.copyload.i.i) #2
>   ret void
> }
> ```
> 
> Note the missing `musttail`.
> 
> (In this case, later passes will make that a tail call anyway, at least on X86, but that wasn't the case in the original program which overflowed the stack instead.)
> 
> (The trick to the reproducer is that the coroutine has a return value the requires a couple of instructions to put together, which blocks `simplifyTerminatorLeadingToRet()`'s search for the return. At `-O0` those instructions come after the `llvm.coro.end` call so they don't block the search for return, but at `-O1` they come before.)

Thanks. The explanation looks slightly odd since I believe we have such cases before. I am wondering if this is a regression from  https://github.com/llvm/llvm-project/commit/f78688134026686288a8d310b493d9327753a022 (this may not be important)

And could you put the reduced example into the patch in somewhere of `clang/test/CodeGenCoroutines` as a regression test.

https://github.com/llvm/llvm-project/pull/85271


More information about the llvm-commits mailing list