xref: /llvm-project/mlir/test/Dialect/Async/async-to-async-runtime.mlir (revision af562fd27f65fa88b324c4f51a39439f109aeef9)
16cca6b9aSyijiagu// RUN: mlir-opt %s -split-input-file -async-func-to-async-runtime             \
26cca6b9aSyijiagu// RUN:   -async-to-async-runtime | FileCheck %s --dump-input=always
325f80e16SEugene Zhulenev
425f80e16SEugene Zhulenev// CHECK-LABEL: @execute_no_async_args
55e7dea22SRiver Riddlefunc.func @execute_no_async_args(%arg0: f32, %arg1: memref<1xf32>) {
625f80e16SEugene Zhulenev  %token = async.execute {
7a54f4eaeSMogball    %c0 = arith.constant 0 : index
8e2310704SJulian Gross    memref.store %arg0, %arg1[%c0] : memref<1xf32>
925f80e16SEugene Zhulenev    async.yield
1025f80e16SEugene Zhulenev  }
1125f80e16SEugene Zhulenev  async.await %token : !async.token
1225f80e16SEugene Zhulenev  return
1325f80e16SEugene Zhulenev}
1425f80e16SEugene Zhulenev
1525f80e16SEugene Zhulenev// Function outlined from the async.execute operation.
1625f80e16SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn
1725f80e16SEugene Zhulenev// CHECK-SAME: -> !async.token
1825f80e16SEugene Zhulenev
1925f80e16SEugene Zhulenev// Create token for return op, and mark a function as a coroutine.
2025f80e16SEugene Zhulenev// CHECK: %[[TOKEN:.*]] = async.runtime.create : !async.token
2125f80e16SEugene Zhulenev// CHECK: %[[ID:.*]] = async.coro.id
2225f80e16SEugene Zhulenev// CHECK: %[[HDL:.*]] = async.coro.begin
2325f80e16SEugene Zhulenev
2425f80e16SEugene Zhulenev// Pass a suspended coroutine to the async runtime.
2525f80e16SEugene Zhulenev// CHECK: %[[SAVED:.*]] = async.coro.save %[[HDL]]
2625f80e16SEugene Zhulenev// CHECK: async.runtime.resume %[[HDL]]
2725f80e16SEugene Zhulenev// CHECK: async.coro.suspend %[[SAVED]]
28*af562fd2SYunlong Liu// CHECK-SAME: ^[[SUSPEND:.*]], ^[[RESUME:.*]], ^[[DESTROY:.*]]
2925f80e16SEugene Zhulenev
3025f80e16SEugene Zhulenev// Resume coroutine after suspension.
3125f80e16SEugene Zhulenev// CHECK: ^[[RESUME]]:
32e2310704SJulian Gross// CHECK:   memref.store
3325f80e16SEugene Zhulenev// CHECK:   async.runtime.set_available %[[TOKEN]]
34*af562fd2SYunlong Liu// CHECK:   cf.br ^[[CLEANUP:.*]]
3525f80e16SEugene Zhulenev
3625f80e16SEugene Zhulenev// Delete coroutine.
3725f80e16SEugene Zhulenev// CHECK: ^[[CLEANUP]]:
3825f80e16SEugene Zhulenev// CHECK:   async.coro.free %[[ID]], %[[HDL]]
3925f80e16SEugene Zhulenev
40*af562fd2SYunlong Liu// Delete coroutine.
41*af562fd2SYunlong Liu// CHECK: ^[[DESTROY]]:
42*af562fd2SYunlong Liu// CHECK:   async.coro.free %[[ID]], %[[HDL]]
43*af562fd2SYunlong Liu
4425f80e16SEugene Zhulenev// Suspend coroutine, and also a return statement for ramp function.
4525f80e16SEugene Zhulenev// CHECK: ^[[SUSPEND]]:
4625f80e16SEugene Zhulenev// CHECK:   async.coro.end %[[HDL]]
4725f80e16SEugene Zhulenev// CHECK:   return %[[TOKEN]]
4825f80e16SEugene Zhulenev
4925f80e16SEugene Zhulenev// -----
5025f80e16SEugene Zhulenev
5125f80e16SEugene Zhulenev// CHECK-LABEL: @nested_async_execute
525e7dea22SRiver Riddlefunc.func @nested_async_execute(%arg0: f32, %arg1: f32, %arg2: memref<1xf32>) {
5325f80e16SEugene Zhulenev  // CHECK: %[[TOKEN:.*]] = call @async_execute_fn_0(%arg0, %arg2, %arg1)
5425f80e16SEugene Zhulenev  %token0 = async.execute {
55a54f4eaeSMogball    %c0 = arith.constant 0 : index
5625f80e16SEugene Zhulenev
5725f80e16SEugene Zhulenev    %token1 = async.execute {
58a54f4eaeSMogball      %c1 = arith.constant 1: index
59e2310704SJulian Gross      memref.store %arg0, %arg2[%c0] : memref<1xf32>
6025f80e16SEugene Zhulenev      async.yield
6125f80e16SEugene Zhulenev    }
6225f80e16SEugene Zhulenev    async.await %token1 : !async.token
6325f80e16SEugene Zhulenev
64e2310704SJulian Gross    memref.store %arg1, %arg2[%c0] : memref<1xf32>
6525f80e16SEugene Zhulenev    async.yield
6625f80e16SEugene Zhulenev  }
6725f80e16SEugene Zhulenev  // CHECK: async.runtime.await %[[TOKEN]]
68fd52b435SEugene Zhulenev  // CHECK: %[[IS_ERROR:.*]] = async.runtime.is_error %[[TOKEN]]
69a54f4eaeSMogball  // CHECK: %[[TRUE:.*]] = arith.constant true
70a54f4eaeSMogball  // CHECK: %[[NOT_ERROR:.*]] = arith.xori %[[IS_ERROR]], %[[TRUE]] : i1
71ace01605SRiver Riddle  // CHECK: cf.assert %[[NOT_ERROR]]
7225f80e16SEugene Zhulenev  // CHECK-NEXT: return
7325f80e16SEugene Zhulenev  async.await %token0 : !async.token
7425f80e16SEugene Zhulenev  return
7525f80e16SEugene Zhulenev}
7625f80e16SEugene Zhulenev
7725f80e16SEugene Zhulenev// Function outlined from the inner async.execute operation.
7825f80e16SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn
7925f80e16SEugene Zhulenev// CHECK-SAME: -> !async.token
8025f80e16SEugene Zhulenev
8125f80e16SEugene Zhulenev// CHECK: %[[TOKEN:.*]] = async.runtime.create : !async.token
8225f80e16SEugene Zhulenev// CHECK: %[[ID:.*]] = async.coro.id
8325f80e16SEugene Zhulenev// CHECK: %[[HDL:.*]] = async.coro.begin
8425f80e16SEugene Zhulenev
8525f80e16SEugene Zhulenev// CHECK: async.runtime.resume %[[HDL]]
8625f80e16SEugene Zhulenev// CHECK: async.coro.suspend
87*af562fd2SYunlong Liu// CHECK-SAME: ^[[SUSPEND:.*]], ^[[RESUME:.*]], ^[[DESTROY:.*]]
8825f80e16SEugene Zhulenev
8925f80e16SEugene Zhulenev// CHECK: ^[[RESUME]]:
90e2310704SJulian Gross// CHECK:   memref.store
9125f80e16SEugene Zhulenev// CHECK:   async.runtime.set_available %[[TOKEN]]
92*af562fd2SYunlong Liu// CHECK:   cf.br ^[[CLEANUP:.*]]
93*af562fd2SYunlong Liu
94*af562fd2SYunlong Liu// CHECK: ^[[CLEANUP]]:
95*af562fd2SYunlong Liu// CHECK: ^[[DESTROY]]:
9625f80e16SEugene Zhulenev
9725f80e16SEugene Zhulenev// Function outlined from the outer async.execute operation.
9825f80e16SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn_0
9925f80e16SEugene Zhulenev// CHECK-SAME: -> !async.token
10025f80e16SEugene Zhulenev
10125f80e16SEugene Zhulenev// CHECK: %[[TOKEN:.*]] = async.runtime.create : !async.token
10225f80e16SEugene Zhulenev// CHECK: %[[ID:.*]] = async.coro.id
10325f80e16SEugene Zhulenev// CHECK: %[[HDL:.*]] = async.coro.begin
10425f80e16SEugene Zhulenev
10525f80e16SEugene Zhulenev// Suspend coroutine in the beginning.
10625f80e16SEugene Zhulenev// CHECK: async.runtime.resume %[[HDL]]
10725f80e16SEugene Zhulenev// CHECK: async.coro.suspend
108*af562fd2SYunlong Liu// CHECK-SAME: ^[[SUSPEND:.*]], ^[[RESUME_0:.*]], ^[[DESTROY_0:.*]]
10925f80e16SEugene Zhulenev
11025f80e16SEugene Zhulenev// Suspend coroutine second time waiting for the completion of inner execute op.
11125f80e16SEugene Zhulenev// CHECK: ^[[RESUME_0]]:
11225f80e16SEugene Zhulenev// CHECK:   %[[INNER_TOKEN:.*]] = call @async_execute_fn
11325f80e16SEugene Zhulenev// CHECK:   %[[SAVED:.*]] = async.coro.save %[[HDL]]
11425f80e16SEugene Zhulenev// CHECK:   async.runtime.await_and_resume %[[INNER_TOKEN]], %[[HDL]]
11525f80e16SEugene Zhulenev// CHECK:   async.coro.suspend %[[SAVED]]
116*af562fd2SYunlong Liu// CHECK-SAME: ^[[SUSPEND]], ^[[RESUME_1:.*]], ^[[DESTROY_0]]
11725f80e16SEugene Zhulenev
11839957aa4SEugene Zhulenev// Check the error of the awaited token after resumption.
11925f80e16SEugene Zhulenev// CHECK: ^[[RESUME_1]]:
12039957aa4SEugene Zhulenev// CHECK:   %[[ERR:.*]] = async.runtime.is_error %[[INNER_TOKEN]]
121ace01605SRiver Riddle// CHECK:   cf.cond_br %[[ERR]], ^[[SET_ERROR:.*]], ^[[CONTINUATION:.*]]
12239957aa4SEugene Zhulenev
12339957aa4SEugene Zhulenev// Set token available if the token is not in the error state.
12439957aa4SEugene Zhulenev// CHECK: ^[[CONTINUATION:.*]]:
125e2310704SJulian Gross// CHECK:   memref.store
12625f80e16SEugene Zhulenev// CHECK:   async.runtime.set_available %[[TOKEN]]
127*af562fd2SYunlong Liu// CHECK:   cf.br ^[[CLEANUP_0:.*]]
12825f80e16SEugene Zhulenev
12939957aa4SEugene Zhulenev// CHECK: ^[[SET_ERROR]]:
130*af562fd2SYunlong Liu// CHECK: ^[[CLEANUP_0]]:
131*af562fd2SYunlong Liu// CHECK: ^[[DESTROY_0]]:
13225f80e16SEugene Zhulenev// CHECK: ^[[SUSPEND]]:
13325f80e16SEugene Zhulenev
13425f80e16SEugene Zhulenev// -----
13525f80e16SEugene Zhulenev
13625f80e16SEugene Zhulenev// CHECK-LABEL: @async_execute_token_dependency
1375e7dea22SRiver Riddlefunc.func @async_execute_token_dependency(%arg0: f32, %arg1: memref<1xf32>) {
13825f80e16SEugene Zhulenev  // CHECK: %[[TOKEN:.*]] = call @async_execute_fn
13925f80e16SEugene Zhulenev  %token = async.execute {
140a54f4eaeSMogball    %c0 = arith.constant 0 : index
141e2310704SJulian Gross    memref.store %arg0, %arg1[%c0] : memref<1xf32>
14225f80e16SEugene Zhulenev    async.yield
14325f80e16SEugene Zhulenev  }
14425f80e16SEugene Zhulenev  // CHECK: call @async_execute_fn_0(%[[TOKEN]], %arg0, %arg1)
14525f80e16SEugene Zhulenev  %token_0 = async.execute [%token] {
146a54f4eaeSMogball    %c0 = arith.constant 0 : index
147e2310704SJulian Gross    memref.store %arg0, %arg1[%c0] : memref<1xf32>
14825f80e16SEugene Zhulenev    async.yield
14925f80e16SEugene Zhulenev  }
15025f80e16SEugene Zhulenev  return
15125f80e16SEugene Zhulenev}
15225f80e16SEugene Zhulenev
15325f80e16SEugene Zhulenev// Function outlined from the first async.execute operation.
15425f80e16SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn
15525f80e16SEugene Zhulenev// CHECK-SAME: -> !async.token
15625f80e16SEugene Zhulenev// CHECK: %[[TOKEN:.*]] = async.runtime.create : !async.token
15725f80e16SEugene Zhulenev// CHECK: return %[[TOKEN]] : !async.token
15825f80e16SEugene Zhulenev
15925f80e16SEugene Zhulenev// Function outlined from the second async.execute operation with dependency.
16025f80e16SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn_0
16125f80e16SEugene Zhulenev// CHECK-SAME:    %[[ARG0:.*]]: !async.token
16225f80e16SEugene Zhulenev// CHECK-SAME:    %[[ARG1:.*]]: f32
16325f80e16SEugene Zhulenev// CHECK-SAME:    %[[ARG2:.*]]: memref<1xf32>
16425f80e16SEugene Zhulenev// CHECK-SAME: -> !async.token
16525f80e16SEugene Zhulenev// CHECK: %[[TOKEN:.*]] = async.runtime.create : !async.token
16625f80e16SEugene Zhulenev// CHECK: %[[HDL:.*]] = async.coro.begin
16725f80e16SEugene Zhulenev
16825f80e16SEugene Zhulenev// Suspend coroutine in the beginning.
16925f80e16SEugene Zhulenev// CHECK: async.runtime.resume %[[HDL]]
17025f80e16SEugene Zhulenev// CHECK: async.coro.suspend
17125f80e16SEugene Zhulenev// CHECK-SAME: ^[[SUSPEND:.*]], ^[[RESUME_0:.*]], ^[[CLEANUP:.*]]
17225f80e16SEugene Zhulenev
17325f80e16SEugene Zhulenev// Suspend coroutine second time waiting for the completion of token dependency.
17425f80e16SEugene Zhulenev// CHECK: ^[[RESUME_0]]:
17525f80e16SEugene Zhulenev// CHECK:   %[[SAVED:.*]] = async.coro.save %[[HDL]]
17625f80e16SEugene Zhulenev// CHECK:   async.runtime.await_and_resume %[[ARG0]], %[[HDL]]
17725f80e16SEugene Zhulenev// CHECK:   async.coro.suspend %[[SAVED]]
17825f80e16SEugene Zhulenev// CHECK-SAME: ^[[SUSPEND]], ^[[RESUME_1:.*]], ^[[CLEANUP]]
17925f80e16SEugene Zhulenev
18039957aa4SEugene Zhulenev// Check the error of the awaited token after resumption.
18125f80e16SEugene Zhulenev// CHECK: ^[[RESUME_1]]:
18239957aa4SEugene Zhulenev// CHECK:   %[[ERR:.*]] = async.runtime.is_error %[[ARG0]]
183ace01605SRiver Riddle// CHECK:   cf.cond_br %[[ERR]], ^[[SET_ERROR:.*]], ^[[CONTINUATION:.*]]
18439957aa4SEugene Zhulenev
18539957aa4SEugene Zhulenev// Emplace result token after second resumption and error checking.
18639957aa4SEugene Zhulenev// CHECK: ^[[CONTINUATION:.*]]:
187e2310704SJulian Gross// CHECK:   memref.store
18825f80e16SEugene Zhulenev// CHECK:   async.runtime.set_available %[[TOKEN]]
18925f80e16SEugene Zhulenev
19025f80e16SEugene Zhulenev// CHECK: ^[[CLEANUP]]:
19125f80e16SEugene Zhulenev// CHECK: ^[[SUSPEND]]:
19225f80e16SEugene Zhulenev
19325f80e16SEugene Zhulenev// -----
19425f80e16SEugene Zhulenev
19525f80e16SEugene Zhulenev// CHECK-LABEL: @async_group_await_all
1965e7dea22SRiver Riddlefunc.func @async_group_await_all(%arg0: f32, %arg1: memref<1xf32>) {
197a54f4eaeSMogball  // CHECK: %[[C:.*]] = arith.constant 1 : index
198a54f4eaeSMogball  %c = arith.constant 1 : index
199d43b2360SEugene Zhulenev  // CHECK: %[[GROUP:.*]] = async.runtime.create_group %[[C]] : !async.group
200d43b2360SEugene Zhulenev  %0 = async.create_group %c : !async.group
20125f80e16SEugene Zhulenev
20225f80e16SEugene Zhulenev  // CHECK: %[[TOKEN:.*]] = call @async_execute_fn
20325f80e16SEugene Zhulenev  %token = async.execute { async.yield }
20425f80e16SEugene Zhulenev  // CHECK: async.runtime.add_to_group %[[TOKEN]], %[[GROUP]]
20525f80e16SEugene Zhulenev  async.add_to_group %token, %0 : !async.token
20625f80e16SEugene Zhulenev
20725f80e16SEugene Zhulenev  // CHECK: call @async_execute_fn_0
20825f80e16SEugene Zhulenev  async.execute {
20925f80e16SEugene Zhulenev    async.await_all %0
21025f80e16SEugene Zhulenev    async.yield
21125f80e16SEugene Zhulenev  }
21225f80e16SEugene Zhulenev
21325f80e16SEugene Zhulenev  // CHECK: async.runtime.await %[[GROUP]] : !async.group
21425f80e16SEugene Zhulenev  async.await_all %0
21525f80e16SEugene Zhulenev  return
21625f80e16SEugene Zhulenev}
21725f80e16SEugene Zhulenev
21825f80e16SEugene Zhulenev// Function outlined from the second async.execute operation.
21925f80e16SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn_0
22025f80e16SEugene Zhulenev// CHECK-SAME: (%[[ARG:.*]]: !async.group) -> !async.token
22125f80e16SEugene Zhulenev
22225f80e16SEugene Zhulenev// CHECK: %[[TOKEN:.*]] = async.runtime.create : !async.token
22325f80e16SEugene Zhulenev// CHECK: %[[HDL:.*]] = async.coro.begin
22425f80e16SEugene Zhulenev
22525f80e16SEugene Zhulenev// Suspend coroutine in the beginning.
22625f80e16SEugene Zhulenev// CHECK: async.runtime.resume %[[HDL]]
22725f80e16SEugene Zhulenev// CHECK: async.coro.suspend
22825f80e16SEugene Zhulenev// CHECK-SAME: ^[[SUSPEND:.*]], ^[[RESUME_0:.*]], ^[[CLEANUP:.*]]
22925f80e16SEugene Zhulenev
23025f80e16SEugene Zhulenev// Suspend coroutine second time waiting for the group.
23125f80e16SEugene Zhulenev// CHECK: ^[[RESUME_0]]:
23225f80e16SEugene Zhulenev// CHECK:   async.runtime.await_and_resume %[[ARG]], %[[HDL]]
23325f80e16SEugene Zhulenev// CHECK:   async.coro.suspend
23425f80e16SEugene Zhulenev// CHECK-SAME: ^[[SUSPEND]], ^[[RESUME_1:.*]], ^[[CLEANUP]]
23525f80e16SEugene Zhulenev
236d8c84d2aSEugene Zhulenev// Check the error of the awaited token after resumption.
23725f80e16SEugene Zhulenev// CHECK: ^[[RESUME_1]]:
238d8c84d2aSEugene Zhulenev// CHECK:   %[[ERR:.*]] = async.runtime.is_error %[[ARG]]
239ace01605SRiver Riddle// CHECK:   cf.cond_br %[[ERR]], ^[[SET_ERROR:.*]], ^[[CONTINUATION:.*]]
240d8c84d2aSEugene Zhulenev
241d8c84d2aSEugene Zhulenev// Emplace result token after error checking.
242d8c84d2aSEugene Zhulenev// CHECK: ^[[CONTINUATION:.*]]:
24325f80e16SEugene Zhulenev// CHECK:   async.runtime.set_available %[[TOKEN]]
24425f80e16SEugene Zhulenev
24525f80e16SEugene Zhulenev// CHECK: ^[[CLEANUP]]:
24625f80e16SEugene Zhulenev// CHECK: ^[[SUSPEND]]:
24725f80e16SEugene Zhulenev
24825f80e16SEugene Zhulenev// -----
24925f80e16SEugene Zhulenev
25025f80e16SEugene Zhulenev// CHECK-LABEL: @execute_and_return_f32
2515e7dea22SRiver Riddlefunc.func @execute_and_return_f32() -> f32 {
25225f80e16SEugene Zhulenev // CHECK: %[[RET:.*]]:2 = call @async_execute_fn
25325f80e16SEugene Zhulenev  %token, %result = async.execute -> !async.value<f32> {
254a54f4eaeSMogball    %c0 = arith.constant 123.0 : f32
25525f80e16SEugene Zhulenev    async.yield %c0 : f32
25625f80e16SEugene Zhulenev  }
25725f80e16SEugene Zhulenev
25825f80e16SEugene Zhulenev  // CHECK: async.runtime.await %[[RET]]#1 : !async.value<f32>
259ee090870SMehdi Amini  // CHECK: %[[VALUE:.*]] = async.runtime.load %[[RET]]#1 : <f32>
26025f80e16SEugene Zhulenev  %0 = async.await %result : !async.value<f32>
26125f80e16SEugene Zhulenev
26225f80e16SEugene Zhulenev  // CHECK: return %[[VALUE]]
26325f80e16SEugene Zhulenev  return %0 : f32
26425f80e16SEugene Zhulenev}
26525f80e16SEugene Zhulenev
26625f80e16SEugene Zhulenev// Function outlined from the async.execute operation.
26725f80e16SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn()
26825f80e16SEugene Zhulenev// CHECK: %[[TOKEN:.*]] = async.runtime.create : !async.token
26925f80e16SEugene Zhulenev// CHECK: %[[VALUE:.*]] = async.runtime.create : !async.value<f32>
27025f80e16SEugene Zhulenev// CHECK: %[[HDL:.*]] = async.coro.begin
27125f80e16SEugene Zhulenev
27225f80e16SEugene Zhulenev// Suspend coroutine in the beginning.
27325f80e16SEugene Zhulenev// CHECK: async.runtime.resume %[[HDL]]
27425f80e16SEugene Zhulenev// CHECK: async.coro.suspend
27525f80e16SEugene Zhulenev// CHECK-SAME: ^[[SUSPEND:.*]], ^[[RESUME:.*]], ^[[CLEANUP:.*]]
27625f80e16SEugene Zhulenev
27725f80e16SEugene Zhulenev// Emplace result value.
27825f80e16SEugene Zhulenev// CHECK: ^[[RESUME]]:
279a54f4eaeSMogball// CHECK:   %[[CST:.*]] = arith.constant 1.230000e+02 : f32
28025f80e16SEugene Zhulenev// CHECK:   async.runtime.store %cst, %[[VALUE]]
28125f80e16SEugene Zhulenev// CHECK:   async.runtime.set_available %[[VALUE]]
28225f80e16SEugene Zhulenev// CHECK:   async.runtime.set_available %[[TOKEN]]
28325f80e16SEugene Zhulenev
28425f80e16SEugene Zhulenev// CHECK: ^[[CLEANUP]]:
28525f80e16SEugene Zhulenev// CHECK: ^[[SUSPEND]]:
28625f80e16SEugene Zhulenev
28725f80e16SEugene Zhulenev// -----
28825f80e16SEugene Zhulenev
28925f80e16SEugene Zhulenev// CHECK-LABEL: @async_value_operands
2905e7dea22SRiver Riddlefunc.func @async_value_operands() {
29125f80e16SEugene Zhulenev  // CHECK: %[[RET:.*]]:2 = call @async_execute_fn
29225f80e16SEugene Zhulenev  %token, %result = async.execute -> !async.value<f32> {
293a54f4eaeSMogball    %c0 = arith.constant 123.0 : f32
29425f80e16SEugene Zhulenev    async.yield %c0 : f32
29525f80e16SEugene Zhulenev  }
29625f80e16SEugene Zhulenev
29725f80e16SEugene Zhulenev  // CHECK: %[[TOKEN:.*]] = call @async_execute_fn_0(%[[RET]]#1)
29825f80e16SEugene Zhulenev  %token0 = async.execute(%result as %value: !async.value<f32>) {
299a54f4eaeSMogball    %0 = arith.addf %value, %value : f32
30025f80e16SEugene Zhulenev    async.yield
30125f80e16SEugene Zhulenev  }
30225f80e16SEugene Zhulenev
30325f80e16SEugene Zhulenev  // CHECK: async.runtime.await %[[TOKEN]] : !async.token
30425f80e16SEugene Zhulenev  async.await %token0 : !async.token
30525f80e16SEugene Zhulenev
30625f80e16SEugene Zhulenev  return
30725f80e16SEugene Zhulenev}
30825f80e16SEugene Zhulenev
30925f80e16SEugene Zhulenev// Function outlined from the first async.execute operation.
31025f80e16SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn()
31125f80e16SEugene Zhulenev
31225f80e16SEugene Zhulenev// Function outlined from the second async.execute operation.
31325f80e16SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn_0
31425f80e16SEugene Zhulenev// CHECK-SAME: (%[[ARG:.*]]: !async.value<f32>) -> !async.token
31525f80e16SEugene Zhulenev
31625f80e16SEugene Zhulenev// CHECK: %[[TOKEN:.*]] = async.runtime.create : !async.token
31725f80e16SEugene Zhulenev// CHECK: %[[HDL:.*]] = async.coro.begin
31825f80e16SEugene Zhulenev
31925f80e16SEugene Zhulenev// Suspend coroutine in the beginning.
32025f80e16SEugene Zhulenev// CHECK: async.runtime.resume %[[HDL]]
32125f80e16SEugene Zhulenev// CHECK: async.coro.suspend
32225f80e16SEugene Zhulenev// CHECK-SAME: ^[[SUSPEND:.*]], ^[[RESUME_0:.*]], ^[[CLEANUP:.*]]
32325f80e16SEugene Zhulenev
32425f80e16SEugene Zhulenev// Suspend coroutine second time waiting for the async operand.
32525f80e16SEugene Zhulenev// CHECK: ^[[RESUME_0]]:
32625f80e16SEugene Zhulenev// CHECK:   async.runtime.await_and_resume %[[ARG]], %[[HDL]]
32725f80e16SEugene Zhulenev// CHECK:   async.coro.suspend
32825f80e16SEugene Zhulenev// CHECK-SAME: ^[[SUSPEND]], ^[[RESUME_1:.*]], ^[[CLEANUP]]
32925f80e16SEugene Zhulenev
33039957aa4SEugene Zhulenev// Check the error of the awaited token after resumption.
33125f80e16SEugene Zhulenev// CHECK: ^[[RESUME_1]]:
33239957aa4SEugene Zhulenev// CHECK:   %[[ERR:.*]] = async.runtime.is_error %[[ARG]]
333ace01605SRiver Riddle// CHECK:   cf.cond_br %[[ERR]], ^[[SET_ERROR:.*]], ^[[CONTINUATION:.*]]
33439957aa4SEugene Zhulenev
33539957aa4SEugene Zhulenev// // Load from the async.value argument after error checking.
33639957aa4SEugene Zhulenev// CHECK: ^[[CONTINUATION:.*]]:
337ee090870SMehdi Amini// CHECK:   %[[LOADED:.*]] = async.runtime.load %[[ARG]] : <f32
338a54f4eaeSMogball// CHECK:   arith.addf %[[LOADED]], %[[LOADED]] : f32
33925f80e16SEugene Zhulenev// CHECK:   async.runtime.set_available %[[TOKEN]]
34025f80e16SEugene Zhulenev
34125f80e16SEugene Zhulenev// CHECK: ^[[CLEANUP]]:
34225f80e16SEugene Zhulenev// CHECK: ^[[SUSPEND]]:
34339957aa4SEugene Zhulenev
34439957aa4SEugene Zhulenev// -----
34539957aa4SEugene Zhulenev
3461c144410Sbakhtiyar// CHECK-LABEL: @execute_assertion
3475e7dea22SRiver Riddlefunc.func @execute_assertion(%arg0: i1) {
34839957aa4SEugene Zhulenev  %token = async.execute {
349ace01605SRiver Riddle    cf.assert %arg0, "error"
35039957aa4SEugene Zhulenev    async.yield
35139957aa4SEugene Zhulenev  }
35239957aa4SEugene Zhulenev  async.await %token : !async.token
35339957aa4SEugene Zhulenev  return
35439957aa4SEugene Zhulenev}
35539957aa4SEugene Zhulenev
35639957aa4SEugene Zhulenev// Function outlined from the async.execute operation.
35739957aa4SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn(
35839957aa4SEugene Zhulenev// CHECK-SAME:  %[[ARG0:.*]]: i1
35939957aa4SEugene Zhulenev// CHECK-SAME:  -> !async.token
36039957aa4SEugene Zhulenev
36139957aa4SEugene Zhulenev// Create token for return op, and mark a function as a coroutine.
36239957aa4SEugene Zhulenev// CHECK: %[[TOKEN:.*]] = async.runtime.create : !async.token
36339957aa4SEugene Zhulenev// CHECK: %[[ID:.*]] = async.coro.id
36439957aa4SEugene Zhulenev// CHECK: %[[HDL:.*]] = async.coro.begin
36539957aa4SEugene Zhulenev
36639957aa4SEugene Zhulenev// Initial coroutine suspension.
36739957aa4SEugene Zhulenev// CHECK:      async.coro.suspend
368*af562fd2SYunlong Liu// CHECK-SAME: ^[[SUSPEND:.*]], ^[[RESUME:.*]], ^[[DESTROY:.*]]
36939957aa4SEugene Zhulenev
37039957aa4SEugene Zhulenev// Resume coroutine after suspension.
37139957aa4SEugene Zhulenev// CHECK: ^[[RESUME]]:
372ace01605SRiver Riddle// CHECK:   cf.cond_br %[[ARG0]], ^[[SET_AVAILABLE:.*]], ^[[SET_ERROR:.*]]
37339957aa4SEugene Zhulenev
37439957aa4SEugene Zhulenev// Set coroutine completion token to available state.
37539957aa4SEugene Zhulenev// CHECK: ^[[SET_AVAILABLE]]:
37639957aa4SEugene Zhulenev// CHECK:   async.runtime.set_available %[[TOKEN]]
377*af562fd2SYunlong Liu// CHECK:   cf.br ^[[CLEANUP:.*]]
37839957aa4SEugene Zhulenev
37939957aa4SEugene Zhulenev// Set coroutine completion token to error state.
38039957aa4SEugene Zhulenev// CHECK: ^[[SET_ERROR]]:
38139957aa4SEugene Zhulenev// CHECK:   async.runtime.set_error %[[TOKEN]]
382ace01605SRiver Riddle// CHECK:   cf.br ^[[CLEANUP]]
38339957aa4SEugene Zhulenev
38439957aa4SEugene Zhulenev// Delete coroutine.
38539957aa4SEugene Zhulenev// CHECK: ^[[CLEANUP]]:
38639957aa4SEugene Zhulenev// CHECK:   async.coro.free %[[ID]], %[[HDL]]
38739957aa4SEugene Zhulenev
388*af562fd2SYunlong Liu// Delete coroutine.
389*af562fd2SYunlong Liu// CHECK: ^[[DESTROY]]:
390*af562fd2SYunlong Liu// CHECK:   async.coro.free %[[ID]], %[[HDL]]
391*af562fd2SYunlong Liu
39239957aa4SEugene Zhulenev// Suspend coroutine, and also a return statement for ramp function.
39339957aa4SEugene Zhulenev// CHECK: ^[[SUSPEND]]:
39439957aa4SEugene Zhulenev// CHECK:   async.coro.end %[[HDL]]
39539957aa4SEugene Zhulenev// CHECK:   return %[[TOKEN]]
396de7a4e53SEugene Zhulenev
397de7a4e53SEugene Zhulenev// -----
398de7a4e53SEugene Zhulenev// Structured control flow operations with async operations in the body must be
399de7a4e53SEugene Zhulenev// lowered to branch-based control flow to enable coroutine CFG rewrite.
400de7a4e53SEugene Zhulenev
401de7a4e53SEugene Zhulenev// CHECK-LABEL: @lower_scf_to_cfg
4025e7dea22SRiver Riddlefunc.func @lower_scf_to_cfg(%arg0: f32, %arg1: memref<1xf32>, %arg2: i1) {
403de7a4e53SEugene Zhulenev  %token0 = async.execute { async.yield }
404de7a4e53SEugene Zhulenev  %token1 = async.execute {
405de7a4e53SEugene Zhulenev    scf.if %arg2 {
406de7a4e53SEugene Zhulenev      async.await %token0 : !async.token
407de7a4e53SEugene Zhulenev    } else {
408de7a4e53SEugene Zhulenev      async.await %token0 : !async.token
409de7a4e53SEugene Zhulenev    }
410de7a4e53SEugene Zhulenev    async.yield
411de7a4e53SEugene Zhulenev  }
412de7a4e53SEugene Zhulenev  return
413de7a4e53SEugene Zhulenev}
414de7a4e53SEugene Zhulenev
415de7a4e53SEugene Zhulenev// Function outlined from the first async.execute operation.
416de7a4e53SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn(
417de7a4e53SEugene Zhulenev// CHECK-SAME: -> !async.token
418de7a4e53SEugene Zhulenev
419de7a4e53SEugene Zhulenev// Function outlined from the second async.execute operation.
420de7a4e53SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn_0(
421de7a4e53SEugene Zhulenev// CHECK:         %[[TOKEN:.*]]: !async.token
422de7a4e53SEugene Zhulenev// CHECK:         %[[FLAG:.*]]: i1
423de7a4e53SEugene Zhulenev// CHECK-SAME: -> !async.token
424de7a4e53SEugene Zhulenev
425de7a4e53SEugene Zhulenev// Check that structured control flow lowered to CFG.
426de7a4e53SEugene Zhulenev// CHECK-NOT: scf.if
427ace01605SRiver Riddle// CHECK: cf.cond_br %[[FLAG]]
428b537c5b4SEugene Zhulenev
429b537c5b4SEugene Zhulenev// -----
430b537c5b4SEugene Zhulenev// Constants captured by the async.execute region should be cloned into the
431b537c5b4SEugene Zhulenev// outline async execute function.
432b537c5b4SEugene Zhulenev
433b537c5b4SEugene Zhulenev// CHECK-LABEL: @clone_constants
4345e7dea22SRiver Riddlefunc.func @clone_constants(%arg0: f32, %arg1: memref<1xf32>) {
435a54f4eaeSMogball  %c0 = arith.constant 0 : index
436b537c5b4SEugene Zhulenev  %token = async.execute {
437b537c5b4SEugene Zhulenev    memref.store %arg0, %arg1[%c0] : memref<1xf32>
438b537c5b4SEugene Zhulenev    async.yield
439b537c5b4SEugene Zhulenev  }
440b537c5b4SEugene Zhulenev  async.await %token : !async.token
441b537c5b4SEugene Zhulenev  return
442b537c5b4SEugene Zhulenev}
443b537c5b4SEugene Zhulenev
444b537c5b4SEugene Zhulenev// Function outlined from the async.execute operation.
445b537c5b4SEugene Zhulenev// CHECK-LABEL: func private @async_execute_fn(
446b537c5b4SEugene Zhulenev// CHECK-SAME:    %[[VALUE:arg[0-9]+]]: f32,
447b537c5b4SEugene Zhulenev// CHECK-SAME:    %[[MEMREF:arg[0-9]+]]: memref<1xf32>
448b537c5b4SEugene Zhulenev// CHECK-SAME:  ) -> !async.token
449a54f4eaeSMogball// CHECK:         %[[CST:.*]] = arith.constant 0 : index
450b537c5b4SEugene Zhulenev// CHECK:         memref.store %[[VALUE]], %[[MEMREF]][%[[CST]]]
451f81f8808Syijiagu
452f81f8808Syijiagu// -----
453f81f8808Syijiagu// Async Functions should be none blocking
454f81f8808Syijiagu
455f81f8808Syijiagu// CHECK-LABEL: @async_func_await
456f81f8808Syijiaguasync.func @async_func_await(%arg0: f32, %arg1: !async.value<f32>)
457f81f8808Syijiagu              -> !async.token {
458f81f8808Syijiagu  %0 = async.await %arg1 : !async.value<f32>
459f81f8808Syijiagu  return
460f81f8808Syijiagu}
461f81f8808Syijiagu// Create token for return op, and mark a function as a coroutine.
462f81f8808Syijiagu// CHECK: %[[TOKEN:.*]] = async.runtime.create : !async.token
463f81f8808Syijiagu// CHECK: %[[ID:.*]] = async.coro.id
464f81f8808Syijiagu// CHECK: %[[HDL:.*]] = async.coro.begin
465f81f8808Syijiagu// CHECK:   cf.br ^[[ORIGIN_ENTRY:.*]]
466f81f8808Syijiagu
467f81f8808Syijiagu// CHECK: ^[[ORIGIN_ENTRY]]:
468f81f8808Syijiagu// CHECK: %[[SAVED:.*]] = async.coro.save %[[HDL]]
469f81f8808Syijiagu// CHECK: async.runtime.await_and_resume %[[arg1:.*]], %[[HDL]] :
470f81f8808Syijiagu// CHECK-SAME: !async.value<f32>
471f81f8808Syijiagu// CHECK: async.coro.suspend %[[SAVED]]
472f81f8808Syijiagu// CHECK-SAME: ^[[SUSPEND:.*]], ^[[RESUME:.*]], ^[[CLEANUP:.*]]
473a5ddd920Syijiagu
474a5ddd920Syijiagu// -----
475a5ddd920Syijiagu// Async execute inside async func
476a5ddd920Syijiagu
477a5ddd920Syijiagu// CHECK-LABEL: @execute_in_async_func
478a5ddd920Syijiaguasync.func @execute_in_async_func(%arg0: f32, %arg1: memref<1xf32>)
479a5ddd920Syijiagu             -> !async.token {
480a5ddd920Syijiagu  %token = async.execute {
481a5ddd920Syijiagu    %c0 = arith.constant 0 : index
482a5ddd920Syijiagu    memref.store %arg0, %arg1[%c0] : memref<1xf32>
483a5ddd920Syijiagu    async.yield
484a5ddd920Syijiagu  }
485a5ddd920Syijiagu  async.await %token : !async.token
486a5ddd920Syijiagu  return
487a5ddd920Syijiagu}
488a5ddd920Syijiagu// Call outlind async execute Function
489a5ddd920Syijiagu// CHECK: %[[RES:.*]] = call @async_execute_fn(
490a5ddd920Syijiagu// CHECK-SAME:    %[[VALUE:arg[0-9]+]],
491a5ddd920Syijiagu// CHECK-SAME:    %[[MEMREF:arg[0-9]+]]
492a5ddd920Syijiagu// CHECK-SAME:  ) : (f32, memref<1xf32>) -> !async.token
493a5ddd920Syijiagu
494a5ddd920Syijiagu// Function outlined from the async.execute operation.
495a5ddd920Syijiagu// CHECK-LABEL: func private @async_execute_fn(
496a5ddd920Syijiagu// CHECK-SAME:    %[[VALUE:arg[0-9]+]]: f32,
497a5ddd920Syijiagu// CHECK-SAME:    %[[MEMREF:arg[0-9]+]]: memref<1xf32>
498a5ddd920Syijiagu// CHECK-SAME:  ) -> !async.token
499a5ddd920Syijiagu// CHECK:         %[[CST:.*]] = arith.constant 0 : index
500a5ddd920Syijiagu// CHECK:         memref.store %[[VALUE]], %[[MEMREF]][%[[CST]]]
501