Skip to content

Commit 980d5fb

Browse files
authored
[MLIR][omp] Add omp operations for OpenMP workshare (#101443)
Add the `omp.workshare` and `omp.workshare.loop_wrapper` operations used for the implementation of the `workshare` construct in flang.
1 parent 55068dc commit 980d5fb

File tree

4 files changed

+169
-0
lines changed

4 files changed

+169
-0
lines changed

mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,49 @@ def SingleOp : OpenMP_Op<"single", traits = [
313313
let hasVerifier = 1;
314314
}
315315

316+
//===----------------------------------------------------------------------===//
317+
// 2.8.3 Workshare Construct
318+
//===----------------------------------------------------------------------===//
319+
320+
def WorkshareOp : OpenMP_Op<"workshare", traits = [
321+
RecursiveMemoryEffects,
322+
], clauses = [
323+
OpenMP_NowaitClause,
324+
], singleRegion = true> {
325+
let summary = "workshare directive";
326+
let description = [{
327+
The workshare construct divides the execution of the enclosed structured
328+
block into separate units of work, and causes the threads of the team to
329+
share the work such that each unit is executed only once by one thread, in
330+
the context of its implicit task
331+
332+
This operation is used for the intermediate representation of the workshare
333+
block before the work gets divided between the threads. See the flang
334+
LowerWorkshare pass for details.
335+
}] # clausesDescription;
336+
337+
let builders = [
338+
OpBuilder<(ins CArg<"const WorkshareOperands &">:$clauses)>
339+
];
340+
}
341+
342+
def WorkshareLoopWrapperOp : OpenMP_Op<"workshare.loop_wrapper", traits = [
343+
DeclareOpInterfaceMethods<LoopWrapperInterface>, NoTerminator,
344+
RecursiveMemoryEffects, SingleBlock
345+
], singleRegion = true> {
346+
let summary = "contains loop nests to be parallelized by workshare";
347+
let description = [{
348+
This operation wraps a loop nest that is marked for dividing into units of
349+
work by an encompassing omp.workshare operation.
350+
}];
351+
352+
let builders = [
353+
OpBuilder<(ins), [{ build($_builder, $_state, {}); }]>
354+
];
355+
let assemblyFormat = "$region attr-dict";
356+
let hasVerifier = 1;
357+
}
358+
316359
//===----------------------------------------------------------------------===//
317360
// Loop Nest
318361
//===----------------------------------------------------------------------===//

mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,6 +1897,27 @@ LogicalResult SingleOp::verify() {
18971897
getCopyprivateSyms());
18981898
}
18991899

1900+
//===----------------------------------------------------------------------===//
1901+
// WorkshareOp
1902+
//===----------------------------------------------------------------------===//
1903+
1904+
void WorkshareOp::build(OpBuilder &builder, OperationState &state,
1905+
const WorkshareOperands &clauses) {
1906+
WorkshareOp::build(builder, state, clauses.nowait);
1907+
}
1908+
1909+
//===----------------------------------------------------------------------===//
1910+
// WorkshareLoopWrapperOp
1911+
//===----------------------------------------------------------------------===//
1912+
1913+
LogicalResult WorkshareLoopWrapperOp::verify() {
1914+
if (!(*this)->getParentOfType<WorkshareOp>())
1915+
return emitError() << "must be nested in an omp.workshare";
1916+
if (getNestedWrapper())
1917+
return emitError() << "cannot be composite";
1918+
return success();
1919+
}
1920+
19001921
//===----------------------------------------------------------------------===//
19011922
// LoopWrapperInterface
19021923
//===----------------------------------------------------------------------===//

mlir/test/Dialect/OpenMP/invalid.mlir

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2620,6 +2620,44 @@ func.func @omp_loop_invalid_binding(%lb : index, %ub : index, %step : index) {
26202620
omp.yield
26212621
}
26222622
}
2623+
return
2624+
}
2625+
2626+
// -----
2627+
func.func @nested_wrapper(%idx : index) {
2628+
omp.workshare {
2629+
// expected-error @below {{cannot be composite}}
2630+
omp.workshare.loop_wrapper {
2631+
omp.simd {
2632+
omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
2633+
omp.yield
2634+
}
2635+
} {omp.composite}
2636+
}
2637+
omp.terminator
2638+
}
2639+
return
2640+
}
2641+
2642+
// -----
2643+
func.func @not_wrapper() {
2644+
omp.workshare {
2645+
// expected-error @below {{op nested in loop wrapper is not another loop wrapper or `omp.loop_nest`}}
2646+
omp.workshare.loop_wrapper {
2647+
%0 = arith.constant 0 : index
2648+
}
2649+
omp.terminator
2650+
}
2651+
return
2652+
}
26232653

2654+
// -----
2655+
func.func @missing_workshare(%idx : index) {
2656+
// expected-error @below {{must be nested in an omp.workshare}}
2657+
omp.workshare.loop_wrapper {
2658+
omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
2659+
omp.yield
2660+
}
2661+
}
26242662
return
26252663
}

mlir/test/Dialect/OpenMP/ops.mlir

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2789,3 +2789,70 @@ func.func @omp_loop(%lb : index, %ub : index, %step : index) {
27892789

27902790
return
27912791
}
2792+
2793+
// CHECK-LABEL: func @omp_workshare
2794+
func.func @omp_workshare() {
2795+
// CHECK: omp.workshare {
2796+
omp.workshare {
2797+
"test.payload"() : () -> ()
2798+
// CHECK: omp.terminator
2799+
omp.terminator
2800+
}
2801+
return
2802+
}
2803+
2804+
// CHECK-LABEL: func @omp_workshare_nowait
2805+
func.func @omp_workshare_nowait() {
2806+
// CHECK: omp.workshare nowait {
2807+
omp.workshare nowait {
2808+
"test.payload"() : () -> ()
2809+
// CHECK: omp.terminator
2810+
omp.terminator
2811+
}
2812+
return
2813+
}
2814+
2815+
// CHECK-LABEL: func @omp_workshare_multiple_blocks
2816+
func.func @omp_workshare_multiple_blocks() {
2817+
// CHECK: omp.workshare {
2818+
omp.workshare {
2819+
cf.br ^bb2
2820+
^bb2:
2821+
// CHECK: omp.terminator
2822+
omp.terminator
2823+
}
2824+
return
2825+
}
2826+
2827+
// CHECK-LABEL: func @omp_workshare_loop_wrapper
2828+
func.func @omp_workshare_loop_wrapper(%idx : index) {
2829+
// CHECK-NEXT: omp.workshare {
2830+
omp.workshare {
2831+
// CHECK-NEXT: omp.workshare.loop_wrapper
2832+
omp.workshare.loop_wrapper {
2833+
// CHECK-NEXT: omp.loop_nest
2834+
omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
2835+
omp.yield
2836+
}
2837+
}
2838+
omp.terminator
2839+
}
2840+
return
2841+
}
2842+
2843+
// CHECK-LABEL: func @omp_workshare_loop_wrapper_attrs
2844+
func.func @omp_workshare_loop_wrapper_attrs(%idx : index) {
2845+
// CHECK-NEXT: omp.workshare {
2846+
omp.workshare {
2847+
// CHECK-NEXT: omp.workshare.loop_wrapper {
2848+
omp.workshare.loop_wrapper {
2849+
// CHECK-NEXT: omp.loop_nest
2850+
omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
2851+
omp.yield
2852+
}
2853+
// CHECK: } {attr_in_dict}
2854+
} {attr_in_dict}
2855+
omp.terminator
2856+
}
2857+
return
2858+
}

0 commit comments

Comments
 (0)