[flang-commits] [flang] [acc][flang] lowering of acc declare on COMMON variables (PR #163676)
Susan Tan ス-ザン タン via flang-commits
flang-commits at lists.llvm.org
Fri Oct 17 11:35:15 PDT 2025
https://github.com/SusanTan updated https://github.com/llvm/llvm-project/pull/163676
>From 3582fd5f7b4588bae0100f068a56c32ad92a790b Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Wed, 15 Oct 2025 15:36:14 -0700
Subject: [PATCH 1/9] initial implementation
---
flang/lib/Lower/OpenACC.cpp | 274 +++++++++++++++++++++++++++++++++++-
1 file changed, 268 insertions(+), 6 deletions(-)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index cfb18914e8126..9e940743bd377 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -4112,12 +4112,26 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
DeclareOp::create(builder, loc, mlir::Value{},
mlir::ValueRange(entryOp.getAccVar()));
if constexpr (std::is_same_v<GlobalOp, mlir::acc::GlobalDestructorOp>) {
- ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
- entryOp.getBounds(), entryOp.getAsyncOperands(),
- entryOp.getAsyncOperandsDeviceTypeAttr(),
- entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
- /*structured=*/false, /*implicit=*/false,
- builder.getStringAttr(*entryOp.getName()));
+ if constexpr (std::is_same_v<ExitOp, mlir::acc::DeclareLinkOp>) {
+ // No destructor emission for declare link in this path to avoid
+ // complex var/varType/varPtrPtr signatures. The ctor registers the link.
+ } else if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
+ std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>) {
+ ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
+ entryOp.getVar(), entryOp.getVarType(),
+ entryOp.getBounds(), entryOp.getAsyncOperands(),
+ entryOp.getAsyncOperandsDeviceTypeAttr(),
+ entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
+ /*structured=*/false, /*implicit=*/false,
+ builder.getStringAttr(*entryOp.getName()));
+ } else {
+ ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
+ entryOp.getBounds(), entryOp.getAsyncOperands(),
+ entryOp.getAsyncOperandsDeviceTypeAttr(),
+ entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
+ /*structured=*/false, /*implicit=*/false,
+ builder.getStringAttr(*entryOp.getName()));
+ }
}
mlir::acc::TerminatorOp::create(builder, loc);
modBuilder.setInsertionPointAfter(declareGlobalOp);
@@ -4329,6 +4343,58 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
createClause->v;
const auto &accObjectList =
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+ // Emit module-level declare for COMMON symbols in this clause.
+ for (const auto &obj : accObjectList.v) {
+ Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+ if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+ Fortran::semantics::FindCommonBlockContaining(sym)) {
+ std::string globalName = converter.mangleName(sym);
+ fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+ if (!globalOp) {
+ if (Fortran::semantics::FindEquivalenceSet(sym)) {
+ for (Fortran::semantics::EquivalenceObject eqObj :
+ *Fortran::semantics::FindEquivalenceSet(sym)) {
+ std::string eqName = converter.mangleName(eqObj.symbol);
+ globalOp = builder.getNamedGlobal(eqName);
+ if (globalOp)
+ break;
+ }
+ }
+ }
+ if (!globalOp)
+ llvm::report_fatal_error("could not retrieve global symbol");
+ std::stringstream ctorName;
+ ctorName << globalName << "_acc_ctor";
+ if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+ ctorName.str())) {
+ mlir::Location operandLocation = genOperandLocation(converter, obj);
+ addDeclareAttr(builder, globalOp.getOperation(),
+ mlir::acc::DataClause::acc_create);
+ mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+ modBuilder.setInsertionPointAfter(globalOp);
+ std::stringstream asFortran;
+ asFortran << sym.name().ToString();
+ auto savedIP = builder.saveInsertionPoint();
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+ mlir::acc::CreateOp,
+ mlir::acc::DeclareEnterOp,
+ mlir::acc::DeleteOp>(modBuilder, builder,
+ operandLocation, globalOp,
+ mlir::acc::DataClause::acc_create, ctorName.str(),
+ /*implicit=*/false, asFortran);
+ std::stringstream dtorName;
+ dtorName << globalName << "_acc_dtor";
+ createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+ mlir::acc::GetDevicePtrOp,
+ mlir::acc::DeclareExitOp,
+ mlir::acc::DeleteOp>(modBuilder, builder,
+ operandLocation, globalOp,
+ mlir::acc::DataClause::acc_create, dtorName.str(),
+ /*implicit=*/false, asFortran);
+ builder.restoreInsertionPoint(savedIP);
+ }
+ }
+ }
auto crtDataStart = dataClauseOperands.size();
genDeclareDataOperandOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
accObjectList, converter, semanticsContext, stmtCtx,
@@ -4349,6 +4415,61 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
dataClauseOperands.end());
} else if (const auto *copyinClause =
std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
+ // Emit module-level declare for COMMON symbols in this clause.
+ const auto &listWithModifier = copyinClause->v;
+ const auto ©inObjs =
+ std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+ for (const auto &obj : copyinObjs.v) {
+ Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+ if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+ Fortran::semantics::FindCommonBlockContaining(sym)) {
+ std::string globalName = converter.mangleName(sym);
+ fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+ if (!globalOp) {
+ if (Fortran::semantics::FindEquivalenceSet(sym)) {
+ for (Fortran::semantics::EquivalenceObject eqObj :
+ *Fortran::semantics::FindEquivalenceSet(sym)) {
+ std::string eqName = converter.mangleName(eqObj.symbol);
+ globalOp = builder.getNamedGlobal(eqName);
+ if (globalOp)
+ break;
+ }
+ }
+ }
+ if (!globalOp)
+ llvm::report_fatal_error("could not retrieve global symbol");
+ std::stringstream ctorName;
+ ctorName << globalName << "_acc_ctor";
+ if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+ ctorName.str())) {
+ mlir::Location operandLocation = genOperandLocation(converter, obj);
+ addDeclareAttr(builder, globalOp.getOperation(),
+ mlir::acc::DataClause::acc_copyin);
+ mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+ modBuilder.setInsertionPointAfter(globalOp);
+ std::stringstream asFortran;
+ asFortran << sym.name().ToString();
+ auto savedIP = builder.saveInsertionPoint();
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+ mlir::acc::CopyinOp,
+ mlir::acc::DeclareEnterOp,
+ mlir::acc::DeleteOp>(modBuilder, builder,
+ operandLocation, globalOp,
+ mlir::acc::DataClause::acc_copyin, ctorName.str(),
+ /*implicit=*/false, asFortran);
+ std::stringstream dtorName;
+ dtorName << globalName << "_acc_dtor";
+ createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+ mlir::acc::GetDevicePtrOp,
+ mlir::acc::DeclareExitOp,
+ mlir::acc::DeleteOp>(modBuilder, builder,
+ operandLocation, globalOp,
+ mlir::acc::DataClause::acc_copyin, dtorName.str(),
+ /*implicit=*/false, asFortran);
+ builder.restoreInsertionPoint(savedIP);
+ }
+ }
+ }
auto crtDataStart = dataClauseOperands.size();
genDeclareDataOperandOperationsWithModifier<mlir::acc::CopyinOp,
mlir::acc::DeleteOp>(
@@ -4365,6 +4486,58 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
copyoutClause->v;
const auto &accObjectList =
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+ // Emit module-level declare for COMMON symbols in this clause.
+ for (const auto &obj : accObjectList.v) {
+ Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+ if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+ Fortran::semantics::FindCommonBlockContaining(sym)) {
+ std::string globalName = converter.mangleName(sym);
+ fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+ if (!globalOp) {
+ if (Fortran::semantics::FindEquivalenceSet(sym)) {
+ for (Fortran::semantics::EquivalenceObject eqObj :
+ *Fortran::semantics::FindEquivalenceSet(sym)) {
+ std::string eqName = converter.mangleName(eqObj.symbol);
+ globalOp = builder.getNamedGlobal(eqName);
+ if (globalOp)
+ break;
+ }
+ }
+ }
+ if (!globalOp)
+ llvm::report_fatal_error("could not retrieve global symbol");
+ std::stringstream ctorName;
+ ctorName << globalName << "_acc_ctor";
+ if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+ ctorName.str())) {
+ mlir::Location operandLocation = genOperandLocation(converter, obj);
+ addDeclareAttr(builder, globalOp.getOperation(),
+ mlir::acc::DataClause::acc_copyout);
+ mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+ modBuilder.setInsertionPointAfter(globalOp);
+ std::stringstream asFortran;
+ asFortran << sym.name().ToString();
+ auto savedIP = builder.saveInsertionPoint();
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+ mlir::acc::CreateOp,
+ mlir::acc::DeclareEnterOp,
+ mlir::acc::CopyoutOp>(modBuilder, builder,
+ operandLocation, globalOp,
+ mlir::acc::DataClause::acc_copyout, ctorName.str(),
+ /*implicit=*/false, asFortran);
+ std::stringstream dtorName;
+ dtorName << globalName << "_acc_dtor";
+ createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+ mlir::acc::GetDevicePtrOp,
+ mlir::acc::DeclareExitOp,
+ mlir::acc::CopyoutOp>(modBuilder, builder,
+ operandLocation, globalOp,
+ mlir::acc::DataClause::acc_copyout, dtorName.str(),
+ /*implicit=*/false, asFortran);
+ builder.restoreInsertionPoint(savedIP);
+ }
+ }
+ }
auto crtDataStart = dataClauseOperands.size();
genDeclareDataOperandOperations<mlir::acc::CreateOp,
mlir::acc::CopyoutOp>(
@@ -4383,6 +4556,50 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
/*structured=*/true, /*implicit=*/false);
} else if (const auto *linkClause =
std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
+ // Emit module-level declare for COMMON symbols in this clause.
+ const auto &linkObjs = linkClause->v;
+ for (const auto &obj : linkObjs.v) {
+ Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+ if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+ Fortran::semantics::FindCommonBlockContaining(sym)) {
+ std::string globalName = converter.mangleName(sym);
+ fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+ if (!globalOp) {
+ if (Fortran::semantics::FindEquivalenceSet(sym)) {
+ for (Fortran::semantics::EquivalenceObject eqObj :
+ *Fortran::semantics::FindEquivalenceSet(sym)) {
+ std::string eqName = converter.mangleName(eqObj.symbol);
+ globalOp = builder.getNamedGlobal(eqName);
+ if (globalOp)
+ break;
+ }
+ }
+ }
+ if (!globalOp)
+ llvm::report_fatal_error("could not retrieve global symbol");
+ std::stringstream ctorName;
+ ctorName << globalName << "_acc_ctor";
+ if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+ ctorName.str())) {
+ mlir::Location operandLocation = genOperandLocation(converter, obj);
+ addDeclareAttr(builder, globalOp.getOperation(),
+ mlir::acc::DataClause::acc_declare_link);
+ mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+ modBuilder.setInsertionPointAfter(globalOp);
+ std::stringstream asFortran;
+ asFortran << sym.name().ToString();
+ auto savedIP = builder.saveInsertionPoint();
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+ mlir::acc::DeclareLinkOp,
+ mlir::acc::DeclareEnterOp,
+ mlir::acc::DeclareLinkOp>(modBuilder, builder,
+ operandLocation, globalOp,
+ mlir::acc::DataClause::acc_declare_link, ctorName.str(),
+ /*implicit=*/false, asFortran);
+ builder.restoreInsertionPoint(savedIP);
+ }
+ }
+ }
genDeclareDataOperandOperations<mlir::acc::DeclareLinkOp,
mlir::acc::DeclareLinkOp>(
linkClause->v, converter, semanticsContext, stmtCtx,
@@ -4391,6 +4608,51 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
} else if (const auto *deviceResidentClause =
std::get_if<Fortran::parser::AccClause::DeviceResident>(
&clause.u)) {
+ // Emit module-level declare for COMMON symbols in this clause.
+ const auto &devResObjs = deviceResidentClause->v;
+ for (const auto &obj : devResObjs.v) {
+ Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+ if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+ Fortran::semantics::FindCommonBlockContaining(sym)) {
+ std::string globalName = converter.mangleName(sym);
+ fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+ if (!globalOp) {
+ if (Fortran::semantics::FindEquivalenceSet(sym)) {
+ for (Fortran::semantics::EquivalenceObject eqObj :
+ *Fortran::semantics::FindEquivalenceSet(sym)) {
+ std::string eqName = converter.mangleName(eqObj.symbol);
+ globalOp = builder.getNamedGlobal(eqName);
+ if (globalOp)
+ break;
+ }
+ }
+ }
+ if (!globalOp)
+ llvm::report_fatal_error("could not retrieve global symbol");
+ std::stringstream ctorName;
+ ctorName << globalName << "_acc_ctor";
+ if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+ ctorName.str())) {
+ mlir::Location operandLocation = genOperandLocation(converter, obj);
+ addDeclareAttr(builder, globalOp.getOperation(),
+ mlir::acc::DataClause::acc_declare_device_resident);
+ mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+ modBuilder.setInsertionPointAfter(globalOp);
+ std::stringstream asFortran;
+ asFortran << sym.name().ToString();
+ auto savedIP = builder.saveInsertionPoint();
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+ mlir::acc::DeclareDeviceResidentOp,
+ mlir::acc::DeclareEnterOp,
+ mlir::acc::DeleteOp>(modBuilder, builder,
+ operandLocation, globalOp,
+ mlir::acc::DataClause::acc_declare_device_resident,
+ ctorName.str(),
+ /*implicit=*/false, asFortran);
+ builder.restoreInsertionPoint(savedIP);
+ }
+ }
+ }
auto crtDataStart = dataClauseOperands.size();
genDeclareDataOperandOperations<mlir::acc::DeclareDeviceResidentOp,
mlir::acc::DeleteOp>(
>From c6ee3b92db518a4e121203556e17b06fb5516825 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Wed, 15 Oct 2025 15:56:11 -0700
Subject: [PATCH 2/9] refactor
---
flang/lib/Lower/OpenACC.cpp | 342 ++++++++++++------------------------
1 file changed, 117 insertions(+), 225 deletions(-)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 9e940743bd377..37abcffc683d9 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -3398,6 +3398,7 @@ genACCHostDataOp(Fortran::lower::AbstractConverter &converter,
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+
for (const Fortran::parser::AccClause &clause : accClauseList.v) {
mlir::Location clauseLocation = converter.genLocation(clause.source);
if (const auto *ifClause =
@@ -4326,6 +4327,50 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
Fortran::lower::StatementContext stmtCtx;
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+ // Inline helper to emit module-level declare for COMMON symbols in a clause.
+ auto emitCommonGlobal = [&](const Fortran::parser::AccObject &obj,
+ mlir::acc::DataClause clause,
+ auto emitCtorDtor) {
+ Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+ if (!(sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+ Fortran::semantics::FindCommonBlockContaining(sym)))
+ return;
+
+ std::string globalName = converter.mangleName(sym);
+ fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+ if (!globalOp) {
+ if (Fortran::semantics::FindEquivalenceSet(sym)) {
+ for (Fortran::semantics::EquivalenceObject eqObj :
+ *Fortran::semantics::FindEquivalenceSet(sym)) {
+ std::string eqName = converter.mangleName(eqObj.symbol);
+ globalOp = builder.getNamedGlobal(eqName);
+ if (globalOp)
+ break;
+ }
+ }
+ }
+ if (!globalOp)
+ llvm::report_fatal_error("could not retrieve global symbol");
+
+ std::stringstream ctorName;
+ ctorName << globalName << "_acc_ctor";
+ if (builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+ ctorName.str()))
+ return;
+
+ mlir::Location operandLocation = genOperandLocation(converter, obj);
+ addDeclareAttr(builder, globalOp.getOperation(), clause);
+ mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+ modBuilder.setInsertionPointAfter(globalOp);
+ std::stringstream asFortran;
+ asFortran << sym.name().ToString();
+
+ auto savedIP = builder.saveInsertionPoint();
+ emitCtorDtor(modBuilder, operandLocation, globalOp, clause, asFortran,
+ ctorName.str());
+ builder.restoreInsertionPoint(savedIP);
+ };
+
for (const Fortran::parser::AccClause &clause : accClauseList.v) {
if (const auto *copyClause =
std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
@@ -4343,57 +4388,26 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
createClause->v;
const auto &accObjectList =
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
- // Emit module-level declare for COMMON symbols in this clause.
for (const auto &obj : accObjectList.v) {
- Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
- if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
- Fortran::semantics::FindCommonBlockContaining(sym)) {
- std::string globalName = converter.mangleName(sym);
- fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
- if (!globalOp) {
- if (Fortran::semantics::FindEquivalenceSet(sym)) {
- for (Fortran::semantics::EquivalenceObject eqObj :
- *Fortran::semantics::FindEquivalenceSet(sym)) {
- std::string eqName = converter.mangleName(eqObj.symbol);
- globalOp = builder.getNamedGlobal(eqName);
- if (globalOp)
- break;
- }
- }
- }
- if (!globalOp)
- llvm::report_fatal_error("could not retrieve global symbol");
- std::stringstream ctorName;
- ctorName << globalName << "_acc_ctor";
- if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
- ctorName.str())) {
- mlir::Location operandLocation = genOperandLocation(converter, obj);
- addDeclareAttr(builder, globalOp.getOperation(),
- mlir::acc::DataClause::acc_create);
- mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
- modBuilder.setInsertionPointAfter(globalOp);
- std::stringstream asFortran;
- asFortran << sym.name().ToString();
- auto savedIP = builder.saveInsertionPoint();
- createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
- mlir::acc::CreateOp,
- mlir::acc::DeclareEnterOp,
- mlir::acc::DeleteOp>(modBuilder, builder,
- operandLocation, globalOp,
- mlir::acc::DataClause::acc_create, ctorName.str(),
+ emitCommonGlobal(obj, mlir::acc::DataClause::acc_create,
+ [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
+ fir::GlobalOp globalOp, mlir::acc::DataClause clause,
+ std::stringstream &asFortran, const std::string &ctorName) {
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+ mlir::acc::CreateOp,
+ mlir::acc::DeclareEnterOp,
+ mlir::acc::DeleteOp>(modBuilder, builder,
+ operandLocation, globalOp, clause, ctorName,
/*implicit=*/false, asFortran);
- std::stringstream dtorName;
- dtorName << globalName << "_acc_dtor";
- createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
- mlir::acc::GetDevicePtrOp,
- mlir::acc::DeclareExitOp,
- mlir::acc::DeleteOp>(modBuilder, builder,
- operandLocation, globalOp,
- mlir::acc::DataClause::acc_create, dtorName.str(),
+ std::stringstream dtorName;
+ dtorName << globalOp.getSymName().str() << "_acc_dtor";
+ createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+ mlir::acc::GetDevicePtrOp,
+ mlir::acc::DeclareExitOp,
+ mlir::acc::DeleteOp>(modBuilder, builder,
+ operandLocation, globalOp, clause, dtorName.str(),
/*implicit=*/false, asFortran);
- builder.restoreInsertionPoint(savedIP);
- }
- }
+ });
}
auto crtDataStart = dataClauseOperands.size();
genDeclareDataOperandOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
@@ -4415,60 +4429,29 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
dataClauseOperands.end());
} else if (const auto *copyinClause =
std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
- // Emit module-level declare for COMMON symbols in this clause.
const auto &listWithModifier = copyinClause->v;
const auto ©inObjs =
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
for (const auto &obj : copyinObjs.v) {
- Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
- if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
- Fortran::semantics::FindCommonBlockContaining(sym)) {
- std::string globalName = converter.mangleName(sym);
- fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
- if (!globalOp) {
- if (Fortran::semantics::FindEquivalenceSet(sym)) {
- for (Fortran::semantics::EquivalenceObject eqObj :
- *Fortran::semantics::FindEquivalenceSet(sym)) {
- std::string eqName = converter.mangleName(eqObj.symbol);
- globalOp = builder.getNamedGlobal(eqName);
- if (globalOp)
- break;
- }
- }
- }
- if (!globalOp)
- llvm::report_fatal_error("could not retrieve global symbol");
- std::stringstream ctorName;
- ctorName << globalName << "_acc_ctor";
- if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
- ctorName.str())) {
- mlir::Location operandLocation = genOperandLocation(converter, obj);
- addDeclareAttr(builder, globalOp.getOperation(),
- mlir::acc::DataClause::acc_copyin);
- mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
- modBuilder.setInsertionPointAfter(globalOp);
- std::stringstream asFortran;
- asFortran << sym.name().ToString();
- auto savedIP = builder.saveInsertionPoint();
- createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
- mlir::acc::CopyinOp,
- mlir::acc::DeclareEnterOp,
- mlir::acc::DeleteOp>(modBuilder, builder,
- operandLocation, globalOp,
- mlir::acc::DataClause::acc_copyin, ctorName.str(),
+ emitCommonGlobal(obj, mlir::acc::DataClause::acc_copyin,
+ [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
+ fir::GlobalOp globalOp, mlir::acc::DataClause clause,
+ std::stringstream &asFortran, const std::string &ctorName) {
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+ mlir::acc::CopyinOp,
+ mlir::acc::DeclareEnterOp,
+ mlir::acc::DeleteOp>(modBuilder, builder,
+ operandLocation, globalOp, clause, ctorName,
/*implicit=*/false, asFortran);
- std::stringstream dtorName;
- dtorName << globalName << "_acc_dtor";
- createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
- mlir::acc::GetDevicePtrOp,
- mlir::acc::DeclareExitOp,
- mlir::acc::DeleteOp>(modBuilder, builder,
- operandLocation, globalOp,
- mlir::acc::DataClause::acc_copyin, dtorName.str(),
+ std::stringstream dtorName;
+ dtorName << globalOp.getSymName().str() << "_acc_dtor";
+ createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+ mlir::acc::GetDevicePtrOp,
+ mlir::acc::DeclareExitOp,
+ mlir::acc::DeleteOp>(modBuilder, builder,
+ operandLocation, globalOp, clause, dtorName.str(),
/*implicit=*/false, asFortran);
- builder.restoreInsertionPoint(savedIP);
- }
- }
+ });
}
auto crtDataStart = dataClauseOperands.size();
genDeclareDataOperandOperationsWithModifier<mlir::acc::CopyinOp,
@@ -4486,57 +4469,26 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
copyoutClause->v;
const auto &accObjectList =
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
- // Emit module-level declare for COMMON symbols in this clause.
for (const auto &obj : accObjectList.v) {
- Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
- if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
- Fortran::semantics::FindCommonBlockContaining(sym)) {
- std::string globalName = converter.mangleName(sym);
- fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
- if (!globalOp) {
- if (Fortran::semantics::FindEquivalenceSet(sym)) {
- for (Fortran::semantics::EquivalenceObject eqObj :
- *Fortran::semantics::FindEquivalenceSet(sym)) {
- std::string eqName = converter.mangleName(eqObj.symbol);
- globalOp = builder.getNamedGlobal(eqName);
- if (globalOp)
- break;
- }
- }
- }
- if (!globalOp)
- llvm::report_fatal_error("could not retrieve global symbol");
- std::stringstream ctorName;
- ctorName << globalName << "_acc_ctor";
- if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
- ctorName.str())) {
- mlir::Location operandLocation = genOperandLocation(converter, obj);
- addDeclareAttr(builder, globalOp.getOperation(),
- mlir::acc::DataClause::acc_copyout);
- mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
- modBuilder.setInsertionPointAfter(globalOp);
- std::stringstream asFortran;
- asFortran << sym.name().ToString();
- auto savedIP = builder.saveInsertionPoint();
- createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
- mlir::acc::CreateOp,
- mlir::acc::DeclareEnterOp,
- mlir::acc::CopyoutOp>(modBuilder, builder,
- operandLocation, globalOp,
- mlir::acc::DataClause::acc_copyout, ctorName.str(),
+ emitCommonGlobal(obj, mlir::acc::DataClause::acc_copyout,
+ [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
+ fir::GlobalOp globalOp, mlir::acc::DataClause clause,
+ std::stringstream &asFortran, const std::string &ctorName) {
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+ mlir::acc::CreateOp,
+ mlir::acc::DeclareEnterOp,
+ mlir::acc::CopyoutOp>(modBuilder, builder,
+ operandLocation, globalOp, clause, ctorName,
/*implicit=*/false, asFortran);
- std::stringstream dtorName;
- dtorName << globalName << "_acc_dtor";
- createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
- mlir::acc::GetDevicePtrOp,
- mlir::acc::DeclareExitOp,
- mlir::acc::CopyoutOp>(modBuilder, builder,
- operandLocation, globalOp,
- mlir::acc::DataClause::acc_copyout, dtorName.str(),
+ std::stringstream dtorName;
+ dtorName << globalOp.getSymName().str() << "_acc_dtor";
+ createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+ mlir::acc::GetDevicePtrOp,
+ mlir::acc::DeclareExitOp,
+ mlir::acc::CopyoutOp>(modBuilder, builder,
+ operandLocation, globalOp, clause, dtorName.str(),
/*implicit=*/false, asFortran);
- builder.restoreInsertionPoint(savedIP);
- }
- }
+ });
}
auto crtDataStart = dataClauseOperands.size();
genDeclareDataOperandOperations<mlir::acc::CreateOp,
@@ -4556,49 +4508,19 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
/*structured=*/true, /*implicit=*/false);
} else if (const auto *linkClause =
std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
- // Emit module-level declare for COMMON symbols in this clause.
const auto &linkObjs = linkClause->v;
for (const auto &obj : linkObjs.v) {
- Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
- if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
- Fortran::semantics::FindCommonBlockContaining(sym)) {
- std::string globalName = converter.mangleName(sym);
- fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
- if (!globalOp) {
- if (Fortran::semantics::FindEquivalenceSet(sym)) {
- for (Fortran::semantics::EquivalenceObject eqObj :
- *Fortran::semantics::FindEquivalenceSet(sym)) {
- std::string eqName = converter.mangleName(eqObj.symbol);
- globalOp = builder.getNamedGlobal(eqName);
- if (globalOp)
- break;
- }
- }
- }
- if (!globalOp)
- llvm::report_fatal_error("could not retrieve global symbol");
- std::stringstream ctorName;
- ctorName << globalName << "_acc_ctor";
- if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
- ctorName.str())) {
- mlir::Location operandLocation = genOperandLocation(converter, obj);
- addDeclareAttr(builder, globalOp.getOperation(),
- mlir::acc::DataClause::acc_declare_link);
- mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
- modBuilder.setInsertionPointAfter(globalOp);
- std::stringstream asFortran;
- asFortran << sym.name().ToString();
- auto savedIP = builder.saveInsertionPoint();
- createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
- mlir::acc::DeclareLinkOp,
- mlir::acc::DeclareEnterOp,
- mlir::acc::DeclareLinkOp>(modBuilder, builder,
- operandLocation, globalOp,
- mlir::acc::DataClause::acc_declare_link, ctorName.str(),
+ emitCommonGlobal(obj, mlir::acc::DataClause::acc_declare_link,
+ [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
+ fir::GlobalOp globalOp, mlir::acc::DataClause clause,
+ std::stringstream &asFortran, const std::string &ctorName) {
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+ mlir::acc::DeclareLinkOp,
+ mlir::acc::DeclareEnterOp,
+ mlir::acc::DeclareLinkOp>(modBuilder,
+ builder, operandLocation, globalOp, clause, ctorName,
/*implicit=*/false, asFortran);
- builder.restoreInsertionPoint(savedIP);
- }
- }
+ });
}
genDeclareDataOperandOperations<mlir::acc::DeclareLinkOp,
mlir::acc::DeclareLinkOp>(
@@ -4608,50 +4530,20 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
} else if (const auto *deviceResidentClause =
std::get_if<Fortran::parser::AccClause::DeviceResident>(
&clause.u)) {
- // Emit module-level declare for COMMON symbols in this clause.
const auto &devResObjs = deviceResidentClause->v;
for (const auto &obj : devResObjs.v) {
- Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
- if (sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
- Fortran::semantics::FindCommonBlockContaining(sym)) {
- std::string globalName = converter.mangleName(sym);
- fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
- if (!globalOp) {
- if (Fortran::semantics::FindEquivalenceSet(sym)) {
- for (Fortran::semantics::EquivalenceObject eqObj :
- *Fortran::semantics::FindEquivalenceSet(sym)) {
- std::string eqName = converter.mangleName(eqObj.symbol);
- globalOp = builder.getNamedGlobal(eqName);
- if (globalOp)
- break;
- }
- }
- }
- if (!globalOp)
- llvm::report_fatal_error("could not retrieve global symbol");
- std::stringstream ctorName;
- ctorName << globalName << "_acc_ctor";
- if (!builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
- ctorName.str())) {
- mlir::Location operandLocation = genOperandLocation(converter, obj);
- addDeclareAttr(builder, globalOp.getOperation(),
- mlir::acc::DataClause::acc_declare_device_resident);
- mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
- modBuilder.setInsertionPointAfter(globalOp);
- std::stringstream asFortran;
- asFortran << sym.name().ToString();
- auto savedIP = builder.saveInsertionPoint();
- createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
- mlir::acc::DeclareDeviceResidentOp,
- mlir::acc::DeclareEnterOp,
- mlir::acc::DeleteOp>(modBuilder, builder,
- operandLocation, globalOp,
- mlir::acc::DataClause::acc_declare_device_resident,
- ctorName.str(),
+ emitCommonGlobal(obj,
+ mlir::acc::DataClause::acc_declare_device_resident,
+ [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
+ fir::GlobalOp globalOp, mlir::acc::DataClause clause,
+ std::stringstream &asFortran, const std::string &ctorName) {
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+ mlir::acc::DeclareDeviceResidentOp,
+ mlir::acc::DeclareEnterOp,
+ mlir::acc::DeleteOp>(modBuilder, builder,
+ operandLocation, globalOp, clause, ctorName,
/*implicit=*/false, asFortran);
- builder.restoreInsertionPoint(savedIP);
- }
- }
+ });
}
auto crtDataStart = dataClauseOperands.size();
genDeclareDataOperandOperations<mlir::acc::DeclareDeviceResidentOp,
>From 3592903f21135f6117623d07634c5d95c8ae6c26 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Wed, 15 Oct 2025 17:24:56 -0700
Subject: [PATCH 3/9] more refactor
---
flang/lib/Lower/OpenACC.cpp | 83 ++++++++++++++++---------------------
1 file changed, 35 insertions(+), 48 deletions(-)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 37abcffc683d9..e493198fd2b51 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -4138,6 +4138,29 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
modBuilder.setInsertionPointAfter(declareGlobalOp);
}
+// Small helper to emit a constructor/destructor pair for a given global
+// declare Entry/Exit Op combination.
+template <typename EntryOp, typename ExitOp>
+static void emitCtorDtorPair(mlir::OpBuilder &modBuilder,
+ fir::FirOpBuilder &builder,
+ mlir::Location operandLocation,
+ fir::GlobalOp globalOp,
+ mlir::acc::DataClause clause,
+ std::stringstream &asFortran,
+ const std::string &ctorName) {
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
+ mlir::acc::DeclareEnterOp, ExitOp>(
+ modBuilder, builder, operandLocation, globalOp, clause, ctorName,
+ /*implicit=*/false, asFortran);
+
+ std::stringstream dtorName;
+ dtorName << globalOp.getSymName().str() << "_acc_dtor";
+ createDeclareGlobalOp<mlir::acc::GlobalDestructorOp, mlir::acc::GetDevicePtrOp,
+ mlir::acc::DeclareExitOp, ExitOp>(
+ modBuilder, builder, operandLocation, globalOp, clause, dtorName.str(),
+ /*implicit=*/false, asFortran);
+}
+
template <typename EntryOp>
static void createDeclareAllocFunc(mlir::OpBuilder &modBuilder,
fir::FirOpBuilder &builder,
@@ -4393,20 +4416,9 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
[&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
fir::GlobalOp globalOp, mlir::acc::DataClause clause,
std::stringstream &asFortran, const std::string &ctorName) {
- createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
- mlir::acc::CreateOp,
- mlir::acc::DeclareEnterOp,
- mlir::acc::DeleteOp>(modBuilder, builder,
- operandLocation, globalOp, clause, ctorName,
- /*implicit=*/false, asFortran);
- std::stringstream dtorName;
- dtorName << globalOp.getSymName().str() << "_acc_dtor";
- createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
- mlir::acc::GetDevicePtrOp,
- mlir::acc::DeclareExitOp,
- mlir::acc::DeleteOp>(modBuilder, builder,
- operandLocation, globalOp, clause, dtorName.str(),
- /*implicit=*/false, asFortran);
+ emitCtorDtorPair<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
+ modBuilder, builder, operandLocation, globalOp, clause,
+ asFortran, ctorName);
});
}
auto crtDataStart = dataClauseOperands.size();
@@ -4437,20 +4449,9 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
[&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
fir::GlobalOp globalOp, mlir::acc::DataClause clause,
std::stringstream &asFortran, const std::string &ctorName) {
- createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
- mlir::acc::CopyinOp,
- mlir::acc::DeclareEnterOp,
- mlir::acc::DeleteOp>(modBuilder, builder,
- operandLocation, globalOp, clause, ctorName,
- /*implicit=*/false, asFortran);
- std::stringstream dtorName;
- dtorName << globalOp.getSymName().str() << "_acc_dtor";
- createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
- mlir::acc::GetDevicePtrOp,
- mlir::acc::DeclareExitOp,
- mlir::acc::DeleteOp>(modBuilder, builder,
- operandLocation, globalOp, clause, dtorName.str(),
- /*implicit=*/false, asFortran);
+ emitCtorDtorPair<mlir::acc::CopyinOp, mlir::acc::DeleteOp>(
+ modBuilder, builder, operandLocation, globalOp, clause,
+ asFortran, ctorName);
});
}
auto crtDataStart = dataClauseOperands.size();
@@ -4474,20 +4475,9 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
[&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
fir::GlobalOp globalOp, mlir::acc::DataClause clause,
std::stringstream &asFortran, const std::string &ctorName) {
- createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
- mlir::acc::CreateOp,
- mlir::acc::DeclareEnterOp,
- mlir::acc::CopyoutOp>(modBuilder, builder,
- operandLocation, globalOp, clause, ctorName,
- /*implicit=*/false, asFortran);
- std::stringstream dtorName;
- dtorName << globalOp.getSymName().str() << "_acc_dtor";
- createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
- mlir::acc::GetDevicePtrOp,
- mlir::acc::DeclareExitOp,
- mlir::acc::CopyoutOp>(modBuilder, builder,
- operandLocation, globalOp, clause, dtorName.str(),
- /*implicit=*/false, asFortran);
+ emitCtorDtorPair<mlir::acc::CreateOp, mlir::acc::CopyoutOp>(
+ modBuilder, builder, operandLocation, globalOp, clause,
+ asFortran, ctorName);
});
}
auto crtDataStart = dataClauseOperands.size();
@@ -4537,12 +4527,9 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
[&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
fir::GlobalOp globalOp, mlir::acc::DataClause clause,
std::stringstream &asFortran, const std::string &ctorName) {
- createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
- mlir::acc::DeclareDeviceResidentOp,
- mlir::acc::DeclareEnterOp,
- mlir::acc::DeleteOp>(modBuilder, builder,
- operandLocation, globalOp, clause, ctorName,
- /*implicit=*/false, asFortran);
+ emitCtorDtorPair<mlir::acc::DeclareDeviceResidentOp,
+ mlir::acc::DeleteOp>(modBuilder, builder,
+ operandLocation, globalOp, clause, asFortran, ctorName);
});
}
auto crtDataStart = dataClauseOperands.size();
>From c76338c64ee5b7c452ffb5eba816ae560511a2b4 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Wed, 15 Oct 2025 18:38:03 -0700
Subject: [PATCH 4/9] add a test
---
flang/lib/Lower/OpenACC.cpp | 9 +++++
.../acc-declare-common-in-function.f90 | 40 +++++++++++++++++++
2 files changed, 49 insertions(+)
create mode 100644 flang/test/Lower/OpenACC/acc-declare-common-in-function.f90
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index e493198fd2b51..f2afc75b7f6b3 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -726,6 +726,10 @@ static void genDeclareDataOperandOperations(
std::stringstream asFortran;
mlir::Location operandLocation = genOperandLocation(converter, accObject);
Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
+ // Skip COMMON/global symbols: handled via global ctor/dtor path in declare.
+ if (symbol.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+ Fortran::semantics::FindCommonBlockContaining(symbol))
+ continue;
Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
[&](auto &&s) { return ea.Analyze(s); }, accObject.u);
fir::factory::AddrAndBoundsInfo info =
@@ -4547,6 +4551,11 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
}
}
+ // If no structured operands were generated (all objects were COMMON),
+ // do not create a declare region.
+ if (dataClauseOperands.empty())
+ return;
+
mlir::func::FuncOp funcOp = builder.getFunction();
auto ops = funcOp.getOps<mlir::acc::DeclareEnterOp>();
mlir::Value declareToken;
diff --git a/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90 b/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90
new file mode 100644
index 0000000000000..bffbe304c7078
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90
@@ -0,0 +1,40 @@
+! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s
+
+! Verify that a COMMON block declared with OpenACC declare inside a function
+! is lowered as a global declare (acc.global_ctor/dtor) rather than a
+! structured declare.
+
+program p
+ implicit none
+ real :: pi
+ integer :: i
+ common /RIEMANN_COM/ pi
+!$acc declare copyin(/RIEMANN_COM/)
+ data pi/0.0/
+
+! CHECK-DAG: acc.global_ctor @{{.*}}_acc_ctor {
+! CHECK-DAG: %[[ADDR0:.*]] = fir.address_of(@{{.*}}) {acc.declare = #acc.declare<dataClause = acc_copyin>} : {{.*}}
+! CHECK-DAG: acc.declare_enter dataOperands(%{{.*}} : {{.*}})
+! CHECK-DAG: acc.terminator
+! CHECK-DAG: }
+
+! CHECK-DAG: acc.global_dtor @{{.*}}_acc_dtor {
+! CHECK-DAG: %[[ADDR1:.*]] = fir.address_of(@{{.*}}) {acc.declare = #acc.declare<dataClause = acc_copyin>} : !fir.ref<tuple<f32>>
+! CHECK-DAG: %[[GDP:.*]] = acc.getdeviceptr varPtr(%[[ADDR1]] : !fir.ref<tuple<f32>>) -> !fir.ref<tuple<f32>> {dataClause = #acc<data_clause acc_copyin>, {{.*}}}
+! CHECK-DAG: acc.declare_exit dataOperands(%[[GDP]] : !fir.ref<tuple<f32>>)
+! CHECK-DAG: acc.delete accPtr(%[[GDP]] : !fir.ref<tuple<f32>>) {dataClause = #acc<data_clause acc_copyin>{{.*}}}
+! CHECK-DAG: acc.terminator
+! CHECK-DAG: }
+
+contains
+
+ subroutine s()
+ implicit none
+ real :: pi
+ common /RIEMANN_COM/ pi
+!$acc declare copyin(/RIEMANN_COM/)
+ end subroutine s
+
+end program p
+
+
>From bd6d4f98943a0f8b1cd4d81a4971f39f2e060920 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Thu, 16 Oct 2025 07:54:42 -0700
Subject: [PATCH 5/9] change test name
---
.../test/Lower/OpenACC/acc-declare-common-in-function.f90 | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90 b/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90
index bffbe304c7078..5038f718517ac 100644
--- a/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90
+++ b/flang/test/Lower/OpenACC/acc-declare-common-in-function.f90
@@ -8,8 +8,8 @@ program p
implicit none
real :: pi
integer :: i
- common /RIEMANN_COM/ pi
-!$acc declare copyin(/RIEMANN_COM/)
+ common /COM/ pi
+!$acc declare copyin(/COM/)
data pi/0.0/
! CHECK-DAG: acc.global_ctor @{{.*}}_acc_ctor {
@@ -31,8 +31,8 @@ program p
subroutine s()
implicit none
real :: pi
- common /RIEMANN_COM/ pi
-!$acc declare copyin(/RIEMANN_COM/)
+ common /COM/ pi
+!$acc declare copyin(/COM/)
end subroutine s
end program p
>From b3f733ca077b05f50e9aeccbd2443dd56173080e Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Fri, 17 Oct 2025 10:34:03 -0700
Subject: [PATCH 6/9] refactor lamda to a standalone function
---
flang/lib/Lower/OpenACC.cpp | 107 +++++++++++++++++++-----------------
1 file changed, 58 insertions(+), 49 deletions(-)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index f2afc75b7f6b3..410d4d3dad18c 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -4342,6 +4342,55 @@ genGlobalCtorsWithModifier(Fortran::lower::AbstractConverter &converter,
dataClause);
}
+// Emit module-level declare for COMMON symbols referenced by an ACC clause.
+// The emitter functor is responsible for creating ctor/dtor operations.
+template <typename EmitterFn>
+static void emitCommonGlobal(Fortran::lower::AbstractConverter &converter,
+ fir::FirOpBuilder &builder, const Fortran::parser::AccObject &obj,
+ mlir::acc::DataClause clause, EmitterFn &&emitCtorDtor) {
+ Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
+ if (!(sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
+ Fortran::semantics::FindCommonBlockContaining(sym))) {
+ return;
+ }
+
+ std::string globalName = converter.mangleName(sym);
+ fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
+ if (!globalOp) {
+ if (Fortran::semantics::FindEquivalenceSet(sym)) {
+ for (Fortran::semantics::EquivalenceObject eqObj :
+ *Fortran::semantics::FindEquivalenceSet(sym)) {
+ std::string eqName = converter.mangleName(eqObj.symbol);
+ globalOp = builder.getNamedGlobal(eqName);
+ if (globalOp)
+ break;
+ }
+ }
+ }
+ if (!globalOp) {
+ llvm::report_fatal_error("could not retrieve global symbol");
+ }
+
+ std::stringstream ctorName;
+ ctorName << globalName << "_acc_ctor";
+ if (builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
+ ctorName.str())) {
+ return;
+ }
+
+ mlir::Location operandLocation = genOperandLocation(converter, obj);
+ addDeclareAttr(builder, globalOp.getOperation(), clause);
+ mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+ modBuilder.setInsertionPointAfter(globalOp);
+ std::stringstream asFortran;
+ asFortran << sym.name().ToString();
+
+ auto savedIP = builder.saveInsertionPoint();
+ emitCtorDtor(modBuilder, operandLocation, globalOp, clause, asFortran,
+ ctorName.str());
+ builder.restoreInsertionPoint(savedIP);
+}
+
static void
genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
Fortran::semantics::SemanticsContext &semanticsContext,
@@ -4354,50 +4403,6 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
Fortran::lower::StatementContext stmtCtx;
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
- // Inline helper to emit module-level declare for COMMON symbols in a clause.
- auto emitCommonGlobal = [&](const Fortran::parser::AccObject &obj,
- mlir::acc::DataClause clause,
- auto emitCtorDtor) {
- Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
- if (!(sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
- Fortran::semantics::FindCommonBlockContaining(sym)))
- return;
-
- std::string globalName = converter.mangleName(sym);
- fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
- if (!globalOp) {
- if (Fortran::semantics::FindEquivalenceSet(sym)) {
- for (Fortran::semantics::EquivalenceObject eqObj :
- *Fortran::semantics::FindEquivalenceSet(sym)) {
- std::string eqName = converter.mangleName(eqObj.symbol);
- globalOp = builder.getNamedGlobal(eqName);
- if (globalOp)
- break;
- }
- }
- }
- if (!globalOp)
- llvm::report_fatal_error("could not retrieve global symbol");
-
- std::stringstream ctorName;
- ctorName << globalName << "_acc_ctor";
- if (builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
- ctorName.str()))
- return;
-
- mlir::Location operandLocation = genOperandLocation(converter, obj);
- addDeclareAttr(builder, globalOp.getOperation(), clause);
- mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
- modBuilder.setInsertionPointAfter(globalOp);
- std::stringstream asFortran;
- asFortran << sym.name().ToString();
-
- auto savedIP = builder.saveInsertionPoint();
- emitCtorDtor(modBuilder, operandLocation, globalOp, clause, asFortran,
- ctorName.str());
- builder.restoreInsertionPoint(savedIP);
- };
-
for (const Fortran::parser::AccClause &clause : accClauseList.v) {
if (const auto *copyClause =
std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
@@ -4416,7 +4421,8 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
const auto &accObjectList =
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
for (const auto &obj : accObjectList.v) {
- emitCommonGlobal(obj, mlir::acc::DataClause::acc_create,
+ emitCommonGlobal(converter, builder, obj,
+ mlir::acc::DataClause::acc_create,
[&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
fir::GlobalOp globalOp, mlir::acc::DataClause clause,
std::stringstream &asFortran, const std::string &ctorName) {
@@ -4449,7 +4455,8 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
const auto ©inObjs =
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
for (const auto &obj : copyinObjs.v) {
- emitCommonGlobal(obj, mlir::acc::DataClause::acc_copyin,
+ emitCommonGlobal(converter, builder, obj,
+ mlir::acc::DataClause::acc_copyin,
[&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
fir::GlobalOp globalOp, mlir::acc::DataClause clause,
std::stringstream &asFortran, const std::string &ctorName) {
@@ -4475,7 +4482,8 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
const auto &accObjectList =
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
for (const auto &obj : accObjectList.v) {
- emitCommonGlobal(obj, mlir::acc::DataClause::acc_copyout,
+ emitCommonGlobal(converter, builder, obj,
+ mlir::acc::DataClause::acc_copyout,
[&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
fir::GlobalOp globalOp, mlir::acc::DataClause clause,
std::stringstream &asFortran, const std::string &ctorName) {
@@ -4504,7 +4512,8 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
const auto &linkObjs = linkClause->v;
for (const auto &obj : linkObjs.v) {
- emitCommonGlobal(obj, mlir::acc::DataClause::acc_declare_link,
+ emitCommonGlobal(converter, builder, obj,
+ mlir::acc::DataClause::acc_declare_link,
[&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
fir::GlobalOp globalOp, mlir::acc::DataClause clause,
std::stringstream &asFortran, const std::string &ctorName) {
@@ -4526,7 +4535,7 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
&clause.u)) {
const auto &devResObjs = deviceResidentClause->v;
for (const auto &obj : devResObjs.v) {
- emitCommonGlobal(obj,
+ emitCommonGlobal(converter, builder, obj,
mlir::acc::DataClause::acc_declare_device_resident,
[&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
fir::GlobalOp globalOp, mlir::acc::DataClause clause,
>From 725382f7bd8162cda83485ba1d211bca4e10240e Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Fri, 17 Oct 2025 10:55:23 -0700
Subject: [PATCH 7/9] get name using the common block name
---
flang/lib/Lower/OpenACC.cpp | 42 +++++++++++++++++++++++--------------
1 file changed, 26 insertions(+), 16 deletions(-)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 410d4d3dad18c..00cfa6a3dadd2 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -4342,8 +4342,30 @@ genGlobalCtorsWithModifier(Fortran::lower::AbstractConverter &converter,
dataClause);
}
-// Emit module-level declare for COMMON symbols referenced by an ACC clause.
-// The emitter functor is responsible for creating ctor/dtor operations.
+static fir::GlobalOp lookupGlobalBySymbolOrEquivalence(
+ Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder,
+ const Fortran::semantics::Symbol &sym) {
+ const Fortran::semantics::Symbol *commonBlock =
+ Fortran::semantics::FindCommonBlockContaining(sym);
+ std::string globalName = commonBlock ? converter.mangleName(*commonBlock)
+ : converter.mangleName(sym);
+ if (fir::GlobalOp g = builder.getNamedGlobal(globalName)) {
+ return g;
+ }
+ // Not found: if not a COMMON member, try equivalence members
+ if (!commonBlock) {
+ if (auto *eqSet = Fortran::semantics::FindEquivalenceSet(sym)) {
+ for (Fortran::semantics::EquivalenceObject eqObj : *eqSet) {
+ std::string eqName = converter.mangleName(eqObj.symbol);
+ if (fir::GlobalOp g = builder.getNamedGlobal(eqName)) {
+ return g;
+ }
+ }
+ }
+ }
+ return {};
+}
+
template <typename EmitterFn>
static void emitCommonGlobal(Fortran::lower::AbstractConverter &converter,
fir::FirOpBuilder &builder, const Fortran::parser::AccObject &obj,
@@ -4354,25 +4376,13 @@ static void emitCommonGlobal(Fortran::lower::AbstractConverter &converter,
return;
}
- std::string globalName = converter.mangleName(sym);
- fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
- if (!globalOp) {
- if (Fortran::semantics::FindEquivalenceSet(sym)) {
- for (Fortran::semantics::EquivalenceObject eqObj :
- *Fortran::semantics::FindEquivalenceSet(sym)) {
- std::string eqName = converter.mangleName(eqObj.symbol);
- globalOp = builder.getNamedGlobal(eqName);
- if (globalOp)
- break;
- }
- }
- }
+ fir::GlobalOp globalOp = lookupGlobalBySymbolOrEquivalence(converter, builder, sym);
if (!globalOp) {
llvm::report_fatal_error("could not retrieve global symbol");
}
std::stringstream ctorName;
- ctorName << globalName << "_acc_ctor";
+ ctorName << globalOp.getSymName().str() << "_acc_ctor";
if (builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
ctorName.str())) {
return;
>From 4f8b2dc2eb663041f8701f446ce827b6c53e21ad Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Fri, 17 Oct 2025 11:33:10 -0700
Subject: [PATCH 8/9] directly implement in genDeclareDataOperandOperations
---
flang/lib/Lower/OpenACC.cpp | 263 +++++++++++++++---------------------
1 file changed, 110 insertions(+), 153 deletions(-)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 00cfa6a3dadd2..d5ce1618a7607 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -711,6 +711,84 @@ static void genDataOperandOperations(
}
}
+template <typename GlobalOp, typename EntryOp, typename DeclareOp,
+ typename ExitOp>
+static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
+ fir::FirOpBuilder &builder,
+ mlir::Location loc, fir::GlobalOp globalOp,
+ mlir::acc::DataClause clause,
+ const std::string &declareGlobalName,
+ bool implicit, std::stringstream &asFortran) {
+ GlobalOp declareGlobalOp =
+ GlobalOp::create(modBuilder, loc, declareGlobalName);
+ builder.createBlock(&declareGlobalOp.getRegion(),
+ declareGlobalOp.getRegion().end(), {}, {});
+ builder.setInsertionPointToEnd(&declareGlobalOp.getRegion().back());
+
+ fir::AddrOfOp addrOp = fir::AddrOfOp::create(
+ builder, loc, fir::ReferenceType::get(globalOp.getType()),
+ globalOp.getSymbol());
+ addDeclareAttr(builder, addrOp, clause);
+
+ llvm::SmallVector<mlir::Value> bounds;
+ EntryOp entryOp = createDataEntryOp<EntryOp>(
+ builder, loc, addrOp.getResTy(), asFortran, bounds,
+ /*structured=*/false, implicit, clause, addrOp.getResTy().getType(),
+ /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
+ if constexpr (std::is_same_v<DeclareOp, mlir::acc::DeclareEnterOp>)
+ DeclareOp::create(builder, loc,
+ mlir::acc::DeclareTokenType::get(entryOp.getContext()),
+ mlir::ValueRange(entryOp.getAccVar()));
+ else
+ DeclareOp::create(builder, loc, mlir::Value{},
+ mlir::ValueRange(entryOp.getAccVar()));
+ if constexpr (std::is_same_v<GlobalOp, mlir::acc::GlobalDestructorOp>) {
+ if constexpr (std::is_same_v<ExitOp, mlir::acc::DeclareLinkOp>) {
+ // No destructor emission for declare link in this path to avoid
+ // complex var/varType/varPtrPtr signatures. The ctor registers the link.
+ } else if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
+ std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>) {
+ ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
+ entryOp.getVar(), entryOp.getVarType(),
+ entryOp.getBounds(), entryOp.getAsyncOperands(),
+ entryOp.getAsyncOperandsDeviceTypeAttr(),
+ entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
+ /*structured=*/false, /*implicit=*/false,
+ builder.getStringAttr(*entryOp.getName()));
+ } else {
+ ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
+ entryOp.getBounds(), entryOp.getAsyncOperands(),
+ entryOp.getAsyncOperandsDeviceTypeAttr(),
+ entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
+ /*structured=*/false, /*implicit=*/false,
+ builder.getStringAttr(*entryOp.getName()));
+ }
+ }
+ mlir::acc::TerminatorOp::create(builder, loc);
+ modBuilder.setInsertionPointAfter(declareGlobalOp);
+}
+
+template <typename EntryOp, typename ExitOp>
+static void emitCtorDtorPair(mlir::OpBuilder &modBuilder,
+ fir::FirOpBuilder &builder,
+ mlir::Location operandLocation,
+ fir::GlobalOp globalOp,
+ mlir::acc::DataClause clause,
+ std::stringstream &asFortran,
+ const std::string &ctorName) {
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
+ mlir::acc::DeclareEnterOp, ExitOp>(
+ modBuilder, builder, operandLocation, globalOp, clause, ctorName,
+ /*implicit=*/false, asFortran);
+
+ std::stringstream dtorName;
+ dtorName << globalOp.getSymName().str() << "_acc_dtor";
+ createDeclareGlobalOp<mlir::acc::GlobalDestructorOp, mlir::acc::GetDevicePtrOp,
+ mlir::acc::DeclareExitOp, ExitOp>(
+ modBuilder, builder, operandLocation, globalOp, clause, dtorName.str(),
+ /*implicit=*/false, asFortran);
+}
+
template <typename EntryOp, typename ExitOp>
static void genDeclareDataOperandOperations(
const Fortran::parser::AccObjectList &objectList,
@@ -726,10 +804,36 @@ static void genDeclareDataOperandOperations(
std::stringstream asFortran;
mlir::Location operandLocation = genOperandLocation(converter, accObject);
Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
- // Skip COMMON/global symbols: handled via global ctor/dtor path in declare.
+ // Handle COMMON/global symbols via module-level ctor/dtor path.
if (symbol.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
- Fortran::semantics::FindCommonBlockContaining(symbol))
+ Fortran::semantics::FindCommonBlockContaining(symbol)) {
+ emitCommonGlobal(converter, builder, accObject, dataClause,
+ [&](mlir::OpBuilder &modBuilder, mlir::Location loc,
+ fir::GlobalOp globalOp, mlir::acc::DataClause clause,
+ std::stringstream &asFortranStr, const std::string &ctorName) {
+ if constexpr (std::is_same_v<EntryOp, mlir::acc::DeclareLinkOp>) {
+ createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
+ mlir::acc::DeclareLinkOp,
+ mlir::acc::DeclareEnterOp,
+ mlir::acc::DeclareLinkOp>(modBuilder,
+ builder, loc, globalOp, clause, ctorName,
+ /*implicit=*/false, asFortranStr);
+ } else if constexpr (
+ std::is_same_v<EntryOp, mlir::acc::CreateOp> ||
+ std::is_same_v<EntryOp, mlir::acc::CopyinOp> ||
+ std::is_same_v<EntryOp, mlir::acc::DeclareDeviceResidentOp> ||
+ std::is_same_v<ExitOp, mlir::acc::CopyoutOp>) {
+ emitCtorDtorPair<EntryOp, ExitOp>(
+ modBuilder, builder, loc, globalOp, clause, asFortranStr,
+ ctorName);
+ } else {
+ // No module-level ctor/dtor for this clause (e.g., deviceptr,
+ // present). Handled via structured declare region only.
+ return;
+ }
+ });
continue;
+ }
Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
[&](auto &&s) { return ea.Analyze(s); }, accObject.u);
fir::factory::AddrAndBoundsInfo info =
@@ -4085,86 +4189,6 @@ static void genACC(Fortran::lower::AbstractConverter &converter,
waitOp.setAsyncAttr(firOpBuilder.getUnitAttr());
}
-template <typename GlobalOp, typename EntryOp, typename DeclareOp,
- typename ExitOp>
-static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
- fir::FirOpBuilder &builder,
- mlir::Location loc, fir::GlobalOp globalOp,
- mlir::acc::DataClause clause,
- const std::string &declareGlobalName,
- bool implicit, std::stringstream &asFortran) {
- GlobalOp declareGlobalOp =
- GlobalOp::create(modBuilder, loc, declareGlobalName);
- builder.createBlock(&declareGlobalOp.getRegion(),
- declareGlobalOp.getRegion().end(), {}, {});
- builder.setInsertionPointToEnd(&declareGlobalOp.getRegion().back());
-
- fir::AddrOfOp addrOp = fir::AddrOfOp::create(
- builder, loc, fir::ReferenceType::get(globalOp.getType()),
- globalOp.getSymbol());
- addDeclareAttr(builder, addrOp, clause);
-
- llvm::SmallVector<mlir::Value> bounds;
- EntryOp entryOp = createDataEntryOp<EntryOp>(
- builder, loc, addrOp.getResTy(), asFortran, bounds,
- /*structured=*/false, implicit, clause, addrOp.getResTy().getType(),
- /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
- if constexpr (std::is_same_v<DeclareOp, mlir::acc::DeclareEnterOp>)
- DeclareOp::create(builder, loc,
- mlir::acc::DeclareTokenType::get(entryOp.getContext()),
- mlir::ValueRange(entryOp.getAccVar()));
- else
- DeclareOp::create(builder, loc, mlir::Value{},
- mlir::ValueRange(entryOp.getAccVar()));
- if constexpr (std::is_same_v<GlobalOp, mlir::acc::GlobalDestructorOp>) {
- if constexpr (std::is_same_v<ExitOp, mlir::acc::DeclareLinkOp>) {
- // No destructor emission for declare link in this path to avoid
- // complex var/varType/varPtrPtr signatures. The ctor registers the link.
- } else if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
- std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>) {
- ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
- entryOp.getVar(), entryOp.getVarType(),
- entryOp.getBounds(), entryOp.getAsyncOperands(),
- entryOp.getAsyncOperandsDeviceTypeAttr(),
- entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
- /*structured=*/false, /*implicit=*/false,
- builder.getStringAttr(*entryOp.getName()));
- } else {
- ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
- entryOp.getBounds(), entryOp.getAsyncOperands(),
- entryOp.getAsyncOperandsDeviceTypeAttr(),
- entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
- /*structured=*/false, /*implicit=*/false,
- builder.getStringAttr(*entryOp.getName()));
- }
- }
- mlir::acc::TerminatorOp::create(builder, loc);
- modBuilder.setInsertionPointAfter(declareGlobalOp);
-}
-
-// Small helper to emit a constructor/destructor pair for a given global
-// declare Entry/Exit Op combination.
-template <typename EntryOp, typename ExitOp>
-static void emitCtorDtorPair(mlir::OpBuilder &modBuilder,
- fir::FirOpBuilder &builder,
- mlir::Location operandLocation,
- fir::GlobalOp globalOp,
- mlir::acc::DataClause clause,
- std::stringstream &asFortran,
- const std::string &ctorName) {
- createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
- mlir::acc::DeclareEnterOp, ExitOp>(
- modBuilder, builder, operandLocation, globalOp, clause, ctorName,
- /*implicit=*/false, asFortran);
-
- std::stringstream dtorName;
- dtorName << globalOp.getSymName().str() << "_acc_dtor";
- createDeclareGlobalOp<mlir::acc::GlobalDestructorOp, mlir::acc::GetDevicePtrOp,
- mlir::acc::DeclareExitOp, ExitOp>(
- modBuilder, builder, operandLocation, globalOp, clause, dtorName.str(),
- /*implicit=*/false, asFortran);
-}
-
template <typename EntryOp>
static void createDeclareAllocFunc(mlir::OpBuilder &modBuilder,
fir::FirOpBuilder &builder,
@@ -4426,22 +4450,9 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
dataClauseOperands.end());
} else if (const auto *createClause =
std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
- const Fortran::parser::AccObjectListWithModifier &listWithModifier =
- createClause->v;
- const auto &accObjectList =
- std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
- for (const auto &obj : accObjectList.v) {
- emitCommonGlobal(converter, builder, obj,
- mlir::acc::DataClause::acc_create,
- [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
- fir::GlobalOp globalOp, mlir::acc::DataClause clause,
- std::stringstream &asFortran, const std::string &ctorName) {
- emitCtorDtorPair<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
- modBuilder, builder, operandLocation, globalOp, clause,
- asFortran, ctorName);
- });
- }
auto crtDataStart = dataClauseOperands.size();
+ const auto &accObjectList =
+ std::get<Fortran::parser::AccObjectList>(createClause->v.t);
genDeclareDataOperandOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
accObjectList, converter, semanticsContext, stmtCtx,
dataClauseOperands, mlir::acc::DataClause::acc_create,
@@ -4461,20 +4472,6 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
dataClauseOperands.end());
} else if (const auto *copyinClause =
std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
- const auto &listWithModifier = copyinClause->v;
- const auto ©inObjs =
- std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
- for (const auto &obj : copyinObjs.v) {
- emitCommonGlobal(converter, builder, obj,
- mlir::acc::DataClause::acc_copyin,
- [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
- fir::GlobalOp globalOp, mlir::acc::DataClause clause,
- std::stringstream &asFortran, const std::string &ctorName) {
- emitCtorDtorPair<mlir::acc::CopyinOp, mlir::acc::DeleteOp>(
- modBuilder, builder, operandLocation, globalOp, clause,
- asFortran, ctorName);
- });
- }
auto crtDataStart = dataClauseOperands.size();
genDeclareDataOperandOperationsWithModifier<mlir::acc::CopyinOp,
mlir::acc::DeleteOp>(
@@ -4487,22 +4484,9 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
} else if (const auto *copyoutClause =
std::get_if<Fortran::parser::AccClause::Copyout>(
&clause.u)) {
- const Fortran::parser::AccObjectListWithModifier &listWithModifier =
- copyoutClause->v;
- const auto &accObjectList =
- std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
- for (const auto &obj : accObjectList.v) {
- emitCommonGlobal(converter, builder, obj,
- mlir::acc::DataClause::acc_copyout,
- [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
- fir::GlobalOp globalOp, mlir::acc::DataClause clause,
- std::stringstream &asFortran, const std::string &ctorName) {
- emitCtorDtorPair<mlir::acc::CreateOp, mlir::acc::CopyoutOp>(
- modBuilder, builder, operandLocation, globalOp, clause,
- asFortran, ctorName);
- });
- }
auto crtDataStart = dataClauseOperands.size();
+ const auto &accObjectList =
+ std::get<Fortran::parser::AccObjectList>(copyoutClause->v.t);
genDeclareDataOperandOperations<mlir::acc::CreateOp,
mlir::acc::CopyoutOp>(
accObjectList, converter, semanticsContext, stmtCtx,
@@ -4520,21 +4504,6 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
/*structured=*/true, /*implicit=*/false);
} else if (const auto *linkClause =
std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
- const auto &linkObjs = linkClause->v;
- for (const auto &obj : linkObjs.v) {
- emitCommonGlobal(converter, builder, obj,
- mlir::acc::DataClause::acc_declare_link,
- [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
- fir::GlobalOp globalOp, mlir::acc::DataClause clause,
- std::stringstream &asFortran, const std::string &ctorName) {
- createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
- mlir::acc::DeclareLinkOp,
- mlir::acc::DeclareEnterOp,
- mlir::acc::DeclareLinkOp>(modBuilder,
- builder, operandLocation, globalOp, clause, ctorName,
- /*implicit=*/false, asFortran);
- });
- }
genDeclareDataOperandOperations<mlir::acc::DeclareLinkOp,
mlir::acc::DeclareLinkOp>(
linkClause->v, converter, semanticsContext, stmtCtx,
@@ -4543,18 +4512,6 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
} else if (const auto *deviceResidentClause =
std::get_if<Fortran::parser::AccClause::DeviceResident>(
&clause.u)) {
- const auto &devResObjs = deviceResidentClause->v;
- for (const auto &obj : devResObjs.v) {
- emitCommonGlobal(converter, builder, obj,
- mlir::acc::DataClause::acc_declare_device_resident,
- [&](mlir::OpBuilder &modBuilder, mlir::Location operandLocation,
- fir::GlobalOp globalOp, mlir::acc::DataClause clause,
- std::stringstream &asFortran, const std::string &ctorName) {
- emitCtorDtorPair<mlir::acc::DeclareDeviceResidentOp,
- mlir::acc::DeleteOp>(modBuilder, builder,
- operandLocation, globalOp, clause, asFortran, ctorName);
- });
- }
auto crtDataStart = dataClauseOperands.size();
genDeclareDataOperandOperations<mlir::acc::DeclareDeviceResidentOp,
mlir::acc::DeleteOp>(
>From d39629b432363b6829445d137da4c2811d5b4afb Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Fri, 17 Oct 2025 11:35:00 -0700
Subject: [PATCH 9/9] format
---
flang/lib/Lower/OpenACC.cpp | 69 +++++++++++++++++++------------------
1 file changed, 36 insertions(+), 33 deletions(-)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index d5ce1618a7607..5bcfb6c9e6bc8 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -769,13 +769,11 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
}
template <typename EntryOp, typename ExitOp>
-static void emitCtorDtorPair(mlir::OpBuilder &modBuilder,
- fir::FirOpBuilder &builder,
- mlir::Location operandLocation,
- fir::GlobalOp globalOp,
- mlir::acc::DataClause clause,
- std::stringstream &asFortran,
- const std::string &ctorName) {
+static void
+emitCtorDtorPair(mlir::OpBuilder &modBuilder, fir::FirOpBuilder &builder,
+ mlir::Location operandLocation, fir::GlobalOp globalOp,
+ mlir::acc::DataClause clause, std::stringstream &asFortran,
+ const std::string &ctorName) {
createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
mlir::acc::DeclareEnterOp, ExitOp>(
modBuilder, builder, operandLocation, globalOp, clause, ctorName,
@@ -783,10 +781,11 @@ static void emitCtorDtorPair(mlir::OpBuilder &modBuilder,
std::stringstream dtorName;
dtorName << globalOp.getSymName().str() << "_acc_dtor";
- createDeclareGlobalOp<mlir::acc::GlobalDestructorOp, mlir::acc::GetDevicePtrOp,
- mlir::acc::DeclareExitOp, ExitOp>(
- modBuilder, builder, operandLocation, globalOp, clause, dtorName.str(),
- /*implicit=*/false, asFortran);
+ createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
+ mlir::acc::GetDevicePtrOp, mlir::acc::DeclareExitOp,
+ ExitOp>(modBuilder, builder, operandLocation, globalOp,
+ clause, dtorName.str(),
+ /*implicit=*/false, asFortran);
}
template <typename EntryOp, typename ExitOp>
@@ -807,25 +806,26 @@ static void genDeclareDataOperandOperations(
// Handle COMMON/global symbols via module-level ctor/dtor path.
if (symbol.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
Fortran::semantics::FindCommonBlockContaining(symbol)) {
- emitCommonGlobal(converter, builder, accObject, dataClause,
+ emitCommonGlobal(
+ converter, builder, accObject, dataClause,
[&](mlir::OpBuilder &modBuilder, mlir::Location loc,
fir::GlobalOp globalOp, mlir::acc::DataClause clause,
std::stringstream &asFortranStr, const std::string &ctorName) {
if constexpr (std::is_same_v<EntryOp, mlir::acc::DeclareLinkOp>) {
- createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
- mlir::acc::DeclareLinkOp,
- mlir::acc::DeclareEnterOp,
- mlir::acc::DeclareLinkOp>(modBuilder,
- builder, loc, globalOp, clause, ctorName,
+ createDeclareGlobalOp<
+ mlir::acc::GlobalConstructorOp, mlir::acc::DeclareLinkOp,
+ mlir::acc::DeclareEnterOp, mlir::acc::DeclareLinkOp>(
+ modBuilder, builder, loc, globalOp, clause, ctorName,
/*implicit=*/false, asFortranStr);
- } else if constexpr (
- std::is_same_v<EntryOp, mlir::acc::CreateOp> ||
- std::is_same_v<EntryOp, mlir::acc::CopyinOp> ||
- std::is_same_v<EntryOp, mlir::acc::DeclareDeviceResidentOp> ||
- std::is_same_v<ExitOp, mlir::acc::CopyoutOp>) {
- emitCtorDtorPair<EntryOp, ExitOp>(
- modBuilder, builder, loc, globalOp, clause, asFortranStr,
- ctorName);
+ } else if constexpr (std::is_same_v<EntryOp, mlir::acc::CreateOp> ||
+ std::is_same_v<EntryOp, mlir::acc::CopyinOp> ||
+ std::is_same_v<
+ EntryOp,
+ mlir::acc::DeclareDeviceResidentOp> ||
+ std::is_same_v<ExitOp, mlir::acc::CopyoutOp>) {
+ emitCtorDtorPair<EntryOp, ExitOp>(modBuilder, builder, loc,
+ globalOp, clause, asFortranStr,
+ ctorName);
} else {
// No module-level ctor/dtor for this clause (e.g., deviceptr,
// present). Handled via structured declare region only.
@@ -3506,7 +3506,6 @@ genACCHostDataOp(Fortran::lower::AbstractConverter &converter,
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
-
for (const Fortran::parser::AccClause &clause : accClauseList.v) {
mlir::Location clauseLocation = converter.genLocation(clause.source);
if (const auto *ifClause =
@@ -4366,9 +4365,10 @@ genGlobalCtorsWithModifier(Fortran::lower::AbstractConverter &converter,
dataClause);
}
-static fir::GlobalOp lookupGlobalBySymbolOrEquivalence(
- Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder,
- const Fortran::semantics::Symbol &sym) {
+static fir::GlobalOp
+lookupGlobalBySymbolOrEquivalence(Fortran::lower::AbstractConverter &converter,
+ fir::FirOpBuilder &builder,
+ const Fortran::semantics::Symbol &sym) {
const Fortran::semantics::Symbol *commonBlock =
Fortran::semantics::FindCommonBlockContaining(sym);
std::string globalName = commonBlock ? converter.mangleName(*commonBlock)
@@ -4392,15 +4392,18 @@ static fir::GlobalOp lookupGlobalBySymbolOrEquivalence(
template <typename EmitterFn>
static void emitCommonGlobal(Fortran::lower::AbstractConverter &converter,
- fir::FirOpBuilder &builder, const Fortran::parser::AccObject &obj,
- mlir::acc::DataClause clause, EmitterFn &&emitCtorDtor) {
+ fir::FirOpBuilder &builder,
+ const Fortran::parser::AccObject &obj,
+ mlir::acc::DataClause clause,
+ EmitterFn &&emitCtorDtor) {
Fortran::semantics::Symbol &sym = getSymbolFromAccObject(obj);
if (!(sym.detailsIf<Fortran::semantics::CommonBlockDetails>() ||
Fortran::semantics::FindCommonBlockContaining(sym))) {
return;
}
- fir::GlobalOp globalOp = lookupGlobalBySymbolOrEquivalence(converter, builder, sym);
+ fir::GlobalOp globalOp =
+ lookupGlobalBySymbolOrEquivalence(converter, builder, sym);
if (!globalOp) {
llvm::report_fatal_error("could not retrieve global symbol");
}
@@ -4421,7 +4424,7 @@ static void emitCommonGlobal(Fortran::lower::AbstractConverter &converter,
auto savedIP = builder.saveInsertionPoint();
emitCtorDtor(modBuilder, operandLocation, globalOp, clause, asFortran,
- ctorName.str());
+ ctorName.str());
builder.restoreInsertionPoint(savedIP);
}
More information about the flang-commits
mailing list