[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 03:34:54 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: jeanPerier
<details>
<summary>Changes</summary>
Fix regression after https://github.com/llvm/llvm-project/pull/193689 when a use_device is referring to variables from a host module.
The original symbol needs to be visited in the PFT so that it will be instantiated, but it is not visible anymore from the parse tree, and not directly connected to the new symbol (this is because variables in use_device are treated in a special way in order to give them the DEVICE attribute, other data clause do not need such handling).
Look into the parent scope for a symbol with the same name and visit it.
---
Full diff: https://github.com/llvm/llvm-project/pull/194588.diff
5 Files Affected:
- (modified) flang/include/flang/Parser/tools.h (+1)
- (modified) flang/lib/Lower/OpenACC.cpp (+2-13)
- (modified) flang/lib/Lower/PFTBuilder.cpp (+19)
- (modified) flang/lib/Parser/tools.cpp (+5)
- (added) flang/test/Lower/host_module_variable_instantiation_use_device.f90 (+45)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/194588
More information about the flang-commits
mailing list