[flang-commits] [flang] 9673aae - [flang][OpenACC] Don't hoist declare directive out of interface bodies (#202806)
via flang-commits
flang-commits at lists.llvm.org
Thu Jun 11 03:05:20 PDT 2026
Author: khaki3
Date: 2026-06-11T10:05:16Z
New Revision: 9673aae1fc67abcab756ed3f6e36dff846e8228c
URL: https://github.com/llvm/llvm-project/commit/9673aae1fc67abcab756ed3f6e36dff846e8228c
DIFF: https://github.com/llvm/llvm-project/commit/9673aae1fc67abcab756ed3f6e36dff846e8228c.diff
LOG: [flang][OpenACC] Don't hoist declare directive out of interface bodies (#202806)
Example:
```fortran
program main
real :: a(10, 60)
interface
subroutine compute(a)
real :: a(10, 60)
!$acc declare present(a)
end subroutine
end interface
call compute(a)
end program
```
In this code, the `!$acc declare` inside the interface body is hoisted
into the
host program unit and lowered there, where its operand (the interface
dummy)
has no IR value, so lowering aborts with "symbol is not mapped to any IR
value".
This happens because interface-body procedures are not function-like
units, so
the directive is appended to the enclosing unit's evaluation list.
Fix: track interface-body nesting in the PFT builder and do not add an
`OpenACCDeclarativeConstruct` to the enclosing unit's evaluation list
while
inside one. The directive is no longer hoisted out and is generated only
in its
proper scope (the procedure definition or a module-level declare).
Added:
flang/test/Lower/OpenACC/acc-declare-interface-body.f90
Modified:
flang/lib/Lower/PFTBuilder.cpp
Removed:
################################################################################
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