@@ -66,7 +66,7 @@ def OpenMP_PointerLikeType : Type<
66
66
def ParallelOp : OpenMP_Op<"parallel", [
67
67
AutomaticAllocationScope, AttrSizedOperandSegments,
68
68
DeclareOpInterfaceMethods<OutlineableOpenMPOpInterface>,
69
- RecursiveSideEffects]> {
69
+ RecursiveSideEffects, ReductionClauseInterface ]> {
70
70
let summary = "parallel construct";
71
71
let description = [{
72
72
The parallel construct includes a region of code which is to be executed
@@ -83,6 +83,18 @@ def ParallelOp : OpenMP_Op<"parallel", [
83
83
The $allocators_vars and $allocate_vars parameters are a variadic list of values
84
84
that specify the memory allocator to be used to obtain storage for private values.
85
85
86
+ Reductions can be performed in a parallel construct by specifying reduction
87
+ accumulator variables in `reduction_vars` and symbols referring to reduction
88
+ declarations in the `reductions` attribute. Each reduction is identified
89
+ by the accumulator it uses and accumulators must not be repeated in the same
90
+ reduction. The `omp.reduction` operation accepts the accumulator and a
91
+ partial value which is considered to be produced by the thread for the
92
+ given reduction. If multiple values are produced for the same accumulator,
93
+ i.e. there are multiple `omp.reduction`s, the last value is taken. The
94
+ reduction declaration specifies how to combine the values from each thread
95
+ into the final value, which is available in the accumulator after all the
96
+ threads complete.
97
+
86
98
The optional $proc_bind_val attribute controls the thread affinity for the execution
87
99
of the parallel region.
88
100
}];
@@ -91,6 +103,8 @@ def ParallelOp : OpenMP_Op<"parallel", [
91
103
Optional<AnyType>:$num_threads_var,
92
104
Variadic<AnyType>:$allocate_vars,
93
105
Variadic<AnyType>:$allocators_vars,
106
+ Variadic<OpenMP_PointerLikeType>:$reduction_vars,
107
+ OptionalAttr<SymbolRefArrayAttr>:$reductions,
94
108
OptionalAttr<ProcBindKindAttr>:$proc_bind_val);
95
109
96
110
let regions = (region AnyRegion:$region);
@@ -99,7 +113,11 @@ def ParallelOp : OpenMP_Op<"parallel", [
99
113
OpBuilder<(ins CArg<"ArrayRef<NamedAttribute>", "{}">:$attributes)>
100
114
];
101
115
let assemblyFormat = [{
102
- oilist( `if` `(` $if_expr_var `:` type($if_expr_var) `)`
116
+ oilist( `reduction` `(`
117
+ custom<ReductionVarList>(
118
+ $reduction_vars, type($reduction_vars), $reductions
119
+ ) `)`
120
+ | `if` `(` $if_expr_var `:` type($if_expr_var) `)`
103
121
| `num_threads` `(` $num_threads_var `:` type($num_threads_var) `)`
104
122
| `allocate` `(`
105
123
custom<AllocateAndAllocator>(
@@ -110,6 +128,12 @@ def ParallelOp : OpenMP_Op<"parallel", [
110
128
) $region attr-dict
111
129
}];
112
130
let hasVerifier = 1;
131
+ let extraClassDeclaration = [{
132
+ // TODO: remove this once emitAccessorPrefix is set to
133
+ // kEmitAccessorPrefix_Prefixed for the dialect.
134
+ /// Returns the reduction variables
135
+ operand_range getReductionVars() { return reduction_vars(); }
136
+ }];
113
137
}
114
138
115
139
def TerminatorOp : OpenMP_Op<"terminator", [Terminator]> {
@@ -156,7 +180,8 @@ def SectionOp : OpenMP_Op<"section", [HasParent<"SectionsOp">]> {
156
180
let assemblyFormat = "$region attr-dict";
157
181
}
158
182
159
- def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments]> {
183
+ def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments,
184
+ ReductionClauseInterface]> {
160
185
let summary = "sections construct";
161
186
let description = [{
162
187
The sections construct is a non-iterative worksharing construct that
@@ -207,6 +232,13 @@ def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments]> {
207
232
208
233
let hasVerifier = 1;
209
234
let hasRegionVerifier = 1;
235
+
236
+ let extraClassDeclaration = [{
237
+ // TODO: remove this once emitAccessorPrefix is set to
238
+ // kEmitAccessorPrefix_Prefixed for the dialect.
239
+ /// Returns the reduction variables
240
+ operand_range getReductionVars() { return reduction_vars(); }
241
+ }];
210
242
}
211
243
212
244
//===----------------------------------------------------------------------===//
@@ -247,7 +279,7 @@ def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments]> {
247
279
248
280
def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
249
281
AllTypesMatch<["lowerBound", "upperBound", "step"]>,
250
- RecursiveSideEffects]> {
282
+ RecursiveSideEffects, ReductionClauseInterface ]> {
251
283
let summary = "workshare loop construct";
252
284
let description = [{
253
285
The workshare loop construct specifies that the iterations of the loop(s)
@@ -338,6 +370,11 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
338
370
339
371
/// Returns the number of reduction variables.
340
372
unsigned getNumReductionVars() { return reduction_vars().size(); }
373
+
374
+ // TODO: remove this once emitAccessorPrefix is set to
375
+ // kEmitAccessorPrefix_Prefixed for the dialect.
376
+ /// Returns the reduction variables
377
+ operand_range getReductionVars() { return reduction_vars(); }
341
378
}];
342
379
let hasCustomAssemblyFormat = 1;
343
380
let assemblyFormat = [{
0 commit comments