River Riddle | 01c857b | 2020-03-30 19:25:00 | [diff] [blame] | 1 | # 'llvm' Dialect |
Alex Zinenko | f0597cb | 2019-02-22 09:00:25 | [diff] [blame] | 2 | |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 3 | This dialect maps [LLVM IR](https://llvm.org/docs/LangRef.html) into MLIR by |
| 4 | defining the corresponding operations and types. LLVM IR metadata is usually |
| 5 | represented as MLIR attributes, which offer additional structure verification. |
Alex Zinenko | f0597cb | 2019-02-22 09:00:25 | [diff] [blame] | 6 | |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 7 | We use "LLVM IR" to designate the |
Alex Zinenko | f0597cb | 2019-02-22 09:00:25 | [diff] [blame] | 8 | [intermediate representation of LLVM](https://llvm.org/docs/LangRef.html) and |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 9 | "LLVM _dialect_" or "LLVM IR _dialect_" to refer to this MLIR dialect. |
| 10 | |
| 11 | Unless explicitly stated otherwise, the semantics of the LLVM dialect operations |
| 12 | must correspond to the semantics of LLVM IR instructions and any divergence is |
| 13 | considered a bug. The dialect also contains auxiliary operations that smoothen |
| 14 | the differences in the IR structure, e.g., MLIR does not have `phi` operations |
| 15 | and LLVM IR does not have a `constant` operation. These auxiliary operations are |
| 16 | systematically prefixed with `mlir`, e.g. `llvm.mlir.constant` where `llvm.` is |
| 17 | the dialect namespace prefix. |
Alex Zinenko | f0597cb | 2019-02-22 09:00:25 | [diff] [blame] | 18 | |
| 19 | [TOC] |
| 20 | |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 21 | ## Dependency on LLVM IR |
Alex Zinenko | f0597cb | 2019-02-22 09:00:25 | [diff] [blame] | 22 | |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 23 | LLVM dialect is not expected to depend on any object that requires an |
| 24 | `LLVMContext`, such as an LLVM IR instruction or type. Instead, MLIR provides |
| 25 | thread-safe alternatives compatible with the rest of the infrastructure. The |
| 26 | dialect is allowed to depend on the LLVM IR objects that don't require a |
| 27 | context, such as data layout and triple description. |
| 28 | |
| 29 | ## Module Structure |
| 30 | |
| 31 | IR modules use the built-in MLIR `ModuleOp` and support all its features. In |
| 32 | particular, modules can be named, nested and are subject to symbol visibility. |
| 33 | Modules can contain any operations, including LLVM functions and globals. |
| 34 | |
| 35 | ### Data Layout and Triple |
| 36 | |
| 37 | An IR module may have an optional data layout and triple information attached |
| 38 | using MLIR attributes `llvm.data_layout` and `llvm.triple`, respectively. Both |
| 39 | are string attributes with the |
| 40 | [same syntax](https://llvm.org/docs/LangRef.html#data-layout) as in LLVM IR and |
| 41 | are verified to be correct. They can be defined as follows. |
| 42 | |
| 43 | ```mlir |
| 44 | module attributes {llvm.data_layout = "e", |
| 45 | llvm.target_triple = "aarch64-linux-android"} { |
| 46 | // module contents |
| 47 | } |
| 48 | ``` |
Alex Zinenko | f0597cb | 2019-02-22 09:00:25 | [diff] [blame] | 49 | |
Alex Zinenko | ccdd8c7 | 2020-12-17 11:19:52 | [diff] [blame] | 50 | ### Functions |
| 51 | |
| 52 | LLVM functions are represented by a special operation, `llvm.func`, that has |
| 53 | syntax similar to that of the built-in function operation but supports |
| 54 | LLVM-related features such as linkage and variadic argument lists. See detailed |
| 55 | description in the operation list [below](#llvmfunc-mlirllvmllvmfuncop). |
| 56 | |
| 57 | ### PHI Nodes and Block Arguments |
| 58 | |
| 59 | MLIR uses block arguments instead of PHI nodes to communicate values between |
| 60 | blocks. Therefore, the LLVM dialect has no operation directly equivalent to |
| 61 | `phi` in LLVM IR. Instead, all terminators can pass values as successor operands |
| 62 | as these values will be forwarded as block arguments when the control flow is |
| 63 | transferred. |
| 64 | |
| 65 | For example: |
| 66 | |
| 67 | ```mlir |
| 68 | ^bb1: |
Alex Zinenko | 2230bf9 | 2021-01-06 15:19:04 | [diff] [blame] | 69 | %0 = llvm.addi %arg0, %cst : i32 |
| 70 | llvm.br ^bb2[%0: i32] |
Alex Zinenko | ccdd8c7 | 2020-12-17 11:19:52 | [diff] [blame] | 71 | |
| 72 | // If the control flow comes from ^bb1, %arg1 == %0. |
Alex Zinenko | 2230bf9 | 2021-01-06 15:19:04 | [diff] [blame] | 73 | ^bb2(%arg1: i32) |
Alex Zinenko | ccdd8c7 | 2020-12-17 11:19:52 | [diff] [blame] | 74 | // ... |
| 75 | ``` |
| 76 | |
| 77 | is equivalent to LLVM IR |
| 78 | |
| 79 | ```llvm |
| 80 | %0: |
| 81 | %1 = add i32 %arg0, %cst |
| 82 | br %3 |
| 83 | |
| 84 | %3: |
| 85 | %arg1 = phi [%1, %0], //... |
| 86 | ``` |
| 87 | |
| 88 | Since there is no need to use the block identifier to differentiate the source |
| 89 | of different values, the LLVM dialect supports terminators that transfer the |
| 90 | control flow to the same block with different arguments. For example: |
| 91 | |
| 92 | ```mlir |
| 93 | ^bb1: |
Alex Zinenko | 2230bf9 | 2021-01-06 15:19:04 | [diff] [blame] | 94 | llvm.cond_br %cond, ^bb2[%0: i32], ^bb2[%1: i32] |
Alex Zinenko | ccdd8c7 | 2020-12-17 11:19:52 | [diff] [blame] | 95 | |
Alex Zinenko | 2230bf9 | 2021-01-06 15:19:04 | [diff] [blame] | 96 | ^bb2(%arg0: i32): |
Alex Zinenko | ccdd8c7 | 2020-12-17 11:19:52 | [diff] [blame] | 97 | // ... |
| 98 | ``` |
| 99 | |
| 100 | ### Context-Level Values |
| 101 | |
| 102 | Some value kinds in LLVM IR, such as constants and undefs, are uniqued in |
| 103 | context and used directly in relevant operations. MLIR does not support such |
| 104 | values for thread-safety and concept parsimony reasons. Instead, regular values |
| 105 | are produced by dedicated operations that have the corresponding semantics: |
| 106 | [`llvm.mlir.constant`](#llvmmlirconstant-mlirllvmconstantop), |
| 107 | [`llvm.mlir.undef`](#llvmmlirundef-mlirllvmundefop), |
Markus Böck | 9b99336 | 2021-05-25 12:50:59 | [diff] [blame] | 108 | [`llvm.mlir.null`](#llvmmlirnull-mlirllvmnullop). Note how these operations are |
Alex Zinenko | ccdd8c7 | 2020-12-17 11:19:52 | [diff] [blame] | 109 | prefixed with `mlir.` to indicate that they don't belong to LLVM IR but are only |
| 110 | necessary to model it in MLIR. The values produced by these operations are |
| 111 | usable just like any other value. |
| 112 | |
| 113 | Examples: |
| 114 | |
| 115 | ```mlir |
| 116 | // Create an undefined value of structure type with a 32-bit integer followed |
| 117 | // by a float. |
Alex Zinenko | dd5165a | 2021-01-06 15:21:08 | [diff] [blame] | 118 | %0 = llvm.mlir.undef : !llvm.struct<(i32, f32)> |
Alex Zinenko | ccdd8c7 | 2020-12-17 11:19:52 | [diff] [blame] | 119 | |
| 120 | // Null pointer to i8. |
| 121 | %1 = llvm.mlir.null : !llvm.ptr<i8> |
| 122 | |
| 123 | // Null pointer to a function with signature void(). |
| 124 | %2 = llvm.mlir.null : !llvm.ptr<func<void ()>> |
| 125 | |
| 126 | // Constant 42 as i32. |
Alex Zinenko | 2230bf9 | 2021-01-06 15:19:04 | [diff] [blame] | 127 | %3 = llvm.mlir.constant(42 : i32) : i32 |
Alex Zinenko | ccdd8c7 | 2020-12-17 11:19:52 | [diff] [blame] | 128 | |
| 129 | // Splat dense vector constant. |
Alex Zinenko | bd30a79 | 2021-01-11 12:58:05 | [diff] [blame] | 130 | %3 = llvm.mlir.constant(dense<1.0> : vector<4xf32>) : vector<4xf32> |
Alex Zinenko | ccdd8c7 | 2020-12-17 11:19:52 | [diff] [blame] | 131 | ``` |
| 132 | |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 133 | Note that constants list the type twice. This is an artifact of the LLVM dialect |
| 134 | not using built-in types, which are used for typed MLIR attributes. The syntax |
| 135 | will be reevaluated after considering composite constants. |
Alex Zinenko | ccdd8c7 | 2020-12-17 11:19:52 | [diff] [blame] | 136 | |
| 137 | ### Globals |
| 138 | |
| 139 | Global variables are also defined using a special operation, |
| 140 | [`llvm.mlir.global`](#llvmmlirglobal-mlirllvmglobalop), located at the module |
| 141 | level. Globals are MLIR symbols and are identified by their name. |
| 142 | |
| 143 | Since functions need to be isolated-from-above, i.e. values defined outside the |
| 144 | function cannot be directly used inside the function, an additional operation, |
| 145 | [`llvm.mlir.addressof`](#llvmmliraddressof-mlirllvmaddressofop), is provided to |
| 146 | locally define a value containing the _address_ of a global. The actual value |
| 147 | can then be loaded from that pointer, or a new value can be stored into it if |
| 148 | the global is not declared constant. This is similar to LLVM IR where globals |
| 149 | are accessed through name and have a pointer type. |
| 150 | |
| 151 | ### Linkage |
| 152 | |
| 153 | Module-level named objects in the LLVM dialect, namely functions and globals, |
| 154 | have an optional _linkage_ attribute derived from LLVM IR |
| 155 | [linkage types](https://llvm.org/docs/LangRef.html#linkage-types). Linkage is |
| 156 | specified by the same keyword as in LLVM IR and is located between the operation |
| 157 | name (`llvm.func` or `llvm.global`) and the symbol name. If no linkage keyword |
Markus Böck | 286a7a4 | 2021-10-29 07:19:11 | [diff] [blame] | 158 | is present, `external` linkage is assumed by default. Linkage is _distinct_ from |
Alex Zinenko | ccdd8c7 | 2020-12-17 11:19:52 | [diff] [blame] | 159 | MLIR symbol visibility. |
| 160 | |
| 161 | ### Attribute Pass-Through |
| 162 | |
| 163 | The LLVM dialect provides a mechanism to forward function-level attributes to |
| 164 | LLVM IR using the `passthrough` attribute. This is an array attribute containing |
| 165 | either string attributes or array attributes. In the former case, the value of |
| 166 | the string is interpreted as the name of LLVM IR function attribute. In the |
| 167 | latter case, the array is expected to contain exactly two string attributes, the |
| 168 | first corresponding to the name of LLVM IR function attribute, and the second |
| 169 | corresponding to its value. Note that even integer LLVM IR function attributes |
| 170 | have their value represented in the string form. |
| 171 | |
| 172 | Example: |
| 173 | |
| 174 | ```mlir |
| 175 | llvm.func @func() attributes { |
| 176 | passthrough = ["noinline", // value-less attribute |
| 177 | ["alignstack", "4"], // integer attribute with value |
| 178 | ["other", "attr"]] // attribute unknown to LLVM |
| 179 | } { |
| 180 | llvm.return |
| 181 | } |
| 182 | ``` |
| 183 | |
| 184 | If the attribute is not known to LLVM IR, it will be attached as a string |
| 185 | attribute. |
| 186 | |
River Riddle | 465ef55 | 2019-04-05 15:19:42 | [diff] [blame] | 187 | ## Types |
Alex Zinenko | f0597cb | 2019-02-22 09:00:25 | [diff] [blame] | 188 | |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 189 | LLVM dialect uses built-in types whenever possible and defines a set of |
| 190 | complementary types, which correspond to the LLVM IR types that cannot be |
| 191 | directly represented with built-in types. Similarly to other MLIR context-owned |
| 192 | objects, the creation and manipulation of LLVM dialect types is thread-safe. |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 193 | |
| 194 | MLIR does not support module-scoped named type declarations, e.g. `%s = type |
| 195 | {i32, i32}` in LLVM IR. Instead, types must be fully specified at each use, |
| 196 | except for recursive types where only the first reference to a named type needs |
Markus Böck | 9b99336 | 2021-05-25 12:50:59 | [diff] [blame] | 197 | to be fully specified. MLIR [type aliases](../LangRef.md/#type-aliases) can be used |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 198 | to achieve more compact syntax. |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 199 | |
| 200 | The general syntax of LLVM dialect types is `!llvm.`, followed by a type kind |
| 201 | identifier (e.g., `ptr` for pointer or `struct` for structure) and by an |
| 202 | optional list of type parameters in angle brackets. The dialect follows MLIR |
| 203 | style for types with nested angle brackets and keyword specifiers rather than |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 204 | using different bracket styles to differentiate types. Types inside the angle |
| 205 | brackets may omit the `!llvm.` prefix for brevity: the parser first attempts to |
| 206 | find a type (starting with `!` or a built-in type) and falls back to accepting a |
| 207 | keyword. For example, `!llvm.ptr<!llvm.ptr<i32>>` and `!llvm.ptr<ptr<i32>>` are |
| 208 | equivalent, with the latter being the canonical form, and denote a pointer to a |
| 209 | pointer to a 32-bit integer. |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 210 | |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 211 | ### Built-in Type Compatibility |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 212 | |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 213 | LLVM dialect accepts a subset of built-in types that are referred to as _LLVM |
| 214 | dialect-compatible types_. The following types are compatible: |
| 215 | |
| 216 | - Signless integers - `iN` (`IntegerType`). |
Valentin Clement | cf0173d | 2021-01-15 15:29:37 | [diff] [blame] | 217 | - Floating point types - `bfloat`, `half`, `float`, `double` , `f80`, `f128` |
| 218 | (`FloatType`). |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 219 | - 1D vectors of signless integers or floating point types - `vector<NxT>` |
| 220 | (`VectorType`). |
| 221 | |
| 222 | Note that only a subset of types that can be represented by a given class is |
| 223 | compatible. For example, signed and unsigned integers are not compatible. LLVM |
| 224 | provides a function, `bool LLVM::isCompatibleType(Type)`, that can be used as a |
| 225 | compatibility check. |
| 226 | |
Alex Zinenko | 9a60ad2 | 2021-01-19 12:42:16 | [diff] [blame] | 227 | Each LLVM IR type corresponds to *exactly one* MLIR type, either built-in or |
| 228 | LLVM dialect type. For example, because `i32` is LLVM-compatible, there is no |
| 229 | `!llvm.i32` type. However, `!llvm.ptr<T>` is defined in the LLVM dialect as |
| 230 | there is no corresponding built-in type. |
| 231 | |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 232 | ### Additional Simple Types |
| 233 | |
| 234 | The following non-parametric types derived from the LLVM IR are available in the |
| 235 | LLVM dialect: |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 236 | |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 237 | - `!llvm.x86_mmx` (`LLVMX86MMXType`) - value held in an MMX register on x86 |
| 238 | machine. |
| 239 | - `!llvm.ppc_fp128` (`LLVMPPCFP128Type`) - 128-bit floating-point value (two |
| 240 | 64 bits). |
| 241 | - `!llvm.token` (`LLVMTokenType`) - a non-inspectable value associated with an |
| 242 | operation. |
| 243 | - `!llvm.metadata` (`LLVMMetadataType`) - LLVM IR metadata, to be used only if |
| 244 | the metadata cannot be represented as structured MLIR attributes. |
| 245 | - `!llvm.void` (`LLVMVoidType`) - does not represent any value; can only |
| 246 | appear in function results. |
| 247 | |
| 248 | These types represent a single value (or an absence thereof in case of `void`) |
| 249 | and correspond to their LLVM IR counterparts. |
| 250 | |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 251 | ### Additional Parametric Types |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 252 | |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 253 | These types are parameterized by the types they contain, e.g., the pointee or |
| 254 | the element type, which can be either compatible built-in or LLVM dialect types. |
Alex Zinenko | f0597cb | 2019-02-22 09:00:25 | [diff] [blame] | 255 | |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 256 | #### Pointer Types |
Alex Zinenko | f0597cb | 2019-02-22 09:00:25 | [diff] [blame] | 257 | |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 258 | Pointer types specify an address in memory. |
| 259 | |
| 260 | Pointer types are parametric types parameterized by the element type and the |
| 261 | address space. The address space is an integer, but this choice may be |
| 262 | reconsidered if MLIR implements named address spaces. Their syntax is as |
| 263 | follows: |
| 264 | |
| 265 | ``` |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 266 | llvm-ptr-type ::= `!llvm.ptr<` type (`,` integer-literal)? `>` |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 267 | ``` |
| 268 | |
| 269 | where the optional integer literal corresponds to the memory space. Both cases |
| 270 | are represented by `LLVMPointerType` internally. |
| 271 | |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 272 | #### Array Types |
| 273 | |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 274 | Array types represent sequences of elements in memory. Array elements can be |
| 275 | addressed with a value unknown at compile time, and can be nested. Only 1D |
| 276 | arrays are allowed though. |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 277 | |
| 278 | Array types are parameterized by the fixed size and the element type. |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 279 | Syntactically, their representation is the following: |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 280 | |
| 281 | ``` |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 282 | llvm-array-type ::= `!llvm.array<` integer-literal `x` type `>` |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 283 | ``` |
| 284 | |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 285 | and they are internally represented as `LLVMArrayType`. |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 286 | |
| 287 | #### Function Types |
| 288 | |
| 289 | Function types represent the type of a function, i.e. its signature. |
| 290 | |
| 291 | Function types are parameterized by the result type, the list of argument types |
| 292 | and by an optional "variadic" flag. Unlike built-in `FunctionType`, LLVM dialect |
| 293 | functions (`LLVMFunctionType`) always have single result, which may be |
| 294 | `!llvm.void` if the function does not return anything. The syntax is as follows: |
| 295 | |
| 296 | ``` |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 297 | llvm-func-type ::= `!llvm.func<` type `(` type-list (`,` `...`)? `)` `>` |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 298 | ``` |
| 299 | |
| 300 | For example, |
| 301 | |
| 302 | ```mlir |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 303 | !llvm.func<void ()> // a function with no arguments; |
| 304 | !llvm.func<i32 (f32, i32)> // a function with two arguments and a result; |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 305 | !llvm.func<void (i32, ...)> // a variadic function with at least one argument. |
| 306 | ``` |
| 307 | |
| 308 | In the LLVM dialect, functions are not first-class objects and one cannot have a |
| 309 | value of function type. Instead, one can take the address of a function and |
| 310 | operate on pointers to functions. |
| 311 | |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 312 | ### Vector Types |
| 313 | |
| 314 | Vector types represent sequences of elements, typically when multiple data |
| 315 | elements are processed by a single instruction (SIMD). Vectors are thought of as |
| 316 | stored in registers and therefore vector elements can only be addressed through |
| 317 | constant indices. |
| 318 | |
| 319 | Vector types are parameterized by the size, which may be either _fixed_ or a |
| 320 | multiple of some fixed size in case of _scalable_ vectors, and the element type. |
| 321 | Vectors cannot be nested and only 1D vectors are supported. Scalable vectors are |
| 322 | still considered 1D. |
| 323 | |
| 324 | LLVM dialect uses built-in vector types for _fixed_-size vectors of built-in |
| 325 | types, and provides additional types for fixed-sized vectors of LLVM dialect |
| 326 | types (`LLVMFixedVectorType`) and scalable vectors of any types |
| 327 | (`LLVMScalableVectorType`). These two additional types share the following |
| 328 | syntax: |
| 329 | |
| 330 | ``` |
| 331 | llvm-vec-type ::= `!llvm.vec<` (`?` `x`)? integer-literal `x` type `>` |
| 332 | ``` |
| 333 | |
| 334 | Note that the sets of element types supported by built-in and LLVM dialect |
| 335 | vector types are mutually exclusive, e.g., the built-in vector type does not |
| 336 | accept `!llvm.ptr<i32>` and the LLVM dialect fixed-width vector type does not |
| 337 | accept `i32`. |
| 338 | |
| 339 | The following functions are provided to operate on any kind of the vector types |
| 340 | compatible with the LLVM dialect: |
| 341 | |
| 342 | - `bool LLVM::isCompatibleVectorType(Type)` - checks whether a type is a |
| 343 | vector type compatible with the LLVM dialect; |
| 344 | - `Type LLVM::getVectorElementType(Type)` - returns the element type of any |
| 345 | vector type compatible with the LLVM dialect; |
| 346 | - `llvm::ElementCount LLVM::getVectorNumElements(Type)` - returns the number |
| 347 | of elements in any vector type compatible with the LLVM dialect; |
| 348 | - `Type LLVM::getFixedVectorType(Type, unsigned)` - gets a fixed vector type |
| 349 | with the given element type and size; the resulting type is either a |
| 350 | built-in or an LLVM dialect vector type depending on which one supports the |
| 351 | given element type. |
| 352 | |
| 353 | #### Examples of Compatible Vector Types |
| 354 | |
| 355 | ```mlir |
| 356 | vector<42 x i32> // Vector of 42 32-bit integers. |
| 357 | !llvm.vec<42 x ptr<i32>> // Vector of 42 pointers to 32-bit integers. |
| 358 | !llvm.vec<? x 4 x i32> // Scalable vector of 32-bit integers with |
| 359 | // size divisible by 4. |
| 360 | !llvm.array<2 x vector<2 x i32>> // Array of 2 vectors of 2 32-bit integers. |
| 361 | !llvm.array<2 x vec<2 x ptr<i32>>> // Array of 2 vectors of 2 pointers to 32-bit |
| 362 | // integers. |
| 363 | ``` |
| 364 | |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 365 | ### Structure Types |
| 366 | |
| 367 | The structure type is used to represent a collection of data members together in |
| 368 | memory. The elements of a structure may be any type that has a size. |
| 369 | |
| 370 | Structure types are represented in a single dedicated class |
| 371 | mlir::LLVM::LLVMStructType. Internally, the struct type stores a (potentially |
| 372 | empty) name, a (potentially empty) list of contained types and a bitmask |
| 373 | indicating whether the struct is named, opaque, packed or uninitialized. |
| 374 | Structure types that don't have a name are referred to as _literal_ structs. |
| 375 | Such structures are uniquely identified by their contents. _Identified_ structs |
| 376 | on the other hand are uniquely identified by the name. |
| 377 | |
| 378 | #### Identified Structure Types |
| 379 | |
| 380 | Identified structure types are uniqued using their name in a given context. |
| 381 | Attempting to construct an identified structure with the same name a structure |
| 382 | that already exists in the context *will result in the existing structure being |
| 383 | returned*. **MLIR does not auto-rename identified structs in case of name |
| 384 | conflicts** because there is no naming scope equivalent to a module in LLVM IR |
| 385 | since MLIR modules can be arbitrarily nested. |
| 386 | |
| 387 | Programmatically, identified structures can be constructed in an _uninitialized_ |
| 388 | state. In this case, they are given a name but the body must be set up by a |
| 389 | later call, using MLIR's type mutation mechanism. Such uninitialized types can |
| 390 | be used in type construction, but must be eventually initialized for IR to be |
| 391 | valid. This mechanism allows for constructing _recursive_ or mutually referring |
| 392 | structure types: an uninitialized type can be used in its own initialization. |
| 393 | |
| 394 | Once the type is initialized, its body cannot be changed anymore. Any further |
| 395 | attempts to modify the body will fail and return failure to the caller _unless |
| 396 | the type is initialized with the exact same body_. Type initialization is |
| 397 | thread-safe; however, if a concurrent thread initializes the type before the |
| 398 | current thread, the initialization may return failure. |
| 399 | |
| 400 | The syntax for identified structure types is as follows. |
| 401 | |
| 402 | ``` |
| 403 | llvm-ident-struct-type ::= `!llvm.struct<` string-literal, `opaque` `>` |
| 404 | | `!llvm.struct<` string-literal, `packed`? |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 405 | `(` type-or-ref-list `)` `>` |
| 406 | type-or-ref-list ::= <maybe empty comma-separated list of type-or-ref> |
| 407 | type-or-ref ::= <any compatible type with optional !llvm.> |
| 408 | | `!llvm.`? `struct<` string-literal `>` |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 409 | ``` |
| 410 | |
| 411 | The body of the identified struct is printed in full unless the it is |
| 412 | transitively contained in the same struct. In the latter case, only the |
| 413 | identifier is printed. For example, the structure containing the pointer to |
| 414 | itself is represented as `!llvm.struct<"A", (ptr<"A">)>`, and the structure `A` |
| 415 | containing two pointers to the structure `B` containing a pointer to the |
| 416 | structure `A` is represented as `!llvm.struct<"A", (ptr<"B", (ptr<"A">)>, |
| 417 | ptr<"B", (ptr<"A">))>`. Note that the structure `B` is "unrolled" for both |
| 418 | elements. _A structure with the same name but different body is a syntax error._ |
| 419 | **The user must ensure structure name uniqueness across all modules processed in |
Kazuaki Ishizaki | 2b638ed | 2021-01-06 17:35:29 | [diff] [blame] | 420 | a given MLIR context.** Structure names are arbitrary string literals and may |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 421 | include, e.g., spaces and keywords. |
| 422 | |
| 423 | Identified structs may be _opaque_. In this case, the body is unknown but the |
| 424 | structure type is considered _initialized_ and is valid in the IR. |
| 425 | |
| 426 | #### Literal Structure Types |
| 427 | |
| 428 | Literal structures are uniqued according to the list of elements they contain, |
| 429 | and can optionally be packed. The syntax for such structs is as follows. |
| 430 | |
| 431 | ``` |
Alex Zinenko | 7fd1850 | 2021-01-12 11:07:12 | [diff] [blame] | 432 | llvm-literal-struct-type ::= `!llvm.struct<` `packed`? `(` type-list `)` `>` |
| 433 | type-list ::= <maybe empty comma-separated list of types with optional !llvm.> |
Alex Zinenko | c275125 | 2020-12-15 17:29:12 | [diff] [blame] | 434 | ``` |
| 435 | |
| 436 | Literal structs cannot be recursive, but can contain other structs. Therefore, |
| 437 | they must be constructed in a single step with the entire list of contained |
| 438 | elements provided. |
| 439 | |
| 440 | #### Examples of Structure Types |
| 441 | |
| 442 | ```mlir |
| 443 | !llvm.struct<> // NOT allowed |
| 444 | !llvm.struct<()> // empty, literal |
| 445 | !llvm.struct<(i32)> // literal |
| 446 | !llvm.struct<(struct<(i32)>)> // struct containing a struct |
| 447 | !llvm.struct<packed (i8, i32)> // packed struct |
| 448 | !llvm.struct<"a"> // recursive reference, only allowed within |
| 449 | // another struct, NOT allowed at top level |
| 450 | !llvm.struct<"a", ptr<struct<"a">>> // supported example of recursive reference |
| 451 | !llvm.struct<"a", ()> // empty, named (necessary to differentiate from |
| 452 | // recursive reference) |
| 453 | !llvm.struct<"a", opaque> // opaque, named |
| 454 | !llvm.struct<"a", (i32)> // named |
| 455 | !llvm.struct<"a", packed (i8, i32)> // named, packed |
| 456 | ``` |
| 457 | |
| 458 | ### Unsupported Types |
| 459 | |
| 460 | LLVM IR `label` type does not have a counterpart in the LLVM dialect since, in |
| 461 | MLIR, blocks are not values and don't need a type. |
Alex Zinenko | f0597cb | 2019-02-22 09:00:25 | [diff] [blame] | 462 | |
River Riddle | 465ef55 | 2019-04-05 15:19:42 | [diff] [blame] | 463 | ## Operations |
Alex Zinenko | f0597cb | 2019-02-22 09:00:25 | [diff] [blame] | 464 | |
Alex Zinenko | 736bef7 | 2019-04-02 22:33:54 | [diff] [blame] | 465 | All operations in the LLVM IR dialect have a custom form in MLIR. The mnemonic |
| 466 | of an operation is that used in LLVM IR prefixed with "`llvm.`". |
Alex Zinenko | f0597cb | 2019-02-22 09:00:25 | [diff] [blame] | 467 | |
Alex Zinenko | eb4917d | 2020-12-17 13:09:11 | [diff] [blame] | 468 | [include "Dialects/LLVMOps.md"] |