According to https://reviews.llvm.org/D43242, coroelide pass only considers llvm.coro.destroy that dominate non-exceptional return. However, this cannot be met if current function is coroutine function because of suspend point.
Consider case from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0978r0.html :
task<> big_task() { // lifetime of `subtask` is fully enclosed in its caller co_await subtask(); // coroutine frame allocation elided }
such cases should be optimized.
this patch does two changes in shouldElide function:
- Consider final coro.suspend as real non-exceptional terminator when function is coroutine, since final suspend is executed with or without exception at last.
- When function body is wrapped by try-catch, block of coro.suspend may has multiple predecessors : one normal path and the others are exceptional path, and they do not dominate each other. If all the predecessors dominate coro.destroys that reference same coro.begin, we consider condition is met.
- Keep normal function as usual
Test Plan:
Compile https://godbolt.org/g/mCKfnr and confirm it is still optimized to a single instruction, 'return 1190'.
Compile and run https://godbolt.org/z/AbdRw4, there is no "new" and "delete" output
Compile and run https://godbolt.org/z/gjYSi5 , there is no "new" and "delete" output
check-llvm
typo: "coroutine". Also, nit-pick comment, but: I would write this "Consider the final coro.suspend as the real terminator when the current function is a coroutine." But I might be misunderstanding what you mean by "real terminator" and "coroutine expanded function" here.