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 @@ -348,7 +348,8 @@ static Op createDataEntryOp(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value baseAddr, std::stringstream &name, mlir::SmallVector bounds, - bool structured, mlir::acc::DataClause dataClause, + bool structured, bool implicit, + mlir::acc::DataClause dataClause, mlir::Type retTy) { mlir::Value varPtrPtr; if (auto boxTy = baseAddr.getType().dyn_cast()) { @@ -359,6 +360,7 @@ Op op = builder.create(loc, retTy, baseAddr); op.setNameAttr(builder.getStringAttr(name.str())); op.setStructured(structured); + op.setImplicit(implicit); op.setDataClause(dataClause); unsigned insPos = 1; @@ -390,7 +392,7 @@ Fortran::lower::StatementContext &stmtCtx, llvm::SmallVectorImpl &dataOperands, mlir::acc::DataClause dataClause, bool structured, - bool setDeclareAttr = false) { + bool implicit, bool setDeclareAttr = false) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); for (const auto &accObject : objectList.v) { llvm::SmallVector bounds; @@ -400,7 +402,7 @@ converter, builder, semanticsContext, stmtCtx, accObject, operandLocation, asFortran, bounds); Op op = createDataEntryOp(builder, operandLocation, baseAddr, asFortran, - bounds, structured, dataClause, + bounds, structured, implicit, dataClause, baseAddr.getType()); dataOperands.push_back(op.getAccPtr()); if (setDeclareAttr) @@ -592,7 +594,7 @@ operandLocation, retTy); auto op = createDataEntryOp( builder, operandLocation, baseAddr, asFortran, bounds, true, - mlir::acc::DataClause::acc_private, retTy); + /*implicit=*/false, mlir::acc::DataClause::acc_private, retTy); dataOperands.push_back(op.getAccPtr()); } else { std::string recipeName = fir::getTypeAsString( @@ -601,7 +603,7 @@ builder, recipeName, operandLocation, retTy); auto op = createDataEntryOp( builder, operandLocation, baseAddr, asFortran, bounds, true, - mlir::acc::DataClause::acc_firstprivate, retTy); + /*implicit=*/false, mlir::acc::DataClause::acc_firstprivate, retTy); dataOperands.push_back(op.getAccPtr()); } privatizations.push_back(mlir::SymbolRefAttr::get( @@ -998,8 +1000,8 @@ auto op = createDataEntryOp( builder, operandLocation, baseAddr, asFortran, bounds, - /*structured=*/true, mlir::acc::DataClause::acc_reduction, - baseAddr.getType()); + /*structured=*/true, /*implicit=*/false, + mlir::acc::DataClause::acc_reduction, baseAddr.getType()); mlir::Type ty = op.getAccPtr().getType(); std::string recipeName = fir::getTypeAsString( ty, converter.getKindMap(), @@ -1339,7 +1341,8 @@ (modifier && (*modifier).v == mod) ? clauseWithModifier : clause; genDataOperandOperations(accObjectList, converter, semanticsContext, stmtCtx, dataClauseOperands, dataClause, - /*structured=*/true, setDeclareAttr); + /*structured=*/true, /*implicit=*/false, + setDeclareAttr); } template @@ -1450,7 +1453,7 @@ genDataOperandOperations( copyClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_copy, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); copyEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *copyinClause = @@ -1490,28 +1493,28 @@ genDataOperandOperations( noCreateClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_no_create, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); } else if (const auto *presentClause = std::get_if( &clause.u)) { genDataOperandOperations( presentClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_present, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); } else if (const auto *devicePtrClause = std::get_if( &clause.u)) { genDataOperandOperations( devicePtrClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_deviceptr, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); } else if (const auto *attachClause = std::get_if(&clause.u)) { auto crtDataStart = dataClauseOperands.size(); genDataOperandOperations( attachClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_attach, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); attachEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *privateClause = @@ -1644,7 +1647,7 @@ genDataOperandOperations( copyClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_copy, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); copyEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *copyinClause = @@ -1684,28 +1687,28 @@ genDataOperandOperations( noCreateClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_no_create, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); } else if (const auto *presentClause = std::get_if( &clause.u)) { genDataOperandOperations( presentClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_present, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); } else if (const auto *deviceptrClause = std::get_if( &clause.u)) { genDataOperandOperations( deviceptrClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_deviceptr, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); } else if (const auto *attachClause = std::get_if(&clause.u)) { auto crtDataStart = dataClauseOperands.size(); genDataOperandOperations( attachClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_attach, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); attachEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *asyncClause = @@ -1783,7 +1786,7 @@ genDataOperandOperations( useDevice->v, converter, semanticsContext, stmtCtx, dataOperands, mlir::acc::DataClause::acc_use_device, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); } else if (std::get_if(&clause.u)) { addIfPresentAttr = true; } @@ -1927,7 +1930,8 @@ std::get(listWithModifier.t); genDataOperandOperations( accObjectList, converter, semanticsContext, stmtCtx, - dataClauseOperands, mlir::acc::DataClause::acc_copyin, false); + dataClauseOperands, mlir::acc::DataClause::acc_copyin, false, + /*implicit=*/false); } else if (const auto *createClause = std::get_if(&clause.u)) { const Fortran::parser::AccObjectListWithModifier &listWithModifier = @@ -1943,12 +1947,13 @@ clause = mlir::acc::DataClause::acc_create_zero; genDataOperandOperations( accObjectList, converter, semanticsContext, stmtCtx, - dataClauseOperands, clause, false); + dataClauseOperands, clause, false, /*implicit=*/false); } else if (const auto *attachClause = std::get_if(&clause.u)) { genDataOperandOperations( attachClause->v, converter, semanticsContext, stmtCtx, - dataClauseOperands, mlir::acc::DataClause::acc_attach, false); + dataClauseOperands, mlir::acc::DataClause::acc_attach, false, + /*implicit=*/false); } else { llvm::report_fatal_error( "Unknown clause in ENTER DATA directive lowering"); @@ -2016,17 +2021,17 @@ std::get(listWithModifier.t); genDataOperandOperations( accObjectList, converter, semanticsContext, stmtCtx, copyoutOperands, - mlir::acc::DataClause::acc_copyout, false); + mlir::acc::DataClause::acc_copyout, false, /*implicit=*/false); } else if (const auto *deleteClause = std::get_if(&clause.u)) { genDataOperandOperations( deleteClause->v, converter, semanticsContext, stmtCtx, deleteOperands, - mlir::acc::DataClause::acc_delete, false); + mlir::acc::DataClause::acc_delete, false, /*implicit=*/false); } else if (const auto *detachClause = std::get_if(&clause.u)) { genDataOperandOperations( detachClause->v, converter, semanticsContext, stmtCtx, detachOperands, - mlir::acc::DataClause::acc_detach, false); + mlir::acc::DataClause::acc_detach, false, /*implicit=*/false); } else if (std::get_if(&clause.u)) { addFinalizeAttr = true; } @@ -2148,12 +2153,14 @@ std::get_if(&clause.u)) { genDataOperandOperations( hostClause->v, converter, semanticsContext, stmtCtx, - updateHostOperands, mlir::acc::DataClause::acc_update_host, false); + updateHostOperands, mlir::acc::DataClause::acc_update_host, false, + /*implicit=*/false); } else if (const auto *deviceClause = std::get_if(&clause.u)) { genDataOperandOperations( deviceClause->v, converter, semanticsContext, stmtCtx, - dataClauseOperands, mlir::acc::DataClause::acc_update_device, false); + dataClauseOperands, mlir::acc::DataClause::acc_update_device, false, + /*implicit=*/false); } else if (std::get_if(&clause.u)) { addIfPresentAttr = true; } else if (const auto *selfClause = @@ -2165,7 +2172,8 @@ assert(accObjectList && "expect AccObjectList"); genDataOperandOperations( *accObjectList, converter, semanticsContext, stmtCtx, - updateHostOperands, mlir::acc::DataClause::acc_update_self, false); + updateHostOperands, mlir::acc::DataClause::acc_update_self, false, + /*implicit=*/false); } } @@ -2302,7 +2310,7 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder, fir::FirOpBuilder &builder, mlir::Location loc, fir::GlobalOp &globalOp, - mlir::acc::DataClause clause) { + mlir::acc::DataClause clause, bool implicit) { std::stringstream declareGlobalName; if constexpr (std::is_same_v) @@ -2325,7 +2333,7 @@ llvm::SmallVector bounds; EntryOp entryOp = createDataEntryOp( builder, loc, addrOp.getResTy(), asFortran, bounds, - /*structured=*/false, clause, addrOp.getResTy().getType()); + /*structured=*/false, implicit, clause, addrOp.getResTy().getType()); builder.create(loc, mlir::ValueRange(entryOp.getAccPtr())); mlir::Value varPtr; if constexpr (std::is_same_v) { @@ -2359,14 +2367,25 @@ addDeclareAttr(builder, globalOp.getOperation(), clause); auto crtPos = builder.saveInsertionPoint(); modBuilder.setInsertionPointAfter(globalOp); - createDeclareGlobalOp( - modBuilder, builder, operandLocation, globalOp, clause); + if (mlir::isa( + fir::unwrapRefType(globalOp.getType()))) { + createDeclareGlobalOp( + modBuilder, builder, operandLocation, globalOp, clause, + /*implicit=*/true); + } else { + createDeclareGlobalOp( + modBuilder, builder, operandLocation, globalOp, clause, + /*implicit=*/false); + } if constexpr (!std::is_same_v) { createDeclareGlobalOp( - modBuilder, builder, operandLocation, globalOp, clause); + modBuilder, builder, operandLocation, globalOp, clause, + /*implicit=*/false); } builder.restoreInsertionPoint(crtPos); } @@ -2414,7 +2433,7 @@ genDataOperandOperations( copyClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_copy, - /*structured=*/true, /*setDeclareAttr=*/true); + /*structured=*/true, /*implicit=*/false, /*setDeclareAttr=*/true); copyEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *createClause = @@ -2427,7 +2446,7 @@ genDataOperandOperations( accObjectList, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_create, - /*structured=*/true, /*setDeclareAttr=*/true); + /*structured=*/true, /*implicit=*/false, /*setDeclareAttr=*/true); createEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *presentClause = @@ -2436,7 +2455,7 @@ genDataOperandOperations( presentClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_present, - /*structured=*/true, /*setDeclareAttr=*/true); + /*structured=*/true, /*implicit=*/false, /*setDeclareAttr=*/true); } else if (const auto *copyinClause = std::get_if(&clause.u)) { genDataOperandOperationsWithModifier( @@ -2455,7 +2474,7 @@ genDataOperandOperations( accObjectList, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_copyout, - /*structured=*/true, /*setDeclareAttr=*/true); + /*structured=*/true, /*implicit=*/false, /*setDeclareAttr=*/true); copyoutEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *devicePtrClause = @@ -2464,13 +2483,13 @@ genDataOperandOperations( devicePtrClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_deviceptr, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); } else if (const auto *linkClause = std::get_if(&clause.u)) { genDataOperandOperations( linkClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_declare_link, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); } else if (const auto *deviceResidentClause = std::get_if( &clause.u)) { @@ -2479,7 +2498,7 @@ deviceResidentClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_declare_device_resident, - /*structured=*/true); + /*structured=*/true, /*implicit=*/false); deviceResidentEntryOperands.append( dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else { 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 @@ -223,3 +223,23 @@ ! CHECK: acc.delete accPtr(%[[DEVICERES]] : !fir.ref>) bounds(%{{.*}}) {dataClause = #acc, name = "a"} end module + +module acc_declare_allocatable_test + integer, allocatable :: data1(:) + !$acc declare create(data1) +end module + +! CHECK-LABEL: acc.global_ctor @_QMacc_declare_allocatable_testEdata1_acc_ctor { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) {acc.declare = #acc.declare} : !fir.ref>>> +! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[GLOBAL_ADDR]] : !fir.ref>>>) -> !fir.ref>>> {dataClause = #acc, implicit = true, name = "data1", structured = false} +! CHECK: acc.declare_enter dataOperands(%[[COPYIN]] : !fir.ref>>>) +! CHECK: acc.terminator +! 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} +! 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: } diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp --- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp +++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp @@ -116,7 +116,7 @@ //===----------------------------------------------------------------------===// LogicalResult acc::CopyinOp::verify() { // Test for all clauses this operation can be decomposed from: - if (getDataClause() != acc::DataClause::acc_copyin && + if (!getImplicit() && getDataClause() != acc::DataClause::acc_copyin && getDataClause() != acc::DataClause::acc_copyin_readonly && getDataClause() != acc::DataClause::acc_copy) return emitError(