[flang-commits] [flang] 9a96b0a - [flang][openacc] Generate pre/post alloc/dealloc function for in subroutine declare
Valentin Clement via flang-commits
flang-commits at lists.llvm.org
Wed Aug 16 13:04:38 PDT 2023
Author: Valentin Clement
Date: 2023-08-16T13:04:33-07:00
New Revision: 9a96b0a0dc13a088fc29977c2e7929c5b2dfab4c
URL: https://github.com/llvm/llvm-project/commit/9a96b0a0dc13a088fc29977c2e7929c5b2dfab4c
DIFF: https://github.com/llvm/llvm-project/commit/9a96b0a0dc13a088fc29977c2e7929c5b2dfab4c.diff
LOG: [flang][openacc] Generate pre/post alloc/dealloc function for in subroutine declare
Lowering was missing to generate the pre/post alloc/dealloc
functions for the acc declare variables. This patch adds the generation.
These functions have the descriptor as their unique argument.
Reviewed By: razvanlupusoru
Differential Revision: https://reviews.llvm.org/D158103
Added:
Modified:
flang/lib/Lower/OpenACC.cpp
flang/test/Lower/OpenACC/acc-declare.f90
Removed:
################################################################################
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 621b6cef5c4ccd..d2c42cf2b76621 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -387,6 +387,148 @@ static void addDeclareAttr(fir::FirOpBuilder &builder, mlir::Operation *op,
builder.getContext(), clause)));
}
+static mlir::func::FuncOp
+createDeclareFunc(mlir::OpBuilder &modBuilder, fir::FirOpBuilder &builder,
+ mlir::Location loc, llvm::StringRef funcName,
+ llvm::SmallVector<mlir::Type> argsTy = {},
+ llvm::SmallVector<mlir::Location> locs = {}) {
+ auto funcTy = mlir::FunctionType::get(modBuilder.getContext(), argsTy, {});
+ auto funcOp = modBuilder.create<mlir::func::FuncOp>(loc, funcName, funcTy);
+ funcOp.setVisibility(mlir::SymbolTable::Visibility::Private);
+ builder.createBlock(&funcOp.getRegion(), funcOp.getRegion().end(), argsTy,
+ locs);
+ builder.setInsertionPointToEnd(&funcOp.getRegion().back());
+ builder.create<mlir::func::ReturnOp>(loc);
+ builder.setInsertionPointToStart(&funcOp.getRegion().back());
+ return funcOp;
+}
+
+template <typename Op>
+static Op
+createSimpleOp(fir::FirOpBuilder &builder, mlir::Location loc,
+ const llvm::SmallVectorImpl<mlir::Value> &operands,
+ const llvm::SmallVectorImpl<int32_t> &operandSegments) {
+ llvm::ArrayRef<mlir::Type> argTy;
+ Op op = builder.create<Op>(loc, argTy, operands);
+ op->setAttr(Op::getOperandSegmentSizeAttr(),
+ builder.getDenseI32ArrayAttr(operandSegments));
+ return op;
+}
+
+template <typename EntryOp>
+static void createDeclareAllocFuncWithArg(mlir::OpBuilder &modBuilder,
+ fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Type descTy,
+ llvm::StringRef funcNamePrefix,
+ std::stringstream &asFortran,
+ mlir::acc::DataClause clause) {
+ auto crtInsPt = builder.saveInsertionPoint();
+ std::stringstream registerFuncName;
+ registerFuncName << funcNamePrefix.str()
+ << Fortran::lower::declarePostAllocSuffix.str();
+
+ if (!mlir::isa<fir::ReferenceType>(descTy))
+ descTy = fir::ReferenceType::get(descTy);
+ auto registerFuncOp = createDeclareFunc(
+ modBuilder, builder, loc, registerFuncName.str(), {descTy}, {loc});
+
+ mlir::Value desc =
+ builder.create<fir::LoadOp>(loc, registerFuncOp.getArgument(0));
+ fir::BoxAddrOp boxAddrOp = builder.create<fir::BoxAddrOp>(loc, desc);
+ addDeclareAttr(builder, boxAddrOp.getOperation(), clause);
+
+ llvm::SmallVector<mlir::Value> bounds;
+ EntryOp entryOp = createDataEntryOp<EntryOp>(
+ builder, loc, boxAddrOp.getResult(), asFortran, bounds,
+ /*structured=*/false, /*implicit=*/false, clause, boxAddrOp.getType());
+ builder.create<mlir::acc::DeclareEnterOp>(
+ loc, mlir::ValueRange(entryOp.getAccPtr()));
+
+ asFortran << "_desc";
+ mlir::acc::UpdateDeviceOp updateDeviceOp =
+ createDataEntryOp<mlir::acc::UpdateDeviceOp>(
+ builder, loc, registerFuncOp.getArgument(0), asFortran, bounds,
+ /*structured=*/false, /*implicit=*/true,
+ mlir::acc::DataClause::acc_update_device, descTy);
+ llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 0, 0, 1};
+ llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
+ createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands, operandSegments);
+ modBuilder.setInsertionPointAfter(registerFuncOp);
+ builder.restoreInsertionPoint(crtInsPt);
+}
+
+template <typename ExitOp>
+static void createDeclareDeallocFuncWithArg(
+ mlir::OpBuilder &modBuilder, fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Type descTy, llvm::StringRef funcNamePrefix,
+ std::stringstream &asFortran, mlir::acc::DataClause clause) {
+ auto crtInsPt = builder.saveInsertionPoint();
+ // Generate the pre dealloc function.
+ std::stringstream preDeallocFuncName;
+ preDeallocFuncName << funcNamePrefix.str()
+ << Fortran::lower::declarePreDeallocSuffix.str();
+ if (!mlir::isa<fir::ReferenceType>(descTy))
+ descTy = fir::ReferenceType::get(descTy);
+ auto preDeallocOp = createDeclareFunc(
+ modBuilder, builder, loc, preDeallocFuncName.str(), {descTy}, {loc});
+ mlir::Value loadOp =
+ builder.create<fir::LoadOp>(loc, preDeallocOp.getArgument(0));
+ fir::BoxAddrOp boxAddrOp = builder.create<fir::BoxAddrOp>(loc, loadOp);
+ addDeclareAttr(builder, boxAddrOp.getOperation(), clause);
+
+ llvm::SmallVector<mlir::Value> bounds;
+ mlir::acc::GetDevicePtrOp entryOp =
+ createDataEntryOp<mlir::acc::GetDevicePtrOp>(
+ builder, loc, boxAddrOp.getResult(), asFortran, bounds,
+ /*structured=*/false, /*implicit=*/false, clause,
+ boxAddrOp.getType());
+ builder.create<mlir::acc::DeclareExitOp>(
+ loc, mlir::ValueRange(entryOp.getAccPtr()));
+
+ mlir::Value varPtr;
+ if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
+ std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>)
+ varPtr = entryOp.getVarPtr();
+ builder.create<ExitOp>(entryOp.getLoc(), entryOp.getAccPtr(), varPtr,
+ entryOp.getBounds(), entryOp.getDataClause(),
+ /*structured=*/false, /*implicit=*/false,
+ builder.getStringAttr(*entryOp.getName()));
+
+ // Generate the post dealloc function.
+ modBuilder.setInsertionPointAfter(preDeallocOp);
+ std::stringstream postDeallocFuncName;
+ postDeallocFuncName << funcNamePrefix.str()
+ << Fortran::lower::declarePostDeallocSuffix.str();
+ auto postDeallocOp = createDeclareFunc(
+ modBuilder, builder, loc, postDeallocFuncName.str(), {descTy}, {loc});
+ loadOp = builder.create<fir::LoadOp>(loc, postDeallocOp.getArgument(0));
+ asFortran << "_desc";
+ mlir::acc::UpdateDeviceOp updateDeviceOp =
+ createDataEntryOp<mlir::acc::UpdateDeviceOp>(
+ builder, loc, loadOp, asFortran, bounds,
+ /*structured=*/false, /*implicit=*/true,
+ mlir::acc::DataClause::acc_update_device, loadOp.getType());
+ llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 0, 0, 1};
+ llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
+ createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands, operandSegments);
+ modBuilder.setInsertionPointAfter(postDeallocOp);
+ builder.restoreInsertionPoint(crtInsPt);
+}
+
+Fortran::semantics::Symbol &
+getSymbolFromAccObject(const Fortran::parser::AccObject &accObject) {
+ if (const auto *designator =
+ std::get_if<Fortran::parser::Designator>(&accObject.u)) {
+ if (const auto *name =
+ Fortran::semantics::getDesignatorNameIfDataRef(*designator))
+ return *name->symbol;
+ } else if (const auto *name =
+ std::get_if<Fortran::parser::Name>(&accObject.u)) {
+ return *name->symbol;
+ }
+ llvm::report_fatal_error("Could not find symbol");
+}
+
template <typename Op>
static void
genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
@@ -408,11 +550,69 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
bounds, structured, implicit, dataClause,
baseAddr.getType());
dataOperands.push_back(op.getAccPtr());
- if (setDeclareAttr)
- addDeclareAttr(builder, op.getVarPtr().getDefiningOp(), dataClause);
}
}
+template <typename EntryOp, typename ExitOp>
+static void genDeclareDataOperandOperations(
+ const Fortran::parser::AccObjectList &objectList,
+ Fortran::lower::AbstractConverter &converter,
+ Fortran::semantics::SemanticsContext &semanticsContext,
+ Fortran::lower::StatementContext &stmtCtx,
+ llvm::SmallVectorImpl<mlir::Value> &dataOperands,
+ mlir::acc::DataClause dataClause, bool structured, bool implicit) {
+ fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+ for (const auto &accObject : objectList.v) {
+ llvm::SmallVector<mlir::Value> bounds;
+ std::stringstream asFortran;
+ mlir::Location operandLocation = genOperandLocation(converter, accObject);
+ mlir::Value baseAddr = gatherDataOperandAddrAndBounds(
+ converter, builder, semanticsContext, stmtCtx, accObject,
+ operandLocation, asFortran, bounds);
+ EntryOp op = createDataEntryOp<EntryOp>(
+ builder, operandLocation, baseAddr, asFortran, bounds, structured,
+ implicit, dataClause, baseAddr.getType());
+ dataOperands.push_back(op.getAccPtr());
+ addDeclareAttr(builder, op.getVarPtr().getDefiningOp(), dataClause);
+ if (mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(baseAddr.getType()))) {
+ mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
+ modBuilder.setInsertionPointAfter(builder.getFunction());
+ std::string prefix =
+ converter.mangleName(getSymbolFromAccObject(accObject));
+ createDeclareAllocFuncWithArg<EntryOp>(
+ modBuilder, builder, operandLocation, baseAddr.getType(), prefix,
+ asFortran, dataClause);
+ if constexpr (!std::is_same_v<EntryOp, ExitOp>)
+ createDeclareDeallocFuncWithArg<ExitOp>(
+ modBuilder, builder, operandLocation, baseAddr.getType(), prefix,
+ asFortran, dataClause);
+ }
+ }
+}
+
+template <typename EntryOp, typename ExitOp, typename Clause>
+static void genDeclareDataOperandOperationsWithModifier(
+ const Clause *x, Fortran::lower::AbstractConverter &converter,
+ Fortran::semantics::SemanticsContext &semanticsContext,
+ Fortran::lower::StatementContext &stmtCtx,
+ Fortran::parser::AccDataModifier::Modifier mod,
+ llvm::SmallVectorImpl<mlir::Value> &dataClauseOperands,
+ const mlir::acc::DataClause clause,
+ const mlir::acc::DataClause clauseWithModifier) {
+ const Fortran::parser::AccObjectListWithModifier &listWithModifier = x->v;
+ const auto &accObjectList =
+ std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+ const auto &modifier =
+ std::get<std::optional<Fortran::parser::AccDataModifier>>(
+ listWithModifier.t);
+ mlir::acc::DataClause dataClause =
+ (modifier && (*modifier).v == mod) ? clauseWithModifier : clause;
+ genDeclareDataOperandOperations<EntryOp, ExitOp>(
+ accObjectList, converter, semanticsContext, stmtCtx, dataClauseOperands,
+ dataClause,
+ /*structured=*/true, /*implicit=*/false);
+}
+
template <typename EntryOp, typename ExitOp>
static void genDataExitOperations(fir::FirOpBuilder &builder,
llvm::SmallVector<mlir::Value> operands,
@@ -1058,18 +1258,6 @@ createRegionOp(fir::FirOpBuilder &builder, mlir::Location loc,
return op;
}
-template <typename Op>
-static Op
-createSimpleOp(fir::FirOpBuilder &builder, mlir::Location loc,
- const llvm::SmallVectorImpl<mlir::Value> &operands,
- const llvm::SmallVectorImpl<int32_t> &operandSegments) {
- llvm::ArrayRef<mlir::Type> argTy;
- Op op = builder.create<Op>(loc, argTy, operands);
- op->setAttr(Op::getOperandSegmentSizeAttr(),
- builder.getDenseI32ArrayAttr(operandSegments));
- return op;
-}
-
static void genAsyncClause(Fortran::lower::AbstractConverter &converter,
const Fortran::parser::AccClause::Async *asyncClause,
mlir::Value &async, bool &addAsyncAttr,
@@ -2349,20 +2537,6 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
modBuilder.setInsertionPointAfter(declareGlobalOp);
}
-static mlir::func::FuncOp createDeclareFunc(mlir::OpBuilder &modBuilder,
- fir::FirOpBuilder &builder,
- mlir::Location loc,
- llvm::StringRef funcName) {
- auto funcTy = mlir::FunctionType::get(modBuilder.getContext(), {}, {});
- auto funcOp = modBuilder.create<mlir::func::FuncOp>(loc, funcName, funcTy);
- funcOp.setVisibility(mlir::SymbolTable::Visibility::Private);
- builder.createBlock(&funcOp.getRegion(), funcOp.getRegion().end(), {}, {});
- builder.setInsertionPointToEnd(&funcOp.getRegion().back());
- builder.create<mlir::func::ReturnOp>(loc);
- builder.setInsertionPointToStart(&funcOp.getRegion().back());
- return funcOp;
-}
-
template <typename EntryOp>
static void createDeclareAllocFunc(mlir::OpBuilder &modBuilder,
fir::FirOpBuilder &builder,
@@ -2556,10 +2730,11 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
if (const auto *copyClause =
std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
auto crtDataStart = dataClauseOperands.size();
- genDataOperandOperations<mlir::acc::CopyinOp>(
+ genDeclareDataOperandOperations<mlir::acc::CopyinOp,
+ mlir::acc::CopyoutOp>(
copyClause->v, converter, semanticsContext, stmtCtx,
dataClauseOperands, mlir::acc::DataClause::acc_copy,
- /*structured=*/true, /*implicit=*/false, /*setDeclareAttr=*/true);
+ /*structured=*/true, /*implicit=*/false);
copyEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
dataClauseOperands.end());
} else if (const auto *createClause =
@@ -2569,26 +2744,28 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
const auto &accObjectList =
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
auto crtDataStart = dataClauseOperands.size();
- genDataOperandOperations<mlir::acc::CreateOp>(
+ genDeclareDataOperandOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
accObjectList, converter, semanticsContext, stmtCtx,
dataClauseOperands, mlir::acc::DataClause::acc_create,
- /*structured=*/true, /*implicit=*/false, /*setDeclareAttr=*/true);
+ /*structured=*/true, /*implicit=*/false);
createEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
dataClauseOperands.end());
} else if (const auto *presentClause =
std::get_if<Fortran::parser::AccClause::Present>(
&clause.u)) {
- genDataOperandOperations<mlir::acc::PresentOp>(
+ genDeclareDataOperandOperations<mlir::acc::PresentOp,
+ mlir::acc::PresentOp>(
presentClause->v, converter, semanticsContext, stmtCtx,
dataClauseOperands, mlir::acc::DataClause::acc_present,
- /*structured=*/true, /*implicit=*/false, /*setDeclareAttr=*/true);
+ /*structured=*/true, /*implicit=*/false);
} else if (const auto *copyinClause =
std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
- genDataOperandOperationsWithModifier<mlir::acc::CopyinOp>(
+ genDeclareDataOperandOperationsWithModifier<mlir::acc::CopyinOp,
+ mlir::acc::DeleteOp>(
copyinClause, converter, semanticsContext, stmtCtx,
Fortran::parser::AccDataModifier::Modifier::ReadOnly,
dataClauseOperands, mlir::acc::DataClause::acc_copyin,
- mlir::acc::DataClause::acc_copyin_readonly, /*setDeclareAttr=*/true);
+ mlir::acc::DataClause::acc_copyin_readonly);
} else if (const auto *copyoutClause =
std::get_if<Fortran::parser::AccClause::Copyout>(
&clause.u)) {
@@ -2597,34 +2774,38 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
const auto &accObjectList =
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
auto crtDataStart = dataClauseOperands.size();
- genDataOperandOperations<mlir::acc::CreateOp>(
+ genDeclareDataOperandOperations<mlir::acc::CreateOp,
+ mlir::acc::CopyoutOp>(
accObjectList, converter, semanticsContext, stmtCtx,
dataClauseOperands, mlir::acc::DataClause::acc_copyout,
- /*structured=*/true, /*implicit=*/false, /*setDeclareAttr=*/true);
+ /*structured=*/true, /*implicit=*/false);
copyoutEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
dataClauseOperands.end());
} else if (const auto *devicePtrClause =
std::get_if<Fortran::parser::AccClause::Deviceptr>(
&clause.u)) {
- genDataOperandOperations<mlir::acc::DevicePtrOp>(
+ genDeclareDataOperandOperations<mlir::acc::DevicePtrOp,
+ mlir::acc::DevicePtrOp>(
devicePtrClause->v, converter, semanticsContext, stmtCtx,
dataClauseOperands, mlir::acc::DataClause::acc_deviceptr,
- /*structured=*/true, /*implicit=*/false, /*setDeclareAttr=*/true);
+ /*structured=*/true, /*implicit=*/false);
} else if (const auto *linkClause =
std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
- genDataOperandOperations<mlir::acc::DeclareLinkOp>(
+ genDeclareDataOperandOperations<mlir::acc::DeclareLinkOp,
+ mlir::acc::DeclareLinkOp>(
linkClause->v, converter, semanticsContext, stmtCtx,
dataClauseOperands, mlir::acc::DataClause::acc_declare_link,
- /*structured=*/true, /*implicit=*/false, /*setDeclareAttr=*/true);
+ /*structured=*/true, /*implicit=*/false);
} else if (const auto *deviceResidentClause =
std::get_if<Fortran::parser::AccClause::DeviceResident>(
&clause.u)) {
auto crtDataStart = dataClauseOperands.size();
- genDataOperandOperations<mlir::acc::DeclareDeviceResidentOp>(
+ genDeclareDataOperandOperations<mlir::acc::DeclareDeviceResidentOp,
+ mlir::acc::DeleteOp>(
deviceResidentClause->v, converter, semanticsContext, stmtCtx,
dataClauseOperands,
mlir::acc::DataClause::acc_declare_device_resident,
- /*structured=*/true, /*implicit=*/false, /*setDeclareAttr=*/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
index 1ba42426d97f80..3687f0a910868e 100644
--- a/flang/test/Lower/OpenACC/acc-declare.f90
+++ b/flang/test/Lower/OpenACC/acc-declare.f90
@@ -283,6 +283,36 @@ subroutine acc_declare_allocate()
end subroutine
+! CHECK-LABEL: func.func private @_QMacc_declareFacc_declare_allocateEa_acc_declare_update_desc_post_alloc(
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) {
+! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] {acc.declare = #acc.declare<dataClause = acc_create>} : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>> {name = "a", structured = false}
+! CHECK: acc.declare_enter dataOperands(%[[CREATE]] : !fir.heap<!fir.array<?xi32>>)
+! CHECK: %[[UPDATE:.*]] = acc.update_device varPtr(%[[ARG0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {implicit = true, name = "a_desc", structured = false}
+! CHECK: acc.update dataOperands(%[[UPDATE]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
+! CHECK: return
+! CHECK: }
+
+! CHECK-LABEL: func.func private @_QMacc_declareFacc_declare_allocateEa_acc_declare_update_desc_pre_dealloc(
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) {
+! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] {acc.declare = #acc.declare<dataClause = acc_create>} : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+! CHECK: %[[GETDEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[BOX_ADDR]] : !fir.heap<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>> {dataClause = #acc<data_clause acc_create>, name = "a_desc", structured = false}
+! CHECK: acc.declare_exit dataOperands(%[[GETDEVICEPTR]] : !fir.heap<!fir.array<?xi32>>)
+! CHECK: acc.delete accPtr(%[[GETDEVICEPTR]] : !fir.heap<!fir.array<?xi32>>) {dataClause = #acc<data_clause acc_create>, name = "a_desc", structured = false}
+! CHECK: return
+! CHECK: }
+
+! CHECK-LABEL: func.func private @_QMacc_declareFacc_declare_allocateEa_acc_declare_update_desc_post_dealloc(
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) {
+! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+! CHECK: %[[UPDATE:.*]] = acc.update_device varPtr(%[[BOX_ADDR]] : !fir.heap<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>> {implicit = true, name = "a_desc_desc", structured = false}
+! CHECK: acc.update dataOperands(%[[UPDATE]] : !fir.heap<!fir.array<?xi32>>)
+! CHECK: return
+! CHECK: }
+
end module
module acc_declare_allocatable_test
More information about the flang-commits
mailing list