blob: 44ba96e3d6b04ba867c655e8db7c99adef2f0ad8 [file] [edit]
// RUN: fir-opt %s --pass-pipeline="builtin.module(acc-initialize-fir-analyses,acc-implicit-routine)" -split-input-file -verify-diagnostics | FileCheck %s
// -----
// Defined procedure called from a compute region gets an implicit acc routine.
module {
func.func @_QPcallee() {
return
}
func.func @_QPtest_defined_call() {
acc.serial {
fir.call @_QPcallee() : () -> ()
acc.yield
}
return
}
}
// CHECK: acc.routine @acc_routine_0 func(@_QPcallee) implicit
// CHECK: func.func @_QPcallee() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>}
// CHECK: func.func @_QPtest_defined_call
// -----
// Nested fir.call from a compute region: both callees get implicit routines.
module {
func.func @_QPleaf() {
return
}
func.func @_QPmiddle() {
fir.call @_QPleaf() : () -> ()
return
}
func.func @_QPtest_nested_calls() {
acc.serial {
fir.call @_QPmiddle() : () -> ()
acc.yield
}
return
}
}
// CHECK: acc.routine @acc_routine_1 func(@_QPleaf) implicit
// CHECK: func.func @_QPleaf() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_1]>}
// CHECK: acc.routine @acc_routine_0 func(@_QPmiddle) implicit
// CHECK: func.func @_QPmiddle() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>}
// CHECK: func.func @_QPtest_nested_calls
// -----
// Fortran intrinsic procedure declarations do not need an implicit routine.
module {
func.func private @_QPsin(!fir.ref<f32>) -> f32 attributes {fir.proc_attrs = #fir.proc_attrs<intrinsic>}
func.func @_QPtest_intrinsic(%arg0: !fir.ref<f32>) {
acc.serial {
%0 = fir.call @_QPsin(%arg0) : (!fir.ref<f32>) -> f32
acc.yield
}
return
}
}
// CHECK: func.func private @_QPsin
// CHECK: fir.call @_QPsin
// CHECK-NOT: acc.routine @{{.*}} func(@_QPsin)
// -----
// BIND(C) procedure declarations do not need an implicit routine.
module {
func.func private @c_func() attributes {fir.bindc_name = "c_func", fir.proc_attrs = #fir.proc_attrs<bind_c>}
func.func @_QPtest_bindc() {
acc.serial {
fir.call @c_func() : () -> ()
acc.yield
}
return
}
}
// CHECK: func.func private @c_func
// CHECK: fir.call @c_func
// CHECK-NOT: acc.routine @{{.*}} func(@c_func)
// -----
// Fortran runtime helpers are already valid device symbols.
module {
func.func private @_FortranASumInteger4(!fir.box<none>) -> i32 attributes {fir.runtime}
func.func @_QPtest_runtime(%arg0: !fir.box<none>) {
acc.serial {
%0 = fir.call @_FortranASumInteger4(%arg0) : (!fir.box<none>) -> i32
acc.yield
}
return
}
}
// CHECK: func.func private @_FortranASumInteger4
// CHECK: fir.call @_FortranASumInteger4
// CHECK-NOT: acc.routine @{{.*}} func(@_FortranASumInteger4)
// -----
// An external procedure that already has an explicit acc routine is valid.
module {
acc.routine @r_ext func(@_QPext_with_routine) seq
func.func private @_QPext_with_routine() attributes {acc.routine_info = #acc.routine_info<[@r_ext]>}
func.func @_QPtest_external_with_explicit_routine() {
acc.serial {
fir.call @_QPext_with_routine() : () -> ()
acc.yield
}
return
}
}
// CHECK: acc.routine @r_ext func(@_QPext_with_routine) seq
// CHECK: func.func private @_QPext_with_routine
// CHECK-NOT: acc.routine @{{.*}} func(@_QPext_with_routine) implicit
// -----
// An external Fortran procedure called from a compute region cannot receive an
// implicit routine; it must already have acc routine information.
module {
func.func private @_QPext_callee()
func.func @_QPtest_external_in_serial() {
acc.serial {
// expected-error @below {{Calls in an acc compute region must be marked with acc routine: "_QPext_callee"}}
fir.call @_QPext_callee() : () -> ()
acc.yield
}
return
}
}
// -----
// Same requirement for an external procedure called from an existing routine.
module {
acc.routine @r_caller func(@_QProutine_caller) seq
func.func private @_QPext_from_routine()
func.func @_QProutine_caller() attributes {acc.routine_info = #acc.routine_info<[@r_caller]>} {
// expected-error @below {{Calls in acc routine must also be marked with acc routine: "_QPext_from_routine"}}
fir.call @_QPext_from_routine() : () -> ()
return
}
}