[flang-commits] [flang] 5b6ebc2 - [flang][cuda][openacc] Support CUDA calls to ACC routines (#210165)
via flang-commits
flang-commits at lists.llvm.org
Tue Jul 21 12:47:29 PDT 2026
Author: nvptm
Date: 2026-07-21T12:47:25-07:00
New Revision: 5b6ebc25e08c35d30edbe6aa7b64d06c46686b18
URL: https://github.com/llvm/llvm-project/commit/5b6ebc25e08c35d30edbe6aa7b64d06c46686b18
DIFF: https://github.com/llvm/llvm-project/commit/5b6ebc25e08c35d30edbe6aa7b64d06c46686b18.diff
LOG: [flang][cuda][openacc] Support CUDA calls to ACC routines (#210165)
Enable CUDA device procedures to call !$acc routine procedures.
- Treat ACC routines as device-callable during CUDA semantic checking.
- Apply implicit-device dummy argument handling to ACC routines called
from CUDA device code.
- Defer CUDA cloning of ACC routines until ACC lowering materializes and
moves the specialized routine into the GPU module.
- Add a CUF device-function transform regression test.
Added:
Modified:
flang/include/flang/Evaluate/characteristics.h
flang/lib/Evaluate/characteristics.cpp
flang/lib/Optimizer/Transforms/CUDA/CUFDeviceFuncTransform.cpp
flang/lib/Semantics/check-call.cpp
flang/lib/Semantics/check-cuda.cpp
flang/test/Fir/CUDA/cuda-device-func-transform.mlir
Removed:
################################################################################
diff --git a/flang/include/flang/Evaluate/characteristics.h b/flang/include/flang/Evaluate/characteristics.h
index af0d429b6aa3b..bc37f3d39c2ec 100644
--- a/flang/include/flang/Evaluate/characteristics.h
+++ b/flang/include/flang/Evaluate/characteristics.h
@@ -418,6 +418,8 @@ struct Procedure {
DummyArguments dummyArguments;
Attrs attrs;
std::optional<common::CUDASubprogramAttrs> cudaSubprogramAttrs;
+ // Used only by CUDA semantic checks; this is not a CUDA procedure attribute.
+ bool hasOpenACCRoutine{false};
};
} // namespace Fortran::evaluate::characteristics
diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp
index b679914f429c4..8750cd3c3ebb6 100644
--- a/flang/lib/Evaluate/characteristics.cpp
+++ b/flang/lib/Evaluate/characteristics.cpp
@@ -668,6 +668,7 @@ static std::optional<Procedure> CharacterizeProcedure(
}
}
result.cudaSubprogramAttrs = subp.cudaSubprogramAttrs();
+ result.hasOpenACCRoutine = !subp.openACCRoutineInfos().empty();
return std::move(result);
},
[&](const semantics::ProcEntityDetails &proc)
@@ -695,6 +696,9 @@ static std::optional<Procedure> CharacterizeProcedure(
// functions as their interfaces.
result->attrs.reset(Procedure::Attr::Elemental);
}
+ if (result && !proc.openACCRoutineInfos().empty()) {
+ result->hasOpenACCRoutine = true;
+ }
return result;
} else {
Procedure result;
@@ -716,6 +720,7 @@ static std::optional<Procedure> CharacterizeProcedure(
} else if (symbol.test(semantics::Symbol::Flag::Function)) {
return std::nullopt;
}
+ result.hasOpenACCRoutine = !proc.openACCRoutineInfos().empty();
// The PASS name, if any, is not a characteristic.
return std::move(result);
}
diff --git a/flang/lib/Optimizer/Transforms/CUDA/CUFDeviceFuncTransform.cpp b/flang/lib/Optimizer/Transforms/CUDA/CUFDeviceFuncTransform.cpp
index 2576dee47d079..307d41cb62a21 100644
--- a/flang/lib/Optimizer/Transforms/CUDA/CUFDeviceFuncTransform.cpp
+++ b/flang/lib/Optimizer/Transforms/CUDA/CUFDeviceFuncTransform.cpp
@@ -18,6 +18,7 @@
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/LLVMIR/NVVMDialect.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/IR/IRMapping.h"
#include "mlir/Pass/Pass.h"
#include "llvm/ADT/SetVector.h"
@@ -216,6 +217,10 @@ class CUFDeviceFuncTransform
if (op.getCallee()) {
auto func = symbolTable.lookup<mlir::func::FuncOp>(
op.getCallee()->getLeafReference());
+ // ACCRoutineToGPUFunc moves the materialized specialized routine into
+ // the GPU module later in the pipeline.
+ if (mlir::acc::isAccRoutine(func))
+ return;
if (deviceFuncs.count(func) == 0)
funcsToClone.insert(func);
}
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index b59053ec0481d..0680a48bac2be 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -1142,10 +1142,13 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
}
dummyDataAttr = dummy.cudaDataAttr;
// Treat MANAGED like DEVICE for nonallocatable nonpointer arguments to
- // device subprograms
- if (procedure.cudaSubprogramAttrs.value_or(
- common::CUDASubprogramAttrs::Host) !=
- common::CUDASubprogramAttrs::Host &&
+ // device subprograms. An OpenACC routine called from CUDA device code has
+ // the same implicit-device dummy-argument behavior.
+ bool isDeviceCallee{procedure.cudaSubprogramAttrs.value_or(
+ common::CUDASubprogramAttrs::Host) !=
+ common::CUDASubprogramAttrs::Host ||
+ (procedure.hasOpenACCRoutine && FindCUDADeviceContext(scope))};
+ if (isDeviceCallee &&
!dummy.attrs.test(
characteristics::DummyDataObject::Attr::Allocatable) &&
!dummy.attrs.test(characteristics::DummyDataObject::Attr::Pointer)) {
@@ -1162,8 +1165,9 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
if (!actualDataAttr &&
(!actualFirstSymbol || IsValue(*actualFirstSymbol) ||
IsFunctionResult(*actualFirstSymbol)) &&
- (*procedure.cudaSubprogramAttrs ==
- common::CUDASubprogramAttrs::Device)) {
+ (procedure.cudaSubprogramAttrs &&
+ *procedure.cudaSubprogramAttrs ==
+ common::CUDASubprogramAttrs::Device)) {
actualDataAttr = common::CUDADataAttr::Device;
}
}
diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp
index a257a47d92ca9..260e17262dcc0 100644
--- a/flang/lib/Semantics/check-cuda.cpp
+++ b/flang/lib/Semantics/check-cuda.cpp
@@ -98,6 +98,9 @@ struct DeviceExprChecker
"not yet implemented: CUDA dynamic parallelism"_err_en_US);
}
}
+ if (!subp->openACCRoutineInfos().empty()) {
+ return {};
+ }
}
const Symbol &ultimate{sym->GetUltimate()};
diff --git a/flang/test/Fir/CUDA/cuda-device-func-transform.mlir b/flang/test/Fir/CUDA/cuda-device-func-transform.mlir
index fae01500edd72..427381732630d 100644
--- a/flang/test/Fir/CUDA/cuda-device-func-transform.mlir
+++ b/flang/test/Fir/CUDA/cuda-device-func-transform.mlir
@@ -201,3 +201,23 @@ func.func @_QPsub_maxtnid_only() attributes {cuf.launch_bounds = #cuf.launch_bou
// CHECK: gpu.func @_QPsub_maxtnid_only() kernel attributes {nvvm.maxntid = array<i32: 256, 1, 1>}
// CHECK-NOT: nvvm.minctasm
+
+// -----
+
+// ACC routines are materialized and moved to the GPU module later by the
+// OpenACC pipeline. Do not clone them while collecting CUDA device callees.
+func.func @acc_routine() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_info]>} {
+ return
+}
+
+func.func @cuda_global() attributes {cuf.proc_attr = #cuf.cuda_proc<global>} {
+ fir.call @acc_routine() : () -> ()
+ return
+}
+
+// CHECK-LABEL: func.func @acc_routine()
+// CHECK-LABEL: gpu.module @cuda_device_mod
+// CHECK-NOT: func.func @acc_routine()
+// CHECK-NOT: gpu.func @acc_routine()
+// CHECK: gpu.func @cuda_global() kernel
+// CHECK: fir.call @acc_routine() : () -> ()
More information about the flang-commits
mailing list