[clang][CodeGen] Promote point of GRO(CWG2563) (#151067)
This patch implement piece of the proposed solution to
[CWG2563](https://cplusplus.github.io/CWG/issues/2563.html):
> [9.6.4 dcl.fct.def.coroutine.p8] This return exits the scope of gro.
It exits the scope of promise only if the coroutine completed without
suspending.
If a coroutine completes without suspending, it does not exit the scope
of the promise until GRO conversion is done, because GRO conversion is
considered part of the coroutine execution. The current behavior
performs conversion after coroutine state cleanup, which does not
conform to the standard:
``` LLVM
before.cleanup:
; ...
br label %coro.cleanup
coro.cleanup:
; cleanup logics
br %coro.end
coro.end:
call void @llvm.coro.end(ptr null, i1 false, token none)
; GRO conversion
; ret GRO or void
```
This patch proposes the following codegen:
``` LLVM
any.suspend:
%suspend = call i8 @llvm.coro.suspend(token %8, i1 true)
switch i8 %suspend, label %pre.gro.conv [
i8 0, label %ready
i8 1, label %coro.cleanup
]
ready:
; ...
pre.gro.conv:
%body.done = phi i1 [ false, %any.suspend ], [ true, %any.ready ]
%InRamp = call i1 @llvm.coro.is_in_ramp()
br i1 %InRamp, label %gro.conv, label %after.gro.conv
gro.conv:
; GRO conversion
br label %after.gro.conv
after.gro.conv:
br i1 %body.done, label %coro.cleanup, label %coro.ret
coro.cleanup:
; cleanup logics
br %coro.ret
coro.ret:
call void @llvm.coro.end(ptr null, i1 false, token none)
; ret GRO or void
```
Close #120200