[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / mlir / docs / DataLayout.md
blobe246e66c7fe227bc3f5ab74fe0cfe7d53e94f193
1 # Data Layout Modeling
3 Data layout information allows the compiler to answer questions related to how a
4 value of a particular type is stored in memory. For example, the size of a value
5 or its address alignment requirements. It enables, among others, the generation
6 of various linear memory addressing schemes for containers of abstract types and
7 deeper reasoning about vectors.
9 The data layout subsystem is designed to scale to MLIR's open type and operation
10 system. At the top level, it consists of:
12 *   attribute interfaces that can be implemented by concrete data layout
13     specifications;
14 *   type interfaces that should be implemented by types subject to data layout;
15 *   operation interfaces that must be implemented by operations that can serve
16     as data layout scopes (e.g., modules);
17 *   and dialect interfaces for data layout properties unrelated to specific
18     types.
20 Built-in types are handled specially to decrease the overall query cost.
21 Similarly, built-in `ModuleOp` supports data layouts without going through the
22 interface.
24 [TOC]
26 ## Usage
28 ### Scoping
30 Following MLIR's nested structure, data layout properties are _scoped_ to
31 regions belonging to either operations that implement the
32 `DataLayoutOpInterface` or `ModuleOp` operations. Such scoping operations
33 partially control the data layout properties and may have attributes that affect
34 them, typically organized in a data layout specification.
36 Types may have a different data layout in different scopes, including scopes
37 that are nested in other scopes such as modules contained in other modules. At
38 the same time, within the given scope excluding any nested scope, a given type
39 has fixed data layout properties. Types are also expected to have a default,
40 "natural" data layout in case they are used outside of any operation that
41 provides data layout scope for them. This ensures that data layout queries
42 always have a valid result.
44 ### Compatibility and Transformations
46 The information necessary to compute layout properties can be combined from
47 nested scopes. For example, an outer scope can define layout properties for a
48 subset of types while inner scopes define them for a disjoint subset, or scopes
49 can progressively relax alignment requirements on a type. This mechanism is
50 supported by the notion of data layout _compatibility_: the layout defined in a
51 nested scope is expected to be compatible with that of the outer scope. MLIR
52 does not prescribe what compatibility means for particular ops and types but
53 provides hooks for them to provide target- and type-specific checks. For
54 example, one may want to only allow relaxation of alignment constraints (i.e.,
55 smaller alignment) in nested modules or, alternatively, one may require nested
56 modules to fully redefine all constraints of the outer scope.
58 Data layout compatibility is also relevant during IR transformation. Any
59 transformation that affects the data layout scoping operation is expected to
60 maintain data layout compatibility. It is under responsibility of the
61 transformation to ensure it is indeed the case.
63 ### Queries
65 Data layout property queries can be performed on the special object --
66 `DataLayout` -- which can be created for the given scoping operation. These
67 objects allow one to interface with the data layout infrastructure and query
68 properties of given types in the scope of the object. The signature of
69 `DataLayout` class is as follows.
71 ```c++
72 class DataLayout {
73 public:
74   explicit DataLayout(DataLayoutOpInterface scope);
76   unsigned getTypeSize(Type type) const;
77   unsigned getTypeSizeInBits(Type type) const;
78   unsigned getTypeABIAlignment(Type type) const;
79   unsigned getTypePreferredAlignment(Type type) const;
81 ```
83 The user can construct the `DataLayout` object for the scope of interest. Since
84 the data layout properties are fixed in the scope, they will be computed only
85 once upon first request and cached for further use. Therefore,
86 `DataLayout(op.getParentOfType<DataLayoutOpInterface>()).getTypeSize(type)` is
87 considered an anti-pattern since it discards the cache after use. Because of
88 caching, a `DataLayout` object returns valid results as long as the data layout
89 properties of enclosing scopes remain the same, that is, as long as none of the
90 ancestor operations are modified in a way that affects data layout. After such a
91 modification, the user is expected to create a fresh `DataLayout` object. To aid
92 with this, `DataLayout` asserts that the scope remains identical if MLIR is
93 compiled with assertions enabled.
95 ## Custom Implementations
97 Extensibility of the data layout modeling is provided through a set of MLIR
98 [Interfaces](Interfaces.md).
100 ### Data Layout Specifications
102 Data layout specification is an [attribute](LangRef.md/#attributes) that is
103 conceptually a collection of key-value pairs called data layout specification
104 _entries_. Data layout specification attributes implement the
105 `DataLayoutSpecInterface`, described below. Each entry is itself an attribute
106 that implements the `DataLayoutEntryInterface`. Entries have a key, either a
107 `Type` or a `StringAttr`, and a value. Keys are used to associate entries with
108 specific types or dialects: when handling a data layout properties request, a
109 type or a dialect can only see the specification entries relevant to them and
110 must go through the supplied `DataLayout` object for any recursive query. This
111 supports and enforces better composability because types cannot (and should not)
112 understand layout details of other types. Entry values are arbitrary attributes,
113 specific to the type.
115 For example, a data layout specification may be an actual list of pairs with
116 simple custom syntax resembling the following:
118 ```mlir
119 #my_dialect.layout_spec<
120   #my_dialect.layout_entry<!my_dialect.type, size=42>,
121   #my_dialect.layout_entry<"my_dialect.endianness", "little">,
122   #my_dialect.layout_entry<!my_dialect.vector, prefer_large_alignment>>
125 The exact details of the specification and entry attributes, as well as their
126 syntax, are up to implementations.
128 We use the notion of _type class_ throughout the data layout subsystem. It
129 corresponds to the C++ class of the given type, e.g., `IntegerType` for built-in
130 integers. MLIR does not have a mechanism to represent type classes in the IR.
131 Instead, data layout entries contain specific _instances_ of a type class, for
132 example, `IntegerType{signedness=signless, bitwidth=8}` (or `i8` in the IR) or
133 `IntegerType{signedness=unsigned, bitwidth=32}` (or `ui32` in the IR). When
134 handling a data layout property query, a type class will be supplied with _all_
135 entries with keys belonging to this type class. For example, `IntegerType` will
136 see the entries for `i8`, `si16` and `ui32`, but will _not_ see those for `f32`
137 or `memref<?xi32>` (neither will `MemRefType` see the entry for `i32`). This
138 allows for type-specific "interpolation" behavior where a type class can compute
139 data layout properties of _any_ specific type instance given properties of other
140 instances. Using integers as an example again, their alignment could be computed
141 by taking that of the closest from above integer type with power-of-two
142 bitwidth.
144 [include "Interfaces/DataLayoutAttrInterface.md"]
146 ### Data Layout Scoping Operations
148 Operations that define a scope for data layout queries, and that can be used to
149 create a `DataLayout` object, are expected to implement the
150 `DataLayoutOpInterface`. Such ops must provide at least a way of obtaining the
151 data layout specification. The specification need not be necessarily attached to
152 the operation as an attribute and may be constructed on-the-fly; it is only
153 fetched once per `DataLayout` object and cached. Such ops may also provide
154 custom handlers for data layout queries that provide results without forwarding
155 the queries down to specific types or post-processing the results returned by
156 types in target- or scope-specific ways. These custom handlers make it possible
157 for scoping operations to (re)define data layout properties for types without
158 having to modify the types themselves, e.g., when types are defined in another
159 dialect.
161 [include "Interfaces/DataLayoutOpInterface.md"]
163 ### Types with Data Layout
165 Type classes that intend to handle data layout queries themselves are expected
166 to implement the `DataLayoutTypeInterface`. This interface provides overridable
167 hooks for each data layout query. Each of these hooks is supplied with the type
168 instance, a `DataLayout` object suitable for recursive queries, and a list of
169 data layout queries relevant for the type class. It is expected to provide a
170 valid result even if the list of entries is empty. These hooks do not have
171 access to the operation in the scope of which the query is handled and should
172 use the supplied entries instead.
174 [include "Interfaces/DataLayoutTypeInterface.md"]
176 ### Dialects with Data Layout Identifiers
178 For data layout entries that are not related to a particular type class, the key
179 of the entry is an Identifier that belongs to some dialect. In this case, the
180 dialect is expected to implement the `DataLayoutDialectInterface`. This dialect
181 provides hooks for verifying the validity of the entry value attributes and for
182 and the compatibility of nested entries.
184 ### Bits and Bytes
186 Two versions of hooks are provided for sizes: in bits and in bytes. The version
187 in bytes has a default implementation that derives the size in bytes by rounding
188 up the result of division of the size in bits by 8. Types exclusively targeting
189 architectures with different assumptions can override this. Operations can
190 redefine this for all types, providing scoped versions for cases of byte sizes
191 other than eight without having to modify types, including built-in types.
193 ### Query Dispatch
195 The overall flow of a data layout property query is as follows.
197 1.  The user constructs a `DataLayout` at the given scope. The constructor
198     fetches the data layout specification and combines it with those of
199     enclosing scopes (layouts are expected to be compatible).
200 2.  The user calls `DataLayout::query(Type ty)`.
201 3.  If `DataLayout` has a cached response, this response is returned
202     immediately.
203 4.  Otherwise, the query is handed down by `DataLayout` to the closest layout
204     scoping operation. If it implements `DataLayoutOpInterface`, then the query
205     is forwarded to`DataLayoutOpInterface::query(ty, *this, relevantEntries)`
206     where the relevant entries are computed as described above. If it does not
207     implement `DataLayoutOpInterface`, it must be a `ModuleOp`, and the query is
208     forwarded to `DataLayoutTypeInterface::query(dataLayout, relevantEntries)`
209     after casting `ty` to the type interface.
210 5.  Unless the `query` hook is reimplemented by the op interface, the query is
211     handled further down to `DataLayoutTypeInterface::query(dataLayout,
212     relevantEntries)` after casting `ty` to the type interface. If the type does
213     not implement the interface, an unrecoverable fatal error is produced.
214 6.  The type is expected to always provide the response, which is returned up
215     the call stack and cached by the `DataLayout.`
217 ## Default Implementation
219 The default implementation of the data layout interfaces directly handles
220 queries for a subset of built-in types.
222 ### Built-in Modules
224 Built-in `ModuleOp` allows at most one attribute that implements
225 `DataLayoutSpecInterface`. It does not implement the entire interface for
226 efficiency and layering reasons. Instead, `DataLayout` can be constructed for
227 `ModuleOp` and handles modules transparently alongside other operations that
228 implement the interface.
230 ### Built-in Types
232 The following describes the default properties of built-in types.
234 The size of built-in integers and floats in bytes is computed as
235 `ceildiv(bitwidth, 8)`. The ABI alignment of integer types with bitwidth below
236 64 and of the float types is the closest from above power-of-two number of
237 bytes. The ABI alignment of integer types with bitwidth 64 and above is 4 bytes
238 (32 bits).
240 The size of built-in vectors is computed by first rounding their number of
241 elements in the _innermost_ dimension to the closest power-of-two from above,
242 then getting the total number of elements, and finally multiplying it with the
243 element size. For example, `vector<3xi32>` and `vector<4xi32>` have the same
244 size. So do `vector<2x3xf32>` and `vector<2x4xf32>`, but `vector<3x4xf32>` and
245 `vector<4x4xf32>` have different sizes. The ABI and preferred alignment of
246 vector types is computed by taking the innermost dimension of the vector,
247 rounding it up to the closest power-of-two, taking a product of that with
248 element size in bytes, and rounding the result up again to the closest
249 power-of-two.
251 Note: these values are selected for consistency with the
252 [default data layout in LLVM](https://llvm.org/docs/LangRef.html#data-layout),
253 which MLIR assumed until the introduction of proper data layout modeling, and
254 with the
255 [modeling of n-D vectors](https://mlir.llvm.org/docs/Dialects/Vector/#deeperdive).
256 They **may change** in the future.
258 #### `index` type
260 Index type is an integer type used for target-specific size information in,
261 e.g., `memref` operations. Its data layout is parameterized by a single integer
262 data layout entry that specifies its bitwidth. For example,
264 ```mlir
265 module attributes { dlti.dl_spec = #dlti.dl_spec<
266   #dlti.dl_entry<index, 32>
267 >} {}
270 specifies that `index` has 32 bits. All other layout properties of `index` match
271 those of the integer type with the same bitwidth defined above.
273 In absence of the corresponding entry, `index` is assumed to be a 64-bit
274 integer.
276 #### `complex` type
278 By default complex type is treated like a 2 element structure of its given
279 element type. This is to say that each of its elements are aligned to their
280 preferred alignment, the entire complex type is also aligned to this preference,
281 and the complex type size includes the possible padding between elements to enforce
282 alignment.
284 ### Byte Size
286 The default data layout assumes 8-bit bytes.
288 ### DLTI Dialect
290 The [DLTI](Dialects/DLTI.md) dialect provides the attributes implementing
291 `DataLayoutSpecInterface` and `DataLayoutEntryInterface`, as well as a dialect
292 attribute that can be used to attach the specification to a given operation. The
293 verifier of this attribute triggers those of the specification and checks the
294 compatibility of nested specifications.