[flang-commits] [flang] [flang][OpenMP] Fix declare target attribute for USE-associated module globals (PR #218339)
via flang-commits
flang-commits at lists.llvm.org
Mon Aug 24 00:50:20 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
@llvm/pr-subscribers-flang-openmp
Author: Urvi Rav (ravurvi20)
<details>
<summary>Changes</summary>
Fixes #<!-- -->218327
#### Summary
When a module variable is marked `!$omp declare target` and used in a separately compiled file, Flang was dropping the `declare target` attribute.
Because of this, the device global was treated as a normal global and got internalized. This broke the device-to-host data copy, so `target update from(...)` returned the stale host value instead of the value computed on the device.
#### Fix
When lowering a USE-associated module variable, preserve the `omp.declare_target` attribute from the original symbol.
The `declare target` information is preserved in the `.mod` file, so it can be restored when the variable is lowered in the USE-ing file.
Before -
```
fir.global @<!-- -->_QMdt_modEarr {alignment = 64 : i64} : !fir.array<100xi32>
```
After -
```
fir.global @<!-- -->_QMdt_modEarr {alignment = 64 : i64, omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to), automap = false>} : !fir.array<100xi32>
```
#### Testing
* Added `declare-target-use-associated-global.f90` to verify that the external `fir.global` keeps the `omp.declare_target` attribute.
---
Full diff: https://github.com/llvm/llvm-project/pull/218339.diff
2 Files Affected:
- (modified) flang/lib/Lower/ConvertVariable.cpp (+45)
- (added) flang/test/Lower/OpenMP/declare-target-use-associated-global.f90 (+28)
``````````diff
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index a808905850922..f48968083dc5a 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -46,6 +46,7 @@
#include "flang/Semantics/tools.h"
#include "flang/Semantics/type.h"
#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -194,6 +195,49 @@ static void attachAccDeclareAttribute(fir::FirOpBuilder &builder,
builder.getContext(), clause)));
}
+/// Copy the `omp.declare_target` attribute onto an external global declaration
+/// created for a USE-associated module variable. The directive lives in the
+/// defining module, so the USE-ing unit must re-attach it here; otherwise the
+/// global is internalized on the device and loses its device-resident copy.
+static void
+attachDeclareTargetAttribute(fir::FirOpBuilder &builder, fir::GlobalOp global,
+ const Fortran::semantics::Symbol &sym) {
+ using Flag = Fortran::semantics::Symbol::Flag;
+ const Fortran::semantics::Symbol &ultimate = sym.GetUltimate();
+ if (!ultimate.test(Flag::OmpDeclareTarget))
+ return;
+ auto declareTargetOp =
+ llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(global.getOperation());
+ if (!declareTargetOp || declareTargetOp.isDeclareTarget())
+ return;
+
+ mlir::omp::DeclareTargetDeviceType deviceType =
+ mlir::omp::DeclareTargetDeviceType::any;
+ mlir::omp::DeclareTargetCaptureClause captureClause =
+ mlir::omp::DeclareTargetCaptureClause::to;
+ if (const auto *details =
+ ultimate.detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
+ if (const std::optional<Fortran::common::OmpDeviceType> &dt =
+ details->ompDeclTargetDeviceType()) {
+ switch (*dt) {
+ case Fortran::common::OmpDeviceType::Host:
+ deviceType = mlir::omp::DeclareTargetDeviceType::host;
+ break;
+ case Fortran::common::OmpDeviceType::Nohost:
+ deviceType = mlir::omp::DeclareTargetDeviceType::nohost;
+ break;
+ case Fortran::common::OmpDeviceType::Any:
+ deviceType = mlir::omp::DeclareTargetDeviceType::any;
+ break;
+ }
+ }
+ if (details->ompDeclTarget().test(llvm::omp::Clause::OMPC_link))
+ captureClause = mlir::omp::DeclareTargetCaptureClause::link;
+ }
+ declareTargetOp.setDeclareTarget(deviceType, captureClause,
+ /*automap=*/false);
+}
+
/// Create the global op declaration without any initializer
static fir::GlobalOp declareGlobal(Fortran::lower::AbstractConverter &converter,
const Fortran::lower::pft::Variable &var,
@@ -225,6 +269,7 @@ static fir::GlobalOp declareGlobal(Fortran::lower::AbstractConverter &converter,
isConstant(ultimate), var.isTarget(), dataAttr,
/*setDefaultAlignment=*/!isBindC);
attachAccDeclareAttribute(builder, global, sym);
+ attachDeclareTargetAttribute(builder, global, sym);
Fortran::lower::declareExternalAccModuleDeclareActionRecipes(converter,
builder, sym);
return global;
diff --git a/flang/test/Lower/OpenMP/declare-target-use-associated-global.f90 b/flang/test/Lower/OpenMP/declare-target-use-associated-global.f90
new file mode 100644
index 0000000000000..4da592366aab4
--- /dev/null
+++ b/flang/test/Lower/OpenMP/declare-target-use-associated-global.f90
@@ -0,0 +1,28 @@
+! A module variable marked `declare target` must keep that attribute when it is
+! USE-associated in a separately compiled file. The directive lives in the
+! module, so the USE-ing file must copy the attribute onto the external global
+! it declares. Without it the device pass internalizes the global and
+! `target update` reads stale data.
+
+! RUN: split-file %s %t
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -module-dir %t %t/mod.f90 -o /dev/null
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-target-device -module-dir %t %t/use.f90 -o - | FileCheck %s
+
+!--- mod.f90
+module dt_mod
+ implicit none
+ integer :: arr(100)
+ !$omp declare target enter(arr)
+end module
+
+!--- use.f90
+! Here the global is only an external declaration, but it still must carry the
+! declare target attribute.
+! CHECK: fir.global @_QMdt_modEarr {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to), automap = false>{{.*}}} : !fir.array<100xi32>
+subroutine sub(i)
+ use dt_mod
+ implicit none
+ !$omp declare target
+ integer :: i
+ arr(i) = i
+end subroutine
``````````
</details>
https://github.com/llvm/llvm-project/pull/218339
More information about the flang-commits
mailing list