diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -209,6 +209,38 @@ let hasRegionVerifier = 1; } +//===----------------------------------------------------------------------===// +// 2.8.2 Single Construct +//===----------------------------------------------------------------------===// + +def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments]> { + let summary = "single directive"; + let description = [{ + The single construct specifies that the associated structured block is + executed by only one of the threads in the team (not necessarily the + master thread), in the context of its implicit task. The other threads + in the team, which do not execute the block, wait at an implicit barrier + at the end of the single construct unless a nowait clause is specified. + }]; + + let arguments = (ins Variadic:$allocate_vars, + Variadic:$allocators_vars, + UnitAttr:$nowait); + + let regions = (region SizedRegion<1>:$region); + + let assemblyFormat = [{ + oilist(`allocate` `(` + custom( + $allocate_vars, type($allocate_vars), + $allocators_vars, type($allocators_vars) + ) `)` + |`nowait` $nowait + ) $region attr-dict + }]; + let hasVerifier = 1; +} + //===----------------------------------------------------------------------===// // 2.9.2 Workshare Loop Construct //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -492,6 +492,15 @@ return success(); } +LogicalResult SingleOp::verify() { + // Check for allocate clause restrictions + if (allocate_vars().size() != allocators_vars().size()) + return emitError( + "expected equal sizes for allocate and allocator variables"); + + return success(); +} + //===----------------------------------------------------------------------===// // WsLoopOp //===----------------------------------------------------------------------===// diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir --- a/mlir/test/Dialect/OpenMP/invalid.mlir +++ b/mlir/test/Dialect/OpenMP/invalid.mlir @@ -970,3 +970,13 @@ } return } + +// ----- + +func @omp_single(%data_var : memref) -> () { + // expected-error @below {{expected equal sizes for allocate and allocator variables}} + "omp.single" (%data_var) ({ + omp.barrier + }) {operand_segment_sizes = dense<[1,0]> : vector<2xi32>} : (memref) -> () + return +} diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -720,3 +720,63 @@ } return } + +// CHECK-LABEL: func @omp_single +func @omp_single() { + omp.parallel { + // CHECK: omp.single { + omp.single { + "test.payload"() : () -> () + // CHECK: omp.terminator + omp.terminator + } + // CHECK: omp.terminator + omp.terminator + } + return +} + +// CHECK-LABEL: func @omp_single_nowait +func @omp_single_nowait() { + omp.parallel { + // CHECK: omp.single nowait { + omp.single nowait { + "test.payload"() : () -> () + // CHECK: omp.terminator + omp.terminator + } + // CHECK: omp.terminator + omp.terminator + } + return +} + +// CHECK-LABEL: func @omp_single_allocate +func @omp_single_allocate(%data_var: memref) { + omp.parallel { + // CHECK: omp.single allocate(%{{.*}} : memref -> %{{.*}} : memref) { + omp.single allocate(%data_var : memref -> %data_var : memref) { + "test.payload"() : () -> () + // CHECK: omp.terminator + omp.terminator + } + // CHECK: omp.terminator + omp.terminator + } + return +} + +// CHECK-LABEL: func @omp_single_allocate_nowait +func @omp_single_allocate_nowait(%data_var: memref) { + omp.parallel { + // CHECK: omp.single allocate(%{{.*}} : memref -> %{{.*}} : memref) nowait { + omp.single allocate(%data_var : memref -> %data_var : memref) nowait { + "test.payload"() : () -> () + // CHECK: omp.terminator + omp.terminator + } + // CHECK: omp.terminator + omp.terminator + } + return +}