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