```
The `affine.apply` operation applies an
-[affine mapping](../LangRef.md#affine-expressions) to a list of SSA values,
+[affine mapping](#affine-expressions) to a list of SSA values,
yielding a single SSA value. The number of dimension and symbol arguments to
affine.apply must be equal to the respective number of dimensional and symbolic
inputs to the affine mapping; the `affine.apply` operation always returns one
`affine.if` may end with an optional `else` clause.
The condition of the `affine.if` is represented by an
-[integer set](../LangRef.md#integer-sets) (a conjunction of affine constraints),
+[integer set](#integer-sets) (a conjunction of affine constraints),
and the SSA values bound to the dimensions and symbols in the integer set. The
[same restrictions](#restrictions-on-dimensions-and-symbols) hold for these SSA
values as for all bindings of SSA values to dimensions and symbols.
[vector](../LangRef.md#vector-type) of the same elemental type. The slice is
further defined by a full-rank index within the MemRef, supplied as the operands
`2 .. 1 + rank(memref)`. The permutation_map [attribute](../LangRef.md#attributes)
-is an [affine-map](../LangRef.md#affine-maps) which specifies the transposition on
+is an [affine-map](Affine.md#affine-maps) which specifies the transposition on
the slice to match the vector shape. The size of the slice is specified by the
size of the vector, given as the return type. Optionally, an `ssa-value` of the
same elemental type as the MemRef is provided as the last operand to specify
supplied as its second operand. The slice is further defined by a full-rank
index within the MemRef, supplied as the operands `3 .. 2 + rank(memref)`. The
permutation_map [attribute](../LangRef.md#attributes) is an
-[affine-map](../LangRef.md#affine-maps) which specifies the transposition on the
+[affine-map](Affine.md#affine-maps) which specifies the transposition on the
slice to match the vector shape. The size of the slice is specified by the size
of the vector. This operation is called 'write' by opposition to 'store' because
the super-vector granularity is generally not representable with a single
dominance relations. Operations may produce zero or more results, and each is a
distinct SSA value with its own type defined by the [type system](#type-system).
-The unit of code in MLIR is an [Operation](#operation). Operations allow for
+The unit of code in MLIR is an [Operation](#operations). Operations allow for
representing many different concepts: allocating buffers, producing views to
transform them, target-independent arithmetic, target-specific operations, and
even arbitrary user-defined high-level operations including the
* The op's traits (e.g., commutative) are modelled along with the op in
the registry.
* The op's operand/return type constraints are modelled along with the op in
- the registry (see [Type constraints](#type-constraints) discussion below),
+ the registry (see [Shape inference](#shape-inference) discussion below),
this allows (e.g.) optimized concise syntax in textual dumps.
* Behavior of the op is documented along with the op with a summary and a
description. The description is written in markdown and extracted for
high level language specific semantics towards a generic linear-algebra
oriented dialect for optimizations. Ultimately we will emit LLVM IR for code
generation.
-- [Chapter #5](Ch-6.md): A REPL?
-- [Chapter #6](Ch-7.md): Custom backends? GPU using LLVM? TPU? XLA
+- [Chapter #6](Ch-6.md): A REPL?
+- [Chapter #7](Ch-7.md): Custom backends? GPU using LLVM? TPU? XLA
## The Language
## Pass Registration
Briefly shown in the example definitions of the various
-[pass types](#pass-types) is the `PassRegistration` class. This is a utility to
+pass types is the `PassRegistration` class. This is a utility to
register derived pass classes so that they may be created, and inspected, by
utilities like mlir-opt. Registering a pass class takes the form: