[flang-commits] [flang] [flang][pft] visit original symbol in acc use_device (PR #194588)
via flang-commits
flang-commits at lists.llvm.org
Tue Apr 28 07:05:50 PDT 2026
https://github.com/jeanPerier updated https://github.com/llvm/llvm-project/pull/194588
>From a03e69105046a8f5796617b341c0f684e8bcf010 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Tue, 28 Apr 2026 03:26:57 -0700
Subject: [PATCH 1/3] [flang][pft] visit original use_device symbol
---
flang/include/flang/Parser/tools.h | 1 +
flang/lib/Lower/OpenACC.cpp | 15 +------
flang/lib/Lower/PFTBuilder.cpp | 19 ++++++++
flang/lib/Parser/tools.cpp | 5 +++
...dule_variable_instantiation_use_device.f90 | 45 +++++++++++++++++++
5 files changed, 72 insertions(+), 13 deletions(-)
create mode 100644 flang/test/Lower/host_module_variable_instantiation_use_device.f90
diff --git a/flang/include/flang/Parser/tools.h b/flang/include/flang/Parser/tools.h
index 04e6fa348f6ca..743446a189a60 100644
--- a/flang/include/flang/Parser/tools.h
+++ b/flang/include/flang/Parser/tools.h
@@ -41,6 +41,7 @@ const Name &GetFirstName(const Call &);
const Name &GetFirstName(const FunctionReference &);
const Name &GetFirstName(const Variable &);
const Name &GetFirstName(const EntityDecl &);
+const Name &GetFirstName(const AccObject &);
// When a parse tree node is an instance of a specific type wrapped in
// layers of packaging, return a pointer to that object.
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index bcb77fdfd52b1..161023aa51db8 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -2983,19 +2983,8 @@ genACCHostDataOp(Fortran::lower::AbstractConverter &converter,
std::get_if<Fortran::parser::AccClause::UseDevice>(&clause.u)) {
const Fortran::parser::AccObjectList &objectList{useDevice->v};
for (const auto &accObject : objectList.v) {
- const Fortran::semantics::Symbol *newSym = nullptr;
- if (const auto *designator =
- std::get_if<Fortran::parser::Designator>(&accObject.u)) {
- if (const auto *name =
- Fortran::parser::GetDesignatorNameIfDataRef(*designator)) {
- newSym = name->symbol;
- } else {
- newSym = Fortran::parser::GetFirstName(*designator).symbol;
- }
- } else if (const auto *name =
- std::get_if<Fortran::parser::Name>(&accObject.u)) {
- newSym = name->symbol;
- }
+ const Fortran::semantics::Symbol *newSym =
+ Fortran::parser::GetFirstName(accObject).symbol;
if (newSym) {
const Fortran::semantics::Symbol *origSym =
localSymbols.lookupSymbolByName(newSym->name().ToString());
diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp
index 3208b5ce921e8..afabb6b29f4f1 100644
--- a/flang/lib/Lower/PFTBuilder.cpp
+++ b/flang/lib/Lower/PFTBuilder.cpp
@@ -2221,6 +2221,25 @@ struct SymbolVisitor {
return false;
}
+ bool Pre(const Fortran::parser::AccClause::UseDevice &useDevice) {
+ // For use_device, each symbol's parser Name has been given a local copy
+ // of the symbol with the DEVICE attribute. The original symbol will be
+ // needed in lowering and may not appear in the parse tree of the function
+ // anymore. Visit it now: it is not directly accessible from the construct
+ // symbol, so the parent scope must be searched to find it.
+ for (const auto &accObject : useDevice.v.v) {
+ if (const semantics::Symbol *deviceSym =
+ Fortran::parser::GetFirstName(accObject).symbol) {
+ if (const semantics::Symbol *hostSym =
+ deviceSym->owner().parent().FindSymbol(deviceSym->name()))
+ visitSymbol(*hostSym);
+ }
+ }
+ // Continue visiting the ACC construct symbol and any symbols used in
+ // designator index expressions.
+ return true;
+ }
+
template <typename T>
void visitExpr(const Fortran::evaluate::Expr<T> &expr) {
for (const semantics::Symbol &symbol :
diff --git a/flang/lib/Parser/tools.cpp b/flang/lib/Parser/tools.cpp
index 9e166c9185096..0e7ae5509f0c2 100644
--- a/flang/lib/Parser/tools.cpp
+++ b/flang/lib/Parser/tools.cpp
@@ -131,6 +131,11 @@ const Name &GetFirstName(const EntityDecl &x) {
return std::get<ObjectName>(x.t);
}
+const Name &GetFirstName(const AccObject &x) {
+ return common::visit(
+ [](const auto &y) -> const Name & { return GetFirstName(y); }, x.u);
+}
+
const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &base) {
return common::visit(
common::visitors{
diff --git a/flang/test/Lower/host_module_variable_instantiation_use_device.f90 b/flang/test/Lower/host_module_variable_instantiation_use_device.f90
new file mode 100644
index 0000000000000..80aaf8a517e8b
--- /dev/null
+++ b/flang/test/Lower/host_module_variable_instantiation_use_device.f90
@@ -0,0 +1,45 @@
+! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
+
+! Test that module symbols used inside the use_device clause
+! in procedures from that same module are correctly instantiated.
+
+module test_use_device
+ real(4) :: a(100)
+ integer :: i, j
+ interface
+ subroutine something(a)
+ real(4) :: a(*)
+ end subroutine
+ end interface
+contains
+ subroutine test_simple
+ !$acc host_data use_device(a)
+ call something(a)
+ !$acc end host_data
+ end subroutine
+ subroutine test_designator
+ !$acc host_data use_device(a(i:j))
+ !$acc end host_data
+ end subroutine
+end module
+
+! CHECK-LABEL: func.func @_QMtest_use_devicePtest_simple() {
+! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK: %[[ADDRESS_OF_0:.*]] = fir.address_of(@_QMtest_use_deviceEa) : !fir.ref<!fir.array<100xf32>>
+! CHECK: %[[CONSTANT_0:.*]] = arith.constant 100 : index
+! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_0]] : (index) -> !fir.shape<1>
+! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ADDRESS_OF_0]](%[[SHAPE_0]]) {uniq_name = "_QMtest_use_deviceEa"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+! CHECK: %[[USE_DEVICE_0:.*]] = acc.use_device varPtr(%[[DECLARE_0]]#0 : !fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<100xf32>> {name = "a"}
+! CHECK: acc.host_data dataOperands(%[[USE_DEVICE_0]] : !fir.ref<!fir.array<100xf32>>) {
+! CHECK: %[[DECLARE_1:.*]]:2 = hlfir.declare %[[USE_DEVICE_0]](%[[SHAPE_0]]) {uniq_name = "_QMtest_use_deviceEa"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+! CHECK: fir.call @_QPsomething(%[[DECLARE_1]]#0) fastmath<contract> : (!fir.ref<!fir.array<100xf32>>) -> ()
+! CHECK: acc.terminator
+! CHECK: }
+! CHECK: return
+! CHECK: }
+
+! CHECK-LABEL: func.func @_QMtest_use_devicePtest_designator() {
+! CHECK: %[[ADDRESS_OF_0:.*]] = fir.address_of(@_QMtest_use_deviceEa) : !fir.ref<!fir.array<100xf32>>
+! CHECK: %[[ADDRESS_OF_1:.*]] = fir.address_of(@_QMtest_use_deviceEi) : !fir.ref<i32>
+! CHECK: %[[ADDRESS_OF_2:.*]] = fir.address_of(@_QMtest_use_deviceEj) : !fir.ref<i32>
+! CHECK: acc.use_device
>From b215491dad52ecfc5b0dfb6b787ee2f8c19b1fa8 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Tue, 28 Apr 2026 06:06:33 -0700
Subject: [PATCH 2/3] fix test
---
.../Lower/host_module_variable_instantiation_use_device.f90 | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/flang/test/Lower/host_module_variable_instantiation_use_device.f90 b/flang/test/Lower/host_module_variable_instantiation_use_device.f90
index 80aaf8a517e8b..e24da6ae4f3cb 100644
--- a/flang/test/Lower/host_module_variable_instantiation_use_device.f90
+++ b/flang/test/Lower/host_module_variable_instantiation_use_device.f90
@@ -1,4 +1,4 @@
-! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir -fopenacc %s -o - | FileCheck %s
! Test that module symbols used inside the use_device clause
! in procedures from that same module are correctly instantiated.
@@ -8,7 +8,7 @@ module test_use_device
integer :: i, j
interface
subroutine something(a)
- real(4) :: a(*)
+ real(4) :: a(100)
end subroutine
end interface
contains
@@ -32,7 +32,7 @@ subroutine test_designator
! CHECK: %[[USE_DEVICE_0:.*]] = acc.use_device varPtr(%[[DECLARE_0]]#0 : !fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<100xf32>> {name = "a"}
! CHECK: acc.host_data dataOperands(%[[USE_DEVICE_0]] : !fir.ref<!fir.array<100xf32>>) {
! CHECK: %[[DECLARE_1:.*]]:2 = hlfir.declare %[[USE_DEVICE_0]](%[[SHAPE_0]]) {uniq_name = "_QMtest_use_deviceEa"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
-! CHECK: fir.call @_QPsomething(%[[DECLARE_1]]#0) fastmath<contract> : (!fir.ref<!fir.array<100xf32>>) -> ()
+! CHECK: fir.call @_QPsomething(%[[DECLARE_1]]#0)
! CHECK: acc.terminator
! CHECK: }
! CHECK: return
>From 98551ae92a09998538412778add7446f6f050f5a Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Tue, 28 Apr 2026 07:05:35 -0700
Subject: [PATCH 3/3] add more tests
---
...dule_variable_instantiation_use_device.f90 | 30 +++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/flang/test/Lower/host_module_variable_instantiation_use_device.f90 b/flang/test/Lower/host_module_variable_instantiation_use_device.f90
index e24da6ae4f3cb..e689fb86b2303 100644
--- a/flang/test/Lower/host_module_variable_instantiation_use_device.f90
+++ b/flang/test/Lower/host_module_variable_instantiation_use_device.f90
@@ -10,6 +10,8 @@ module test_use_device
subroutine something(a)
real(4) :: a(100)
end subroutine
+ module subroutine test_submodule()
+ end subroutine
end interface
contains
subroutine test_simple
@@ -21,6 +23,13 @@ subroutine test_designator
!$acc host_data use_device(a(i:j))
!$acc end host_data
end subroutine
+ subroutine test_shadowed
+ real :: a(100)
+ !$acc declare copy(a)
+ !$acc host_data use_device(a)
+ call something(a)
+ !$acc end host_data
+ end subroutine
end module
! CHECK-LABEL: func.func @_QMtest_use_devicePtest_simple() {
@@ -43,3 +52,24 @@ subroutine test_designator
! CHECK: %[[ADDRESS_OF_1:.*]] = fir.address_of(@_QMtest_use_deviceEi) : !fir.ref<i32>
! CHECK: %[[ADDRESS_OF_2:.*]] = fir.address_of(@_QMtest_use_deviceEj) : !fir.ref<i32>
! CHECK: acc.use_device
+
+! CHECK-LABEL: func.func @_QMtest_use_devicePtest_shadowed() {
+! CHECK-NOT: fir.address_of(@_QMtest_use_deviceEa)
+! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<100xf32> {bindc_name = "a", uniq_name = "_QMtest_use_deviceFtest_shadowedEa"}
+! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](
+! CHECK-NOT: fir.address_of(@_QMtest_use_deviceEa)
+! CHECK: %[[USE_DEVICE_0:.*]] = acc.use_device varPtr(%[[DECLARE_0]]#0
+
+submodule (test_use_device) some_submodule
+contains
+ module subroutine test_submodule
+ !$acc host_data use_device(a)
+ call something(a)
+ !$acc end host_data
+ end subroutine
+end submodule
+
+! CHECK-LABEL: func.func @_QMtest_use_devicePtest_submodule() {
+! CHECK: %[[ADDRESS_OF_0:.*]] = fir.address_of(@_QMtest_use_deviceEa) : !fir.ref<!fir.array<100xf32>>
+! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ADDRESS_OF_0]]
+! CHECK: acc.use_device varPtr(%[[DECLARE_0]]#0
More information about the flang-commits
mailing list