Skip to content

[MLIR][OpenMP] Document entry block argument-defining clauses (NFC) #109811

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 1, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 72 additions & 2 deletions mlir/docs/Dialects/OpenMPDialect/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ and optional list of `traits`, a list of `clauses` where all the applicable
would have to be defined in the operation's body are the `summary` and
`description`. For the latter, only the operation itself would have to be
defined, and the description for its clause-inherited arguments is appended
through the inherited `clausesDescription` property.
through the inherited `clausesDescription` property. By convention, the list of
clauses for an operation must be specified in alphabetical order.

If the operation is intended to have a single region, this is better achieved by
setting the `singleRegion=true` template argument of `OpenMP_Op` rather manually
Expand Down Expand Up @@ -285,7 +286,76 @@ argument's type:
specific `mlir::Attribute` subclass) will be used instead.
- Other attribute types will be represented with their `storageType`.
- It will create `<Name>Operands` structure for each operation, which is an
empty structure subclassing all operand structures defined for the corresponding `OpenMP_Op`'s clauses.
empty structure subclassing all operand structures defined for the corresponding
`OpenMP_Op`'s clauses.

### Entry Block Argument-Defining Clauses

In their MLIR representation, certain OpenMP clauses introduce a mapping between
values defined outside the operation they are applied to and entry block
arguments for the region of that MLIR operation. This enables, for example, the
introduction of private copies of the same underlying variable defined outside
the MLIR operation the clause is attached to. Currently, clauses with this
property can be classified into three main categories:
- Map-like clauses: `map`, `use_device_addr` and `use_device_ptr`.
- Reduction-like clauses: `in_reduction`, `reduction` and `task_reduction`.
- Privatization clauses: `private`.

All three kinds of entry block argument-defining clauses use a similar custom
assembly format representation, only differing based on the different pieces of
information attached to each kind. Below, one example of each is shown:

```mlir
omp.target map_entries(%x -> %x.m, %y -> %y.m : !llvm.ptr, !llvm.ptr) {
// Use %x.m, %y.m in place of %x and %y...
}

omp.wsloop reduction(@add.i32 %x -> %x.r, byref @add.f32 %y -> %y.r : !llvm.ptr, !llvm.ptr) {
// Use %x.r, %y.r in place of %x and %y...
}

omp.parallel private(@x.privatizer %x -> %x.p, @y.privatizer %y -> %y.p : !llvm.ptr, !llvm.ptr) {
// Use %x.p, %y.p in place of %x and %y...
}
```

As a consequence of parsing and printing the operation's first region entry
block argument names together with the custom assembly format of these clauses,
entry block arguments (i.e. the `^bb0(...):` line) must not be explicitly
defined for these operations. Additionally, it is not possible to implement this
feature while allowing each clause to be independently parsed and printed,
because they need to be printed/parsed together with the corresponding
operation's first region. They must have a well-defined ordering in which
multiple of these clauses are specified for a given operation, as well.

The parsing/printing of these clauses together with the region provides the
ability to define entry block arguments directly after the `->`. Forcing a
specific ordering between these clauses makes the block argument ordering
well-defined, which is the property used to easily match each clause with the
entry block arguments defined by it.

Custom printers and parsers for operation regions based on the entry block
argument-defining clauses they take are implemented based on the
`{parse,print}BlockArgRegion` functions, which take care of the sorting and
formatting of each kind of clause, minimizing code duplication resulting from
this approach. One example of the custom assembly format of an operation taking
the `private` and `reduction` clauses is the following:

```tablegen
let assemblyFormat = clausesAssemblyFormat # [{
custom<PrivateReductionRegion>($region, $private_vars, type($private_vars),
$private_syms, $reduction_vars, type($reduction_vars), $reduction_byref,
$reduction_syms) attr-dict
}];
```

The `BlockArgOpenMPOpInterface` has been introduced to simplify the addition and
handling of these kinds of clauses. It holds `num<ClauseName>BlockArgs()`
functions that by default return 0, to be overriden by each clause through the
`extraClassDeclaration` property. Based on these functions and the expected
alphabetical sorting between entry block argument-defining clauses, it
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am assuming the tablegen backend for openmp that you have implemented doesn't do the sorting and the onus for the alphabetical sorting is on the user, correct? If that's the case i think that expectation must be made explicit, either here or (preferably) in Adding an Operation

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In reality the alphabetical sorting of entry block argument-defining clauses is enforced by the custom parsers/printers and the interface itself, regardless of the order in which these clauses are specified in the operation's definition by the user. Either way, I think it's a good idea to state in the section you mention that the convention is to specify clauses in alphabetical order.

implements `get<ClauseName>BlockArgs()` functions that are the intended method
of accessing clause-defined block arguments.

## Loop-Associated Directives

Expand Down
Loading