[flang-commits] [flang] [flang][openmp] Support importing module declare target globals (PR #213930)

via flang-commits flang-commits at lists.llvm.org
Tue Aug 4 06:10:27 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-openmp

Author: Ville-Markus Yli-Suutala (VeeEM)

<details>
<summary>Changes</summary>

Attach device type and capture clause attributes to declare target globals that have been imported from a module file.

Fixes https://github.com/llvm/llvm-project/issues/212333

---
Full diff: https://github.com/llvm/llvm-project/pull/213930.diff


4 Files Affected:

- (modified) flang/include/flang/Lower/OpenMP.h (+5) 
- (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+50-10) 
- (added) flang/test/Lower/OpenMP/declare_target_module.f90 (+37) 
- (added) flang/test/Lower/OpenMP/declare_target_module.mod (+11) 


``````````diff
diff --git a/flang/include/flang/Lower/OpenMP.h b/flang/include/flang/Lower/OpenMP.h
index a3f35498b9180..47f27ceece165 100644
--- a/flang/include/flang/Lower/OpenMP.h
+++ b/flang/include/flang/Lower/OpenMP.h
@@ -106,6 +106,11 @@ void materializeOpenMPDeclareMappers(
     Fortran::lower::AbstractConverter &, Fortran::semantics::SemanticsContext &,
     const Fortran::semantics::Scope *scope = nullptr);
 
+// Attach declare target attributes to declare target global variables
+// imported from a module file.
+void attachOpenMPDeclareTargetAttributes(lower::AbstractConverter &converter,
+                                         const lower::pft::Variable &var);
+
 namespace omp {
 /// If \p base carries OpenMP DECLARE VARIANT entries, return the variant symbol
 /// that best matches the enclosing OpenMP context, or nullptr if none matches.
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index ae1eb897c9348..9eab03e2a1884 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -6846,8 +6846,12 @@ void Fortran::lower::genOpenMPSymbolProperties(
   if (sym.test(semantics::Symbol::Flag::OmpThreadprivate))
     lower::genThreadprivateOp(converter, var);
 
-  if (sym.test(semantics::Symbol::Flag::OmpDeclareTarget))
-    lower::genDeclareTargetIntGlobal(converter, var);
+  if (sym.test(semantics::Symbol::Flag::OmpDeclareTarget)) {
+    if (var.isGlobal())
+      lower::attachOpenMPDeclareTargetAttributes(converter, var);
+    else
+      lower::genDeclareTargetIntGlobal(converter, var);
+  }
 }
 
 void Fortran::lower::genGroupprivateOp(lower::AbstractConverter &converter,
@@ -6947,14 +6951,12 @@ void Fortran::lower::genThreadprivateOp(lower::AbstractConverter &converter,
 // generation.
 void Fortran::lower::genDeclareTargetIntGlobal(
     lower::AbstractConverter &converter, const lower::pft::Variable &var) {
-  if (!var.isGlobal()) {
-    // A non-global variable which can be in a declare target directive must
-    // be a variable in the main program, and it has the implicit SAVE
-    // attribute. We create a GlobalOp for it to simplify the translation to
-    // LLVM IR.
-    globalInitialization(converter, converter.getFirOpBuilder(),
-                         var.getSymbol(), var, converter.getCurrentLocation());
-  }
+  // A non-global variable which can be in a declare target directive must
+  // be a variable in the main program, and it has the implicit SAVE
+  // attribute. We create a GlobalOp for it to simplify the translation to
+  // LLVM IR.
+  globalInitialization(converter, converter.getFirOpBuilder(), var.getSymbol(),
+                       var, converter.getCurrentLocation());
 }
 
 bool Fortran::lower::isOpenMPTargetConstruct(
@@ -7109,3 +7111,41 @@ void Fortran::lower::materializeOpenMPDeclareMappers(
 // Walk scopes and materialize omp.declare_reduction ops for user-defined
 // operator reductions imported from modules (deleted: replaced by lazy,
 // clause-driven materialization).
+
+void Fortran::lower::attachOpenMPDeclareTargetAttributes(
+    lower::AbstractConverter &converter, const lower::pft::Variable &var) {
+  auto module = converter.getModuleOp();
+
+  mlir::Operation *globalOp =
+      module.lookupSymbol(converter.mangleName(var.getSymbol()));
+
+  auto ultimateSymbol = var.getSymbol().GetUltimate();
+
+  if (globalOp && ultimateSymbol.IsFromModFile()) {
+    auto declareTargetOp =
+        llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(globalOp);
+    Fortran::common::visit(
+        [&](const auto &details) {
+          if constexpr (std::is_base_of_v<semantics::WithOmpDeclarative,
+                                          std::decay_t<decltype(details)>>) {
+            mlir::omp::DeclareTargetCaptureClause clause;
+            mlir::omp::DeclareTargetDeviceType deviceType =
+                toMLIRDeclareTargetDeviceType(
+                    details.ompDeclTargetDeviceType().value_or(
+                        Fortran::common::OmpDeviceType::Any));
+
+            const llvm::omp::ClauseSet clauses = details.ompDeclTarget();
+
+            if (clauses.test(llvm::omp::Clause::OMPC_link))
+              clause = mlir::omp::DeclareTargetCaptureClause::link;
+            else if (clauses.test(llvm::omp::Clause::OMPC_to))
+              clause = mlir::omp::DeclareTargetCaptureClause::to;
+            else
+              clause = mlir::omp::DeclareTargetCaptureClause::enter;
+
+            declareTargetOp.setDeclareTarget(deviceType, clause, false);
+          }
+        },
+        ultimateSymbol.details());
+  }
+}
diff --git a/flang/test/Lower/OpenMP/declare_target_module.f90 b/flang/test/Lower/OpenMP/declare_target_module.f90
new file mode 100644
index 0000000000000..07a0b2d921e60
--- /dev/null
+++ b/flang/test/Lower/OpenMP/declare_target_module.f90
@@ -0,0 +1,37 @@
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -I%S %s -o - | FileCheck %s
+!RUN: rm use_declare_target_module.mod
+
+! declare_target_module source
+#if 0
+module declare_target_module
+  implicit none
+  integer, dimension(10) :: global_arr
+  !$omp declare target (global_arr)
+  real :: global_real
+  !$omp declare target link(global_real)
+  integer :: global_integer
+  !$omp declare target to(global_integer)
+  integer :: global_device_integer
+  !$omp declare target enter(global_device_integer) device_type(nohost)
+end module
+#endif
+
+module use_declare_target_module
+use declare_target_module
+implicit none
+contains
+subroutine s()
+  !$omp declare target
+  global_arr(1) = 1
+  global_real = 1.0
+  global_integer = 1
+end subroutine
+!CHECK-DAG: fir.global @_QMdeclare_target_moduleEglobal_arr {alignment = 64 : i64, omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter), automap = false>} : !fir.array<10xi32>
+!CHECK-DAG: fir.global @_QMdeclare_target_moduleEglobal_real {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link), automap = false>} : f32
+!CHECK-DAG: fir.global @_QMdeclare_target_moduleEglobal_integer {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to), automap = false>} : i32
+subroutine device_s()
+  !$omp declare target enter(device_s) device_type(nohost)
+  global_device_integer = 1
+end subroutine
+!CHECK-DAG: fir.global @_QMdeclare_target_moduleEglobal_device_integer {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>} : i32
+end module
diff --git a/flang/test/Lower/OpenMP/declare_target_module.mod b/flang/test/Lower/OpenMP/declare_target_module.mod
new file mode 100644
index 0000000000000..eeb940ba425d0
--- /dev/null
+++ b/flang/test/Lower/OpenMP/declare_target_module.mod
@@ -0,0 +1,11 @@
+!mod$ v1 sum:24be1f891770838c
+module declare_target_module
+integer(4)::global_arr(1_8:10_8)
+real(4)::global_real
+integer(4)::global_integer
+integer(4)::global_device_integer
+!$omp declare target enter(global_arr)
+!$omp declare target link(global_real)
+!$omp declare target to(global_integer)
+!$omp declare target device_type(nohost) enter(global_device_integer)
+end

``````````

</details>


https://github.com/llvm/llvm-project/pull/213930


More information about the flang-commits mailing list