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 @@ -2392,6 +2392,53 @@ modBuilder.setInsertionPointAfter(registerFuncOp); } +template +static void createUnregisterFunc(mlir::OpBuilder &modBuilder, + fir::FirOpBuilder &builder, mlir::Location loc, + fir::GlobalOp &globalOp, + mlir::acc::DataClause clause) { + std::stringstream unregisterFuncName; + unregisterFuncName << globalOp.getSymName().str() + << "_acc_declare_update_desc_post_dealloc"; + auto funcTy = mlir::FunctionType::get(modBuilder.getContext(), {}, {}); + mlir::func::FuncOp unregisterFuncOp = modBuilder.create( + loc, unregisterFuncName.str(), funcTy); + unregisterFuncOp.setVisibility(mlir::SymbolTable::Visibility::Private); + builder.createBlock(&unregisterFuncOp.getRegion(), + unregisterFuncOp.getRegion().end(), {}, {}); + builder.setInsertionPointToEnd(&unregisterFuncOp.getRegion().back()); + + fir::AddrOfOp addrOp = builder.create( + loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol()); + auto loadOp = builder.create(loc, addrOp.getResult()); + fir::BoxAddrOp boxAddrOp = builder.create(loc, loadOp); + addDeclareAttr(builder, boxAddrOp.getOperation(), clause); + + std::stringstream asFortran; + asFortran << Fortran::lower::mangle::demangleName(globalOp.getSymName()); + llvm::SmallVector bounds; + mlir::acc::GetDevicePtrOp entryOp = + createDataEntryOp( + builder, loc, boxAddrOp.getResult(), asFortran, bounds, + /*structured=*/false, /*implicit=*/false, clause, + boxAddrOp.getType()); + + builder.create( + loc, mlir::ValueRange(entryOp.getAccPtr())); + + mlir::Value varPtr; + if constexpr (std::is_same_v || + std::is_same_v) + varPtr = entryOp.getVarPtr(); + builder.create(entryOp.getLoc(), entryOp.getAccPtr(), varPtr, + entryOp.getBounds(), entryOp.getDataClause(), + /*structured=*/false, /*implicit=*/false, + builder.getStringAttr(*entryOp.getName())); + + builder.create(loc); + modBuilder.setInsertionPointAfter(unregisterFuncOp); +} + template static void genGlobalCtors(Fortran::lower::AbstractConverter &converter, mlir::OpBuilder &modBuilder, @@ -2422,6 +2469,9 @@ /*implicit=*/true); createRegisterFunc( modBuilder, builder, operandLocation, globalOp, clause); + if constexpr (!std::is_same_v) + createUnregisterFunc( + modBuilder, builder, operandLocation, globalOp, clause); } else { createDeclareGlobalOp( 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 @@ -282,6 +282,16 @@ ! CHECK: return ! CHECK: } +! CHECK-LABEL: func.func private @_QMacc_declare_allocatable_testEdata1_acc_declare_update_desc_post_dealloc() { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) : !fir.ref>>> +! CHECK: %[[LOAD]] = fir.load %[[GLOBAL_ADDR]] : !fir.ref>>> +! CHECK: %[[BOXADDR:.*]] = fir.box_addr %[[LOAD]] {acc.declare = #acc.declare} : (!fir.box>>) -> !fir.heap> +! CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[BOXADDR]] : !fir.heap>) -> !fir.heap> {dataClause = #acc, name = "data1", structured = false} +! CHECK: acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.heap>) +! CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.heap>) {dataClause = #acc, name = "data1", structured = false} +! CHECK: return +! CHECK: } + ! CHECK-LABEL: acc.global_dtor @_QMacc_declare_allocatable_testEdata1_acc_dtor { ! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) {acc.declare = #acc.declare} : !fir.ref>>> ! CHECK: %[[DEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[GLOBAL_ADDR]] : !fir.ref>>>) -> !fir.ref>>> {dataClause = #acc, name = "data1", structured = false}