[flang-commits] [flang] [flang][acc] Fix separate compilation for module !$acc declare create on allocatables. (PR #202409)
via flang-commits
flang-commits at lists.llvm.org
Mon Jun 8 11:48:44 PDT 2026
https://github.com/nvptm updated https://github.com/llvm/llvm-project/pull/202409
>From 7f5b1aab32fa092e90cfaa8ef7d969fe9db9c41e Mon Sep 17 00:00:00 2001
From: nvpm <pmathew at nvidia.com>
Date: Wed, 3 Jun 2026 22:51:28 -0700
Subject: [PATCH 1/2] Fix declare create on module allocatable separate file
---
flang/include/flang/Lower/OpenACC.h | 3 ++
flang/include/flang/Semantics/symbol.h | 2 +
flang/lib/Lower/ConvertVariable.cpp | 3 ++
flang/lib/Lower/OpenACC.cpp | 50 ++++++++++++++++---
flang/lib/Semantics/resolve-directives.cpp | 2 +
...acc-declare-use-associated-allocatable.f90 | 37 ++++++++++++++
flang/test/Lower/OpenACC/acc-declare.f90 | 4 +-
7 files changed, 93 insertions(+), 8 deletions(-)
create mode 100644 flang/test/Lower/OpenACC/acc-declare-use-associated-allocatable.f90
diff --git a/flang/include/flang/Lower/OpenACC.h b/flang/include/flang/Lower/OpenACC.h
index 473cf3013ce8d..c76390a3bb85e 100644
--- a/flang/include/flang/Lower/OpenACC.h
+++ b/flang/include/flang/Lower/OpenACC.h
@@ -86,6 +86,9 @@ void genOpenACCRoutineConstruct(
AbstractConverter &, mlir::ModuleOp, mlir::func::FuncOp,
const std::vector<Fortran::semantics::OpenACCRoutineInfo> &);
+void declareExternalAccModuleDeclareActionRecipes(AbstractConverter &,
+ fir::FirOpBuilder &,
+ const Fortran::semantics::Symbol &);
void attachDeclarePostAllocAction(AbstractConverter &, fir::FirOpBuilder &,
const Fortran::semantics::Symbol &);
void attachDeclarePreDeallocAction(AbstractConverter &, fir::FirOpBuilder &,
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index c794c20abcec5..84b5cd0ddd280 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -881,6 +881,8 @@ class Symbol {
AccPresent, AccLink, AccDeviceResident, AccDevicePtr, AccUseDevice,
// OpenACC declare
AccDeclare,
+ // OpenACC declare on allocatable/pointer needs cross-TU action recipes
+ AccDeclareAction,
// OpenACC data-movement attribute
AccDevice, AccHost, AccSelf,
// OpenACC miscellaneous flags
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 0cbc80cc94285..3527b50e74d1c 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -21,6 +21,7 @@
#include "flang/Lower/ConvertExprToHLFIR.h"
#include "flang/Lower/ConvertProcedureDesignator.h"
#include "flang/Lower/Mangler.h"
+#include "flang/Lower/OpenACC.h"
#include "flang/Lower/MultiImageFortran.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/StatementContext.h"
@@ -224,6 +225,8 @@ static fir::GlobalOp declareGlobal(Fortran::lower::AbstractConverter &converter,
isConstant(ultimate), var.isTarget(), dataAttr,
/*setDefaultAlignment=*/!isBindC);
attachAccDeclareAttribute(builder, global, sym);
+ Fortran::lower::declareExternalAccModuleDeclareActionRecipes(converter,
+ builder, sym);
return global;
}
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 7ee32b31b5e17..a7ef4dd6b0284 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -182,15 +182,20 @@ static mlir::func::FuncOp
createDeclareFunc(mlir::OpBuilder &modBuilder, fir::FirOpBuilder &builder,
mlir::Location loc, llvm::StringRef funcName,
llvm::SmallVector<mlir::Type> argsTy = {},
- llvm::SmallVector<mlir::Location> locs = {}) {
+ llvm::SmallVector<mlir::Location> locs = {},
+ bool linkable = false) {
auto funcTy = mlir::FunctionType::get(modBuilder.getContext(), argsTy, {});
auto funcOp = mlir::func::FuncOp::create(modBuilder, loc, funcName, funcTy);
- funcOp.setVisibility(mlir::SymbolTable::Visibility::Private);
+ funcOp.setVisibility(linkable ? mlir::SymbolTable::Visibility::Public
+ : mlir::SymbolTable::Visibility::Private);
builder.createBlock(&funcOp.getRegion(), funcOp.getRegion().end(), argsTy,
locs);
builder.setInsertionPointToEnd(&funcOp.getRegion().back());
mlir::func::ReturnOp::create(builder, loc);
builder.setInsertionPointToStart(&funcOp.getRegion().back());
+ if (linkable)
+ funcOp->setAttr(mlir::acc::getDeclareActionAttrName(),
+ mlir::UnitAttr::get(modBuilder.getContext()));
return funcOp;
}
@@ -3717,8 +3722,9 @@ static void createDeclareAllocFunc(mlir::OpBuilder &modBuilder,
std::stringstream registerFuncName;
registerFuncName << globalOp.getSymName().str()
<< Fortran::lower::declarePostAllocSuffix.str();
- auto registerFuncOp =
- createDeclareFunc(modBuilder, builder, loc, registerFuncName.str());
+ auto registerFuncOp = createDeclareFunc(
+ modBuilder, builder, loc, registerFuncName.str(),
+ /*argsTy=*/{}, /*locs=*/{}, /*linkable=*/true);
fir::AddrOfOp addrOp = fir::AddrOfOp::create(
builder, loc, fir::ReferenceType::get(globalOp.getType()),
@@ -3757,8 +3763,9 @@ static void createDeclareDeallocFunc(mlir::OpBuilder &modBuilder,
std::stringstream postDeallocFuncName;
postDeallocFuncName << globalOp.getSymName().str()
<< Fortran::lower::declarePostDeallocSuffix.str();
- auto postDeallocOp =
- createDeclareFunc(modBuilder, builder, loc, postDeallocFuncName.str());
+ auto postDeallocOp = createDeclareFunc(
+ modBuilder, builder, loc, postDeallocFuncName.str(),
+ /*argsTy=*/{}, /*locs=*/{}, /*linkable=*/true);
fir::AddrOfOp addrOp = fir::AddrOfOp::create(
builder, loc, fir::ReferenceType::get(globalOp.getType()),
@@ -4715,6 +4722,37 @@ void Fortran::lower::genOpenACCDeclarativeConstruct(
accDeclConstruct.u);
}
+void Fortran::lower::declareExternalAccModuleDeclareActionRecipes(
+ AbstractConverter &converter, fir::FirOpBuilder &builder,
+ const Fortran::semantics::Symbol &sym) {
+ using Flag = Fortran::semantics::Symbol::Flag;
+ const Fortran::semantics::Symbol &ultimate = sym.GetUltimate();
+ if (!ultimate.test(Flag::AccDeclareAction))
+ return;
+
+ mlir::ModuleOp module = builder.getModule();
+ mlir::Location loc = converter.genLocation(sym.name());
+ std::string prefix = converter.mangleName(ultimate);
+
+ auto declareExternalRecipe = [&](llvm::StringRef suffix) {
+ std::string name = prefix + suffix.str();
+ if (module.lookupSymbol<mlir::func::FuncOp>(name))
+ return;
+ auto funcTy = mlir::FunctionType::get(builder.getContext(), {}, {});
+ mlir::OpBuilder modBuilder(module.getBodyRegion());
+ modBuilder.setInsertionPointToEnd(module.getBody());
+ auto funcOp = mlir::func::FuncOp::create(modBuilder, loc, name, funcTy);
+ funcOp.setVisibility(mlir::SymbolTable::Visibility::Private);
+ };
+
+ declareExternalRecipe(declarePostAllocSuffix);
+ if (ultimate.test(Flag::AccCreate) || ultimate.test(Flag::AccCopyIn) ||
+ ultimate.test(Flag::AccCopyInReadOnly) || ultimate.test(Flag::AccCopy) ||
+ ultimate.test(Flag::AccCopyOut) ||
+ ultimate.test(Flag::AccDeviceResident))
+ declareExternalRecipe(declarePostDeallocSuffix);
+}
+
void Fortran::lower::attachDeclarePostAllocAction(
AbstractConverter &converter, fir::FirOpBuilder &builder,
const Fortran::semantics::Symbol &sym) {
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 821724fedc7d4..be5a95025c31e 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1955,6 +1955,8 @@ Symbol *AccAttributeVisitor::DeclareOrMarkOtherAccessEntity(
if (GetContext().directive == llvm::acc::ACCD_declare) {
object.set(Symbol::Flag::AccDeclare);
object.set(accFlag);
+ if (IsAllocatableOrObjectPointer(&object))
+ object.set(Symbol::Flag::AccDeclareAction);
}
}
return &object;
diff --git a/flang/test/Lower/OpenACC/acc-declare-use-associated-allocatable.f90 b/flang/test/Lower/OpenACC/acc-declare-use-associated-allocatable.f90
new file mode 100644
index 0000000000000..67171f732be3b
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-declare-use-associated-allocatable.f90
@@ -0,0 +1,37 @@
+! Test separate compilation of !$acc declare create on a module allocatable:
+! - the defining unit exports linkable declare-action recipe definitions
+! - the using unit declares the module global and external recipe symbols so
+! acc-declare-action-conversion can insert fir.call to the recipes.
+
+! RUN: split-file %s %t
+! RUN: bbc -fopenacc -emit-hlfir %t/mod.f90 -o %t/mod.mlir --module=%t
+! RUN: bbc -fopenacc -emit-hlfir %t/use.f90 -o %t/use.mlir -I %t
+! RUN: FileCheck %s --check-prefix=MOD < %t/mod.mlir
+! RUN: FileCheck %s --check-prefix=USE < %t/use.mlir
+! RUN: fir-opt %t/use.mlir --acc-declare-action-conversion -o - | FileCheck %s --check-prefix=CONV
+
+//--- mod.f90
+module acc_declare_alloc_mod
+ integer, allocatable :: data(:)
+ !$acc declare create(data)
+end module
+
+//--- use.f90
+subroutine use_mod()
+ use acc_declare_alloc_mod
+ implicit none
+ allocate(data(100))
+end subroutine
+
+! MOD: func.func @_QMacc_declare_alloc_modEdata_acc_declare_post_alloc() attributes {acc.declare_action} {
+! MOD: acc.declare_enter
+! MOD: func.func @_QMacc_declare_alloc_modEdata_acc_declare_post_dealloc() attributes {acc.declare_action} {
+
+! USE: func.func @_QPuse_mod() {
+! USE: acc.declare_action = #acc.declare_action<postAlloc = @_QMacc_declare_alloc_modEdata_acc_declare_post_alloc>
+! USE: fir.global @_QMacc_declare_alloc_modEdata {acc.declare = #acc.declare<dataClause = acc_create>
+! USE: func.func private @_QMacc_declare_alloc_modEdata_acc_declare_post_alloc()
+! USE: func.func private @_QMacc_declare_alloc_modEdata_acc_declare_post_dealloc()
+! USE-NOT: acc.declare_enter
+
+! CONV: fir.call @_QMacc_declare_alloc_modEdata_acc_declare_post_alloc()
diff --git a/flang/test/Lower/OpenACC/acc-declare.f90 b/flang/test/Lower/OpenACC/acc-declare.f90
index 206a690e3c951..3339fa31c3d27 100644
--- a/flang/test/Lower/OpenACC/acc-declare.f90
+++ b/flang/test/Lower/OpenACC/acc-declare.f90
@@ -418,14 +418,14 @@ subroutine init_in_data(e)
! CHECK: acc.terminator
! CHECK: }
-! CHECK-LABEL: func.func private @_QMacc_declare_allocatable_testEdata1_acc_declare_post_alloc() {
+! CHECK-LABEL: func.func @_QMacc_declare_allocatable_testEdata1_acc_declare_post_alloc() attributes {acc.declare_action} {
! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK: %[[CREATE_DESC:.*]] = acc.create varPtr(%[[GLOBAL_ADDR]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {implicit = true, name = "data1", structured = false}
! CHECK: acc.declare_enter dataOperands(%[[CREATE_DESC]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
! CHECK: return
! CHECK: }
-! CHECK-LABEL: func.func private @_QMacc_declare_allocatable_testEdata1_acc_declare_post_dealloc() {
+! CHECK-LABEL: func.func @_QMacc_declare_allocatable_testEdata1_acc_declare_post_dealloc() attributes {acc.declare_action} {
! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[GLOBAL_ADDR]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {dataClause = #acc<data_clause acc_create>, implicit = true, name = "data1", structured = false}
! CHECK: acc.declare_exit dataOperands(%[[DEVPTR]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
>From 411d89999b3f855c22feda7f768e29981c6c95fb Mon Sep 17 00:00:00 2001
From: nvpm <pmathew at nvidia.com>
Date: Mon, 8 Jun 2026 11:45:35 -0700
Subject: [PATCH 2/2] Format
---
flang/include/flang/Lower/OpenACC.h | 6 +++---
flang/include/flang/Semantics/symbol.h | 2 +-
flang/lib/Lower/ConvertVariable.cpp | 2 +-
flang/lib/Lower/OpenACC.cpp | 25 +++++++++++--------------
4 files changed, 16 insertions(+), 19 deletions(-)
diff --git a/flang/include/flang/Lower/OpenACC.h b/flang/include/flang/Lower/OpenACC.h
index c76390a3bb85e..8ba72f356656e 100644
--- a/flang/include/flang/Lower/OpenACC.h
+++ b/flang/include/flang/Lower/OpenACC.h
@@ -86,9 +86,9 @@ void genOpenACCRoutineConstruct(
AbstractConverter &, mlir::ModuleOp, mlir::func::FuncOp,
const std::vector<Fortran::semantics::OpenACCRoutineInfo> &);
-void declareExternalAccModuleDeclareActionRecipes(AbstractConverter &,
- fir::FirOpBuilder &,
- const Fortran::semantics::Symbol &);
+void declareExternalAccModuleDeclareActionRecipes(
+ AbstractConverter &, fir::FirOpBuilder &,
+ const Fortran::semantics::Symbol &);
void attachDeclarePostAllocAction(AbstractConverter &, fir::FirOpBuilder &,
const Fortran::semantics::Symbol &);
void attachDeclarePreDeallocAction(AbstractConverter &, fir::FirOpBuilder &,
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 84b5cd0ddd280..5790846d163b1 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -32,7 +32,7 @@ class raw_ostream;
namespace Fortran::parser {
struct Expr;
struct OpenMPDeclarativeConstruct;
-}
+} // namespace Fortran::parser
namespace Fortran::semantics {
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 3527b50e74d1c..9e309858deb4c 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -21,8 +21,8 @@
#include "flang/Lower/ConvertExprToHLFIR.h"
#include "flang/Lower/ConvertProcedureDesignator.h"
#include "flang/Lower/Mangler.h"
-#include "flang/Lower/OpenACC.h"
#include "flang/Lower/MultiImageFortran.h"
+#include "flang/Lower/OpenACC.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/StatementContext.h"
#include "flang/Lower/Support/Utils.h"
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index a7ef4dd6b0284..1c51cf7fa6ca5 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -178,12 +178,10 @@ static void addDeclareAttr(fir::FirOpBuilder &builder, mlir::Operation *op,
builder.getContext(), clause)));
}
-static mlir::func::FuncOp
-createDeclareFunc(mlir::OpBuilder &modBuilder, fir::FirOpBuilder &builder,
- mlir::Location loc, llvm::StringRef funcName,
- llvm::SmallVector<mlir::Type> argsTy = {},
- llvm::SmallVector<mlir::Location> locs = {},
- bool linkable = false) {
+static mlir::func::FuncOp createDeclareFunc(
+ mlir::OpBuilder &modBuilder, fir::FirOpBuilder &builder, mlir::Location loc,
+ llvm::StringRef funcName, llvm::SmallVector<mlir::Type> argsTy = {},
+ llvm::SmallVector<mlir::Location> locs = {}, bool linkable = false) {
auto funcTy = mlir::FunctionType::get(modBuilder.getContext(), argsTy, {});
auto funcOp = mlir::func::FuncOp::create(modBuilder, loc, funcName, funcTy);
funcOp.setVisibility(linkable ? mlir::SymbolTable::Visibility::Public
@@ -3722,9 +3720,9 @@ static void createDeclareAllocFunc(mlir::OpBuilder &modBuilder,
std::stringstream registerFuncName;
registerFuncName << globalOp.getSymName().str()
<< Fortran::lower::declarePostAllocSuffix.str();
- auto registerFuncOp = createDeclareFunc(
- modBuilder, builder, loc, registerFuncName.str(),
- /*argsTy=*/{}, /*locs=*/{}, /*linkable=*/true);
+ auto registerFuncOp =
+ createDeclareFunc(modBuilder, builder, loc, registerFuncName.str(),
+ /*argsTy=*/{}, /*locs=*/{}, /*linkable=*/true);
fir::AddrOfOp addrOp = fir::AddrOfOp::create(
builder, loc, fir::ReferenceType::get(globalOp.getType()),
@@ -3763,9 +3761,9 @@ static void createDeclareDeallocFunc(mlir::OpBuilder &modBuilder,
std::stringstream postDeallocFuncName;
postDeallocFuncName << globalOp.getSymName().str()
<< Fortran::lower::declarePostDeallocSuffix.str();
- auto postDeallocOp = createDeclareFunc(
- modBuilder, builder, loc, postDeallocFuncName.str(),
- /*argsTy=*/{}, /*locs=*/{}, /*linkable=*/true);
+ auto postDeallocOp =
+ createDeclareFunc(modBuilder, builder, loc, postDeallocFuncName.str(),
+ /*argsTy=*/{}, /*locs=*/{}, /*linkable=*/true);
fir::AddrOfOp addrOp = fir::AddrOfOp::create(
builder, loc, fir::ReferenceType::get(globalOp.getType()),
@@ -4748,8 +4746,7 @@ void Fortran::lower::declareExternalAccModuleDeclareActionRecipes(
declareExternalRecipe(declarePostAllocSuffix);
if (ultimate.test(Flag::AccCreate) || ultimate.test(Flag::AccCopyIn) ||
ultimate.test(Flag::AccCopyInReadOnly) || ultimate.test(Flag::AccCopy) ||
- ultimate.test(Flag::AccCopyOut) ||
- ultimate.test(Flag::AccDeviceResident))
+ ultimate.test(Flag::AccCopyOut) || ultimate.test(Flag::AccDeviceResident))
declareExternalRecipe(declarePostDeallocSuffix);
}
More information about the flang-commits
mailing list