Index: mlir/docs/Tutorials/CreatingADialect.md =================================================================== --- mlir/docs/Tutorials/CreatingADialect.md +++ mlir/docs/Tutorials/CreatingADialect.md @@ -10,7 +10,7 @@ * mlir/test/Dialect/Foo (for tests) Along with other public headers, the 'include' directory contains a -TableGen file in the [ODS format](OpDefinitions.md), describing the +TableGen file in the [ODS format](../OpDefinitions.md), describing the operations in the dialect. This is used to generate operation declarations (FooOps.h.inc) and definitions (FooOps.cpp.inc) and operation interface declarations (FooOpsInterfaces.h.inc) and @@ -23,7 +23,7 @@ The 'Transforms' directory contains rewrite rules for the dialect, typically described in TableGen file using the [DDR -format](DeclarativeRewrites.md). +format](../DeclarativeRewrites.md). Note that dialect names should not generally be suffixed with “Ops”, although some files pertaining only to the operations of a dialect (e.g. Index: mlir/docs/Tutorials/DefiningAttributesAndTypes.md =================================================================== --- mlir/docs/Tutorials/DefiningAttributesAndTypes.md +++ mlir/docs/Tutorials/DefiningAttributesAndTypes.md @@ -1,11 +1,11 @@ # Defining Dialect Attributes and Types This document is a quickstart to defining dialect specific extensions to the -[attribute](LangRef.md#attributes) and [type](LangRef.md#type-system) systems in +[attribute](../LangRef.md/#attributes) and [type](../LangRef.md/#type-system) systems in MLIR. The main part of this tutorial focuses on defining types, but the instructions are nearly identical for defining attributes. -See [MLIR specification](LangRef.md) for more information about MLIR, the +See [MLIR specification](../LangRef.md) for more information about MLIR, the structure of the IR, operations, etc. ## Types @@ -25,13 +25,13 @@ classes of `Type` we are defining: Some types are _singleton_ in nature, meaning they have no parameters and only -ever have one instance, like the [`index` type](../Dialects/Builtin.md#indextype). +ever have one instance, like the [`index` type](../Dialects/Builtin.md/#indextype). Other types are _parametric_, and contain additional information that differentiates different instances of the same `Type`. For example the -[`integer` type](../Dialects/Builtin.md#integertype) contains a bitwidth, with `i8` and +[`integer` type](../Dialects/Builtin.md/#integertype) contains a bitwidth, with `i8` and `i16` representing different instances of -[`integer` type](../Dialects/Builtin.md#integertype). _Parametric_ may also contain a +[`integer` type](../Dialects/Builtin.md/#integertype). _Parametric_ may also contain a mutable component, which can be used, for example, to construct self-referring recursive types. The mutable component _cannot_ be used to differentiate instances of a type class, so usually such types contain other parametric @@ -319,7 +319,7 @@ Once the dialect types have been defined, they must then be registered with a `Dialect`. This is done via a similar mechanism to -[operations](LangRef.md#operations), with the `addTypes` method. The one +[operations](../LangRef.md/#operations), with the `addTypes` method. The one distinct difference with operations, is that when a type is registered the definition of its storage class must be visible. @@ -351,7 +351,7 @@ These methods take an instance of a high-level parser or printer that allows for easily implementing the necessary functionality. As described in the -[MLIR language reference](../../LangRef.md#dialect-types), dialect types are +[MLIR language reference](../LangRef.md/#dialect-types), dialect types are generally represented as: `! dialect-namespace < type-data >`, with a pretty form available under certain circumstances. The responsibility of our parser and printer is to provide the `type-data` bits. Index: mlir/docs/Tutorials/QuickstartRewrites.md =================================================================== --- mlir/docs/Tutorials/QuickstartRewrites.md +++ mlir/docs/Tutorials/QuickstartRewrites.md @@ -6,10 +6,10 @@ patterns and the rewrite engine is preferred, showing the walker is for demonstration purposes). -See [MLIR specification](LangRef.md) for more information about MLIR, the +See [MLIR specification](../LangRef.md) for more information about MLIR, the structure of the IR, operations, etc. See -[Table-driven Operation Definition](OpDefinitions.md) and -[Declarative Rewrite Rule](DeclarativeRewrites.md) for the detailed explanation +[Table-driven Operation Definition](../OpDefinitions.md) and +[Declarative Rewrite Rule](../DeclarativeRewrites.md) for the detailed explanation of all available mechanisms for defining operations and rewrites in a table-driven manner. Index: mlir/docs/Tutorials/Toy/Ch-2.md =================================================================== --- mlir/docs/Tutorials/Toy/Ch-2.md +++ mlir/docs/Tutorials/Toy/Ch-2.md @@ -29,10 +29,10 @@ MLIR is designed to be a completely extensible infrastructure; there is no closed set of attributes (think: constant metadata), operations, or types. MLIR supports this extensibility with the concept of -[Dialects](../../LangRef.md#dialects). Dialects provide a grouping mechanism for +[Dialects](../../LangRef.md/#dialects). Dialects provide a grouping mechanism for abstraction under a unique `namespace`. -In MLIR, [`Operations`](../../LangRef.md#operations) are the core unit of +In MLIR, [`Operations`](../../LangRef.md/#operations) are the core unit of abstraction and computation, similar in many ways to LLVM instructions. Operations can have application-specific semantics and can be used to represent all of the core IR structures in LLVM: instructions, globals (like functions), @@ -49,7 +49,7 @@ - `%t_tensor` * The name given to the result defined by this operation (which includes - [a prefixed sigil to avoid collisions](../../LangRef.md#identifiers-and-keywords)). + [a prefixed sigil to avoid collisions](../../LangRef.md/#identifiers-and-keywords)). An operation may define zero or more results (in the context of Toy, we will limit ourselves to single-result operations), which are SSA values. The name is used during parsing but is not persistent (e.g., it is not @@ -90,13 +90,13 @@ - A name for the operation. - A list of SSA operand values. -- A list of [attributes](../../LangRef.md#attributes). -- A list of [types](../../LangRef.md#type-system) for result values. -- A [source location](../../Diagnostics.md#source-locations) for debugging +- A list of [attributes](../../LangRef.md/#attributes). +- A list of [types](../../LangRef.md/#type-system) for result values. +- A [source location](../../Diagnostics.md/#source-locations) for debugging purposes. -- A list of successors [blocks](../../LangRef.md#blocks) (for branches, +- A list of successors [blocks](../../LangRef.md/#blocks) (for branches, mostly). -- A list of [regions](../../LangRef.md#regions) (for structural operations +- A list of [regions](../../LangRef.md/#regions) (for structural operations like functions). In MLIR, every operation has a mandatory source location associated with it. @@ -118,7 +118,7 @@ MLIR is designed to allow all IR elements, such as attributes, operations, and types, to be customized. At the same time, IR elements can always be reduced to the above fundamental concepts. This allows MLIR to parse, represent, and -[round-trip](../../../getting_started/Glossary.md#round-trip) IR for *any* +[round-trip](../../../getting_started/Glossary.md/#round-trip) IR for *any* operation. For example, we could place our Toy operation from above into an `.mlir` file and round-trip through *mlir-opt* without registering any dialect: @@ -240,10 +240,10 @@ ``` This operation takes zero operands, a -[dense elements](../../LangRef.md#dense-elements-attribute) attribute named +[dense elements](../../Dialects/Builtin.md/#denseintorfpelementsattr) attribute named `value` to represent the constant value, and returns a single result of -[TensorType](../../LangRef.md#tensor-type). An operation class inherits from the -[CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) +[RankedTensorType](../../Dialects/Builtin.md/#rankedtensortype). An operation class +inherits from the [CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) `mlir::Op` class which also takes some optional [*traits*](../../Traits.md) to customize its behavior. `Traits` are a mechanism with which we can inject additional behavior into an Operation, such as additional accessors, @@ -378,7 +378,7 @@ We define a toy operation by inheriting from our base 'Toy_Op' class above. Here we provide the mnemonic and a list of traits for the operation. The -[mnemonic](../../OpDefinitions.md#operation-name) here matches the one given in +[mnemonic](../../OpDefinitions.md/#operation-name) here matches the one given in `ConstantOp::getOperationName` without the dialect prefix; `toy.`. Missing here from our C++ definition are the `ZeroOperands` and `OneResult` traits; these will be automatically inferred based upon the `arguments` and `results` fields @@ -404,8 +404,8 @@ #### Defining Arguments and Results With the shell of the operation defined, we can now provide the -[inputs](../../OpDefinitions.md#operation-arguments) and -[outputs](../../OpDefinitions.md#operation-results) to our operation. The +[inputs](../../OpDefinitions.md/#operation-arguments) and +[outputs](../../OpDefinitions.md/#operation-results) to our operation. The inputs, or arguments, to an operation may be attributes or types for SSA operand values. The results correspond to a set of types for the values produced by the operation: @@ -430,7 +430,7 @@ The next step after defining the operation is to document it. Operations may provide -[`summary` and `description`](../../OpDefinitions.md#operation-documentation) +[`summary` and `description`](../../OpDefinitions.md/#operation-documentation) fields to describe the semantics of the operation. This information is useful for users of the dialect and can even be used to auto-generate Markdown documents. @@ -468,7 +468,7 @@ means that we don't need to verify the structure of the return type, or even the input attribute `value`. In many cases, additional verification is not even necessary for ODS operations. To add additional verification logic, an operation -can override the [`verifier`](../../OpDefinitions.md#custom-verifier-code) +can override the [`verifier`](../../OpDefinitions.md/#custom-verifier-code) field. The `verifier` field allows for defining a C++ code blob that will be run as part of `ConstantOp::verify`. This blob can assume that all of the other invariants of the operation have already been verified: @@ -508,7 +508,7 @@ The final missing component here from our original C++ example are the `build` methods. ODS can generate some simple build methods automatically, and in this case it will generate our first build method for us. For the rest, we define the -[`builders`](../../OpDefinitions.md#custom-builder-methods) field. This field +[`builders`](../../OpDefinitions.md/#custom-builder-methods) field. This field takes a list of `OpBuilder` objects that take a string corresponding to a list of C++ parameters, as well as an optional code block that can be used to specify the implementation inline. @@ -580,7 +580,7 @@ generic assembly format. This format is the one shown when breaking down `toy.transpose` at the beginning of this chapter. MLIR allows for operations to define their own custom assembly format, either -[declaratively](../../OpDefinitions.md#declarative-assembly-format) or +[declaratively](../../OpDefinitions.md/#declarative-assembly-format) or imperatively via C++. Defining a custom assembly format allows for tailoring the generated IR into something a bit more readable by removing a lot of the fluff that is required by the generic format. Let's walk through an example of an @@ -655,7 +655,7 @@ ``` With the C++ implementation defined, let's see how this can be mapped to the -[declarative format](../../OpDefinitions.md#declarative-assembly-format). The +[declarative format](../../OpDefinitions.md/#declarative-assembly-format). The declarative format is largely composed of three different components: * Directives @@ -681,7 +681,7 @@ } ``` -The [declarative format](../../OpDefinitions.md#declarative-assembly-format) has +The [declarative format](../../OpDefinitions.md/#declarative-assembly-format) has many more interesting features, so be sure to check it out before implementing a custom format in C++. After beautifying the format of a few of our operations we now get a much more readable: Index: mlir/docs/Tutorials/Toy/Ch-3.md =================================================================== --- mlir/docs/Tutorials/Toy/Ch-3.md +++ mlir/docs/Tutorials/Toy/Ch-3.md @@ -108,7 +108,7 @@ [canonicalization pass](../../Canonicalization.md) applies transformations defined by operations in a greedy, iterative manner. To ensure that the canonicalization pass applies our new transform, we set -[hasCanonicalizer = 1](../../OpDefinitions.md#hascanonicalizer) and register the +[hasCanonicalizer = 1](../../OpDefinitions.md/#hascanonicalizer) and register the pattern with the canonicalization framework. ```c++ Index: mlir/docs/Tutorials/Toy/Ch-4.md =================================================================== --- mlir/docs/Tutorials/Toy/Ch-4.md +++ mlir/docs/Tutorials/Toy/Ch-4.md @@ -50,7 +50,7 @@ The first thing we need to do is to define the constraints on inlining operations in the Toy dialect. This information is provided through a -[dialect interface](../../Interfaces.md#dialect-interfaces). This is essentially +[dialect interface](../../Interfaces.md/#dialect-interfaces). This is essentially a class containing a set of virtual hooks which the dialect can override. In this case, the interface is `DialectInlinerInterface`. @@ -106,7 +106,7 @@ Next, we need to provide a way for the inliner to know that `toy.generic_call` represents a call to a function. MLIR provides an -[operation interface](../../Interfaces.md#operation-interfaces) that can be used +[operation interface](../../Interfaces.md/#attributeoperationtype-interfaces) that can be used to mark an operation as being "call-like". Unlike dialect interfaces, operation interfaces provide a more refined granularity of information that is specific and core to a single operation. The interface that we will be adding here is the @@ -284,7 +284,7 @@ to have their result shapes inferred. Similarly to operations, we can also -[define operation interfaces](../../OpDefinitions.md#operation-interfaces) using +[define operation interfaces](../../Interfaces.md/#attributeoperationtype-interfaces) using the operation definition specification (ODS) framework. The interface is defined by inheriting from `OpInterface`, which takes the name @@ -305,7 +305,7 @@ An interface method is comprised of: a description; a C++ return type in string form; a method name in string form; and a few optional components, depending on the need. See the -[ODS documentation](../../OpDefinitions.md#operation-interfaces) for more +[ODS documentation](../../Interfaces.md/#attributeoperationtype-interfaces) for more information. ```tablegen @@ -342,7 +342,7 @@ At this point, each of the necessary Toy operations provide a mechanism by which to infer their output shapes. The ShapeInferencePass is a FunctionPass: it will run on each Function in isolation. MLIR also supports general -[OperationPasses](../../PassManagement.md#operation-pass) that run on any isolated +[OperationPasses](../../PassManagement.md/#operation-pass) that run on any isolated operation (i.e. other function-like operations), but here our module only contains functions, so there is no need to generalize to all operations. Index: mlir/docs/Tutorials/Toy/Ch-5.md =================================================================== --- mlir/docs/Tutorials/Toy/Ch-5.md +++ mlir/docs/Tutorials/Toy/Ch-5.md @@ -15,34 +15,35 @@ `Affine` for the computation heavy part of Toy, and in the [next chapter](Ch-6.md) directly target the `LLVM IR` dialect for lowering `print`. As part of this lowering, we will be lowering from the -[TensorType](../../LangRef.md#tensor-type) that `Toy` operates on to the -[MemRefType](../../LangRef.md#memref-type) that is indexed via an affine -loop-nest. Tensors represent an abstract value-typed sequence of data, meaning -that they don't live in any memory. MemRefs, on the other hand, represent lower -level buffer access, as they are concrete references to a region of memory. +[RankedTensorType](../../Dialects/Builtin.md/#rankedtensortype) that `Toy` +operates on to the [MemRefType](../../Dialects/Builtin.md/#memreftype) that is +indexed via an affine loop-nest. Tensors represent an abstract value-typed +sequence of data, meaning that they don't live in any memory. MemRefs, on the +other hand, represent lower level buffer access, as they are concrete +references to a region of memory. # Dialect Conversions MLIR has many different dialects, so it is important to have a unified framework -for [converting](../../../getting_started/Glossary.md#conversion) between them. This is where the +for [converting](../../../getting_started/Glossary.md/#conversion) between them. This is where the `DialectConversion` framework comes into play. This framework allows for transforming a set of *illegal* operations to a set of *legal* ones. To use this framework, we need to provide two things (and an optional third): -* A [Conversion Target](../../DialectConversion.md#conversion-target) +* A [Conversion Target](../../DialectConversion.md/#conversion-target) - This is the formal specification of what operations or dialects are legal for the conversion. Operations that aren't legal will require rewrite patterns to perform - [legalization](../../../getting_started/Glossary.md#legalization). + [legalization](../../../getting_started/Glossary.md/#legalization). * A set of - [Rewrite Patterns](../../DialectConversion.md#rewrite-pattern-specification) + [Rewrite Patterns](../../DialectConversion.md/#rewrite-pattern-specification) - This is the set of [patterns](../QuickstartRewrites.md) used to convert *illegal* operations into a set of zero or more *legal* ones. -* Optionally, a [Type Converter](../../DialectConversion.md#type-conversion). +* Optionally, a [Type Converter](../../DialectConversion.md/#type-conversion). - If provided, this is used to convert the types of block arguments. We won't be needing this for our conversion. @@ -96,9 +97,9 @@ remapped/replaced. This is used when dealing with type conversions, as the pattern will want to operate on values of the new type but match against the old. For our lowering, this invariant will be useful as it translates from the -[TensorType](../../LangRef.md#tensor-type) currently being operated on to the -[MemRefType](../../LangRef.md#memref-type). Let's look at a snippet of lowering -the `toy.transpose` operation: +[RankedTensorType](../../Dialects/Builtin.md/#rankedtensortype) currently +being operated on to the [MemRefType](../../Dialects/Builtin.md/#memreftype). +Let's look at a snippet of lowering the `toy.transpose` operation: ```c++ /// Lower the `toy.transpose` operation to an affine loop nest. Index: mlir/docs/Tutorials/Toy/Ch-6.md =================================================================== --- mlir/docs/Tutorials/Toy/Ch-6.md +++ mlir/docs/Tutorials/Toy/Ch-6.md @@ -16,7 +16,7 @@ Before going over the conversion to LLVM, let's lower the `toy.print` operation. We will lower this operation to a non-affine loop nest that invokes `printf` for each element. Note that, because the dialect conversion framework supports -[transitive lowering](../../../getting_started/Glossary.md#transitive-lowering), we don't need to +[transitive lowering](../../../getting_started/Glossary.md/#transitive-lowering), we don't need to directly emit operations in the LLVM dialect. By transitive lowering, we mean that the conversion framework may apply multiple patterns to fully legalize an operation. In this example, we are generating a structured loop nest instead of @@ -87,7 +87,7 @@ combination of `toy`, `affine`, and `std` operations. Luckily, the `std` and `affine` dialects already provide the set of patterns needed to transform them into LLVM dialect. These patterns allow for lowering the IR in multiple stages -by relying on [transitive lowering](../../../getting_started/Glossary.md#transitive-lowering). +by relying on [transitive lowering](../../../getting_started/Glossary.md/#transitive-lowering). ```c++ mlir::RewritePatternSet patterns(&getContext()); @@ -318,7 +318,7 @@ You can also play with `-emit=mlir`, `-emit=mlir-affine`, `-emit=mlir-llvm`, and `-emit=llvm` to compare the various levels of IR involved. Also try options like -[`--print-ir-after-all`](../../PassManagement.md#ir-printing) to track the +[`--print-ir-after-all`](../../PassManagement.md/#ir-printing) to track the evolution of the IR throughout the pipeline. The example code used throughout this section can be found in Index: mlir/docs/Tutorials/Toy/Ch-7.md =================================================================== --- mlir/docs/Tutorials/Toy/Ch-7.md +++ mlir/docs/Tutorials/Toy/Ch-7.md @@ -62,7 +62,7 @@ #### Defining the Type Class -As mentioned in [chapter 2](Ch-2.md), [`Type`](../../LangRef.md#type-system) +As mentioned in [chapter 2](Ch-2.md), [`Type`](../../LangRef.md/#type-system) objects in MLIR are value-typed and rely on having an internal storage object that holds the actual data for the type. The `Type` class in itself acts as a simple wrapper around an internal `TypeStorage` object that is uniqued within an @@ -72,7 +72,7 @@ When defining a new `Type` that contains parametric data (e.g. the `struct` type, which requires additional information to hold the element types), we will need to provide a derived storage class. The `singleton` types that don't have -any additional data (e.g. the [`index` type](../../Dialects/Builtin.md#indextype)) don't +any additional data (e.g. the [`index` type](../../Dialects/Builtin.md/#indextype)) don't require a storage class and use the default `TypeStorage`. ##### Defining the Storage Class @@ -235,7 +235,7 @@ easily implementing the necessary functionality. Before going into the implementation, let's think about the syntax that we want for the `struct` type in the printed IR. As described in the -[MLIR language reference](../../LangRef.md#dialect-types), dialect types are +[MLIR language reference](../../LangRef.md/#dialect-types), dialect types are generally represented as: `! dialect-namespace < type-data >`, with a pretty form available under certain circumstances. The responsibility of our `Toy` parser and printer is to provide the `type-data` bits. We will define our @@ -359,7 +359,7 @@ ##### `toy.struct_constant` This new operation materializes a constant value for a struct. In our current -modeling, we just use an [array attribute](../../LangRef.md#array-attribute) +modeling, we just use an [array attribute](../../Dialects/Builtin.md/#arrayattr) that contains a set of constant values for each of the `struct` elements. ```mlir Index: mlir/docs/Tutorials/Toy/_index.md =================================================================== --- mlir/docs/Tutorials/Toy/_index.md +++ mlir/docs/Tutorials/Toy/_index.md @@ -2,7 +2,7 @@ This tutorial runs through the implementation of a basic toy language on top of MLIR. The goal of this tutorial is to introduce the concepts of MLIR; in -particular, how [dialects](../../LangRef.md#dialects) can help easily support +particular, how [dialects](../../LangRef.md/#dialects) can help easily support language specific constructs and transformations while still offering an easy path to lower to LLVM or other codegen infrastructure. This tutorial is based on the model of the @@ -13,7 +13,7 @@ This tutorial assumes you have cloned and built MLIR; if you have not yet done so, see -[Getting started with MLIR](https://mlir.llvm.org/getting_started/). +[Getting started with MLIR](../../../getting_started/). This tutorial is divided in the following chapters: Index: mlir/docs/Tutorials/UnderstandingTheIRStructure.md =================================================================== --- mlir/docs/Tutorials/UnderstandingTheIRStructure.md +++ mlir/docs/Tutorials/UnderstandingTheIRStructure.md @@ -1,11 +1,11 @@ # Understanding the IR Structure The MLIR Language Reference describes the -[High Level Structure](../LangRef/#high-level-structure), this document +[High Level Structure](../LangRef.md/#high-level-structure), this document illustrates this structure through examples, and introduces at the same time the C++ APIs involved in manipulating it. -We will implement a [pass](../PassManagement/#operation-pass) that traverses any +We will implement a [pass](../PassManagement.md/#operation-pass) that traverses any MLIR input and prints the entity inside the IR. A pass (or in general almost any piece of IR) is always rooted with an operation. Most of the time the top-level operation is a `ModuleOp`, the MLIR `PassManager` is actually limited to @@ -217,7 +217,7 @@ Another relationship in the IR is the one that links a `Value` with its users. As defined in the -[language reference](https://mlir.llvm.org/docs/LangRef/#high-level-structure), +[language reference](../LangRef.md/#high-level-structure), each Value is either a `BlockArgument` or the result of exactly one `Operation` (an `Operation` can have multiple results, each of them is a separate `Value`). The users of a `Value` are `Operation`s, through their arguments: each