[mlir] Convert from Async dialect to LLVM coroutines
Lower from Async dialect to LLVM by converting async regions attached to async.execute operations into LLVM coroutines (https://llvm.org/docs/Coroutines.html):
- Outline all async regions to functions
- Add LLVM coro intrinsics to mark coroutine begin/end
- Use MLIR conversion framework to convert all remaining async types and ops to LLVM + Async runtime function calls
All async.await operations inside async regions converted to coroutine suspension points. Await operation outside of a coroutine converted to the blocking wait operations.
Implement simple runtime to support concurrent execution of coroutines.
Reviewed By: herhut
Differential Revision: https://reviews.llvm.org/D89292