[flang-commits] [flang] [flang][OpenACC] Don't hoist declare directive out of interface bodies (PR #202806)

via flang-commits flang-commits at lists.llvm.org
Thu Jun 11 02:54:09 PDT 2026


https://github.com/khaki3 updated https://github.com/llvm/llvm-project/pull/202806

>From 0b3361d38fbb7ffe2fa980426266a8a3439086a8 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Tue, 9 Jun 2026 16:38:15 -0700
Subject: [PATCH] [flang][OpenACC] Don't hoist declare from interface body into
 host

A declarative OpenACC construct written inside an interface body was
added to the enclosing program unit's evaluation list and lowered in
that scope. Its operands are the interface's dummy arguments, which have
no IR value there, so lowering aborted with "symbol is not mapped to any
IR value". Interface bodies are not lowered, so skip their declarative
constructs in the PFT builder; the procedure's actual definition still
lowers its own declare.
---
 flang/lib/Lower/PFTBuilder.cpp                | 15 +++++++
 .../OpenACC/acc-declare-interface-body.f90    | 43 +++++++++++++++++++
 2 files changed, 58 insertions(+)
 create mode 100644 flang/test/Lower/OpenACC/acc-declare-interface-body.f90

diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp
index a7cf64ccb583b..5003e625a2694 100644
--- a/flang/lib/Lower/PFTBuilder.cpp
+++ b/flang/lib/Lower/PFTBuilder.cpp
@@ -335,6 +335,20 @@ class PFTBuilder {
   }
   void Post(const parser::SpecificationPart &) { --specificationPartLevel; }
 
+  bool Pre(const parser::InterfaceBody &) {
+    ++interfaceBodyLevel;
+    return true;
+  }
+  void Post(const parser::InterfaceBody &) { --interfaceBodyLevel; }
+
+  // An acc declare in an interface body describes the interface's procedure,
+  // not the enclosing unit; skip it so it is not hoisted and lowered there.
+  bool Pre(const parser::OpenACCDeclarativeConstruct &accDecl) {
+    if (interfaceBodyLevel > 0)
+      return false;
+    return enterConstructOrDirective(accDecl);
+  }
+
   bool Pre(const parser::ContainsStmt &) {
     if (!specificationPartLevel) {
       assert(containsStmtStack.size() && "empty contains stack");
@@ -1261,6 +1275,7 @@ class PFTBuilder {
   lower::pft::SymbolLabelMap *assignSymbolLabelMap{};
   std::map<std::string, lower::pft::Evaluation *> constructNameMap{};
   int specificationPartLevel{};
+  int interfaceBodyLevel{};
   lower::pft::Evaluation *lastLexicalEvaluation{};
   /// Current function-like unit being processed (for USE statement tracking)
   lower::pft::FunctionLikeUnit *currentFunctionUnit{nullptr};
diff --git a/flang/test/Lower/OpenACC/acc-declare-interface-body.f90 b/flang/test/Lower/OpenACC/acc-declare-interface-body.f90
new file mode 100644
index 0000000000000..c119d527a0fb6
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-declare-interface-body.f90
@@ -0,0 +1,43 @@
+! Check that an acc declare in an interface body is not hoisted into the
+! enclosing program unit and lowered there (which crashed lowering), while the
+! actual procedure definition still lowers its own declare.
+
+! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s
+
+program test_acc_declare_interface
+  implicit none
+  integer, parameter :: n1 = 10, nlev = 60
+  real, dimension(n1, nlev) :: a
+
+  interface
+    subroutine compute(n1, nlev, a)
+      integer :: n1, nlev
+      real, dimension(n1, nlev) :: a
+!$acc declare present(a)
+    end subroutine compute
+  end interface
+
+  a = 0.1
+  call compute(n1, nlev, a)
+end program
+
+subroutine compute(n1, nlev, a)
+  integer :: n1, nlev
+  real, dimension(n1, nlev) :: a
+!$acc declare present(a)
+  a = a * a
+end subroutine compute
+
+! The interface-body declare is not hoisted into the host, so nothing is lowered.
+! CHECK-LABEL: func.func @_QQmain()
+! CHECK-NOT:     acc.declare_enter
+! CHECK-NOT:     acc.present
+! CHECK:         fir.call @_QPcompute
+! CHECK:         return
+
+! The actual definition lowers the present declare on its dummy argument.
+! CHECK-LABEL: func.func @_QPcompute(
+! CHECK:         %[[DECL:.*]]:2 = hlfir.declare %{{.*}} {acc.declare = #acc.declare<dataClause = acc_present>, uniq_name = "_QFcomputeEa"}
+! CHECK:         %[[PRES:.*]] = acc.present var(%[[DECL]]#0
+! CHECK:         acc.declare_enter dataOperands(%[[PRES]]
+! CHECK:         acc.declare_exit



More information about the flang-commits mailing list