[flang-commits] [flang] [flang][openacc][cuda] Recover acc routine bind info in CUDA Fortran module reads (PR #223595)
Valentin Clement バレンタイン クレメン via flang-commits
flang-commits at lists.llvm.org
Tue Sep 15 10:55:02 PDT 2026
https://github.com/clementval updated https://github.com/llvm/llvm-project/pull/223595
>From d55d185dd0e50e8c3c330b7a01a447da8788494b Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Mon, 14 Sep 2026 20:43:57 -0700
Subject: [PATCH] [flang][acc] Recover acc routine bind info in CUDA Fortran
module reads
---
flang/lib/Semantics/mod-file.cpp | 7 ++-
flang/lib/Semantics/resolve-directives.cpp | 8 +++-
.../OpenACC/acc-routine-bind-cuda-modfile.cuf | 45 +++++++++++++++++++
3 files changed, 58 insertions(+), 2 deletions(-)
create mode 100644 flang/test/Lower/OpenACC/acc-routine-bind-cuda-modfile.cuf
diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp
index edbca4a9015aa..e17bfb2ee3f32 100644
--- a/flang/lib/Semantics/mod-file.cpp
+++ b/flang/lib/Semantics/mod-file.cpp
@@ -1754,7 +1754,12 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
parser::Options options;
options.isModuleFile = true;
options.features.Enable(common::LanguageFeature::BackslashEscapes);
- if (context_.languageFeatures().IsEnabled(common::LanguageFeature::OpenACC)) {
+ // CUDA Fortran device code can call procedures whose device-side call target
+ // is described by an `acc routine bind(...)` directive in the module that
+ // declares them, so the sentinel must be recognized here even when this
+ // compilation itself was not given an OpenACC target.
+ if (context_.languageFeatures().IsEnabled(common::LanguageFeature::OpenACC) ||
+ context_.languageFeatures().IsEnabled(common::LanguageFeature::CUDA)) {
options.features.Enable(common::LanguageFeature::OpenACC);
}
options.features.Enable(common::LanguageFeature::OpenMP);
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 143fe385768d7..f7a9e252d0d49 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1058,7 +1058,13 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
void ResolveAccParts(SemanticsContext &context, const parser::ProgramUnit &node,
Scope *topScope) {
- if (context.IsEnabled(common::LanguageFeature::OpenACC)) {
+ // A CUDA Fortran compilation that was not given an OpenACC target still has
+ // to resolve the directives recovered from module files, because they can
+ // describe the device-side call target of a procedure through
+ // `acc routine bind(...)`. The sentinel is not recognized in the main source
+ // in that case, so no user directive can reach this point.
+ if (context.IsEnabled(common::LanguageFeature::OpenACC) ||
+ context.IsEnabled(common::LanguageFeature::CUDA)) {
AccAttributeVisitor{context, topScope}.Walk(node);
}
}
diff --git a/flang/test/Lower/OpenACC/acc-routine-bind-cuda-modfile.cuf b/flang/test/Lower/OpenACC/acc-routine-bind-cuda-modfile.cuf
new file mode 100644
index 0000000000000..87adadcefcdf8
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-routine-bind-cuda-modfile.cuf
@@ -0,0 +1,45 @@
+! CUDA Fortran can consume `acc routine bind(...)` recovered from a module
+! file even when this translation unit is compiled without -fopenacc.
+
+! RUN: split-file %s %t
+! RUN: bbc -fopenacc -fcuda -emit-hlfir %t/mod.cuf -o %t/mod.mlir --module=%t
+! RUN: bbc -fcuda -emit-hlfir %t/use.cuf -o - -I %t | FileCheck %s
+
+//--- mod.cuf
+module m
+ interface
+ attributes(host,device) function my_device_func(x) bind(c) result(res)
+ integer(4), value :: x
+ integer(4) :: res
+ end function
+ end interface
+
+ interface
+ attributes(host,device) subroutine my_device_sub(x, res) bind(c)
+ integer(4), value :: x
+ integer(4) :: res
+ end subroutine
+ end interface
+
+ !$acc routine(my_device_func) seq bind('__wrapper_my_device_func')
+ !$acc routine(my_device_sub) seq bind('__wrapper_my_device_sub')
+end module
+
+//--- use.cuf
+attributes(device) subroutine test
+ use m
+ implicit none
+ integer(4) :: a, b
+
+ b = my_device_func(a)
+ call my_device_sub(a, b)
+end subroutine test
+
+! CHECK-DAG: acc.routine @[[ROUT_FUNC:.*]] func(@my_device_func) bind("__wrapper_my_device_func") seq
+! CHECK-DAG: acc.routine @[[ROUT_SUB:.*]] func(@my_device_sub) bind("__wrapper_my_device_sub") seq
+! CHECK-LABEL: func.func @_QPtest()
+! CHECK-SAME: attributes {cuf.proc_attr = #cuf.cuda_proc<device>}
+! CHECK: fir.call @my_device_func(
+! CHECK: fir.call @my_device_sub(
+! CHECK: func.func private @my_device_func{{.*}}acc.routine_info = #acc.routine_info<[@[[ROUT_FUNC]]]>
+! CHECK: func.func private @my_device_sub{{.*}}acc.routine_info = #acc.routine_info<[@[[ROUT_SUB]]]>
More information about the flang-commits
mailing list