Close https://github.com/llvm/llvm-project/issues/56301
Close https://github.com/llvm/llvm-project/issues/64151
See the summary and the discussion of https://reviews.llvm.org/D157070 to get the full context.
As @rjmccall pointed out, the key point of the root cause is that currently we didn't implement the semantics well ("after the await-ready returns false, the coroutine is considered to be suspended ") well. Since the semantics implies that we (the compiler) shouldn't write the spills into the coroutine frame in the await_suspend. Now it is possible due to some combinations of the optimizations so the semantics are broken. And the inlining is the root optimization of such optimizations. So in this patch, we tried to add the noinline attribute to the await_suspend call.
Also as an optimization, we don't add the noinline attribute to the await_suspend call if the awaiter is an empty class. This should be correct since the programmers can't access the local variables in await_suspend if the awaiter is empty. I think this is necessary for the performance since it is pretty common.
Another potential optimization chance is to remove the noinline attribute in CoroSplit so that we can still inline it finally. But I didn't do that in this patch since I want to separate the llvm patches and clang patches as much as possible.
Suggestion: