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