diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td --- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td +++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td @@ -87,6 +87,7 @@ def OpenACC_UpdateHost : I64EnumAttrCase<"acc_update_host", 17>; def OpenACC_UpdateSelf : I64EnumAttrCase<"acc_update_self", 18>; def OpenACC_UpdateDevice : I64EnumAttrCase<"acc_update_device", 19>; +def OpenACC_UseDevice : I64EnumAttrCase<"acc_use_device", 20>; def OpenACC_DataClauseEnum : I64EnumAttr<"DataClause", "data clauses supported by OpenACC", @@ -96,7 +97,7 @@ OpenACC_AttachClause, OpenACC_DetachClause, OpenACC_NoCreateClause, OpenACC_PrivateClause, OpenACC_FirstPrivateClause, OpenACC_IsDevicePtrClause, OpenACC_GetDevicePtrClause, OpenACC_UpdateHost, - OpenACC_UpdateSelf, OpenACC_UpdateDevice, + OpenACC_UpdateSelf, OpenACC_UpdateDevice, OpenACC_UseDevice, ]> { let cppNamespace = "::mlir::acc"; } @@ -298,6 +299,14 @@ let summary = "Represents acc update device semantics."; } +//===----------------------------------------------------------------------===// +// 2.8 use_device clause +//===----------------------------------------------------------------------===// +def OpenACC_UseDeviceOp : OpenACC_DataEntryOp<"use_device", + "mlir::acc::DataClause::acc_use_device"> { + let summary = "Represents acc use_device semantics."; +} + // Data exit operation does not refer to OpenACC spec terminology, but to // terminology used in this dialect. It refers to data operations that will appear // after data or compute region. It will be used as the base of acc dialect @@ -789,6 +798,43 @@ let hasVerifier = 1; } +//===----------------------------------------------------------------------===// +// 2.8 Host_Data Construct +//===----------------------------------------------------------------------===// + +def OpenACC_HostDataOp : OpenACC_Op<"host_data", [AttrSizedOperandSegments]> { + let summary = "host_data construct"; + + let description = [{ + The "acc.host_data" operation represents the OpenACC host_data construct. + + Example: + + ```mlir + %0 = acc.use_device varPtr(%a : !llvm.ptr) -> !llvm.ptr + acc.host_data dataOperands(%0 : !llvm.ptr) { + + } + ``` + }]; + + let arguments = (ins Optional:$ifCond, + Variadic:$dataOperands, + UnitAttr:$ifPresent); + + let regions = (region AnyRegion:$region); + + let assemblyFormat = [{ + oilist( + `if` `(` $ifCond `)` + | `dataOperands` `(` $dataOperands `:` type($dataOperands) `)` + ) + $region attr-dict-with-keyword + }]; + + let hasVerifier = 1; +} + //===----------------------------------------------------------------------===// // 2.9 loop Construct //===----------------------------------------------------------------------===// 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 @@ -235,6 +235,18 @@ return success(); } +//===----------------------------------------------------------------------===// +// UseDeviceOp +//===----------------------------------------------------------------------===// +LogicalResult acc::UseDeviceOp::verify() { + // Test for all clauses this operation can be decomposed from: + if (getDataClause() != acc::DataClause::acc_use_device) + return emitError( + "data clause associated with use_device operation must match its intent" + " or specify original clause this operation was decomposed from"); + return success(); +} + template static ParseResult parseRegions(OpAsmParser &parser, OperationState &state, unsigned nRegions = 1) { @@ -370,6 +382,21 @@ return checkDataOperands(*this, getDataClauseOperands()); } +//===----------------------------------------------------------------------===// +// HostDataOp +//===----------------------------------------------------------------------===// + +LogicalResult acc::HostDataOp::verify() { + if (getDataOperands().empty()) + return emitError("at least one operand must appear on the host_data " + "operation"); + + for (mlir::Value operand : getDataOperands()) + if (!mlir::isa(operand.getDefiningOp())) + return emitError("expect data entry operation as defining op"); + return success(); +} + //===----------------------------------------------------------------------===// // LoopOp //===----------------------------------------------------------------------===// diff --git a/mlir/test/Dialect/OpenACC/ops.mlir b/mlir/test/Dialect/OpenACC/ops.mlir --- a/mlir/test/Dialect/OpenACC/ops.mlir +++ b/mlir/test/Dialect/OpenACC/ops.mlir @@ -1314,3 +1314,24 @@ acc.update dataOperands(%accPtr : memref<10xf32>) return } + +// ----- + +func.func @host_data_ops(%a: !llvm.ptr, %ifCond: i1) -> () { + %0 = acc.use_device varPtr(%a : !llvm.ptr) -> !llvm.ptr + acc.host_data dataOperands(%0: !llvm.ptr) { + } + acc.host_data dataOperands(%0: !llvm.ptr) { + } attributes {if_present} + acc.host_data if(%ifCond) dataOperands(%0: !llvm.ptr) { + } + return +} + +// CHECK-LABEL: func.func @host_data_ops( +// CHECK-SAME: %[[A:.*]]: !llvm.ptr, %[[IFCOND:.*]]: i1) +// CHECK: %[[PTR:.*]] = acc.use_device varPtr(%[[A]] : !llvm.ptr) -> !llvm.ptr +// CHECK: acc.host_data dataOperands(%[[PTR]] : !llvm.ptr) +// CHECK: acc.host_data dataOperands(%[[PTR]] : !llvm.ptr) { +// CHECK: } attributes {if_present} +// CHECK: acc.host_data if(%[[IFCOND]]) dataOperands(%[[PTR]] : !llvm.ptr)