1# MLIR Specification 2 3MLIR (Multi-Level IR) is a compiler intermediate representation with 4similarities to traditional three-address SSA representations (like 5[LLVM IR](http://llvm.org/docs/LangRef.html) or 6[SIL](https://github.com/apple/swift/blob/master/docs/SIL.rst)), but which 7introduces notions from polyhedral loop optimization as first-class concepts. 8This hybrid design is optimized to represent, analyze, and transform high level 9dataflow graphs as well as target-specific code generated for high performance 10data parallel systems. Beyond its representational capabilities, its single 11continuous design provides a framework to lower from dataflow graphs to 12high-performance target-specific code. 13 14This document defines and describes the key concepts in MLIR, and is intended to 15be a dry reference document - the [rationale documentation](Rationale.md), 16[glossary](../getting_started/Glossary.md), and other content are hosted elsewhere. 17 18MLIR is designed to be used in three different forms: a human-readable textual 19form suitable for debugging, an in-memory form suitable for programmatic 20transformations and analysis, and a compact serialized form suitable for storage 21and transport. The different forms all describe the same semantic content. This 22document describes the human-readable textual form. 23 24[TOC] 25 26## High-Level Structure 27 28MLIR is an 29[SSA-based](https://en.wikipedia.org/wiki/Static_single_assignment_form) IR, 30which means that values are defined before use and have scope defined by their 31dominance relations. Operations may produce zero or more results, and each is a 32distinct SSA value with its own type defined by the [type system](#type-system). 33 34The unit of code in MLIR is an [Operation](#operations). Operations allow for 35representing many different concepts: allocating buffers, producing views to 36transform them, target-independent arithmetic, target-specific operations, and 37even arbitrary user-defined high-level operations including the 38[Module](#module) and [Function](#functions) operations. Operations may contain 39[Regions](#regions) that represent a Control Flow Graph (CFG) of 40[Blocks](#blocks), that contain operations and end with a 41[terminator operation](#terminator-operations) (like branches). 42 43Here's an example of an MLIR module: 44 45```mlir 46// Compute A*B using an implementation of multiply kernel and print the 47// result using a TensorFlow op. The dimensions of A and B are partially 48// known. The shapes are assumed to match. 49func @mul(%A: tensor<100x?xf32>, %B: tensor<?x50xf32>) -> (tensor<100x50xf32>) { 50 // Compute the inner dimension of %A using the dim operation. 51 %n = dim %A, 1 : tensor<100x?xf32> 52 53 // Allocate addressable "buffers" and copy tensors %A and %B into them. 54 %A_m = alloc(%n) : memref<100x?xf32> 55 tensor_store %A to %A_m : memref<100x?xf32> 56 57 %B_m = alloc(%n) : memref<?x50xf32> 58 tensor_store %B to %B_m : memref<?x50xf32> 59 60 // Call function @multiply passing memrefs as arguments, 61 // and getting returned the result of the multiplication. 62 %C_m = call @multiply(%A_m, %B_m) 63 : (memref<100x?xf32>, memref<?x50xf32>) -> (memref<100x50xf32>) 64 65 dealloc %A_m : memref<100x?xf32> 66 dealloc %B_m : memref<?x50xf32> 67 68 // Load the buffer data into a higher level "tensor" value. 69 %C = tensor_load %C_m : memref<100x50xf32> 70 dealloc %C_m : memref<100x50xf32> 71 72 // Call TensorFlow built-in function to print the result tensor. 73 "tf.Print"(%C){message: "mul result"} 74 : (tensor<100x50xf32) -> (tensor<100x50xf32>) 75 76 return %C : tensor<100x50xf32> 77} 78 79// A function that multiplies two memrefs and returns the result. 80func @multiply(%A: memref<100x?xf32>, %B: memref<?x50xf32>) 81 -> (memref<100x50xf32>) { 82 // Compute the inner dimension of %A. 83 %n = dim %A, 1 : memref<100x?xf32> 84 85 // Allocate memory for the multiplication result. 86 %C = alloc() : memref<100x50xf32> 87 88 // Multiplication loop nest. 89 affine.for %i = 0 to 100 { 90 affine.for %j = 0 to 50 { 91 store 0 to %C[%i, %j] : memref<100x50xf32> 92 affine.for %k = 0 to %n { 93 %a_v = load %A[%i, %k] : memref<100x?xf32> 94 %b_v = load %B[%k, %j] : memref<?x50xf32> 95 %prod = mulf %a_v, %b_v : f32 96 %c_v = load %C[%i, %j] : memref<100x50xf32> 97 %sum = addf %c_v, %prod : f32 98 store %sum, %C[%i, %j] : memref<100x50xf32> 99 } 100 } 101 } 102 return %C : memref<100x50xf32> 103} 104``` 105 106## Notation 107 108MLIR has a simple and unambiguous grammar, allowing it to reliably round-trip 109through a textual form. This is important for development of the compiler - e.g. 110for understanding the state of code as it is being transformed and writing test 111cases. 112 113This document describes the grammar using 114[Extended Backus-Naur Form (EBNF)](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form). 115 116This is the EBNF grammar used in this document, presented in yellow boxes. 117 118``` 119alternation ::= expr0 | expr1 | expr2 // Either expr0 or expr1 or expr2. 120sequence ::= expr0 expr1 expr2 // Sequence of expr0 expr1 expr2. 121repetition0 ::= expr* // 0 or more occurrences. 122repetition1 ::= expr+ // 1 or more occurrences. 123optionality ::= expr? // 0 or 1 occurrence. 124grouping ::= (expr) // Everything inside parens is grouped together. 125literal ::= `abcd` // Matches the literal `abcd`. 126``` 127 128Code examples are presented in blue boxes. 129 130```mlir 131// This is an example use of the grammar above: 132// This matches things like: ba, bana, boma, banana, banoma, bomana... 133example ::= `b` (`an` | `om`)* `a` 134``` 135 136### Common syntax 137 138The following core grammar productions are used in this document: 139 140``` 141// TODO: Clarify the split between lexing (tokens) and parsing (grammar). 142digit ::= [0-9] 143hex_digit ::= [0-9a-fA-F] 144letter ::= [a-zA-Z] 145id-punct ::= [$._-] 146 147integer-literal ::= decimal-literal | hexadecimal-literal 148decimal-literal ::= digit+ 149hexadecimal-literal ::= `0x` hex_digit+ 150float-literal ::= [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)? 151string-literal ::= `"` [^"\n\f\v\r]* `"` TODO define escaping rules 152``` 153 154Not listed here, but MLIR does support comments. They use standard BCPL syntax, 155starting with a `//` and going until the end of the line. 156 157### Identifiers and keywords 158 159Syntax: 160 161``` 162// Identifiers 163bare-id ::= (letter|[_]) (letter|digit|[_$.])* 164bare-id-list ::= bare-id (`,` bare-id)* 165ssa-id ::= `%` suffix-id 166suffix-id ::= (digit+ | ((letter|id-punct) (letter|id-punct|digit)*)) 167 168symbol-ref-id ::= `@` (suffix-id | string-literal) 169ssa-id-list ::= ssa-id (`,` ssa-id)* 170 171// Uses of an SSA value, e.g. in an operand list to an operation. 172ssa-use ::= ssa-id 173ssa-use-list ::= ssa-use (`,` ssa-use)* 174``` 175 176Identifiers name entities such as SSA values, types and functions, and are 177chosen by the writer of MLIR code. Identifiers may be descriptive (e.g. 178`%batch_size`, `@matmul`), or may be non-descriptive when they are 179auto-generated (e.g. `%23`, `@func42`). Identifier names for SSA values may be 180used in an MLIR text file but are not persisted as part of the IR - the printer 181will give them anonymous names like `%42`. 182 183MLIR guarantees identifiers never collide with keywords by prefixing identifiers 184with a sigil (e.g. `%`, `#`, `@`, `^`, `!`). In certain unambiguous contexts 185(e.g. affine expressions), identifiers are not prefixed, for brevity. New 186keywords may be added to future versions of MLIR without danger of collision 187with existing identifiers. 188 189The scope of SSA values is defined based on the standard definition of 190[dominance](https://en.wikipedia.org/wiki/Dominator_\(graph_theory\)). Argument 191identifiers in mapping functions are in scope for the mapping body. Function 192identifiers and mapping identifiers are visible across the entire module. 193 194## Dialects 195 196Dialects are the mechanism by which to engage with and extend the MLIR 197ecosystem. They allow for defining new [operations](#operations), as well as 198[attributes](#attributes) and [types](#type-system). Each dialect is given a 199unique `namespace` that is prefixed to each defined attribute/operation/type. 200For example, the [Affine dialect](Dialects/Affine.md) defines the namespace: 201`affine`. 202 203MLIR allows for multiple dialects, even those outside of the main tree, to 204co-exist together within one module. Dialects are produced and consumed by 205certain passes. MLIR provides a [framework](DialectConversion.md) to convert 206between, and within, different dialects. 207 208A few of the dialects supported by MLIR: 209 210* [Affine dialect](Dialects/Affine.md) 211* [GPU dialect](Dialects/GPU.md) 212* [LLVM dialect](Dialects/LLVM.md) 213* [SPIR-V dialect](Dialects/SPIR-V.md) 214* [Standard dialect](Dialects/Standard.md) 215* [Vector dialect](Dialects/Vector.md) 216 217### Target specific operations 218 219Dialects provide a modular way in which targets can expose target-specific 220operations directly through to MLIR. As an example, some targets go through 221LLVM. LLVM has a rich set of intrinsics for certain target-independent 222operations (e.g. addition with overflow check) as well as providing access to 223target-specific operations for the targets it supports (e.g. vector permutation 224operations). LLVM intrinsics in MLIR are represented via operations that start 225with an "llvm." name. 226 227Example: 228 229```mlir 230// LLVM: %x = call {i16, i1} @llvm.sadd.with.overflow.i16(i16 %a, i16 %b) 231%x:2 = "llvm.sadd.with.overflow.i16"(%a, %b) : (i16, i16) -> (i16, i1) 232``` 233 234These operations only work when targeting LLVM as a backend (e.g. for CPUs and 235GPUs), and are required to align with the LLVM definition of these intrinsics. 236 237## Operations 238 239Syntax: 240 241``` 242operation ::= op-result-list? (generic-operation | custom-operation) 243 trailing-location? 244generic-operation ::= string-literal `(` ssa-use-list? `)` successor-list? 245 (`(` region-list `)`)? attribute-dict? `:` function-type 246custom-operation ::= bare-id custom-operation-format 247op-result-list ::= op-result (`,` op-result)* `=` 248op-result ::= ssa-id (`:` integer-literal) 249successor-list ::= successor (`,` successor)* 250successor ::= caret-id (`:` bb-arg-list)? 251region-list ::= region (`,` region)* 252trailing-location ::= (`loc` `(` location `)`)? 253``` 254 255MLIR introduces a uniform concept called _operations_ to enable describing many 256different levels of abstractions and computations. Operations in MLIR are fully 257extensible (there is no fixed list of operations) and have application-specific 258semantics. For example, MLIR supports 259[target-independent operations](Dialects/Standard.md#memory-operations), 260[affine operations](Dialects/Affine.md), and 261[target-specific machine operations](#target-specific-operations). 262 263The internal representation of an operation is simple: an operation is 264identified by a unique string (e.g. `dim`, `tf.Conv2d`, `x86.repmovsb`, 265`ppc.eieio`, etc), can return zero or more results, take zero or more SSA 266operands, may have zero or more attributes, may have zero or more successors, 267and zero or more enclosed [regions](#regions). The generic printing form 268includes all these elements literally, with a function type to indicate the 269types of the results and operands. 270 271Example: 272 273```mlir 274// An operation that produces two results. 275// The results of %result can be accessed via the <name> `#` <opNo> syntax. 276%result:2 = "foo_div"() : () -> (f32, i32) 277 278// Pretty form that defines a unique name for each result. 279%foo, %bar = "foo_div"() : () -> (f32, i32) 280 281// Invoke a TensorFlow function called tf.scramble with two inputs 282// and an attribute "fruit". 283%2 = "tf.scramble"(%result#0, %bar) {fruit: "banana"} : (f32, i32) -> f32 284``` 285 286In addition to the basic syntax above, dialects may register known operations. 287This allows those dialects to support _custom assembly form_ for parsing and 288printing operations. In the operation sets listed below, we show both forms. 289 290### Terminator Operations 291 292These are a special category of operations that *must* terminate a block, e.g. 293[branches](Dialects/Standard.md#terminator-operations). These operations may 294also have a list of successors ([blocks](#blocks) and their arguments). 295 296Example: 297 298```mlir 299// Branch to ^bb1 or ^bb2 depending on the condition %cond. 300// Pass value %v to ^bb2, but not to ^bb1. 301"cond_br"(%cond)[^bb1, ^bb2(%v : index)] : (i1) -> () 302``` 303 304### Module 305 306``` 307module ::= `module` symbol-ref-id? (`attributes` attribute-dict)? region 308``` 309 310An MLIR module represents an opaque top-level container operation. It contains a 311single region containing a single block that is comprised of any operations. 312Operations within this region must not implicitly capture values defined above 313it. Modules have an optional symbol name that can be used to refer to them in 314operations. 315 316### Functions 317 318An MLIR Function is an operation with a name containing one [region](#regions). 319The region of a function is not allowed to implicitly capture values defined 320outside of the function, and all external references must use function arguments 321or attributes that establish a symbolic connection (e.g. symbols referenced by 322name via a string attribute like [SymbolRefAttr](#symbol-reference-attribute)): 323 324``` 325function ::= `func` function-signature function-attributes? function-body? 326 327function-signature ::= symbol-ref-id `(` argument-list `)` 328 (`->` function-result-list)? 329 330argument-list ::= (named-argument (`,` named-argument)*) | /*empty*/ 331argument-list ::= (type attribute-dict? (`,` type attribute-dict?)*) | /*empty*/ 332named-argument ::= ssa-id `:` type attribute-dict? 333 334function-result-list ::= function-result-list-parens 335 | non-function-type 336function-result-list-parens ::= `(` `)` 337 | `(` function-result-list-no-parens `)` 338function-result-list-no-parens ::= function-result (`,` function-result)* 339function-result ::= type attribute-dict? 340 341function-attributes ::= `attributes` attribute-dict 342function-body ::= region 343``` 344 345An external function declaration (used when referring to a function declared in 346some other module) has no body. While the MLIR textual form provides a nice 347inline syntax for function arguments, they are internally represented as "block 348arguments" to the first block in the region. 349 350Only dialect attribute names may be specified in the attribute dictionaries for 351function arguments, results, or the function itself. 352 353Examples: 354 355```mlir 356// External function definitions. 357func @abort() 358func @scribble(i32, i64, memref<? x 128 x f32, #layout_map0>) -> f64 359 360// A function that returns its argument twice: 361func @count(%x: i64) -> (i64, i64) 362 attributes {fruit: "banana"} { 363 return %x, %x: i64, i64 364} 365 366// A function with an argument attribute 367func @example_fn_arg(%x: i32 {swift.self = unit}) 368 369// A function with a result attribute 370func @example_fn_result() -> (f64 {dialectName.attrName = 0 : i64}) 371 372// A function with an attribute 373func @example_fn_attr() attributes {dialectName.attrName = false} 374``` 375 376## Blocks 377 378Syntax: 379 380``` 381block ::= block-label operation+ 382block-label ::= block-id block-arg-list? `:` 383block-id ::= caret-id 384caret-id ::= `^` suffix-id 385ssa-id-and-type ::= ssa-id `:` type 386 387// Non-empty list of names and types. 388ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)* 389 390block-arg-list ::= `(` ssa-id-and-type-list? `)` 391``` 392 393A [block](https://en.wikipedia.org/wiki/Basic_block) is a sequential list of 394operations without control flow (a call or entering an op's region is not 395considered control flow for this purpose) that are executed from top to bottom. 396The last operation in a block is a 397[terminator operation](#terminator-operations), which ends the block. 398 399Blocks in MLIR take a list of block arguments, which represent SSA PHI nodes in 400a functional notation. The arguments are defined by the block, and values are 401provided for these block arguments by branches that go to the block. 402 403Here is a simple example function showing branches, returns, and block 404arguments: 405 406```mlir 407func @simple(i64, i1) -> i64 { 408^bb0(%a: i64, %cond: i1): // Code dominated by ^bb0 may refer to %a 409 cond_br %cond, ^bb1, ^bb2 410 411^bb1: 412 br ^bb3(%a: i64) // Branch passes %a as the argument 413 414^bb2: 415 %b = addi %a, %a : i64 416 br ^bb3(%b: i64) // Branch passes %b as the argument 417 418// ^bb3 receives an argument, named %c, from predecessors 419// and passes it on to bb4 twice. 420^bb3(%c: i64): 421 br ^bb4(%c, %c : i64, i64) 422 423^bb4(%d : i64, %e : i64): 424 %0 = addi %d, %e : i64 425 return %0 : i64 426} 427``` 428 429**Context:** The "block argument" representation eliminates a number of special 430cases from the IR compared to traditional "PHI nodes are operations" SSA IRs 431(like LLVM). For example, the 432[parallel copy semantics](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.524.5461&rep=rep1&type=pdf) 433of SSA is immediately apparent, and function arguments are no longer a special 434case: they become arguments to the entry block 435[[more rationale](Rationale.md#block-arguments-vs-phi-nodes)]. 436 437## Regions 438 439### Definition 440 441A region is a CFG of MLIR [Blocks](#blocks). Regions serve to group semantically 442connected blocks, where the semantics is not imposed by the IR. Instead, the 443containing operation defines the semantics of the regions it contains. Regions 444do not have a name or an address, only the blocks contained in a region do. 445Regions are meaningless outside of the containing entity and have no type or 446attributes. 447 448The first block in the region cannot be a successor of any other block. The 449syntax for the region is as follows: 450 451``` 452region ::= `{` block* `}` 453``` 454 455The function body is an example of a region: it consists of a CFG of blocks and 456has additional semantic restrictions that other types of regions may not have 457(block terminators must either branch to a different block, or return from a 458function where the types of the `return` arguments must match the result types 459of the function signature). 460 461### Control and Value Scoping 462 463Regions provide nested control isolation: it is impossible to branch to a block 464within a region from outside it or to branch from within a region to a block 465outside it. Similarly, it provides a natural scoping for value visibility: SSA 466values defined in a region don't escape to the enclosing region, if any. By 467default, a region can reference values defined outside of the region whenever it 468would have been legal to use them as operands to the enclosing operation. 469 470Example: 471 472```mlir 473func @accelerator_compute(i64, i1) -> i64 { 474^bb0(%a: i64, %cond: i1): // Code dominated by ^bb0 may refer to %a 475 cond_br %cond, ^bb1, ^bb2 476 477^bb1: 478 // This def for %value does not dominate ^bb2 479 %value = "op.convert"(%a) : (i64) -> i64 480 br ^bb3(%a: i64) // Branch passes %a as the argument 481 482^bb2: 483 "accelerator.launch"() { 484 ^bb0: 485 // Region of code nested under "accelerator.launch", it can reference %a but 486 // not %value. 487 %new_value = "accelerator.do_something"(%a) : (i64) -> () 488 } 489 // %new_value cannot be referenced outside of the region 490 491^bb3: 492 ... 493} 494``` 495 496This can be further restricted using the custom verifier associated with the 497enclosing operation, for example, disallowing references to values defined 498outside the region completely. 499 500### Control Flow 501 502Regions are Single-Entry-Multiple-Exit (SEME). This means that control can only 503flow into the first block of the region, but can flow out of the region at the 504end of any of the contained blocks (This behavior is similar to that of a 505function body in most programming languages). A terminator of a block within a 506region may transfer the control flow to another block in this region, or return 507it to the immediately enclosing op. The semantics of the enclosing op defines 508where the control flow is transmitted next. It may, for example, enter a region 509of the same op, including the same region that returned the control flow. 510 511The enclosing operation determines the way in which control is transmitted into 512the entry block of a Region. The successor to a region’s exit points may not 513necessarily exist: for example a call to a function that does not return. 514Concurrent or asynchronous execution of regions is unspecified. Operations may 515define specific rules of execution, e.g. sequential loops or switch cases. 516 517A Region may also enter another region within the enclosing operation. If an 518operation has multiple regions, the semantics of the operation defines into 519which regions the control flows and in which order, if any. An operation may 520transmit control into regions that were specified in other operations, in 521particular those that defined the values the given operation uses. Thus such 522operations can be treated opaquely in the enclosing control flow graph, 523providing a level of control flow isolation similar to that of the call 524operation. 525 526#### Closure 527 528Regions allow defining an operation that creates a closure, for example by 529“boxing” the body of the region into a value they produce. It remains up to the 530operation to define its semantics. Note that if an operation triggers 531asynchronous execution of the region, it is under the responsibility of the 532operation caller to wait for the region to be executed guaranteeing that any 533directly used values remain live. 534 535### Arguments and Results 536 537The arguments of the first block of a region are treated as arguments of the 538region. The source of these arguments is defined by the semantics of the parent 539operation. They may correspond to some of the values the operation itself uses. 540 541Regions produce a (possibly empty) list of values. The operation semantics 542defines the relation between the region results and the operation results. 543 544## Type System 545 546Each SSA value in MLIR has a type defined by the type system below. There are a 547number of primitive types (like integers) and also aggregate types for tensors 548and memory buffers. MLIR [standard types](#standard-types) do not include 549structures, arrays, or dictionaries. 550 551MLIR has an open type system (i.e. there is no fixed list of types), and types 552may have application-specific semantics. For example, MLIR supports a set of 553[dialect types](#dialect-types). 554 555``` 556type ::= type-alias | dialect-type | standard-type 557 558type-list-no-parens ::= type (`,` type)* 559type-list-parens ::= `(` `)` 560 | `(` type-list-no-parens `)` 561 562// This is a common way to refer to an SSA value with a specified type. 563ssa-use-and-type ::= ssa-use `:` type 564 565// Non-empty list of names and types. 566ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)* 567``` 568 569### Type Aliases 570 571``` 572type-alias-def ::= '!' alias-name '=' 'type' type 573type-alias ::= '!' alias-name 574``` 575 576MLIR supports defining named aliases for types. A type alias is an identifier 577that can be used in the place of the type that it defines. These aliases *must* 578be defined before their uses. Alias names may not contain a '.', since those 579names are reserved for [dialect types](#dialect-types). 580 581Example: 582 583```mlir 584!avx_m128 = type vector<4 x f32> 585 586// Using the original type. 587"foo"(%x) : vector<4 x f32> -> () 588 589// Using the type alias. 590"foo"(%x) : !avx_m128 -> () 591``` 592 593### Dialect Types 594 595Similarly to operations, dialects may define custom extensions to the type 596system. 597 598``` 599dialect-namespace ::= bare-id 600 601opaque-dialect-item ::= dialect-namespace '<' string-literal '>' 602 603pretty-dialect-item ::= dialect-namespace '.' pretty-dialect-item-lead-ident 604 pretty-dialect-item-body? 605 606pretty-dialect-item-lead-ident ::= '[A-Za-z][A-Za-z0-9._]*' 607pretty-dialect-item-body ::= '<' pretty-dialect-item-contents+ '>' 608pretty-dialect-item-contents ::= pretty-dialect-item-body 609 | '(' pretty-dialect-item-contents+ ')' 610 | '[' pretty-dialect-item-contents+ ']' 611 | '{' pretty-dialect-item-contents+ '}' 612 | '[^[<({>\])}\0]+' 613 614dialect-type ::= '!' opaque-dialect-item 615dialect-type ::= '!' pretty-dialect-item 616``` 617 618Dialect types can be specified in a verbose form, e.g. like this: 619 620```mlir 621// LLVM type that wraps around llvm IR types. 622!llvm<"i32*"> 623 624// Tensor flow string type. 625!tf.string 626 627// Complex type 628!foo<"something<abcd>"> 629 630// Even more complex type 631!foo<"something<a%%123^^^>>>"> 632``` 633 634Dialect types that are simple enough can use the pretty format, which is a 635lighter weight syntax that is equivalent to the above forms: 636 637```mlir 638// Tensor flow string type. 639!tf.string 640 641// Complex type 642!foo.something<abcd> 643``` 644 645Sufficiently complex dialect types are required to use the verbose form for 646generality. For example, the more complex type shown above wouldn't be valid in 647the lighter syntax: `!foo.something<a%%123^^^>>>` because it contains characters 648that are not allowed in the lighter syntax, as well as unbalanced `<>` 649characters. 650 651See [here](DefiningAttributesAndTypes.md) to learn how to define dialect types. 652 653### Standard Types 654 655Standard types are a core set of [dialect types](#dialect-types) that are 656defined in a builtin dialect and thus available to all users of MLIR. 657 658``` 659standard-type ::= complex-type 660 | float-type 661 | function-type 662 | index-type 663 | integer-type 664 | memref-type 665 | none-type 666 | tensor-type 667 | tuple-type 668 | vector-type 669``` 670 671#### Complex Type 672 673Syntax: 674 675``` 676complex-type ::= `complex` `<` type `>` 677``` 678 679The value of `complex` type represents a complex number with a parameterized 680element type, which is composed of a real and imaginary value of that element 681type. The element must be a floating point or integer scalar type. 682 683Examples: 684 685```mlir 686complex<f32> 687complex<i32> 688``` 689 690#### Floating Point Types 691 692Syntax: 693 694``` 695// Floating point. 696float-type ::= `f16` | `bf16` | `f32` | `f64` 697``` 698 699MLIR supports float types of certain widths that are widely used as indicated 700above. 701 702#### Function Type 703 704Syntax: 705 706``` 707// MLIR functions can return multiple values. 708function-result-type ::= type-list-parens 709 | non-function-type 710 711function-type ::= type-list-parens `->` function-result-type 712``` 713 714MLIR supports first-class functions: for example, the 715[`constant` operation](Dialects/Standard.md#constant-operation) produces the 716address of a function as an SSA value. This SSA value may be passed to and 717returned from functions, merged across control flow boundaries with 718[block arguments](#blocks), and called with the 719[`call_indirect` operation](Dialects/Standard.md#call-indirect-operation). 720 721Function types are also used to indicate the arguments and results of 722[operations](#operations). 723 724#### Index Type 725 726Syntax: 727 728``` 729// Target word-sized integer. 730index-type ::= `index` 731``` 732 733The `index` type is a signless integer whose size is equal to the natural 734machine word of the target ([rationale](Rationale.md#signless-types)) and is 735used by the affine constructs in MLIR. Unlike fixed-size integers, it cannot be 736used as an element of vector, tensor or memref type 737([rationale](Rationale.md#index-type-disallowed-in-vectortensormemref-types)). 738 739**Rationale:** integers of platform-specific bit widths are practical to express 740sizes, dimensionalities and subscripts. 741 742#### Integer Type 743 744Syntax: 745 746``` 747// Sized integers like i1, i4, i8, i16, i32. 748signed-integer-type ::= `si` [1-9][0-9]* 749unsigned-integer-type ::= `ui` [1-9][0-9]* 750signless-integer-type ::= `i` [1-9][0-9]* 751integer-type ::= signed-integer-type | 752 unsigned-integer-type | 753 signless-integer-type 754``` 755 756MLIR supports arbitrary precision integer types. Integer types have a designated 757width and may have signedness semantics. 758 759**Rationale:** low precision integers (like `i2`, `i4` etc) are useful for 760low-precision inference chips, and arbitrary precision integers are useful for 761hardware synthesis (where a 13 bit multiplier is a lot cheaper/smaller than a 16 762bit one). 763 764TODO: Need to decide on a representation for quantized integers 765([initial thoughts](Rationale.md#quantized-integer-operations)). 766 767#### Memref Type 768 769Syntax: 770 771``` 772memref-type ::= ranked-memref-type | unranked-memref-type 773 774ranked-memref-type ::= `memref` `<` dimension-list-ranked tensor-memref-element-type 775 (`,` layout-specification)? | 776 (`,` memory-space)? `>` 777 778unranked-memref-type ::= `memref` `<*x` tensor-memref-element-type 779 (`,` memory-space)? `>` 780 781stride-list ::= `[` (dimension (`,` dimension)*)? `]` 782strided-layout ::= `offset:` dimension `,` `strides: ` stride-list 783layout-specification ::= semi-affine-map | strided-layout 784memory-space ::= integer-literal /* | TODO: address-space-id */ 785``` 786 787A `memref` type is a reference to a region of memory (similar to a buffer 788pointer, but more powerful). The buffer pointed to by a memref can be allocated, 789aliased and deallocated. A memref can be used to read and write data from/to the 790memory region which it references. Memref types use the same shape specifier as 791tensor types. Note that `memref<f32>`, `memref<0 x f32>`, `memref<1 x 0 x f32>`, 792and `memref<0 x 1 x f32>` are all different types. 793 794A `memref` is allowed to have an unknown rank (e.g. `memref<*xf32>`). The 795purpose of unranked memrefs is to allow external library functions to receive 796memref arguments of any rank without versioning the functions based on the rank. 797Other uses of this type are disallowed or will have undefined behavior. 798 799##### Codegen of Unranked Memref 800 801Using unranked memref in codegen besides the case mentioned above is highly 802discouraged. Codegen is concerned with generating loop nests and specialized 803instructions for high-performance, unranked memref is concerned with hiding the 804rank and thus, the number of enclosing loops required to iterate over the data. 805However, if there is a need to code-gen unranked memref, one possible path is to 806cast into a static ranked type based on the dynamic rank. Another possible path 807is to emit a single while loop conditioned on a linear index and perform 808delinearization of the linear index to a dynamic array containing the (unranked) 809indices. While this is possible, it is expected to not be a good idea to perform 810this during codegen as the cost of the translations is expected to be 811prohibitive and optimizations at this level are not expected to be worthwhile. 812If expressiveness is the main concern, irrespective of performance, passing 813unranked memrefs to an external C++ library and implementing rank-agnostic logic 814there is expected to be significantly simpler. 815 816Unranked memrefs may provide expressiveness gains in the future and help bridge 817the gap with unranked tensors. Unranked memrefs will not be expected to be 818exposed to codegen but one may query the rank of an unranked memref (a special 819op will be needed for this purpose) and perform a switch and cast to a ranked 820memref as a prerequisite to codegen. 821 822Example: 823 824```mlir 825// With static ranks, we need a function for each possible argument type 826%A = alloc() : memref<16x32xf32> %B = alloc() : 827memref<16x32x64xf32> call @helper_2D(%A) : (memref<16x32xf32>)->() call 828@helper_3D(%B) : (memref<16x32x64xf32>)->() 829 830// With unknown rank, the functions can be unified under one unranked type 831%A = alloc() : memref<16x32xf32> 832%B = alloc() : memref<16x32x64xf32> 833// Remove rank info 834%A_u = memref_cast %A : memref<16x32xf32> -> memref<*xf32> 835%B_u = memref_cast %B : memref<16x32x64xf32> -> memref<*xf32> 836// call same function with dynamic ranks 837call @helper(%A_u) : (memref<*xf32>)->() 838call @helper(%B_u) : (memref<*xf32>)->() 839``` 840 841The core syntax and representation of a layout specification is a 842[semi-affine map](Dialects/Affine.md#semi-affine-maps). Additionally, syntactic 843sugar is supported to make certain layout specifications more intuitive to read. 844For the moment, a `memref` supports parsing a strided form which is converted to 845a semi-affine map automatically. 846 847The memory space of a memref is specified by a target-specific integer index. If 848no memory space is specified, then the default memory space (0) is used. The 849default space is target specific but always at index 0. 850 851TODO: MLIR will eventually have target-dialects which allow symbolic use of 852memory hierarchy names (e.g. L3, L2, L1, ...) but we have not spec'd the details 853of that mechanism yet. Until then, this document pretends that it is valid to 854refer to these memories by `bare-id`. 855 856The notionally dynamic value of a memref value includes the address of the 857buffer allocated, as well as the symbols referred to by the shape, layout map, 858and index maps. 859 860Examples of memref static type 861 862```mlir 863// Identity index/layout map 864#identity = affine_map<(d0, d1) -> (d0, d1)> 865 866// Column major layout. 867#col_major = affine_map<(d0, d1, d2) -> (d2, d1, d0)> 868 869// A 2-d tiled layout with tiles of size 128 x 256. 870#tiled_2d_128x256 = affine_map<(d0, d1) -> (d0 div 128, d1 div 256, d0 mod 128, d1 mod 256)> 871 872// A tiled data layout with non-constant tile sizes. 873#tiled_dynamic = affine_map<(d0, d1)[s0, s1] -> (d0 floordiv s0, d1 floordiv s1, 874 d0 mod s0, d1 mod s1)> 875 876// A layout that yields a padding on two at either end of the minor dimension. 877#padded = affine_map<(d0, d1) -> (d0, (d1 + 2) floordiv 2, (d1 + 2) mod 2)> 878 879 880// The dimension list "16x32" defines the following 2D index space: 881// 882// { (i, j) : 0 <= i < 16, 0 <= j < 32 } 883// 884memref<16x32xf32, #identity, memspace0> 885 886// The dimension list "16x4x?" defines the following 3D index space: 887// 888// { (i, j, k) : 0 <= i < 16, 0 <= j < 4, 0 <= k < N } 889// 890// where N is a symbol which represents the runtime value of the size of 891// the third dimension. 892// 893// %N here binds to the size of the third dimension. 894%A = alloc(%N) : memref<16x4x?xf32, #col_major, memspace0> 895 896// A 2-d dynamic shaped memref that also has a dynamically sized tiled layout. 897// The memref index space is of size %M x %N, while %B1 and %B2 bind to the 898// symbols s0, s1 respectively of the layout map #tiled_dynamic. Data tiles of 899// size %B1 x %B2 in the logical space will be stored contiguously in memory. 900// The allocation size will be (%M ceildiv %B1) * %B1 * (%N ceildiv %B2) * %B2 901// f32 elements. 902%T = alloc(%M, %N) [%B1, %B2] : memref<?x?xf32, #tiled_dynamic> 903 904// A memref that has a two-element padding at either end. The allocation size 905// will fit 16 * 64 float elements of data. 906%P = alloc() : memref<16x64xf32, #padded> 907 908// Affine map with symbol 's0' used as offset for the first dimension. 909#imapS = affine_map<(d0, d1) [s0] -> (d0 + s0, d1)> 910// Allocate memref and bind the following symbols: 911// '%n' is bound to the dynamic second dimension of the memref type. 912// '%o' is bound to the symbol 's0' in the affine map of the memref type. 913%n = ... 914%o = ... 915%A = alloc (%n)[%o] : <16x?xf32, #imapS> 916``` 917 918##### Index Space 919 920A memref dimension list defines an index space within which the memref can be 921indexed to access data. 922 923##### Index 924 925Data is accessed through a memref type using a multidimensional index into the 926multidimensional index space defined by the memref's dimension list. 927 928Examples 929 930```mlir 931// Allocates a memref with 2D index space: 932// { (i, j) : 0 <= i < 16, 0 <= j < 32 } 933%A = alloc() : memref<16x32xf32, #imapA, memspace0> 934 935// Loads data from memref '%A' using a 2D index: (%i, %j) 936%v = load %A[%i, %j] : memref<16x32xf32, #imapA, memspace0> 937``` 938 939##### Index Map 940 941An index map is a one-to-one 942[semi-affine map](Dialects/Affine.md#semi-affine-maps) that transforms a 943multidimensional index from one index space to another. For example, the 944following figure shows an index map which maps a 2-dimensional index from a 2x2 945index space to a 3x3 index space, using symbols `S0` and `S1` as offsets. 946 947 948 949The number of domain dimensions and range dimensions of an index map can be 950different, but must match the number of dimensions of the input and output index 951spaces on which the map operates. The index space is always non-negative and 952integral. In addition, an index map must specify the size of each of its range 953dimensions onto which it maps. Index map symbols must be listed in order with 954symbols for dynamic dimension sizes first, followed by other required symbols. 955 956##### Layout Map 957 958A layout map is a [semi-affine map](Dialects/Affine.md#semi-affine-maps) which 959encodes logical to physical index space mapping, by mapping input dimensions to 960their ordering from most-major (slowest varying) to most-minor (fastest 961varying). Therefore, an identity layout map corresponds to a row-major layout. 962Identity layout maps do not contribute to the MemRef type identification and are 963discarded on construction. That is, a type with an explicit identity map is 964`memref<?x?xf32, (i,j)->(i,j)>` is strictly the same as the one without layout 965maps, `memref<?x?xf32>`. 966 967Layout map examples: 968 969```mlir 970// MxN matrix stored in row major layout in memory: 971#layout_map_row_major = (i, j) -> (i, j) 972 973// MxN matrix stored in column major layout in memory: 974#layout_map_col_major = (i, j) -> (j, i) 975 976// MxN matrix stored in a 2-d blocked/tiled layout with 64x64 tiles. 977#layout_tiled = (i, j) -> (i floordiv 64, j floordiv 64, i mod 64, j mod 64) 978``` 979 980##### Affine Map Composition 981 982A memref specifies a semi-affine map composition as part of its type. A 983semi-affine map composition is a composition of semi-affine maps beginning with 984zero or more index maps, and ending with a layout map. The composition must be 985conformant: the number of dimensions of the range of one map, must match the 986number of dimensions of the domain of the next map in the composition. 987 988The semi-affine map composition specified in the memref type, maps from accesses 989used to index the memref in load/store operations to other index spaces (i.e. 990logical to physical index mapping). Each of the 991[semi-affine maps](Dialects/Affine.md) and thus its composition is required to 992be one-to-one. 993 994The semi-affine map composition can be used in dependence analysis, memory 995access pattern analysis, and for performance optimizations like vectorization, 996copy elision and in-place updates. If an affine map composition is not specified 997for the memref, the identity affine map is assumed. 998 999##### Strided MemRef 1000 1001A memref may specify strides as part of its type. A stride specification is a 1002list of integer values that are either static or `?` (dynamic case). Strides 1003encode the distance, in number of elements, in (linear) memory between 1004successive entries along a particular dimension. A stride specification is 1005syntactic sugar for an equivalent strided memref representation using 1006semi-affine maps. For example, `memref<42x16xf32, offset: 33 strides: [1, 64]>` 1007specifies a non-contiguous memory region of `42` by `16` `f32` elements such 1008that: 1009 10101. the minimal size of the enclosing memory region must be `33 + 42 * 1 + 16 * 1011 64 = 1066` elements; 10122. the address calculation for accessing element `(i, j)` computes `33 + i + 1013 64 * j` 10143. the distance between two consecutive elements along the outer dimension is 1015 `1` element and the distance between two consecutive elements along the 1016 outer dimension is `64` elements. 1017 1018This corresponds to a column major view of the memory region and is internally 1019represented as the type `memref<42x16xf32, (i, j) -> (33 + i + 64 * j)>`. 1020 1021The specification of strides must not alias: given an n-D strided memref, 1022indices `(i1, ..., in)` and `(j1, ..., jn)` may not refer to the same memory 1023address unless `i1 == j1, ..., in == jn`. 1024 1025Strided memrefs represent a view abstraction over preallocated data. They are 1026constructed with special ops, yet to be introduced. Strided memrefs are a 1027special subclass of memrefs with generic semi-affine map and correspond to a 1028normalized memref descriptor when lowering to LLVM. 1029 1030#### None Type 1031 1032Syntax: 1033 1034``` 1035none-type ::= `none` 1036``` 1037 1038The `none` type is a unit type, i.e. a type with exactly one possible value, 1039where its value does not have a defined dynamic representation. 1040 1041#### Tensor Type 1042 1043Syntax: 1044 1045``` 1046tensor-type ::= `tensor` `<` dimension-list tensor-memref-element-type `>` 1047tensor-memref-element-type ::= vector-element-type | vector-type | complex-type 1048 1049// memref requires a known rank, but tensor does not. 1050dimension-list ::= dimension-list-ranked | (`*` `x`) 1051dimension-list-ranked ::= (dimension `x`)* 1052dimension ::= `?` | decimal-literal 1053``` 1054 1055SSA values of tensor type represents aggregate N-dimensional data values, and 1056have a known element type. It may have an unknown rank (indicated by `*`) or may 1057have a fixed rank with a list of dimensions. Each dimension may be a static 1058non-negative decimal constant or be dynamically determined (indicated by `?`). 1059 1060The runtime representation of the MLIR tensor type is intentionally abstracted - 1061you cannot control layout or get a pointer to the data. For low level buffer 1062access, MLIR has a [`memref` type](#memref-type). This abstracted runtime 1063representation holds both the tensor data values as well as information about 1064the (potentially dynamic) shape of the tensor. The 1065[`dim` operation](Dialects/Standard.md#dim-operation) returns the size of a 1066dimension from a value of tensor type. 1067 1068Note: hexadecimal integer literals are not allowed in tensor type declarations 1069to avoid confusion between `0xf32` and `0 x f32`. Zero sizes are allowed in 1070tensors and treated as other sizes, e.g., `tensor<0 x 1 x i32>` and `tensor<1 x 10710 x i32>` are different types. Since zero sizes are not allowed in some other 1072types, such tensors should be optimized away before lowering tensors to vectors. 1073 1074Examples: 1075 1076```mlir 1077// Tensor with unknown rank. 1078tensor<* x f32> 1079 1080// Known rank but unknown dimensions. 1081tensor<? x ? x ? x ? x f32> 1082 1083// Partially known dimensions. 1084tensor<? x ? x 13 x ? x f32> 1085 1086// Full static shape. 1087tensor<17 x 4 x 13 x 4 x f32> 1088 1089// Tensor with rank zero. Represents a scalar. 1090tensor<f32> 1091 1092// Zero-element dimensions are allowed. 1093tensor<0 x 42 x f32> 1094 1095// Zero-element tensor of f32 type (hexadecimal literals not allowed here). 1096tensor<0xf32> 1097``` 1098 1099#### Tuple Type 1100 1101Syntax: 1102 1103``` 1104tuple-type ::= `tuple` `<` (type ( `,` type)*)? `>` 1105``` 1106 1107The value of `tuple` type represents a fixed-size collection of elements, where 1108each element may be of a different type. 1109 1110**Rationale:** Though this type is first class in the type system, MLIR provides 1111no standard operations for operating on `tuple` types 1112([rationale](Rationale.md#tuple-types)). 1113 1114Examples: 1115 1116```mlir 1117// Empty tuple. 1118tuple<> 1119 1120// Single element 1121tuple<f32> 1122 1123// Many elements. 1124tuple<i32, f32, tensor<i1>, i5> 1125``` 1126 1127#### Vector Type 1128 1129Syntax: 1130 1131``` 1132vector-type ::= `vector` `<` static-dimension-list vector-element-type `>` 1133vector-element-type ::= float-type | integer-type 1134 1135static-dimension-list ::= (decimal-literal `x`)+ 1136``` 1137 1138The vector type represents a SIMD style vector, used by target-specific 1139operation sets like AVX. While the most common use is for 1D vectors (e.g. 1140vector<16 x f32>) we also support multidimensional registers on targets that 1141support them (like TPUs). 1142 1143Vector shapes must be positive decimal integers. 1144 1145Note: hexadecimal integer literals are not allowed in vector type declarations, 1146`vector<0x42xi32>` is invalid because it is interpreted as a 2D vector with 1147shape `(0, 42)` and zero shapes are not allowed. 1148 1149## Attributes 1150 1151Syntax: 1152 1153``` 1154attribute-dict ::= `{` `}` 1155 | `{` attribute-entry (`,` attribute-entry)* `}` 1156attribute-entry ::= dialect-attribute-entry | dependent-attribute-entry 1157dialect-attribute-entry ::= dialect-namespace `.` bare-id `=` attribute-value 1158dependent-attribute-entry ::= dependent-attribute-name `=` attribute-value 1159dependent-attribute-name ::= ((letter|[_]) (letter|digit|[_$])*) 1160 | string-literal 1161``` 1162 1163Attributes are the mechanism for specifying constant data on operations in 1164places where a variable is never allowed - e.g. the index of a 1165[`dim` operation](Dialects/Standard.md#dim-operation), or the stride of a 1166convolution. They consist of a name and a concrete attribute value. The set of 1167expected attributes, their structure, and their interpretation are all 1168contextually dependent on what they are attached to. 1169 1170There are two main classes of attributes: dependent and dialect. Dependent 1171attributes derive their structure and meaning from what they are attached to; 1172e.g., the meaning of the `index` attribute on a `dim` operation is defined by 1173the `dim` operation. Dialect attributes, on the other hand, derive their context 1174and meaning from a specific dialect. An example of a dialect attribute may be a 1175`swift.self` function argument attribute that indicates an argument is the 1176self/context parameter. The context of this attribute is defined by the `swift` 1177dialect and not the function argument. 1178 1179Attribute values are represented by the following forms: 1180 1181``` 1182attribute-value ::= attribute-alias | dialect-attribute | standard-attribute 1183``` 1184 1185### Attribute Value Aliases 1186 1187``` 1188attribute-alias ::= '#' alias-name '=' attribute-value 1189attribute-alias ::= '#' alias-name 1190``` 1191 1192MLIR supports defining named aliases for attribute values. An attribute alias is 1193an identifier that can be used in the place of the attribute that it defines. 1194These aliases *must* be defined before their uses. Alias names may not contain a 1195'.', since those names are reserved for 1196[dialect attributes](#dialect-attribute-values). 1197 1198Example: 1199 1200```mlir 1201#map = affine_map<(d0) -> (d0 + 10)> 1202 1203// Using the original attribute. 1204%b = affine.apply affine_map<(d0) -> (d0 + 10)> (%a) 1205 1206// Using the attribute alias. 1207%b = affine.apply #map(%a) 1208``` 1209 1210### Dialect Attribute Values 1211 1212Similarly to operations, dialects may define custom attribute values. The 1213syntactic structure of these values is identical to custom dialect type values, 1214except that dialect attributes values are distinguished with a leading '#', 1215while dialect types are distinguished with a leading '!'. 1216 1217``` 1218dialect-attribute ::= '#' opaque-dialect-item 1219dialect-attribute ::= '#' pretty-dialect-item 1220``` 1221 1222Dialect attributes can be specified in a verbose form, e.g. like this: 1223 1224```mlir 1225// Complex attribute 1226#foo<"something<abcd>"> 1227 1228// Even more complex attribute 1229#foo<"something<a%%123^^^>>>"> 1230``` 1231 1232Dialect attributes that are simple enough can use the pretty format, which is a 1233lighter weight syntax that is equivalent to the above forms: 1234 1235```mlir 1236// Complex attribute 1237#foo.something<abcd> 1238``` 1239 1240Sufficiently complex dialect attributes are required to use the verbose form for 1241generality. For example, the more complex type shown above wouldn't be valid in 1242the lighter syntax: `#foo.something<a%%123^^^>>>` because it contains characters 1243that are not allowed in the lighter syntax, as well as unbalanced `<>` 1244characters. 1245 1246See [here](DefiningAttributesAndTypes.md) to learn how to define dialect 1247attribute values. 1248 1249### Standard Attribute Values 1250 1251Standard attributes are a core set of 1252[dialect attributes](#dialect-attribute-values) that are defined in a builtin 1253dialect and thus available to all users of MLIR. 1254 1255``` 1256standard-attribute ::= affine-map-attribute 1257 | array-attribute 1258 | bool-attribute 1259 | dictionary-attribute 1260 | elements-attribute 1261 | float-attribute 1262 | integer-attribute 1263 | integer-set-attribute 1264 | string-attribute 1265 | symbol-ref-attribute 1266 | type-attribute 1267 | unit-attribute 1268``` 1269 1270#### AffineMap Attribute 1271 1272Syntax: 1273 1274``` 1275affine-map-attribute ::= `affine_map` `<` affine-map `>` 1276``` 1277 1278An affine-map attribute is an attribute that represents an affine-map object. 1279 1280#### Array Attribute 1281 1282Syntax: 1283 1284``` 1285array-attribute ::= `[` (attribute-value (`,` attribute-value)*)? `]` 1286``` 1287 1288An array attribute is an attribute that represents a collection of attribute 1289values. 1290 1291#### Boolean Attribute 1292 1293Syntax: 1294 1295``` 1296bool-attribute ::= bool-literal 1297``` 1298 1299A boolean attribute is a literal attribute that represents a one-bit boolean 1300value, true or false. 1301 1302#### Dictionary Attribute 1303 1304Syntax: 1305 1306``` 1307dictionary-attribute ::= `{` (attribute-entry (`,` attribute-entry)*)? `}` 1308``` 1309 1310A dictionary attribute is an attribute that represents a sorted collection of 1311named attribute values. The elements are sorted by name, and each name must be 1312unique within the collection. 1313 1314#### Elements Attributes 1315 1316Syntax: 1317 1318``` 1319elements-attribute ::= dense-elements-attribute 1320 | opaque-elements-attribute 1321 | sparse-elements-attribute 1322``` 1323 1324An elements attribute is a literal attribute that represents a constant 1325[vector](#vector-type) or [tensor](#tensor-type) value. 1326 1327##### Dense Elements Attribute 1328 1329Syntax: 1330 1331``` 1332dense-elements-attribute ::= `dense` `<` attribute-value `>` `:` 1333 ( tensor-type | vector-type ) 1334``` 1335 1336A dense elements attribute is an elements attribute where the storage for the 1337constant vector or tensor value has been packed to the element bitwidth. The 1338element type of the vector or tensor constant must be of integer, index, or 1339floating point type. 1340 1341##### Opaque Elements Attribute 1342 1343Syntax: 1344 1345``` 1346opaque-elements-attribute ::= `opaque` `<` dialect-namespace `,` 1347 hex-string-literal `>` `:` 1348 ( tensor-type | vector-type ) 1349``` 1350 1351An opaque elements attribute is an elements attribute where the content of the 1352value is opaque. The representation of the constant stored by this elements 1353attribute is only understood, and thus decodable, by the dialect that created 1354it. 1355 1356Note: The parsed string literal must be in hexadecimal form. 1357 1358##### Sparse Elements Attribute 1359 1360Syntax: 1361 1362``` 1363sparse-elements-attribute ::= `sparse` `<` attribute-value `,` attribute-value 1364 `>` `:` ( tensor-type | vector-type ) 1365``` 1366 1367A sparse elements attribute is an elements attribute that represents a sparse 1368vector or tensor object. This is where very few of the elements are non-zero. 1369 1370The attribute uses COO (coordinate list) encoding to represent the sparse 1371elements of the elements attribute. The indices are stored via a 2-D tensor of 137264-bit integer elements with shape [N, ndims], which specifies the indices of 1373the elements in the sparse tensor that contains non-zero values. The element 1374values are stored via a 1-D tensor with shape [N], that supplies the 1375corresponding values for the indices. 1376 1377Example: 1378 1379```mlir 1380 sparse<[[0, 0], [1, 2]], [1, 5]> : tensor<3x4xi32> 1381 1382// This represents the following tensor: 1383/// [[1, 0, 0, 0], 1384/// [0, 0, 5, 0], 1385/// [0, 0, 0, 0]] 1386``` 1387 1388#### Float Attribute 1389 1390Syntax: 1391 1392``` 1393float-attribute ::= (float-literal (`:` float-type)?) 1394 | (hexadecimal-literal `:` float-type) 1395``` 1396 1397A float attribute is a literal attribute that represents a floating point value 1398of the specified [float type](#floating-point-types). It can be represented in 1399the hexadecimal form where the hexadecimal value is interpreted as bits of the 1400underlying binary representation. This form is useful for representing infinity 1401and NaN floating point values. To avoid confusion with integer attributes, 1402hexadecimal literals _must_ be followed by a float type to define a float 1403attribute. 1404 1405Examples: 1406 1407``` 140842.0 // float attribute defaults to f64 type 140942.0 : f32 // float attribute of f32 type 14100x7C00 : f16 // positive infinity 14110x7CFF : f16 // NaN (one of possible values) 141242 : f32 // Error: expected integer type 1413``` 1414 1415#### Integer Attribute 1416 1417Syntax: 1418 1419``` 1420integer-attribute ::= integer-literal ( `:` (index-type | integer-type) )? 1421``` 1422 1423An integer attribute is a literal attribute that represents an integral value of 1424the specified integer or index type. The default type for this attribute, if one 1425is not specified, is a 64-bit integer. 1426 1427##### Integer Set Attribute 1428 1429Syntax: 1430 1431``` 1432integer-set-attribute ::= `affine_set` `<` integer-set `>` 1433``` 1434 1435An integer-set attribute is an attribute that represents an integer-set object. 1436 1437#### String Attribute 1438 1439Syntax: 1440 1441``` 1442string-attribute ::= string-literal (`:` type)? 1443``` 1444 1445A string attribute is an attribute that represents a string literal value. 1446 1447#### Symbol Reference Attribute 1448 1449Syntax: 1450 1451``` 1452symbol-ref-attribute ::= symbol-ref-id (`::` symbol-ref-id)* 1453``` 1454 1455A symbol reference attribute is a literal attribute that represents a named 1456reference to an operation that is nested within an operation with the 1457`OpTrait::SymbolTable` trait. As such, this reference is given meaning by the 1458nearest parent operation containing the `OpTrait::SymbolTable` trait. It may 1459optionally contain a set of nested references that further resolve to a symbol 1460nested within a different symbol table. 1461 1462This attribute can only be held internally by 1463[array attributes](#array-attribute) and 1464[dictionary attributes](#dictionary-attribute)(including the top-level operation 1465attribute dictionary), i.e. no other attribute kinds such as Locations or 1466extended attribute kinds. 1467 1468**Rationale:** Given that MLIR models global accesses with symbol references, to 1469enable efficient multi-threading, it becomes difficult to effectively reason 1470about their uses. By restricting the places that can legally hold a symbol 1471reference, we can always opaquely reason about a symbols usage characteristics. 1472 1473See [`Symbols And SymbolTables`](SymbolsAndSymbolTables.md) for more 1474information. 1475 1476#### Type Attribute 1477 1478Syntax: 1479 1480``` 1481type-attribute ::= type 1482``` 1483 1484A type attribute is an attribute that represents a [type object](#type-system). 1485 1486#### Unit Attribute 1487 1488``` 1489unit-attribute ::= `unit` 1490``` 1491 1492A unit attribute is an attribute that represents a value of `unit` type. The 1493`unit` type allows only one value forming a singleton set. This attribute value 1494is used to represent attributes that only have meaning from their existence. 1495 1496One example of such an attribute could be the `swift.self` attribute. This 1497attribute indicates that a function parameter is the self/context parameter. It 1498could be represented as a [boolean attribute](#boolean-attribute)(true or 1499false), but a value of false doesn't really bring any value. The parameter 1500either is the self/context or it isn't. 1501 1502```mlir 1503// A unit attribute defined with the `unit` value specifier. 1504func @verbose_form(i1) attributes {dialectName.unitAttr = unit} 1505 1506// A unit attribute can also be defined without the value specifier. 1507func @simple_form(i1) attributes {dialectName.unitAttr} 1508``` 1509