[flang-commits] [flang] 734adda - [flang][openacc] Lower copyout, detach and delete to data exit operations
Valentin Clement via flang-commits
flang-commits at lists.llvm.org
Thu May 4 09:39:32 PDT 2023
Author: Valentin Clement
Date: 2023-05-04T09:39:25-07:00
New Revision: 734adda3536de8cf450dcc4064b2f976189919ce
URL: https://github.com/llvm/llvm-project/commit/734adda3536de8cf450dcc4064b2f976189919ce
DIFF: https://github.com/llvm/llvm-project/commit/734adda3536de8cf450dcc4064b2f976189919ce.diff
LOG: [flang][openacc] Lower copyout, detach and delete to data exit operations
Add support to lower data exit operations and use it for the
copyout, detach and delete clause on the `!$acc exit data` construct.
This patch refactor the data entry op creation so most part of the code
can be shared with the data exit op.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D149601
Added:
Modified:
flang/lib/Lower/OpenACC.cpp
flang/test/Lower/OpenACC/acc-exit-data.f90
mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
Removed:
################################################################################
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 2054ae78f9c61..1b5e305a66ce4 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -271,6 +271,175 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
return bounds;
}
+static mlir::Value
+getDataOperandBaseAddr(Fortran::lower::AbstractConverter &converter,
+ fir::FirOpBuilder &builder,
+ Fortran::lower::SymbolRef sym, mlir::Location loc) {
+ mlir::Value symAddr = converter.getSymbolAddress(sym);
+ // TODO: Might need revisiting to handle for non-shared clauses
+ if (!symAddr) {
+ if (const auto *details =
+ sym->detailsIf<Fortran::semantics::HostAssocDetails>())
+ symAddr = converter.getSymbolAddress(details->symbol());
+ }
+
+ if (!symAddr)
+ llvm::report_fatal_error("could not retrieve symbol address");
+
+ if (auto boxTy =
+ fir::unwrapRefType(symAddr.getType()).dyn_cast<fir::BaseBoxType>()) {
+ if (boxTy.getEleTy().isa<fir::RecordType>())
+ TODO(loc, "derived type");
+
+ // Load the box when baseAddr is a `fir.ref<fir.box<T>>` or a
+ // `fir.ref<fir.class<T>>` type.
+ if (symAddr.getType().isa<fir::ReferenceType>())
+ return builder.create<fir::LoadOp>(loc, symAddr);
+ }
+ return symAddr;
+}
+
+static mlir::Value gatherDataOperandAddrAndBounds(
+ Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder,
+ Fortran::semantics::SemanticsContext &semanticsContext,
+ Fortran::lower::StatementContext &stmtCtx,
+ const Fortran::parser::AccObject &accObject, mlir::Location operandLocation,
+ std::stringstream &asFortran, llvm::SmallVector<mlir::Value> &bounds) {
+ mlir::Value baseAddr;
+ std::visit(
+ Fortran::common::visitors{
+ [&](const Fortran::parser::Designator &designator) {
+ if (auto expr{Fortran::semantics::AnalyzeExpr(semanticsContext,
+ designator)}) {
+ if ((*expr).Rank() > 0 &&
+ Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
+ designator)) {
+ const auto *arrayElement =
+ Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
+ designator);
+ const auto *dataRef =
+ std::get_if<Fortran::parser::DataRef>(&designator.u);
+ fir::ExtendedValue dataExv;
+ if (Fortran::parser::Unwrap<
+ Fortran::parser::StructureComponent>(
+ arrayElement->base)) {
+ auto exprBase = Fortran::semantics::AnalyzeExpr(
+ semanticsContext, arrayElement->base);
+ dataExv = converter.genExprAddr(operandLocation, *exprBase,
+ stmtCtx);
+ baseAddr = fir::getBase(dataExv);
+ asFortran << (*exprBase).AsFortran();
+ } else {
+ const Fortran::parser::Name &name =
+ Fortran::parser::GetLastName(*dataRef);
+ baseAddr = getDataOperandBaseAddr(
+ converter, builder, *name.symbol, operandLocation);
+ dataExv = converter.getSymbolExtendedValue(*name.symbol);
+ asFortran << name.ToString();
+ }
+
+ if (!arrayElement->subscripts.empty()) {
+ asFortran << '(';
+ bounds = genBoundsOps(builder, operandLocation, converter,
+ stmtCtx, arrayElement->subscripts,
+ asFortran, dataExv, baseAddr);
+ }
+ asFortran << ')';
+ } else if (Fortran::parser::Unwrap<
+ Fortran::parser::StructureComponent>(designator)) {
+ fir::ExtendedValue compExv =
+ converter.genExprAddr(operandLocation, *expr, stmtCtx);
+ baseAddr = fir::getBase(compExv);
+ if (fir::unwrapRefType(baseAddr.getType())
+ .isa<fir::SequenceType>())
+ bounds = genBaseBoundsOps(builder, operandLocation, converter,
+ compExv, baseAddr);
+ asFortran << (*expr).AsFortran();
+
+ // If the component is an allocatable or pointer the result of
+ // genExprAddr will be the result of a fir.box_addr operation.
+ // Retrieve the box so we handle it like other descriptor.
+ if (auto boxAddrOp = mlir::dyn_cast_or_null<fir::BoxAddrOp>(
+ baseAddr.getDefiningOp())) {
+ baseAddr = boxAddrOp.getVal();
+ bounds = genBoundsOpsFromBox(builder, operandLocation,
+ converter, compExv, baseAddr);
+ }
+ } else {
+ // Scalar or full array.
+ if (const auto *dataRef{
+ std::get_if<Fortran::parser::DataRef>(&designator.u)}) {
+ const Fortran::parser::Name &name =
+ Fortran::parser::GetLastName(*dataRef);
+ fir::ExtendedValue dataExv =
+ converter.getSymbolExtendedValue(*name.symbol);
+ baseAddr = getDataOperandBaseAddr(
+ converter, builder, *name.symbol, operandLocation);
+ if (fir::unwrapRefType(baseAddr.getType())
+ .isa<fir::BaseBoxType>())
+ bounds = genBoundsOpsFromBox(builder, operandLocation,
+ converter, dataExv, baseAddr);
+ if (fir::unwrapRefType(baseAddr.getType())
+ .isa<fir::SequenceType>())
+ bounds = genBaseBoundsOps(builder, operandLocation,
+ converter, dataExv, baseAddr);
+ asFortran << name.ToString();
+ } else { // Unsupported
+ llvm::report_fatal_error(
+ "Unsupported type of OpenACC operand");
+ }
+ }
+ }
+ },
+ [&](const Fortran::parser::Name &name) {
+ baseAddr = getDataOperandBaseAddr(converter, builder, *name.symbol,
+ operandLocation);
+ asFortran << name.ToString();
+ }},
+ accObject.u);
+ return baseAddr;
+}
+
+static mlir::Location
+genOperandLocation(Fortran::lower::AbstractConverter &converter,
+ const Fortran::parser::AccObject &accObject) {
+ mlir::Location loc = converter.genUnknownLocation();
+ std::visit(Fortran::common::visitors{
+ [&](const Fortran::parser::Designator &designator) {
+ loc = converter.genLocation(designator.source);
+ },
+ [&](const Fortran::parser::Name &name) {
+ loc = converter.genLocation(name.source);
+ }},
+ accObject.u);
+ return loc;
+}
+
+template <typename Op>
+static Op createDataEntryOp(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value baseAddr, std::stringstream &name,
+ mlir::SmallVector<mlir::Value> bounds,
+ bool structured, mlir::acc::DataClause dataClause) {
+ mlir::Value varPtrPtr;
+ if (auto boxTy = baseAddr.getType().dyn_cast<fir::BaseBoxType>())
+ baseAddr = builder.create<fir::BoxAddrOp>(loc, baseAddr);
+
+ Op op = builder.create<Op>(loc, baseAddr.getType(), baseAddr);
+ op.setNameAttr(builder.getStringAttr(name.str()));
+ op.setStructured(structured);
+ op.setDataClause(dataClause);
+
+ unsigned insPos = 1;
+ if (varPtrPtr)
+ op->insertOperands(insPos++, varPtrPtr);
+ if (bounds.size() > 0)
+ op->insertOperands(insPos, bounds);
+ op->setAttr(Op::getOperandSegmentSizeAttr(),
+ builder.getDenseI32ArrayAttr(
+ {1, varPtrPtr ? 1 : 0, static_cast<int32_t>(bounds.size())}));
+ return op;
+}
+
template <typename Op>
static void
genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
@@ -279,164 +448,35 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
Fortran::lower::StatementContext &stmtCtx,
llvm::SmallVectorImpl<mlir::Value> &dataOperands,
mlir::acc::DataClause dataClause, bool structured) {
-
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
-
- auto getDataOperandBaseAddr = [&](Fortran::lower::SymbolRef sym,
- mlir::Location loc) -> mlir::Value {
- mlir::Value symAddr = converter.getSymbolAddress(sym);
- // TODO: Might need revisiting to handle for non-shared clauses
- if (!symAddr) {
- if (const auto *details =
- sym->detailsIf<Fortran::semantics::HostAssocDetails>())
- symAddr = converter.getSymbolAddress(details->symbol());
- }
-
- if (!symAddr)
- llvm::report_fatal_error("could not retrieve symbol address");
-
- if (auto boxTy = fir::unwrapRefType(symAddr.getType())
- .dyn_cast<fir::BaseBoxType>()) {
- if (boxTy.getEleTy().isa<fir::RecordType>())
- TODO(loc, "derived type");
-
- // Load the box when baseAddr is a `fir.ref<fir.box<T>>` or a
- // `fir.ref<fir.class<T>>` type.
- if (symAddr.getType().isa<fir::ReferenceType>())
- return builder.create<fir::LoadOp>(loc, symAddr);
- }
- return symAddr;
- };
-
- auto createOpAndAddOperand = [&](mlir::Value baseAddr, llvm::StringRef name,
- mlir::Location loc,
- llvm::SmallVector<mlir::Value> &bounds) {
- if (auto boxTy = baseAddr.getType().dyn_cast<fir::BaseBoxType>())
- baseAddr = builder.create<fir::BoxAddrOp>(loc, baseAddr);
-
- Op op = builder.create<Op>(loc, baseAddr.getType(), baseAddr);
- op.setNameAttr(builder.getStringAttr(name));
- op.setStructured(structured);
- op.setDataClause(dataClause);
- unsigned insPos = 1;
- if (bounds.size() > 0)
- op->insertOperands(insPos, bounds);
- op->setAttr(Op::getOperandSegmentSizeAttr(),
- builder.getDenseI32ArrayAttr(
- {1, 0, static_cast<int32_t>(bounds.size())}));
- dataOperands.push_back(op.getAccPtr());
- return op;
- };
-
for (const auto &accObject : objectList.v) {
- std::visit(
- Fortran::common::visitors{
- [&](const Fortran::parser::Designator &designator) {
- mlir::Location operandLocation =
- converter.genLocation(designator.source);
- if (auto expr{Fortran::semantics::AnalyzeExpr(semanticsContext,
- designator)}) {
- if ((*expr).Rank() > 0 &&
- Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
- designator)) {
- const auto *arrayElement =
- Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
- designator);
- llvm::SmallVector<mlir::Value> bounds;
- const auto *dataRef =
- std::get_if<Fortran::parser::DataRef>(&designator.u);
- mlir::Value addr;
- std::stringstream asFortran;
- fir::ExtendedValue dataExv;
- if (Fortran::parser::Unwrap<
- Fortran::parser::StructureComponent>(
- arrayElement->base)) {
- auto exprBase = Fortran::semantics::AnalyzeExpr(
- semanticsContext, arrayElement->base);
- dataExv = converter.genExprAddr(operandLocation, *exprBase,
- stmtCtx);
- addr = fir::getBase(dataExv);
- asFortran << (*exprBase).AsFortran();
- } else {
- const Fortran::parser::Name &name =
- Fortran::parser::GetLastName(*dataRef);
- addr =
- getDataOperandBaseAddr(*name.symbol, operandLocation);
- dataExv = converter.getSymbolExtendedValue(*name.symbol);
- asFortran << name.ToString();
- }
- if (!arrayElement->subscripts.empty()) {
- asFortran << '(';
- bounds = genBoundsOps(builder, operandLocation, converter,
- stmtCtx, arrayElement->subscripts,
- asFortran, dataExv, addr);
- }
- asFortran << ')';
- createOpAndAddOperand(addr, asFortran.str(), operandLocation,
- bounds);
- } else if (Fortran::parser::Unwrap<
- Fortran::parser::StructureComponent>(
- designator)) {
- fir::ExtendedValue compExv =
- converter.genExprAddr(operandLocation, *expr, stmtCtx);
- mlir::Value addr = fir::getBase(compExv);
- llvm::SmallVector<mlir::Value> bounds;
- if (fir::unwrapRefType(addr.getType())
- .isa<fir::SequenceType>())
- bounds = genBaseBoundsOps(builder, operandLocation,
- converter, compExv, addr);
-
- // If the component is an allocatable or pointer the result of
- // genExprAddr will be the result of a fir.box_addr operation.
- // Retrieve the box so we handle it like other descriptor.
- if (auto boxAddrOp = mlir::dyn_cast_or_null<fir::BoxAddrOp>(
- addr.getDefiningOp())) {
- addr = boxAddrOp.getVal();
- bounds = genBoundsOpsFromBox(builder, operandLocation,
- converter, compExv, addr);
- }
+ 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);
+ Op op = createDataEntryOp<Op>(builder, operandLocation, baseAddr, asFortran,
+ bounds, structured, dataClause);
+ dataOperands.push_back(op.getAccPtr());
+ }
+}
- createOpAndAddOperand(addr, (*expr).AsFortran(),
- operandLocation, bounds);
- } else {
- // Scalar or full array.
- if (const auto *dataRef{std::get_if<Fortran::parser::DataRef>(
- &designator.u)}) {
- const Fortran::parser::Name &name =
- Fortran::parser::GetLastName(*dataRef);
- fir::ExtendedValue dataExv =
- converter.getSymbolExtendedValue(*name.symbol);
- mlir::Value baseAddr =
- getDataOperandBaseAddr(*name.symbol, operandLocation);
- llvm::SmallVector<mlir::Value> bounds;
- if (fir::unwrapRefType(baseAddr.getType())
- .isa<fir::BaseBoxType>())
- bounds =
- genBoundsOpsFromBox(builder, operandLocation,
- converter, dataExv, baseAddr);
- else if (fir::unwrapRefType(baseAddr.getType())
- .isa<fir::SequenceType>())
- bounds = genBaseBoundsOps(builder, operandLocation,
- converter, dataExv, baseAddr);
- createOpAndAddOperand(baseAddr, name.ToString(),
- operandLocation, bounds);
- } else { // Unsupported
- llvm::report_fatal_error(
- "Unsupported type of OpenACC operand");
- }
- }
- }
- },
- [&](const Fortran::parser::Name &name) {
- mlir::Location operandLocation =
- converter.genLocation(name.source);
- mlir::Value baseAddr =
- getDataOperandBaseAddr(*name.symbol, operandLocation);
- llvm::SmallVector<mlir::Value> bounds;
- createOpAndAddOperand(baseAddr, name.ToString(), operandLocation,
- bounds);
- }},
- accObject.u);
+template <typename Op>
+static void genDataExitOperantions(fir::FirOpBuilder &builder,
+ llvm::SmallVector<mlir::Value> operands,
+ bool structured, bool implicit) {
+ for (mlir::Value operand : operands) {
+ auto getDevicePtrOp = mlir::dyn_cast_or_null<mlir::acc::GetDevicePtrOp>(
+ operand.getDefiningOp());
+ assert(getDevicePtrOp && "acc.getdeivceptr op expected");
+ mlir::Value varPtr;
+ if constexpr (std::is_same_v<Op, mlir::acc::CopyoutOp>)
+ varPtr = getDevicePtrOp.getVarPtr();
+ builder.create<Op>(getDevicePtrOp.getLoc(), getDevicePtrOp.getAccPtr(),
+ varPtr, getDevicePtrOp.getBounds(),
+ getDevicePtrOp.getDataClause(), structured, implicit,
+ builder.getStringAttr(*getDevicePtrOp.getName()));
}
}
@@ -1193,8 +1233,8 @@ genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
Fortran::lower::StatementContext &stmtCtx,
const Fortran::parser::AccClauseList &accClauseList) {
mlir::Value ifCond, async, waitDevnum;
- llvm::SmallVector<mlir::Value> copyoutOperands, deleteOperands,
- detachOperands, waitOperands, dataClauseOperands;
+ llvm::SmallVector<mlir::Value> waitOperands, dataClauseOperands,
+ copyoutOperands, deleteOperands, detachOperands;
// Async and wait clause have optional values but can be present with
// no value as well. When there is no value, the op has an attribute to
@@ -1203,7 +1243,7 @@ genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
bool addWaitAttr = false;
bool addFinalizeAttr = false;
- fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
+ fir::FirOpBuilder &builder = converter.getFirOpBuilder();
// Lower clauses values mapped to operands.
// Keep track of each group of operands separatly as clauses can appear
@@ -1227,21 +1267,28 @@ genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
copyoutClause->v;
const auto &accObjectList =
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
- genObjectList(accObjectList, converter, semanticsContext, stmtCtx,
- copyoutOperands);
+ genDataOperandOperations<mlir::acc::GetDevicePtrOp>(
+ accObjectList, converter, semanticsContext, stmtCtx, copyoutOperands,
+ mlir::acc::DataClause::acc_copyout, false);
} else if (const auto *deleteClause =
std::get_if<Fortran::parser::AccClause::Delete>(&clause.u)) {
- genObjectList(deleteClause->v, converter, semanticsContext, stmtCtx,
- deleteOperands);
+ genDataOperandOperations<mlir::acc::GetDevicePtrOp>(
+ deleteClause->v, converter, semanticsContext, stmtCtx, deleteOperands,
+ mlir::acc::DataClause::acc_delete, false);
} else if (const auto *detachClause =
std::get_if<Fortran::parser::AccClause::Detach>(&clause.u)) {
- genObjectList(detachClause->v, converter, semanticsContext, stmtCtx,
- detachOperands);
+ genDataOperandOperations<mlir::acc::GetDevicePtrOp>(
+ detachClause->v, converter, semanticsContext, stmtCtx, detachOperands,
+ mlir::acc::DataClause::acc_detach, false);
} else if (std::get_if<Fortran::parser::AccClause::Finalize>(&clause.u)) {
addFinalizeAttr = true;
}
}
+ dataClauseOperands.append(copyoutOperands);
+ dataClauseOperands.append(deleteOperands);
+ dataClauseOperands.append(detachOperands);
+
// Prepare the operand segment size attribute and the operands value range.
llvm::SmallVector<mlir::Value, 14> operands;
llvm::SmallVector<int32_t, 7> operandSegments;
@@ -1249,20 +1296,25 @@ genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
addOperand(operands, operandSegments, async);
addOperand(operands, operandSegments, waitDevnum);
addOperands(operands, operandSegments, waitOperands);
- addOperands(operands, operandSegments, copyoutOperands);
- addOperands(operands, operandSegments, deleteOperands);
- addOperands(operands, operandSegments, detachOperands);
+ operandSegments.append({0, 0, 0});
addOperands(operands, operandSegments, dataClauseOperands);
mlir::acc::ExitDataOp exitDataOp = createSimpleOp<mlir::acc::ExitDataOp>(
- firOpBuilder, currentLocation, operands, operandSegments);
+ builder, currentLocation, operands, operandSegments);
if (addAsyncAttr)
- exitDataOp.setAsyncAttr(firOpBuilder.getUnitAttr());
+ exitDataOp.setAsyncAttr(builder.getUnitAttr());
if (addWaitAttr)
- exitDataOp.setWaitAttr(firOpBuilder.getUnitAttr());
+ exitDataOp.setWaitAttr(builder.getUnitAttr());
if (addFinalizeAttr)
- exitDataOp.setFinalizeAttr(firOpBuilder.getUnitAttr());
+ exitDataOp.setFinalizeAttr(builder.getUnitAttr());
+
+ genDataExitOperantions<mlir::acc::CopyoutOp>(
+ builder, copyoutOperands, /*structured=*/false, /*implicit=*/false);
+ genDataExitOperantions<mlir::acc::DeleteOp>(
+ builder, deleteOperands, /*structured=*/false, /*implicit=*/false);
+ genDataExitOperantions<mlir::acc::DetachOp>(
+ builder, detachOperands, /*structured=*/false, /*implicit=*/false);
}
template <typename Op>
diff --git a/flang/test/Lower/OpenACC/acc-exit-data.f90 b/flang/test/Lower/OpenACC/acc-exit-data.f90
index 5bae065bf1ea6..88ed4f580a9fe 100644
--- a/flang/test/Lower/OpenACC/acc-exit-data.f90
+++ b/flang/test/Lower/OpenACC/acc-exit-data.f90
@@ -8,59 +8,96 @@ subroutine acc_exit_data
real, pointer :: d
logical :: ifCondition = .TRUE.
-!CHECK: [[A:%.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"}
-!CHECK: [[B:%.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"}
-!CHECK: [[C:%.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"}
-!CHECK: [[D:%.*]] = fir.alloca !fir.box<!fir.ptr<f32>> {bindc_name = "d", uniq_name = "{{.*}}Ed"}
+!CHECK: %[[A:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"}
+!CHECK: %[[B:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"}
+!CHECK: %[[C:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"}
+!CHECK: %[[D:.*]] = fir.alloca !fir.box<!fir.ptr<f32>> {bindc_name = "d", uniq_name = "{{.*}}Ed"}
!$acc exit data delete(a)
-!CHECK: acc.exit_data delete([[A]] : !fir.ref<!fir.array<10x10xf32>>){{$}}
+!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "a", structured = false}
+!CHECK: acc.exit_data dataOperands(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>)
+!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false}
!$acc exit data delete(a) if(.true.)
-!CHECK: [[IF1:%.*]] = arith.constant true
-!CHECK: acc.exit_data if([[IF1]]) delete([[A]] : !fir.ref<!fir.array<10x10xf32>>){{$}}
+!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "a", structured = false}
+!CHECK: %[[IF1:.*]] = arith.constant true
+!CHECK: acc.exit_data if(%[[IF1]]) dataOperands(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>)
+!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false}
!$acc exit data delete(a) if(ifCondition)
-!CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref<!fir.logical<4>>
-!CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1
-!CHECK: acc.exit_data if([[IF2]]) delete([[A]] : !fir.ref<!fir.array<10x10xf32>>){{$}}
+!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "a", structured = false}
+!CHECK: %[[IFCOND:.*]] = fir.load %{{.*}} : !fir.ref<!fir.logical<4>>
+!CHECK: %[[IF2:.*]] = fir.convert %[[IFCOND]] : (!fir.logical<4>) -> i1
+!CHECK: acc.exit_data if(%[[IF2]]) dataOperands(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>){{$}}
+!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false}
!$acc exit data delete(a) delete(b) delete(c)
-!CHECK: acc.exit_data delete([[A]], [[B]], [[C]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>){{$}}
+!CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "a", structured = false}
+!CHECK: %[[DEVPTR_B:.*]] = acc.getdeviceptr varPtr(%[[B]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "b", structured = false}
+!CHECK: %[[DEVPTR_C:.*]] = acc.getdeviceptr varPtr(%[[C]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "c", structured = false}
+!CHECK: acc.exit_data dataOperands(%[[DEVPTR_A]], %[[DEVPTR_B]], %[[DEVPTR_C]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>){{$}}
+!CHECK: acc.delete accPtr(%[[DEVPTR_A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false}
+!CHECK: acc.delete accPtr(%[[DEVPTR_B]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "b", structured = false}
+!CHECK: acc.delete accPtr(%[[DEVPTR_C]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "c", structured = false}
!$acc exit data copyout(a) delete(b) detach(d)
-!CHECK: acc.exit_data copyout([[A]] : !fir.ref<!fir.array<10x10xf32>>) delete([[B]] : !fir.ref<!fir.array<10x10xf32>>) detach([[D]] : !fir.ref<!fir.box<!fir.ptr<f32>>>){{$}}
+!CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 4 : i64, name = "a", structured = false}
+!CHECK: %[[DEVPTR_B:.*]] = acc.getdeviceptr varPtr(%[[B]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "b", structured = false}
+!CHECK: %[[BOX_D:.*]] = fir.load %[[D]] : !fir.ref<!fir.box<!fir.ptr<f32>>>
+!CHECK: %[[D_ADDR:.*]] = fir.box_addr %[[BOX_D]] : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32>
+!CHECK: %[[DEVPTR_D:.*]] = acc.getdeviceptr varPtr(%[[D_ADDR]] : !fir.ptr<f32>) -> !fir.ptr<f32> {dataClause = 11 : i64, name = "d", structured = false}
+!CHECK: acc.exit_data dataOperands(%[[DEVPTR_A]], %[[DEVPTR_B]], %[[DEVPTR_D]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ptr<f32>)
+!CHECK: acc.copyout accPtr(%[[DEVPTR_A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) {name = "a", structured = false}
+!CHECK: acc.delete accPtr(%[[DEVPTR_B]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "b", structured = false}
+!CHECK: acc.detach accPtr(%[[DEVPTR_D]] : !fir.ptr<f32>) {name = "d", structured = false}
!$acc exit data delete(a) async
-!CHECK: acc.exit_data delete([[A]] : !fir.ref<!fir.array<10x10xf32>>) attributes {async}
+!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "a", structured = false}
+!CHECK: acc.exit_data dataOperands(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) attributes {async}
+!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false}
!$acc exit data delete(a) wait
-!CHECK: acc.exit_data delete([[A]] : !fir.ref<!fir.array<10x10xf32>>) attributes {wait}
+!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "a", structured = false}
+!CHECK: acc.exit_data dataOperands(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) attributes {wait}
+!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false}
!$acc exit data delete(a) async wait
-!CHECK: acc.exit_data delete([[A]] : !fir.ref<!fir.array<10x10xf32>>) attributes {async, wait}
+!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "a", structured = false}
+!CHECK: acc.exit_data dataOperands(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) attributes {async, wait}
+!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false}
!$acc exit data delete(a) async(1)
-!CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32
-!CHECK: acc.exit_data async([[ASYNC1]] : i32) delete([[A]] : !fir.ref<!fir.array<10x10xf32>>)
+!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "a", structured = false}
+!CHECK: %[[ASYNC1:.*]] = arith.constant 1 : i32
+!CHECK: acc.exit_data async(%[[ASYNC1]] : i32) dataOperands(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>)
+!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false}
+
!$acc exit data delete(a) async(async)
-!CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref<i32>
-!CHECK: acc.exit_data async([[ASYNC2]] : i32) delete([[A]] : !fir.ref<!fir.array<10x10xf32>>)
+!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "a", structured = false}
+!CHECK: %[[ASYNC2:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+!CHECK: acc.exit_data async(%[[ASYNC2]] : i32) dataOperands(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>)
+!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false}
!$acc exit data delete(a) wait(1)
-!CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32
-!CHECK: acc.exit_data wait([[WAIT1]] : i32) delete([[A]] : !fir.ref<!fir.array<10x10xf32>>)
+!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "a", structured = false}
+!CHECK: %[[WAIT1:.*]] = arith.constant 1 : i32
+!CHECK: acc.exit_data wait(%[[WAIT1]] : i32) dataOperands(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>)
+!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false}
!$acc exit data delete(a) wait(queues: 1, 2)
-!CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32
-!CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32
-!CHECK: acc.exit_data wait([[WAIT2]], [[WAIT3]] : i32, i32) delete([[A]] : !fir.ref<!fir.array<10x10xf32>>)
+!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "a", structured = false}
+!CHECK: %[[WAIT2:.*]] = arith.constant 1 : i32
+!CHECK: %[[WAIT3:.*]] = arith.constant 2 : i32
+!CHECK: acc.exit_data wait(%[[WAIT2]], %[[WAIT3]] : i32, i32) dataOperands(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>)
+!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false}
!$acc exit data delete(a) wait(devnum: 1: queues: 1, 2)
-!CHECK: [[WAIT4:%.*]] = arith.constant 1 : i32
-!CHECK: [[WAIT5:%.*]] = arith.constant 2 : i32
-!CHECK: [[WAIT6:%.*]] = arith.constant 1 : i32
-!CHECK: acc.exit_data wait_devnum([[WAIT6]] : i32) wait([[WAIT4]], [[WAIT5]] : i32, i32) delete([[A]] : !fir.ref<!fir.array<10x10xf32>>)
+!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 9 : i64, name = "a", structured = false}
+!CHECK: %[[WAIT4:.*]] = arith.constant 1 : i32
+!CHECK: %[[WAIT5:.*]] = arith.constant 2 : i32
+!CHECK: %[[WAIT6:.*]] = arith.constant 1 : i32
+!CHECK: acc.exit_data wait_devnum(%[[WAIT6]] : i32) wait(%[[WAIT4]], %[[WAIT5]] : i32, i32) dataOperands(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>)
+!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false}
end subroutine acc_exit_data
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index c027d0ce199a5..3c1c36778c6f6 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -293,8 +293,8 @@ def OpenACC_GetDevicePtrOp : OpenACC_DataEntryOp<"getdeviceptr",
class OpenACC_DataExitOp<string mnemonic, string clause, list<Trait> traits = []> :
OpenACC_Op<mnemonic, !listconcat(traits,
[AttrSizedOperandSegments])> {
- let arguments = (ins Optional<OpenACC_PointerLikeTypeInterface>:$varPtr,
- OpenACC_PointerLikeTypeInterface:$accPtr,
+ let arguments = (ins OpenACC_PointerLikeTypeInterface:$accPtr,
+ Optional<OpenACC_PointerLikeTypeInterface>:$varPtr,
Variadic<OpenACC_DataBoundsType>:$bounds,
DefaultValuedAttr<OpenACC_DataClauseEnum,clause>:$dataClause,
DefaultValuedAttr<BoolAttr, "true">:$structured,
More information about the flang-commits
mailing list