Skip to content

Commit

Permalink
[mlir][doc] Fix links and references in documentation of Tutorials
Browse files Browse the repository at this point in the history
This patch is the third in a series of patches fixing markdown links and references inside the mlir documentation.

This patch addresses all broken references to other markdown files and sections inside the Tutorials folder.

Differential Revision: https://reviews.llvm.org/D103017
  • Loading branch information
zero9178 committed May 25, 2021
1 parent dfd1bbd commit 31d1ae7
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 64 deletions.
4 changes: 2 additions & 2 deletions mlir/docs/Tutorials/CreatingADialect.md
Expand Up @@ -10,7 +10,7 @@ Public dialects are typically separated into at least 3 directories:
* 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
Expand All @@ -23,7 +23,7 @@ FooOpsInterfaces.h.inc.

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.
Expand Down
14 changes: 7 additions & 7 deletions 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
Expand All @@ -25,13 +25,13 @@ So before defining the derived `Type`, it's important to know which of the two
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
Expand Down Expand Up @@ -319,7 +319,7 @@ public:
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.
Expand Down Expand Up @@ -351,7 +351,7 @@ public:
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.
Expand Down
6 changes: 3 additions & 3 deletions mlir/docs/Tutorials/QuickstartRewrites.md
Expand Up @@ -6,10 +6,10 @@ patterns, as well as defining the rewrite using a graph walker (note: using
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.

Expand Down
42 changes: 21 additions & 21 deletions mlir/docs/Tutorials/Toy/Ch-2.md
Expand Up @@ -29,10 +29,10 @@ pre-defined instructions (*operations* in MLIR terminology) or types.
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),
Expand All @@ -49,7 +49,7 @@ Let's break down the anatomy of this MLIR operation:
- `%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
Expand Down Expand Up @@ -90,13 +90,13 @@ about and manipulated generically. These concepts are:

- 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.
Expand All @@ -118,7 +118,7 @@ compiler passes - does not include locations in the output by default. The
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:

Expand Down Expand Up @@ -240,10 +240,10 @@ operation. This operation will represent a constant value in the Toy language.
```
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,
Expand Down Expand Up @@ -378,7 +378,7 @@ operation.

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
Expand All @@ -404,8 +404,8 @@ implementation is incredibly useful when getting started with TableGen.
#### 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:
Expand All @@ -430,7 +430,7 @@ ConstantOp::value()`.

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.
Expand Down Expand Up @@ -468,7 +468,7 @@ necessary verification logic based upon the constraints we have given. This
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:
Expand Down Expand Up @@ -508,7 +508,7 @@ def ConstantOp : Toy_Op<"constant"> {
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.
Expand Down Expand Up @@ -580,7 +580,7 @@ One thing to notice here is that all of our Toy operations are printed using the
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
Expand Down Expand Up @@ -655,7 +655,7 @@ static mlir::ParseResult parsePrintOp(mlir::OpAsmParser &parser,
```
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
Expand All @@ -681,7 +681,7 @@ def PrintOp : Toy_Op<"print"> {
}
```

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:
Expand Down
2 changes: 1 addition & 1 deletion mlir/docs/Tutorials/Toy/Ch-3.md
Expand Up @@ -108,7 +108,7 @@ The implementation of this rewriter is in `ToyCombine.cpp`. The
[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++
Expand Down
10 changes: 5 additions & 5 deletions mlir/docs/Tutorials/Toy/Ch-4.md
Expand Up @@ -50,7 +50,7 @@ hook into.

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`.

Expand Down Expand Up @@ -106,7 +106,7 @@ void ToyDialect::initialize() {

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
Expand Down Expand Up @@ -284,7 +284,7 @@ can define an operation interface that can be specified on operations that need
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
Expand All @@ -305,7 +305,7 @@ Next, we define the interface methods that the operations will need to provide.
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
Expand Down Expand Up @@ -342,7 +342,7 @@ void MulOp::inferShapes() { getResult().setType(getOperand(0).getType()); }
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.
Expand Down
27 changes: 14 additions & 13 deletions mlir/docs/Tutorials/Toy/Ch-5.md
Expand Up @@ -15,34 +15,35 @@ part of the program and is limited: it doesn't support representing our
`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.
[TensorType](../../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.
Expand Down Expand Up @@ -96,9 +97,9 @@ additional `operands` parameter containing operands that have been
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:
[TensorType](../../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.
Expand Down

0 comments on commit 31d1ae7

Please sign in to comment.