@@ -238,6 +238,55 @@ corresponding operation, except if it is explicitly skipped as described
238
238
tablegen failure while processing OpenMP dialect operations, earlier messages
239
239
triggered by that pass can point to a likely solution.
240
240
241
+ ### Operand Structures
242
+
243
+ One consequence of basing the representation of operations on the set of values
244
+ and attributes defined for each clause applicable to the corresponding OpenMP
245
+ directive is that operation argument lists tend to be long. This has the effect
246
+ of making C++ operation builders difficult to work with and easy to mistakenly
247
+ pass arguments in the wrong order, which may sometimes introduce hard to detect
248
+ problems.
249
+
250
+ A solution provided to this issue are operand structures. The main idea behind
251
+ them is that there is one defined for each clause, holding a set of fields that
252
+ contain the data needed to initialize each of the arguments associated with that
253
+ clause. Clause operand structures are aggregated into operation operand
254
+ structures via class inheritance. Then, a custom builder is defined for each
255
+ operation taking the corresponding operand structure as a parameter. Since each
256
+ argument is a named member of the structure, it becomes much simpler to set up
257
+ the desired arguments to create a new operation.
258
+
259
+ Ad-hoc operand structures available for use within the ODS definition of custom
260
+ operation builders might be defined in
261
+ [ OpenMPClauseOperands.h] ( https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h ) .
262
+ However, this is generally not needed for clause-based operation definitions.
263
+ The ` -gen-openmp-clause-ops ` tablegen backend, triggered when building the 'omp'
264
+ dialect, will automatically produce structures in the following way:
265
+
266
+ - It will create a ` <Name>ClauseOps ` structure for each ` OpenMP_Clause `
267
+ definition with one field per argument.
268
+ - The name of each field will match the tablegen name of the corresponding
269
+ argument, except for replacing snake case with camel case.
270
+ - The type of the field will be obtained from the corresponding tablegen
271
+ argument's type:
272
+ - Values are represented with ` mlir::Value ` , except for ` Variadic ` , which
273
+ makes it an ` llvm::SmallVector<mlir::Value> ` .
274
+ - ` OptionalAttr ` is represented by the translation of its ` baseAttr ` .
275
+ - ` TypedArrayAttrBase ` -based attribute types are represented by wrapping the
276
+ translation of their ` elementAttr ` in an ` llvm::SmallVector ` . The only
277
+ exception for this case is if the ` elementAttr ` is a "scalar" (i.e. non
278
+ array-like) attribute type, in which case the more generic ` mlir::Attribute `
279
+ will be used in place of its ` storageType ` .
280
+ - For ` ElementsAttrBase ` -based attribute types a best effort is attempted to
281
+ obtain an element type (` llvm::APInt ` , ` llvm::APFloat ` or
282
+ ` DenseArrayAttrBase ` 's ` returnType ` ) to be wrapped in an ` llvm::SmallVector ` .
283
+ If it cannot be obtained, which will happen with non-builtin direct subclasses
284
+ of ` ElementsAttrBase ` , a warning will be emitted and the ` storageType ` (i.e.
285
+ specific ` mlir::Attribute ` subclass) will be used instead.
286
+ - Other attribute types will be represented with their ` storageType ` .
287
+ - 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
+
241
290
## Loop-Associated Directives
242
291
243
292
Loop-associated OpenMP constructs are represented in the dialect as loop wrapper
0 commit comments