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<AnyType>:$allocate_vars,
+ Variadic<AnyType>:$allocators_vars,
+ UnitAttr:$nowait);
+
+ let regions = (region SizedRegion<1>:$region);
+
+ let assemblyFormat = [{
+ oilist(`allocate` `(`
+ custom<AllocateAndAllocator>(
+ $allocate_vars, type($allocate_vars),
+ $allocators_vars, type($allocators_vars)
+ ) `)`
+ |`nowait` $nowait
+ ) $region attr-dict
+ }];
+ let hasVerifier = 1;
+}
+
//===----------------------------------------------------------------------===//
// 2.9.2 Workshare Loop Construct
//===----------------------------------------------------------------------===//
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
//===----------------------------------------------------------------------===//
}
return
}
+
+// -----
+
+func @omp_single(%data_var : memref<i32>) -> () {
+ // 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<i32>) -> ()
+ return
+}
}
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<i32>) {
+ omp.parallel {
+ // CHECK: omp.single allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) {
+ omp.single allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
+ "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<i32>) {
+ omp.parallel {
+ // CHECK: omp.single allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) nowait {
+ omp.single allocate(%data_var : memref<i32> -> %data_var : memref<i32>) nowait {
+ "test.payload"() : () -> ()
+ // CHECK: omp.terminator
+ omp.terminator
+ }
+ // CHECK: omp.terminator
+ omp.terminator
+ }
+ return
+}