diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -2291,6 +2291,48 @@ builder.getContext(), clause))); } +template +static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder, + fir::FirOpBuilder &builder, + mlir::Location loc, fir::GlobalOp &globalOp, + mlir::acc::DataClause clause) { + std::stringstream declareGlobalName; + + if constexpr (std::is_same_v) + declareGlobalName << globalOp.getSymName().str() << "_acc_ctor"; + else if constexpr (std::is_same_v) + declareGlobalName << globalOp.getSymName().str() << "_acc_dtor"; + + GlobalOp declareGlobalOp = + modBuilder.create(loc, declareGlobalName.str()); + builder.createBlock(&declareGlobalOp.getRegion(), + declareGlobalOp.getRegion().end(), {}, {}); + builder.setInsertionPointToEnd(&declareGlobalOp.getRegion().back()); + + fir::AddrOfOp addrOp = builder.create( + loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol()); + addDeclareAttr(builder, addrOp.getOperation(), clause); + + std::stringstream asFortran; + asFortran << Fortran::lower::mangle::demangleName(globalOp.getSymName()); + llvm::SmallVector bounds; + EntryOp entryOp = createDataEntryOp(builder, loc, addrOp.getResTy(), + asFortran, bounds, true, clause, + addrOp.getResTy().getType()); + builder.create(loc, mlir::ValueRange(entryOp.getAccPtr())); + mlir::Value varPtr; + if constexpr (std::is_same_v) { + builder.create(entryOp.getLoc(), entryOp.getAccPtr(), varPtr, + entryOp.getBounds(), entryOp.getDataClause(), + /*structured=*/false, /*implicit=*/false, + builder.getStringAttr(*entryOp.getName())); + } + builder.create(loc); + modBuilder.setInsertionPointAfter(declareGlobalOp); +} + +template static void genGlobalCtors(Fortran::lower::AbstractConverter &converter, mlir::OpBuilder &modBuilder, const Fortran::parser::AccObjectList &accObjectList, @@ -2308,39 +2350,17 @@ fir::GlobalOp globalOp = builder.getNamedGlobal(globalName); if (!globalOp) llvm::report_fatal_error("could not retrieve global symbol"); - - // Create the new global constructor op after the FIR global. - std::stringstream globalCtorName; - globalCtorName << globalName << "_acc_ctor"; - auto crtPos = builder.saveInsertionPoint(); addDeclareAttr(builder, globalOp.getOperation(), clause); + auto crtPos = builder.saveInsertionPoint(); modBuilder.setInsertionPointAfter(globalOp); - auto globalCtor = - modBuilder.create( - operandLocation, globalCtorName.str()); - builder.createBlock(&globalCtor.getRegion(), - globalCtor.getRegion().end(), {}, {}); - builder.setInsertionPointToEnd(&globalCtor.getRegion().back()); - - // Fill up the global constructor region. - fir::AddrOfOp addrOp = builder.create( - operandLocation, - fir::ReferenceType::get(globalOp.getType()), - globalOp.getSymbol()); - addDeclareAttr(builder, addrOp.getOperation(), clause); - std::stringstream asFortran; - asFortran << Fortran::lower::mangle::demangleName(globalName); - llvm::SmallVector bounds; - mlir::acc::CreateOp entry = - createDataEntryOp( - builder, operandLocation, addrOp.getResTy(), asFortran, - bounds, true, clause, addrOp.getResTy().getType()); - builder.create( - operandLocation, mlir::ValueRange{entry.getAccPtr()}); - builder.create(operandLocation); + createDeclareGlobalOp( + modBuilder, builder, operandLocation, globalOp, clause); + createDeclareGlobalOp( + modBuilder, builder, operandLocation, globalOp, clause); builder.restoreInsertionPoint(crtPos); - - // TODO: global destructor. } }, [&](const Fortran::parser::Name &name) { @@ -2350,7 +2370,7 @@ } } -template +template static void genGlobalCtorsWithModifier(Fortran::lower::AbstractConverter &converter, mlir::OpBuilder &modBuilder, const Clause *x, @@ -2365,7 +2385,8 @@ listWithModifier.t); mlir::acc::DataClause dataClause = (modifier && (*modifier).v == mod) ? clauseWithModifier : clause; - genGlobalCtors(converter, modBuilder, accObjectList, dataClause); + genGlobalCtors(converter, modBuilder, accObjectList, + dataClause); } static void genACC(Fortran::lower::AbstractConverter &converter, @@ -2396,7 +2417,8 @@ mlir::Location clauseLocation = converter.genLocation(clause.source); if (const auto *createClause = std::get_if(&clause.u)) { - genGlobalCtorsWithModifier( + genGlobalCtorsWithModifier( converter, modBuilder, createClause, Fortran::parser::AccDataModifier::Modifier::Zero, mlir::acc::DataClause::acc_create, diff --git a/flang/test/Lower/OpenACC/acc-declare.f90 b/flang/test/Lower/OpenACC/acc-declare.f90 --- a/flang/test/Lower/OpenACC/acc-declare.f90 +++ b/flang/test/Lower/OpenACC/acc-declare.f90 @@ -17,6 +17,14 @@ ! CHECK: acc.terminator ! CHECK: } +! CHECK-LABEL: acc.global_dtor @_QMacc_declare_testEdata1_acc_dtor { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_testEdata1) {acc.declare = #acc.declare} : !fir.ref> +! CHECK: %[[DEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[GLOBAL_ADDR]] : !fir.ref>) -> !fir.ref> {dataClause = #acc, name = "data1"} +! CHECK: acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[DEVICEPTR]] : !fir.ref>) {dataClause = #acc, name = "data1", structured = false} +! CHECK: acc.terminator +! CHECK: } + ! CHECK-LABEL: fir.global @_QMacc_declare_testEdata2 {acc.declare = #acc.declare} : !fir.array<100000xf32> ! CHECK-LABEL: acc.global_ctor @_QMacc_declare_testEdata2_acc_ctor { @@ -25,3 +33,11 @@ ! CHECK: acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref>) ! CHECK: acc.terminator ! CHECK: } + +! CHECK-LABEL: acc.global_dtor @_QMacc_declare_testEdata2_acc_dtor { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_testEdata2) {acc.declare = #acc.declare} : !fir.ref> +! CHECK: %[[DEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[GLOBAL_ADDR]] : !fir.ref>) -> !fir.ref> {dataClause = #acc, name = "data2"} +! CHECK: acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[DEVICEPTR]] : !fir.ref>) {dataClause = #acc, name = "data2", structured = false} +! CHECK: acc.terminator +! CHECK: }