@@ -132,7 +132,8 @@ and optional list of `traits`, a list of `clauses` where all the applicable
132
132
would have to be defined in the operation's body are the ` summary ` and
133
133
` description ` . For the latter, only the operation itself would have to be
134
134
defined, and the description for its clause-inherited arguments is appended
135
- through the inherited ` clausesDescription ` property.
135
+ through the inherited ` clausesDescription ` property. By convention, the list of
136
+ clauses for an operation must be specified in alphabetical order.
136
137
137
138
If the operation is intended to have a single region, this is better achieved by
138
139
setting the ` singleRegion=true ` template argument of ` OpenMP_Op ` rather manually
@@ -285,7 +286,76 @@ argument's type:
285
286
specific ` mlir::Attribute ` subclass) will be used instead.
286
287
- Other attribute types will be represented with their ` storageType ` .
287
288
- It will create ` <Name>Operands ` structure for each operation, which is an
288
- empty structure subclassing all operand structures defined for the corresponding ` OpenMP_Op ` 's clauses.
289
+ empty structure subclassing all operand structures defined for the corresponding
290
+ ` OpenMP_Op ` 's clauses.
291
+
292
+ ### Entry Block Argument-Defining Clauses
293
+
294
+ In their MLIR representation, certain OpenMP clauses introduce a mapping between
295
+ values defined outside the operation they are applied to and entry block
296
+ arguments for the region of that MLIR operation. This enables, for example, the
297
+ introduction of private copies of the same underlying variable defined outside
298
+ the MLIR operation the clause is attached to. Currently, clauses with this
299
+ property can be classified into three main categories:
300
+ - Map-like clauses: ` map ` , ` use_device_addr ` and ` use_device_ptr ` .
301
+ - Reduction-like clauses: ` in_reduction ` , ` reduction ` and ` task_reduction ` .
302
+ - Privatization clauses: ` private ` .
303
+
304
+ All three kinds of entry block argument-defining clauses use a similar custom
305
+ assembly format representation, only differing based on the different pieces of
306
+ information attached to each kind. Below, one example of each is shown:
307
+
308
+ ``` mlir
309
+ omp.target map_entries(%x -> %x.m, %y -> %y.m : !llvm.ptr, !llvm.ptr) {
310
+ // Use %x.m, %y.m in place of %x and %y...
311
+ }
312
+
313
+ omp.wsloop reduction(@add.i32 %x -> %x.r, byref @add.f32 %y -> %y.r : !llvm.ptr, !llvm.ptr) {
314
+ // Use %x.r, %y.r in place of %x and %y...
315
+ }
316
+
317
+ omp.parallel private(@x.privatizer %x -> %x.p, @y.privatizer %y -> %y.p : !llvm.ptr, !llvm.ptr) {
318
+ // Use %x.p, %y.p in place of %x and %y...
319
+ }
320
+ ```
321
+
322
+ As a consequence of parsing and printing the operation's first region entry
323
+ block argument names together with the custom assembly format of these clauses,
324
+ entry block arguments (i.e. the ` ^bb0(...): ` line) must not be explicitly
325
+ defined for these operations. Additionally, it is not possible to implement this
326
+ feature while allowing each clause to be independently parsed and printed,
327
+ because they need to be printed/parsed together with the corresponding
328
+ operation's first region. They must have a well-defined ordering in which
329
+ multiple of these clauses are specified for a given operation, as well.
330
+
331
+ The parsing/printing of these clauses together with the region provides the
332
+ ability to define entry block arguments directly after the ` -> ` . Forcing a
333
+ specific ordering between these clauses makes the block argument ordering
334
+ well-defined, which is the property used to easily match each clause with the
335
+ entry block arguments defined by it.
336
+
337
+ Custom printers and parsers for operation regions based on the entry block
338
+ argument-defining clauses they take are implemented based on the
339
+ ` {parse,print}BlockArgRegion ` functions, which take care of the sorting and
340
+ formatting of each kind of clause, minimizing code duplication resulting from
341
+ this approach. One example of the custom assembly format of an operation taking
342
+ the ` private ` and ` reduction ` clauses is the following:
343
+
344
+ ``` tablegen
345
+ let assemblyFormat = clausesAssemblyFormat # [{
346
+ custom<PrivateReductionRegion>($region, $private_vars, type($private_vars),
347
+ $private_syms, $reduction_vars, type($reduction_vars), $reduction_byref,
348
+ $reduction_syms) attr-dict
349
+ }];
350
+ ```
351
+
352
+ The ` BlockArgOpenMPOpInterface ` has been introduced to simplify the addition and
353
+ handling of these kinds of clauses. It holds ` num<ClauseName>BlockArgs() `
354
+ functions that by default return 0, to be overriden by each clause through the
355
+ ` extraClassDeclaration ` property. Based on these functions and the expected
356
+ alphabetical sorting between entry block argument-defining clauses, it
357
+ implements ` get<ClauseName>BlockArgs() ` functions that are the intended method
358
+ of accessing clause-defined block arguments.
289
359
290
360
## Loop-Associated Directives
291
361
0 commit comments