diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index 809fd3b3be7cf..875db135d15ad 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -27,6 +27,7 @@ #include "flang/Optimizer/Builder/Todo.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/expression.h" +#include "flang/Semantics/scope.h" #include "flang/Semantics/tools.h" #include "llvm/Frontend/OpenACC/ACC.h.inc" @@ -2742,27 +2743,21 @@ template static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder, fir::FirOpBuilder &builder, - mlir::Location loc, fir::GlobalOp &globalOp, - mlir::acc::DataClause clause, bool implicit) { - 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"; - + mlir::Location loc, fir::GlobalOp globalOp, + mlir::acc::DataClause clause, + const std::string declareGlobalName, + bool implicit, std::stringstream &asFortran) { GlobalOp declareGlobalOp = - modBuilder.create(loc, declareGlobalName.str()); + modBuilder.create(loc, declareGlobalName); builder.createBlock(&declareGlobalOp.getRegion(), declareGlobalOp.getRegion().end(), {}, {}); builder.setInsertionPointToEnd(&declareGlobalOp.getRegion().back()); + mlir::Value entryAddr; fir::AddrOfOp addrOp = builder.create( loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol()); - addDeclareAttr(builder, addrOp.getOperation(), clause); + addDeclareAttr(builder, addrOp, clause); - std::stringstream asFortran; - asFortran << Fortran::lower::mangle::demangleName(globalOp.getSymName()); llvm::SmallVector bounds; EntryOp entryOp = createDataEntryOp( builder, loc, addrOp.getResTy(), asFortran, bounds, @@ -2904,8 +2899,33 @@ static void genGlobalCtors(Fortran::lower::AbstractConverter &converter, designator)) { std::string globalName = converter.mangleName(*name->symbol); fir::GlobalOp globalOp = builder.getNamedGlobal(globalName); - if (!globalOp) - llvm::report_fatal_error("could not retrieve global symbol"); + std::stringstream declareGlobalCtorName; + declareGlobalCtorName << globalName << "_acc_ctor"; + std::stringstream declareGlobalDtorName; + declareGlobalDtorName << globalName << "_acc_dtor"; + std::stringstream asFortran; + asFortran << name->symbol->name().ToString(); + + 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); @@ -2915,7 +2935,8 @@ static void genGlobalCtors(Fortran::lower::AbstractConverter &converter, mlir::acc::CopyinOp, mlir::acc::DeclareEnterOp, ExitOp>( modBuilder, builder, operandLocation, globalOp, clause, - /*implicit=*/true); + declareGlobalCtorName.str(), /*implicit=*/true, + asFortran); createDeclareAllocFunc( modBuilder, builder, operandLocation, globalOp, clause); if constexpr (!std::is_same_v) @@ -2925,14 +2946,16 @@ static void genGlobalCtors(Fortran::lower::AbstractConverter &converter, createDeclareGlobalOp( modBuilder, builder, operandLocation, globalOp, clause, - /*implicit=*/false); + declareGlobalCtorName.str(), /*implicit=*/false, + asFortran); } if constexpr (!std::is_same_v) { createDeclareGlobalOp( modBuilder, builder, operandLocation, globalOp, clause, - /*implicit=*/false); + declareGlobalDtorName.str(), /*implicit=*/false, + asFortran); } builder.restoreInsertionPoint(crtPos); } diff --git a/flang/test/Lower/OpenACC/HLFIR/acc-declare.f90 b/flang/test/Lower/OpenACC/HLFIR/acc-declare.f90 index 0a45967ce82ef..6ebdd39802fef 100644 --- a/flang/test/Lower/OpenACC/HLFIR/acc-declare.f90 +++ b/flang/test/Lower/OpenACC/HLFIR/acc-declare.f90 @@ -258,3 +258,49 @@ module acc_declare_allocatable_test ! ALL: acc.delete accPtr(%[[DEVICEPTR]] : !fir.ref>>>) {dataClause = #acc, name = "data1", structured = false} ! ALL: acc.terminator ! ALL: } + + +module acc_declare_equivalent + integer, parameter :: n = 10 + real :: v1(n) + real :: v2(n) + equivalence(v1(1), v2(1)) + !$acc declare create(v2) +end module + +! ALL-LABEL: acc.global_ctor @_QMacc_declare_equivalentEv2_acc_ctor { +! ALL: %[[ADDR:.*]] = fir.address_of(@_QMacc_declare_equivalentEv1) {acc.declare = #acc.declare} : !fir.ref> +! ALL: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) -> !fir.ref> {name = "v2", structured = false} +! ALL: acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref>) +! ALL: acc.terminator +! ALL: } + +! ALL-LABEL: acc.global_dtor @_QMacc_declare_equivalentEv2_acc_dtor { +! ALL: %[[ADDR:.*]] = fir.address_of(@_QMacc_declare_equivalentEv1) {acc.declare = #acc.declare} : !fir.ref> +! ALL: %[[DEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[ADDR]] : !fir.ref>) -> !fir.ref> {dataClause = #acc, name = "v2", structured = false} +! ALL: acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.ref>) +! ALL: acc.delete accPtr(%[[DEVICEPTR]] : !fir.ref>) {dataClause = #acc, name = "v2", structured = false} +! ALL: acc.terminator +! ALL: } + +module acc_declare_equivalent2 + real :: v1(10) + real :: v2(5) + equivalence(v1(6), v2(1)) + !$acc declare create(v2) +end module + +! ALL-LABEL: acc.global_ctor @_QMacc_declare_equivalent2Ev2_acc_ctor { +! ALL: %[[ADDR:.*]] = fir.address_of(@_QMacc_declare_equivalent2Ev1) {acc.declare = #acc.declare} : !fir.ref> +! ALL: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) -> !fir.ref> {name = "v2", structured = false} +! ALL: acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref>) +! ALL: acc.terminator +! ALL: } + +! ALL-LABEL: acc.global_dtor @_QMacc_declare_equivalent2Ev2_acc_dtor { +! ALL: %[[ADDR:.*]] = fir.address_of(@_QMacc_declare_equivalent2Ev1) {acc.declare = #acc.declare} : !fir.ref> +! ALL: %[[DEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[ADDR]] : !fir.ref>) -> !fir.ref> {dataClause = #acc, name = "v2", structured = false} +! ALL: acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.ref>) +! ALL: acc.delete accPtr(%[[DEVICEPTR]] : !fir.ref>) {dataClause = #acc, name = "v2", structured = false} +! ALL: acc.terminator +! ALL: }