The C++20 Coroutines couldn't be compiled to WebAssembly due to an optimization named symmetric transfer requires the support for musttail calls but WebAssembly doesn't support it yet. So the revision tried to disable the optimization for WebAssembly to make we could compile standard C++20 codes in that platform.
Details
Diff Detail
Event Timeline
Thanks for taking a look at this!
llvm/lib/Transforms/Coroutines/CoroSplit.cpp | ||
---|---|---|
1570 | It would be good if we could call out to the TargetTransformInfo to ask the backend whether it supports tail calls. Then we could gracefully handle the case where the WebAssembly tail-call target feature is enabled. |
Afaict, symmetric transfer is guaranteed by the C++20 standard.
https://eel.is/c++draft/expr.await#note-1 states
[...] Any number of coroutines can be successively resumed in this fashion, eventually returning control flow to the current coroutine caller or resumer [...]
Without symmetric transfer or an equivalent optimization, this statement wouldn't hold true, because we would run out of stack space before resuming an arbitrary number of coroutines
Also, note that cppcoro (afaict, the de-facto reference implementation for C++20 coroutine types) mentions in a comment, that
[...] the compiler supports returning a coroutine_handle from the await_suspend() method as a way of transferring execution to another coroutine with a guaranteed tail-call.
(emphasis mine)
Oh, my bad. Thanks for reporting this. But it is still odd to me since it is not supported by all archs and C++ is intended to be target independent. I've sent this question to WG21. I would take an eye on this. And let's not block this one to not prevent C++ coroutines to be used in more targets.
llvm/lib/Transforms/Coroutines/CoroSplit.cpp | ||
---|---|---|
1570 | I tried to look TargetTransformInfo at first but I don't find the wanted methods. Then I don't find similar things in CodeGen and Target as well. So it looks like there is not on-the-shelf tool. I prefer the current method as a workaround and replace this workaround later if we or anyone implemented thing interface we want. |
I think it would make sense to add a new method to TTI for this, since hardcoding an exception for Wasm is not going to be future-proof at all. The tail-call target feature, while not standard yet, is very close to being standardized and shipped in browsers. It's already available behind a flag in Chrome and Node. Also, if possible, it would be good to perform a different transformation that can still do symmetric transfer without tail calls if the prevailing view is that symmetric transfer is guaranteed by the spec (but simply omitting musttail for now seems like a reasonable stopgap measure).
Yeah, it makes sense.
Also, if possible, it would be good to perform a different transformation that can still do symmetric transfer without tail calls if the prevailing view is that symmetric transfer is guaranteed by the spec (but simply omitting musttail for now seems like a reasonable stopgap measure).
Maybe it is possible to perform symmetric transfer without tail call. But the complexity of implementation and efficiency may be a problem. So the first step might omit it simply and I'll file an issue for it.
It would be good if we could call out to the TargetTransformInfo to ask the backend whether it supports tail calls. Then we could gracefully handle the case where the WebAssembly tail-call target feature is enabled.