Skip to content

[flang][acc] Generate constructors and destructors for common blocks #137691

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 71 additions & 67 deletions flang/lib/Lower/OpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3754,6 +3754,66 @@ static void genGlobalCtors(Fortran::lower::AbstractConverter &converter,
const Fortran::parser::AccObjectList &accObjectList,
mlir::acc::DataClause clause) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
auto genCtors = [&](const mlir::Location operandLocation,
const Fortran::semantics::Symbol &symbol) {
std::string globalName = converter.mangleName(symbol);
fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
std::stringstream declareGlobalCtorName;
declareGlobalCtorName << globalName << "_acc_ctor";
std::stringstream declareGlobalDtorName;
declareGlobalDtorName << globalName << "_acc_dtor";
std::stringstream asFortran;
asFortran << symbol.name().ToString();

if (builder.getModule().lookupSymbol<mlir::acc::GlobalConstructorOp>(
declareGlobalCtorName.str()))
return;

if (!globalOp) {
if (Fortran::semantics::FindEquivalenceSet(symbol)) {
for (Fortran::semantics::EquivalenceObject eqObj :
*Fortran::semantics::FindEquivalenceSet(symbol)) {
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");
} else {
llvm::report_fatal_error("could not retrieve global symbol");
}
}

addDeclareAttr(builder, globalOp.getOperation(), clause);
auto crtPos = builder.saveInsertionPoint();
modBuilder.setInsertionPointAfter(globalOp);
if (mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(globalOp.getType()))) {
createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, mlir::acc::CopyinOp,
mlir::acc::DeclareEnterOp, ExitOp>(
modBuilder, builder, operandLocation, globalOp, clause,
declareGlobalCtorName.str(), /*implicit=*/true, asFortran);
createDeclareAllocFunc<EntryOp>(modBuilder, builder, operandLocation,
globalOp, clause);
if constexpr (!std::is_same_v<EntryOp, ExitOp>)
createDeclareDeallocFunc<ExitOp>(modBuilder, builder, operandLocation,
globalOp, clause);
} else {
createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
mlir::acc::DeclareEnterOp, ExitOp>(
modBuilder, builder, operandLocation, globalOp, clause,
declareGlobalCtorName.str(), /*implicit=*/false, asFortran);
}
if constexpr (!std::is_same_v<EntryOp, ExitOp>) {
createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
mlir::acc::GetDevicePtrOp, mlir::acc::DeclareExitOp,
ExitOp>(
modBuilder, builder, operandLocation, globalOp, clause,
declareGlobalDtorName.str(), /*implicit=*/false, asFortran);
}
builder.restoreInsertionPoint(crtPos);
};
for (const auto &accObject : accObjectList.v) {
mlir::Location operandLocation = genOperandLocation(converter, accObject);
Fortran::common::visit(
Expand All @@ -3762,76 +3822,20 @@ static void genGlobalCtors(Fortran::lower::AbstractConverter &converter,
if (const auto *name =
Fortran::semantics::getDesignatorNameIfDataRef(
designator)) {
std::string globalName = converter.mangleName(*name->symbol);
fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
std::stringstream declareGlobalCtorName;
declareGlobalCtorName << globalName << "_acc_ctor";
std::stringstream declareGlobalDtorName;
declareGlobalDtorName << globalName << "_acc_dtor";
std::stringstream asFortran;
asFortran << name->symbol->name().ToString();

if (builder.getModule()
.lookupSymbol<mlir::acc::GlobalConstructorOp>(
declareGlobalCtorName.str()))
return;

if (!globalOp) {
if (Fortran::semantics::FindEquivalenceSet(*name->symbol)) {
for (Fortran::semantics::EquivalenceObject eqObj :
*Fortran::semantics::FindEquivalenceSet(
*name->symbol)) {
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");
} else {
llvm::report_fatal_error(
"could not retrieve global symbol");
}
}

addDeclareAttr(builder, globalOp.getOperation(), clause);
auto crtPos = builder.saveInsertionPoint();
modBuilder.setInsertionPointAfter(globalOp);
if (mlir::isa<fir::BaseBoxType>(
fir::unwrapRefType(globalOp.getType()))) {
createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
mlir::acc::CopyinOp,
mlir::acc::DeclareEnterOp, ExitOp>(
modBuilder, builder, operandLocation, globalOp, clause,
declareGlobalCtorName.str(), /*implicit=*/true,
asFortran);
createDeclareAllocFunc<EntryOp>(
modBuilder, builder, operandLocation, globalOp, clause);
if constexpr (!std::is_same_v<EntryOp, ExitOp>)
createDeclareDeallocFunc<ExitOp>(
modBuilder, builder, operandLocation, globalOp, clause);
} else {
createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
mlir::acc::DeclareEnterOp, ExitOp>(
modBuilder, builder, operandLocation, globalOp, clause,
declareGlobalCtorName.str(), /*implicit=*/false,
asFortran);
}
if constexpr (!std::is_same_v<EntryOp, ExitOp>) {
createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
mlir::acc::GetDevicePtrOp,
mlir::acc::DeclareExitOp, ExitOp>(
modBuilder, builder, operandLocation, globalOp, clause,
declareGlobalDtorName.str(), /*implicit=*/false,
asFortran);
}
builder.restoreInsertionPoint(crtPos);
genCtors(operandLocation, *name->symbol);
}
},
[&](const Fortran::parser::Name &name) {
TODO(operandLocation, "OpenACC Global Ctor from parser::Name");
if (const auto *symbol = name.symbol) {
if (const auto *commonBlockDetails =
symbol->detailsIf<
Fortran::semantics::CommonBlockDetails>()) {
genCtors(operandLocation, *symbol);
} else {
TODO(operandLocation,
"OpenACC Global Ctor from parser::Name");
}
}
}},
accObject.u);
}
Expand Down
33 changes: 33 additions & 0 deletions flang/test/Lower/OpenACC/acc-declare-globals.f90
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,39 @@

! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s

module acc_declare_common_test
! CHECK-LABEL: fir.global @numbers_ {acc.declare = #acc.declare<dataClause = acc_declare_device_resident>, alignment = 4 : i64} : tuple<f32, f32> {
! CHECK: acc.global_ctor @numbers__acc_ctor
! CHECK: acc.global_dtor @numbers__acc_dtor
REAL :: one = 1
REAL :: two = 2
COMMON /numbers/ one, two
!$acc declare device_resident(/numbers/)

! CHECK-LABEL: fir.global @numbers_create_ {acc.declare = #acc.declare<dataClause = acc_create>, alignment = 4 : i64} : tuple<f32, f32> {
! CHECK: acc.global_ctor @numbers_create__acc_ctor
! CHECK: acc.global_dtor @numbers_create__acc_dtor
REAL :: one_create = 1
REAL :: two_create = 2
COMMON /numbers_create/ one_create, two_create
!$acc declare create(/numbers_create/)

! CHECK-LABEL: fir.global @numbers_in_ {acc.declare = #acc.declare<dataClause = acc_copyin>, alignment = 4 : i64} : tuple<f32, f32> {
! CHECK: acc.global_ctor @numbers_in__acc_ctor
! CHECK: acc.global_dtor @numbers_in__acc_dtor
REAL :: one_in = 1
REAL :: two_in = 2
COMMON /numbers_in/ one_in, two_in
!$acc declare copyin(/numbers_in/)

! CHECK-LABEL: fir.global @numbers_link_ {acc.declare = #acc.declare<dataClause = acc_declare_link>, alignment = 4 : i64} : tuple<f32, f32> {
! CHECK: acc.global_ctor @numbers_link__acc_ctor
REAL :: one_link = 1
REAL :: two_link = 2
COMMON /numbers_link/ one_link, two_link
!$acc declare link(/numbers_link/)
end module

module acc_declare_test
integer, parameter :: n = 100000
real, dimension(n) :: data1
Expand Down