[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