annotate mlir/docs/Traits.md @ 173:0572611fdcc8 llvm10 llvm12

reorgnization done
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 11:55:54 +0900
parents 1d019706d866
children 2e18cbf3894f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1 # Operation Traits
150
anatofuz
parents:
diff changeset
2
anatofuz
parents:
diff changeset
3 [TOC]
anatofuz
parents:
diff changeset
4
anatofuz
parents:
diff changeset
5 MLIR allows for a truly open operation ecosystem, as any dialect may define
anatofuz
parents:
diff changeset
6 operations that suit a specific level of abstraction. `Traits` are a mechanism
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
7 which abstracts implementation details and properties that are common
150
anatofuz
parents:
diff changeset
8 across many different operations. `Traits` may be used to specify special
anatofuz
parents:
diff changeset
9 properties and constraints of the operation, including whether the operation has
anatofuz
parents:
diff changeset
10 side effects or whether its output has the same type as the input. Some examples
anatofuz
parents:
diff changeset
11 of traits are `Commutative`, `SingleResult`, `Terminator`, etc. See the more
anatofuz
parents:
diff changeset
12 [comprehensive list](#traits) below for more examples of what is possible.
anatofuz
parents:
diff changeset
13
anatofuz
parents:
diff changeset
14 ## Defining a Trait
anatofuz
parents:
diff changeset
15
anatofuz
parents:
diff changeset
16 Traits may be defined in C++ by inheriting from the
anatofuz
parents:
diff changeset
17 `OpTrait::TraitBase<ConcreteType, TraitType>` class. This base class takes as
anatofuz
parents:
diff changeset
18 template parameters:
anatofuz
parents:
diff changeset
19
anatofuz
parents:
diff changeset
20 * ConcreteType
anatofuz
parents:
diff changeset
21 - The concrete operation type that this trait was attached to.
anatofuz
parents:
diff changeset
22 * TraitType
anatofuz
parents:
diff changeset
23 - The type of the trait class that is being defined, for use with the
anatofuz
parents:
diff changeset
24 [`Curiously Recurring Template Pattern`](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).
anatofuz
parents:
diff changeset
25
anatofuz
parents:
diff changeset
26 A derived trait class is expected to take a single template that corresponds to
anatofuz
parents:
diff changeset
27 the `ConcreteType`. An example trait definition is shown below:
anatofuz
parents:
diff changeset
28
anatofuz
parents:
diff changeset
29 ```c++
anatofuz
parents:
diff changeset
30 template <typename ConcreteType>
anatofuz
parents:
diff changeset
31 class MyTrait : public OpTrait::TraitBase<ConcreteType, MyTrait> {
anatofuz
parents:
diff changeset
32 };
anatofuz
parents:
diff changeset
33 ```
anatofuz
parents:
diff changeset
34
anatofuz
parents:
diff changeset
35 Derived traits may also provide a `verifyTrait` hook, that is called when
anatofuz
parents:
diff changeset
36 verifying the concrete operation. The trait verifiers will currently always be
anatofuz
parents:
diff changeset
37 invoked before the main `Op::verify`.
anatofuz
parents:
diff changeset
38
anatofuz
parents:
diff changeset
39 ```c++
anatofuz
parents:
diff changeset
40 template <typename ConcreteType>
anatofuz
parents:
diff changeset
41 class MyTrait : public OpTrait::TraitBase<ConcreteType, MyTrait> {
anatofuz
parents:
diff changeset
42 public:
anatofuz
parents:
diff changeset
43 /// Override the 'verifyTrait' hook to add additional verification on the
anatofuz
parents:
diff changeset
44 /// concrete operation.
anatofuz
parents:
diff changeset
45 static LogicalResult verifyTrait(Operation *op) {
anatofuz
parents:
diff changeset
46 // ...
anatofuz
parents:
diff changeset
47 }
anatofuz
parents:
diff changeset
48 };
anatofuz
parents:
diff changeset
49 ```
anatofuz
parents:
diff changeset
50
anatofuz
parents:
diff changeset
51 Note: It is generally good practice to define the implementation of the
anatofuz
parents:
diff changeset
52 `verifyTrait` hook out-of-line as a free function when possible to avoid
anatofuz
parents:
diff changeset
53 instantiating the implementation for every concrete operation type.
anatofuz
parents:
diff changeset
54
anatofuz
parents:
diff changeset
55 ### Parametric Traits
anatofuz
parents:
diff changeset
56
anatofuz
parents:
diff changeset
57 The above demonstrates the definition of a simple self-contained trait. It is
anatofuz
parents:
diff changeset
58 also often useful to provide some static parameters to the trait to control its
anatofuz
parents:
diff changeset
59 behavior. Given that the definition of the trait class is rigid, i.e. we must
anatofuz
parents:
diff changeset
60 have a single template argument for the concrete operation, the templates for
anatofuz
parents:
diff changeset
61 the parameters will need to be split out. An example is shown below:
anatofuz
parents:
diff changeset
62
anatofuz
parents:
diff changeset
63 ```c++
anatofuz
parents:
diff changeset
64 template <int Parameter>
anatofuz
parents:
diff changeset
65 class MyParametricTrait {
anatofuz
parents:
diff changeset
66 public:
anatofuz
parents:
diff changeset
67 template <typename ConcreteType>
anatofuz
parents:
diff changeset
68 class Impl : public OpTrait::TraitBase<ConcreteType, Impl> {
anatofuz
parents:
diff changeset
69 // Inside of 'Impl' we have full access to the template parameters
anatofuz
parents:
diff changeset
70 // specified above.
anatofuz
parents:
diff changeset
71 };
anatofuz
parents:
diff changeset
72 };
anatofuz
parents:
diff changeset
73 ```
anatofuz
parents:
diff changeset
74
anatofuz
parents:
diff changeset
75 ## Attaching a Trait
anatofuz
parents:
diff changeset
76
anatofuz
parents:
diff changeset
77 Traits may be used when defining a derived operation type, by simply adding the
anatofuz
parents:
diff changeset
78 name of the trait class to the `Op` class after the concrete operation type:
anatofuz
parents:
diff changeset
79
anatofuz
parents:
diff changeset
80 ```c++
anatofuz
parents:
diff changeset
81 /// Here we define 'MyOp' along with the 'MyTrait' and `MyParametric trait
anatofuz
parents:
diff changeset
82 /// classes we defined previously.
anatofuz
parents:
diff changeset
83 class MyOp : public Op<MyOp, MyTrait, MyParametricTrait<10>::Impl> {};
anatofuz
parents:
diff changeset
84 ```
anatofuz
parents:
diff changeset
85
anatofuz
parents:
diff changeset
86 To use a trait in the [ODS](OpDefinitions.md) framework, we need to provide a
anatofuz
parents:
diff changeset
87 definition of the trait class. This can be done using the `NativeOpTrait` and
anatofuz
parents:
diff changeset
88 `ParamNativeOpTrait` classes. `ParamNativeOpTrait` provides a mechanism in which
anatofuz
parents:
diff changeset
89 to specify arguments to a parametric trait class with an internal `Impl`.
anatofuz
parents:
diff changeset
90
anatofuz
parents:
diff changeset
91 ```tablegen
anatofuz
parents:
diff changeset
92 // The argument is the c++ trait class name.
anatofuz
parents:
diff changeset
93 def MyTrait : NativeOpTrait<"MyTrait">;
anatofuz
parents:
diff changeset
94
anatofuz
parents:
diff changeset
95 // The first argument is the parent c++ class name. The second argument is a
anatofuz
parents:
diff changeset
96 // string containing the parameter list.
anatofuz
parents:
diff changeset
97 class MyParametricTrait<int prop>
anatofuz
parents:
diff changeset
98 : NativeOpTrait<"MyParametricTrait", !cast<string>(!head(parameters))>;
anatofuz
parents:
diff changeset
99 ```
anatofuz
parents:
diff changeset
100
anatofuz
parents:
diff changeset
101 These can then be used in the `traits` list of an op definition:
anatofuz
parents:
diff changeset
102
anatofuz
parents:
diff changeset
103 ```tablegen
anatofuz
parents:
diff changeset
104 def OpWithInferTypeInterfaceOp : Op<...[MyTrait, MyParametricTrait<10>]> { ... }
anatofuz
parents:
diff changeset
105 ```
anatofuz
parents:
diff changeset
106
anatofuz
parents:
diff changeset
107 See the documentation on [operation definitions](OpDefinitions.md) for more
anatofuz
parents:
diff changeset
108 details.
anatofuz
parents:
diff changeset
109
anatofuz
parents:
diff changeset
110 ## Using a Trait
anatofuz
parents:
diff changeset
111
anatofuz
parents:
diff changeset
112 Traits may be used to provide additional methods, static fields, or other
anatofuz
parents:
diff changeset
113 information directly on the concrete operation. `Traits` internally become
anatofuz
parents:
diff changeset
114 `Base` classes of the concrete operation, so all of these are directly
anatofuz
parents:
diff changeset
115 accessible. To expose this information opaquely to transformations and analyses,
anatofuz
parents:
diff changeset
116 [`interfaces`](Interfaces.md) may be used.
anatofuz
parents:
diff changeset
117
anatofuz
parents:
diff changeset
118 To query if a specific operation contains a specific trait, the `hasTrait<>`
anatofuz
parents:
diff changeset
119 method may be used. This takes as a template parameter the trait class, which is
anatofuz
parents:
diff changeset
120 the same as the one passed when attaching the trait to an operation.
anatofuz
parents:
diff changeset
121
anatofuz
parents:
diff changeset
122 ```c++
anatofuz
parents:
diff changeset
123 Operation *op = ..;
anatofuz
parents:
diff changeset
124 if (op->hasTrait<MyTrait>() || op->hasTrait<MyParametricTrait<10>::Impl>())
anatofuz
parents:
diff changeset
125 ...;
anatofuz
parents:
diff changeset
126 ```
anatofuz
parents:
diff changeset
127
anatofuz
parents:
diff changeset
128 ## Trait List
anatofuz
parents:
diff changeset
129
anatofuz
parents:
diff changeset
130 MLIR provides a suite of traits that provide various functionalities that are
anatofuz
parents:
diff changeset
131 common across many different operations. Below is a list of some key traits that
anatofuz
parents:
diff changeset
132 may be used directly by any dialect. The format of the header for each trait
anatofuz
parents:
diff changeset
133 section goes as follows:
anatofuz
parents:
diff changeset
134
anatofuz
parents:
diff changeset
135 * `Header`
anatofuz
parents:
diff changeset
136 - (`C++ class` -- `ODS class`(if applicable))
anatofuz
parents:
diff changeset
137
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
138 ### AffineScope
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
139
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
140 * `OpTrait::AffineScope` -- `AffineScope`
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
141
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
142 This trait is carried by region holding operations that define a new scope for
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
143 the purposes of polyhedral optimization and the affine dialect in particular.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
144 Any SSA values of 'index' type that either dominate such operations, or are
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
145 defined at the top-level of such operations, or appear as region arguments for
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
146 such operations automatically become valid symbols for the polyhedral scope
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
147 defined by that operation. As a result, such SSA values could be used as the
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
148 operands or index operands of various affine dialect operations like affine.for,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
149 affine.load, and affine.store. The polyhedral scope defined by an operation
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
150 with this trait includes all operations in its region excluding operations that
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
151 are nested inside of other operations that themselves have this trait.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
152
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
153 ### AutomaticAllocationScope
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
154
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
155 * `OpTrait::AutomaticAllocationScope` -- `AutomaticAllocationScope`
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
156
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
157 This trait is carried by region holding operations that define a new scope for
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
158 automatic allocation. Such allocations are automatically freed when control is
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
159 transferred back from the regions of such operations. As an example, allocations
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
160 performed by [`std.alloca`](Dialects/Standard.md#stdalloca-allocaop) are
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
161 automatically freed when control leaves the region of its closest surrounding op
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
162 that has the trait AutomaticAllocationScope.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
163
150
anatofuz
parents:
diff changeset
164 ### Broadcastable
anatofuz
parents:
diff changeset
165
anatofuz
parents:
diff changeset
166 * `OpTrait::ResultsBroadcastableShape` -- `ResultsBroadcastableShape`
anatofuz
parents:
diff changeset
167
anatofuz
parents:
diff changeset
168 This trait adds the property that the operation is known to have
anatofuz
parents:
diff changeset
169 [broadcast-compatible](https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
anatofuz
parents:
diff changeset
170 operands and its result types' shape is the broadcast compatible with the shape
anatofuz
parents:
diff changeset
171 of the broadcasted operands. Specifically, starting from the most varying
anatofuz
parents:
diff changeset
172 dimension, each dimension pair of the two operands' shapes should either be the
anatofuz
parents:
diff changeset
173 same or one of them is one. Also, the result shape should have the corresponding
anatofuz
parents:
diff changeset
174 dimension equal to the larger one, if known. Shapes are checked partially if
anatofuz
parents:
diff changeset
175 ranks or dimensions are not known. For example, an op with `tensor<?x2xf32>` and
anatofuz
parents:
diff changeset
176 `tensor<2xf32>` as operand types and `tensor<3x2xf32>` as the result type is
anatofuz
parents:
diff changeset
177 broadcast-compatible.
anatofuz
parents:
diff changeset
178
anatofuz
parents:
diff changeset
179 This trait requires that the operands are either vector or tensor types.
anatofuz
parents:
diff changeset
180
anatofuz
parents:
diff changeset
181 ### Commutative
anatofuz
parents:
diff changeset
182
anatofuz
parents:
diff changeset
183 * `OpTrait::IsCommutative` -- `Commutative`
anatofuz
parents:
diff changeset
184
anatofuz
parents:
diff changeset
185 This trait adds the property that the operation is commutative, i.e. `X op Y ==
anatofuz
parents:
diff changeset
186 Y op X`
anatofuz
parents:
diff changeset
187
anatofuz
parents:
diff changeset
188 ### Function-Like
anatofuz
parents:
diff changeset
189
anatofuz
parents:
diff changeset
190 * `OpTrait::FunctionLike`
anatofuz
parents:
diff changeset
191
anatofuz
parents:
diff changeset
192 This trait provides APIs for operations that behave like functions. In
anatofuz
parents:
diff changeset
193 particular:
anatofuz
parents:
diff changeset
194
anatofuz
parents:
diff changeset
195 - Ops must be symbols, i.e. also have the `Symbol` trait;
anatofuz
parents:
diff changeset
196 - Ops have a single region with multiple blocks that corresponds to the body
anatofuz
parents:
diff changeset
197 of the function;
anatofuz
parents:
diff changeset
198 - the absence of a region corresponds to an external function;
anatofuz
parents:
diff changeset
199 - arguments of the first block of the region are treated as function
anatofuz
parents:
diff changeset
200 arguments;
anatofuz
parents:
diff changeset
201 - they can have argument and result attributes that are stored in dictionary
anatofuz
parents:
diff changeset
202 attributes on the operation itself.
anatofuz
parents:
diff changeset
203
anatofuz
parents:
diff changeset
204 This trait does *NOT* provide type support for the functions, meaning that
anatofuz
parents:
diff changeset
205 concrete Ops must handle the type of the declared or defined function.
anatofuz
parents:
diff changeset
206 `getTypeAttrName()` is a convenience function that returns the name of the
anatofuz
parents:
diff changeset
207 attribute that can be used to store the function type, but the trait makes no
anatofuz
parents:
diff changeset
208 assumption based on it.
anatofuz
parents:
diff changeset
209
anatofuz
parents:
diff changeset
210 ### HasParent
anatofuz
parents:
diff changeset
211
anatofuz
parents:
diff changeset
212 * `OpTrait::HasParent<typename ParentOpType>` -- `HasParent<string op>`
anatofuz
parents:
diff changeset
213
anatofuz
parents:
diff changeset
214 This trait provides APIs and verifiers for operations that can only be nested
anatofuz
parents:
diff changeset
215 within regions that are attached to operations of `ParentOpType`.
anatofuz
parents:
diff changeset
216
anatofuz
parents:
diff changeset
217 ### IsolatedFromAbove
anatofuz
parents:
diff changeset
218
anatofuz
parents:
diff changeset
219 * `OpTrait::IsIsolatedFromAbove` -- `IsolatedFromAbove`
anatofuz
parents:
diff changeset
220
anatofuz
parents:
diff changeset
221 This trait signals that the regions of an operations are known to be isolated
anatofuz
parents:
diff changeset
222 from above. This trait asserts that the regions of an operation will not
anatofuz
parents:
diff changeset
223 capture, or reference, SSA values defined above the region scope. This means
anatofuz
parents:
diff changeset
224 that the following is invalid if `foo.region_op` is defined as
anatofuz
parents:
diff changeset
225 `IsolatedFromAbove`:
anatofuz
parents:
diff changeset
226
anatofuz
parents:
diff changeset
227 ```mlir
anatofuz
parents:
diff changeset
228 %result = constant 10 : i32
anatofuz
parents:
diff changeset
229 foo.region_op {
anatofuz
parents:
diff changeset
230 foo.yield %result : i32
anatofuz
parents:
diff changeset
231 }
anatofuz
parents:
diff changeset
232 ```
anatofuz
parents:
diff changeset
233
anatofuz
parents:
diff changeset
234 This trait is an important structural property of the IR, and enables operations
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
235 to have [passes](PassManagement.md) scheduled under them.
150
anatofuz
parents:
diff changeset
236
anatofuz
parents:
diff changeset
237 ### Single Block with Implicit Terminator
anatofuz
parents:
diff changeset
238
anatofuz
parents:
diff changeset
239 * `OpTrait::SingleBlockImplicitTerminator<typename TerminatorOpType>` :
anatofuz
parents:
diff changeset
240 `SingleBlockImplicitTerminator<string op>`
anatofuz
parents:
diff changeset
241
anatofuz
parents:
diff changeset
242 This trait provides APIs and verifiers for operations with regions that have a
anatofuz
parents:
diff changeset
243 single block that must terminate with `TerminatorOpType`.
anatofuz
parents:
diff changeset
244
anatofuz
parents:
diff changeset
245 ### Symbol
anatofuz
parents:
diff changeset
246
anatofuz
parents:
diff changeset
247 * `OpTrait::Symbol` -- `Symbol`
anatofuz
parents:
diff changeset
248
anatofuz
parents:
diff changeset
249 This trait is used for operations that define a
anatofuz
parents:
diff changeset
250 [`Symbol`](SymbolsAndSymbolTables.md#symbol).
anatofuz
parents:
diff changeset
251
anatofuz
parents:
diff changeset
252 ### SymbolTable
anatofuz
parents:
diff changeset
253
anatofuz
parents:
diff changeset
254 * `OpTrait::SymbolTable` -- `SymbolTable`
anatofuz
parents:
diff changeset
255
anatofuz
parents:
diff changeset
256 This trait is used for operations that define a
anatofuz
parents:
diff changeset
257 [`SymbolTable`](SymbolsAndSymbolTables.md#symbol-table).
anatofuz
parents:
diff changeset
258
anatofuz
parents:
diff changeset
259 ### Terminator
anatofuz
parents:
diff changeset
260
anatofuz
parents:
diff changeset
261 * `OpTrait::IsTerminator` -- `Terminator`
anatofuz
parents:
diff changeset
262
anatofuz
parents:
diff changeset
263 This trait provides verification and functionality for operations that are known
anatofuz
parents:
diff changeset
264 to be [terminators](LangRef.md#terminator-operations).