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 @@ -348,6 +348,36 @@ }]; } +//===----------------------------------------------------------------------===// +// 2.14.2. Shutdown +//===----------------------------------------------------------------------===// + +def OpenACC_ShutdownOp : OpenACC_Op<"shutdown", [AttrSizedOperandSegments]> { + let summary = "shutdown operation"; + + let description = [{ + The "acc.shutdown" operation represents the OpenACC shutdown executable + directive. + + Example: + + ```mlir + acc.shutdown + acc.shutdown device_num(%dev1 : i32) + ``` + }]; + + let arguments = (ins Variadic:$deviceTypeOperands, + Optional:$deviceNumOperand, + Optional:$ifCond); + + let assemblyFormat = [{ + ( `device_type` `(` $deviceTypeOperands^ `:` type($deviceTypeOperands) `)` )? + ( `device_num` `(` $deviceNumOperand^ `:` type($deviceNumOperand) `)` )? + ( `if` `(` $ifCond^ `)` )? attr-dict-with-keyword + }]; +} + //===----------------------------------------------------------------------===// // 2.14.4. Update Directive //===----------------------------------------------------------------------===// 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 @@ -149,6 +149,10 @@ return llvm::None; } +static bool isComputeOperation(Operation *op) { + return isa(op) || isa(op); +} + //===----------------------------------------------------------------------===// // ParallelOp //===----------------------------------------------------------------------===// @@ -655,12 +659,25 @@ static LogicalResult verify(acc::InitOp initOp) { Operation *currOp = initOp; while ((currOp = currOp->getParentOp())) { - if (isa(currOp) || isa(currOp)) + if (isComputeOperation(currOp)) return initOp.emitOpError("cannot be nested in a compute operation"); } return success(); } +//===----------------------------------------------------------------------===// +// ShutdownOp +//===----------------------------------------------------------------------===// + +static LogicalResult verify(acc::ShutdownOp op) { + Operation *currOp = op; + while ((currOp = currOp->getParentOp())) { + if (isComputeOperation(currOp)) + return op.emitOpError("cannot be nested in a compute operation"); + } + return success(); +} + //===----------------------------------------------------------------------===// // UpdateOp //===----------------------------------------------------------------------===// diff --git a/mlir/test/Dialect/OpenACC/invalid.mlir b/mlir/test/Dialect/OpenACC/invalid.mlir --- a/mlir/test/Dialect/OpenACC/invalid.mlir +++ b/mlir/test/Dialect/OpenACC/invalid.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt -split-input-file -verify-diagnostics %s +// RUN: mlir-opt -allow-unregistered-dialect -split-input-file -verify-diagnostics %s // expected-error@+1 {{gang, worker or vector cannot appear with the seq attr}} acc.loop gang { @@ -127,3 +127,29 @@ acc.init acc.yield } + +// ----- + +acc.parallel { +// expected-error@+1 {{'acc.shutdown' op cannot be nested in a compute operation}} + acc.shutdown + acc.yield +} + +// ----- + +acc.loop { +// expected-error@+1 {{'acc.shutdown' op cannot be nested in a compute operation}} + acc.shutdown + acc.yield +} + +// ----- + +acc.loop { + "some.op"() ({ + // expected-error@+1 {{'acc.shutdown' op cannot be nested in a compute operation}} + acc.shutdown + }) : () -> () + acc.yield +} 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 @@ -620,3 +620,31 @@ // CHECK: acc.init device_num([[I32VALUE]] : i32) // CHECK: acc.init device_num([[IDXVALUE]] : index) // CHECK: acc.init if([[IFCOND]]) + +// ----- + +%i64Value = constant 1 : i64 +%i32Value = constant 1 : i32 +%i32Value2 = constant 2 : i32 +%idxValue = constant 1 : index +%ifCond = constant true +acc.shutdown +acc.shutdown device_type(%i32Value : i32) +acc.shutdown device_type(%i32Value, %i32Value2 : i32, i32) +acc.shutdown device_num(%i64Value : i64) +acc.shutdown device_num(%i32Value : i32) +acc.shutdown device_num(%idxValue : index) +acc.shutdown if(%ifCond) + +// CHECK: [[I64VALUE:%.*]] = constant 1 : i64 +// CHECK: [[I32VALUE:%.*]] = constant 1 : i32 +// CHECK: [[I32VALUE2:%.*]] = constant 2 : i32 +// CHECK: [[IDXVALUE:%.*]] = constant 1 : index +// CHECK: [[IFCOND:%.*]] = constant true +// CHECK: acc.shutdown +// CHECK: acc.shutdown device_type([[I32VALUE]] : i32) +// CHECK: acc.shutdown device_type([[I32VALUE]], [[I32VALUE2]] : i32, i32) +// CHECK: acc.shutdown device_num([[I64VALUE]] : i64) +// CHECK: acc.shutdown device_num([[I32VALUE]] : i32) +// CHECK: acc.shutdown device_num([[IDXVALUE]] : index) +// CHECK: acc.shutdown if([[IFCOND]])