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 @@ -156,6 +156,88 @@ }]; } +//===----------------------------------------------------------------------===// +// 2.5.2 serial Construct +//===----------------------------------------------------------------------===// + +def OpenACC_SerialOp : OpenACC_Op<"serial", [AttrSizedOperandSegments]> { + let summary = "serial construct"; + let description = [{ + The "acc.serial" operation represents a serial construct block. It has + one region to be executed in serial on the current device. + + Example: + + ```mlir + acc.serial private(%c : memref<10xf32>) { + // serial region + } + ``` + }]; + + let arguments = (ins Optional:$async, + UnitAttr:$asyncAttr, + Variadic:$waitOperands, + UnitAttr:$waitAttr, + Optional:$ifCond, + Optional:$selfCond, + UnitAttr:$selfAttr, + OptionalAttr:$reductionOp, + Variadic:$reductionOperands, + Variadic:$copyOperands, + Variadic:$copyinOperands, + Variadic:$copyinReadonlyOperands, + Variadic:$copyoutOperands, + Variadic:$copyoutZeroOperands, + Variadic:$createOperands, + Variadic:$createZeroOperands, + Variadic:$noCreateOperands, + Variadic:$presentOperands, + Variadic:$devicePtrOperands, + Variadic:$attachOperands, + Variadic:$gangPrivateOperands, + Variadic:$gangFirstPrivateOperands, + OptionalAttr:$defaultAttr); + + let regions = (region AnyRegion:$region); + + let extraClassDeclaration = [{ + /// The number of data operands. + unsigned getNumDataOperands(); + + /// The i-th data operand passed. + Value getDataOperand(unsigned i); + }]; + + let assemblyFormat = [{ + oilist( + `attach` `(` $attachOperands `:` type($attachOperands) `)` + | `async` `(` $async `:` type($async) `)` + | `copy` `(` $copyOperands `:` type($copyOperands) `)` + | `copyin` `(` $copyinOperands `:` type($copyinOperands) `)` + | `copyin_readonly` `(` $copyinReadonlyOperands `:` + type($copyinReadonlyOperands) `)` + | `copyout` `(` $copyoutOperands `:` type($copyoutOperands) `)` + | `copyout_zero` `(` $copyoutZeroOperands `:` + type($copyoutZeroOperands) `)` + | `create` `(` $createOperands `:` type($createOperands) `)` + | `create_zero` `(` $createZeroOperands `:` + type($createZeroOperands) `)` + | `deviceptr` `(` $devicePtrOperands `:` type($devicePtrOperands) `)` + | `firstprivate` `(` $gangFirstPrivateOperands `:` + type($gangFirstPrivateOperands) `)` + | `no_create` `(` $noCreateOperands `:` type($noCreateOperands) `)` + | `private` `(` $gangPrivateOperands `:` type($gangPrivateOperands) `)` + | `present` `(` $presentOperands `:` type($presentOperands) `)` + | `wait` `(` $waitOperands `:` type($waitOperands) `)` + | `self` `(` $selfCond `)` + | `if` `(` $ifCond `)` + | `reduction` `(` $reductionOperands `:` type($reductionOperands) `)` + ) + $region attr-dict-with-keyword + }]; +} + //===----------------------------------------------------------------------===// // 2.6.5 data 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 @@ -187,6 +187,27 @@ return getOperand(getWaitOperands().size() + numOptional + i); } +//===----------------------------------------------------------------------===// +// SerialOp +//===----------------------------------------------------------------------===// + +unsigned SerialOp::getNumDataOperands() { + return getReductionOperands().size() + getCopyOperands().size() + + getCopyinOperands().size() + getCopyinReadonlyOperands().size() + + getCopyoutOperands().size() + getCopyoutZeroOperands().size() + + getCreateOperands().size() + getCreateZeroOperands().size() + + getNoCreateOperands().size() + getPresentOperands().size() + + getDevicePtrOperands().size() + getAttachOperands().size() + + getGangPrivateOperands().size() + getGangFirstPrivateOperands().size(); +} + +Value SerialOp::getDataOperand(unsigned i) { + unsigned numOptional = getAsync() ? 1 : 0; + numOptional += getIfCond() ? 1 : 0; + numOptional += getSelfCond() ? 1 : 0; + return getOperand(getWaitOperands().size() + numOptional + i); +} + //===----------------------------------------------------------------------===// // 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 @@ -484,6 +484,102 @@ // ----- +// ----- + +func.func @testserialop(%a: memref<10xf32>, %b: memref<10xf32>, %c: memref<10x10xf32>) -> () { + %i64value = arith.constant 1 : i64 + %i32value = arith.constant 1 : i32 + %idxValue = arith.constant 1 : index + acc.serial async(%i64value: i64) { + } + acc.serial async(%i32value: i32) { + } + acc.serial async(%idxValue: index) { + } + acc.serial wait(%i64value: i64) { + } + acc.serial wait(%i32value: i32) { + } + acc.serial wait(%idxValue: index) { + } + acc.serial wait(%i64value, %i32value, %idxValue : i64, i32, index) { + } + acc.serial copyin(%a, %b : memref<10xf32>, memref<10xf32>) { + } + acc.serial copyin_readonly(%a, %b : memref<10xf32>, memref<10xf32>) { + } + acc.serial copyin(%a: memref<10xf32>) copyout_zero(%b, %c : memref<10xf32>, memref<10x10xf32>) { + } + acc.serial copyout(%b, %c : memref<10xf32>, memref<10x10xf32>) create(%a: memref<10xf32>) { + } + acc.serial copyout_zero(%b, %c : memref<10xf32>, memref<10x10xf32>) create_zero(%a: memref<10xf32>) { + } + acc.serial no_create(%a: memref<10xf32>) present(%b, %c : memref<10xf32>, memref<10x10xf32>) { + } + acc.serial deviceptr(%a: memref<10xf32>) attach(%b, %c : memref<10xf32>, memref<10x10xf32>) { + } + acc.serial private(%a, %c : memref<10xf32>, memref<10x10xf32>) firstprivate(%b: memref<10xf32>) { + } + acc.serial { + } attributes {defaultAttr = #acc} + acc.serial { + } attributes {defaultAttr = #acc} + acc.serial { + } attributes {asyncAttr} + acc.serial { + } attributes {waitAttr} + acc.serial { + } attributes {selfAttr} + return +} + +// CHECK: func @testserialop([[ARGA:%.*]]: memref<10xf32>, [[ARGB:%.*]]: memref<10xf32>, [[ARGC:%.*]]: memref<10x10xf32>) { +// CHECK: [[I64VALUE:%.*]] = arith.constant 1 : i64 +// CHECK: [[I32VALUE:%.*]] = arith.constant 1 : i32 +// CHECK: [[IDXVALUE:%.*]] = arith.constant 1 : index +// CHECK: acc.serial async([[I64VALUE]] : i64) { +// CHECK-NEXT: } +// CHECK: acc.serial async([[I32VALUE]] : i32) { +// CHECK-NEXT: } +// CHECK: acc.serial async([[IDXVALUE]] : index) { +// CHECK-NEXT: } +// CHECK: acc.serial wait([[I64VALUE]] : i64) { +// CHECK-NEXT: } +// CHECK: acc.serial wait([[I32VALUE]] : i32) { +// CHECK-NEXT: } +// CHECK: acc.serial wait([[IDXVALUE]] : index) { +// CHECK-NEXT: } +// CHECK: acc.serial wait([[I64VALUE]], [[I32VALUE]], [[IDXVALUE]] : i64, i32, index) { +// CHECK-NEXT: } +// CHECK: acc.serial copyin([[ARGA]], [[ARGB]] : memref<10xf32>, memref<10xf32>) { +// CHECK-NEXT: } +// CHECK: acc.serial copyin_readonly([[ARGA]], [[ARGB]] : memref<10xf32>, memref<10xf32>) { +// CHECK-NEXT: } +// CHECK: acc.serial copyin([[ARGA]] : memref<10xf32>) copyout_zero([[ARGB]], [[ARGC]] : memref<10xf32>, memref<10x10xf32>) { +// CHECK-NEXT: } +// CHECK: acc.serial copyout([[ARGB]], [[ARGC]] : memref<10xf32>, memref<10x10xf32>) create([[ARGA]] : memref<10xf32>) { +// CHECK-NEXT: } +// CHECK: acc.serial copyout_zero([[ARGB]], [[ARGC]] : memref<10xf32>, memref<10x10xf32>) create_zero([[ARGA]] : memref<10xf32>) { +// CHECK-NEXT: } +// CHECK: acc.serial no_create([[ARGA]] : memref<10xf32>) present([[ARGB]], [[ARGC]] : memref<10xf32>, memref<10x10xf32>) { +// CHECK-NEXT: } +// CHECK: acc.serial attach([[ARGB]], [[ARGC]] : memref<10xf32>, memref<10x10xf32>) deviceptr([[ARGA]] : memref<10xf32>) { +// CHECK-NEXT: } +// CHECK: acc.serial firstprivate([[ARGB]] : memref<10xf32>) private([[ARGA]], [[ARGC]] : memref<10xf32>, memref<10x10xf32>) { +// CHECK-NEXT: } +// CHECK: acc.serial { +// CHECK-NEXT: } attributes {defaultAttr = #acc} +// CHECK: acc.serial { +// CHECK-NEXT: } attributes {defaultAttr = #acc} +// CHECK: acc.serial { +// CHECK-NEXT: } attributes {asyncAttr} +// CHECK: acc.serial { +// CHECK-NEXT: } attributes {waitAttr} +// CHECK: acc.serial { +// CHECK-NEXT: } attributes {selfAttr} + +// ----- + func.func @testdataop(%a: memref<10xf32>, %b: memref<10xf32>, %c: memref<10x10xf32>) -> () { %ifCond = arith.constant true acc.data if(%ifCond) present(%a : memref<10xf32>) {