blob: 6c49196249e287fede334e4ab5a5424116a2e3cc [file] [edit]
// RUN: mlir-opt %s --pass-pipeline='builtin.module(gpu.module(any(acc-bind-routine)), any(acc-bind-routine))' -split-input-file | FileCheck %s
// Call to routine with bind is rewritten to the bound symbol inside
// offload region.
module {
acc.routine @r_bind func(@foo) seq bind(@bar)
func.func @foo() attributes {acc.routine_info = #acc.routine_info<[@r_bind]>} {
return
}
func.func @bar() {
return
}
func.func @main() {
acc.serial {
func.call @foo() : () -> ()
acc.yield
}
return
}
}
// CHECK: acc.routine @r_bind func(@foo) bind(@bar) seq
// CHECK: func.call @bar() : () -> ()
// -----
// Bind with string name: call is rewritten to the string symbol.
module {
acc.routine @r_bind_str func(@wrapped) seq bind("actual_impl")
func.func @wrapped() attributes {acc.routine_info = #acc.routine_info<[@r_bind_str]>} {
return
}
func.func @actual_impl() {
return
}
func.func @entry() {
acc.serial {
func.call @wrapped() : () -> ()
acc.yield
}
return
}
}
// CHECK: func.call @actual_impl() : () -> ()
// -----
// Call outside offload region is unchanged.
module {
acc.routine @r_bind func(@foo) seq bind(@bar)
func.func @foo() attributes {acc.routine_info = #acc.routine_info<[@r_bind]>} {
return
}
func.func @bar() {
return
}
func.func @main() {
func.call @foo() : () -> ()
acc.serial {
func.call @foo() : () -> ()
acc.yield
}
return
}
}
// CHECK: call @foo() : () -> ()
// CHECK: func.call @bar() : () -> ()
// -----
// Indirect call (callee is value) is skipped; no crash.
module {
acc.routine @r_bind func(@target) seq bind(@bound)
func.func @target() attributes {acc.routine_info = #acc.routine_info<[@r_bind]>} {
return
}
func.func @bound() {
return
}
func.func @caller(%callee: () -> ()) {
acc.serial {
func.call_indirect %callee() : () -> ()
acc.yield
}
return
}
}
// CHECK: func.call_indirect %{{.*}}() : () -> ()
// -----
module {
acc.routine @acc_routine_0 func(@my_device_func) bind("__wrapper_my_device_func") seq
acc.routine @acc_routine_1 func(@my_device_sub) bind("__wrapper_my_device_sub") seq
func.func private @my_device_func(i32) -> i32 attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>}
func.func private @my_device_sub(i32, memref<i32>) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_1]>}
gpu.module @cuda_device_mod {
gpu.func @test(%arg0: i32, %arg1: memref<i32>) {
%0 = func.call @my_device_func(%arg0) : (i32) -> i32
func.call @my_device_sub(%arg0, %arg1) : (i32, memref<i32>) -> ()
gpu.return
}
func.func private @my_device_func(i32) -> i32 attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>}
func.func private @my_device_sub(i32, memref<i32>) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_1]>}
}
}
// CHECK-LABEL: gpu.func @test
// CHECK: func.call @__wrapper_my_device_func
// CHECK: func.call @__wrapper_my_device_sub
// CHECK: func.func private @__wrapper_my_device_func
// CHECK: func.func private @__wrapper_my_device_sub