Skip to content

Commit ee74860

Browse files
committed
[mlir][Toy] Update the tutorial to use tablegen for dialect declarations
This was missed when the feature was originally added. Differential Revision: https://reviews.llvm.org/D87060
1 parent f4bb076 commit ee74860

File tree

22 files changed

+114
-188
lines changed

22 files changed

+114
-188
lines changed

mlir/docs/Tutorials/Toy/Ch-2.md

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -168,19 +168,49 @@ provide an easy avenue for high-level analysis and transformation.
168168
/// constructor). It can also override virtual methods to change some general
169169
/// behavior, which will be demonstrated in later chapters of the tutorial.
170170
class ToyDialect : public mlir::Dialect {
171-
public:
171+
public:
172172
explicit ToyDialect(mlir::MLIRContext *ctx);
173173

174174
/// Provide a utility accessor to the dialect namespace. This is used by
175175
/// several utilities.
176176
static llvm::StringRef getDialectNamespace() { return "toy"; }
177+
178+
/// An initializer called from the constructor of ToyDialect that is used to
179+
/// register operations, types, and more within the Toy dialect.
180+
void initialize();
177181
};
178182
```
179183
180-
The dialect can now be registered in the global registry:
184+
This is the C++ definition of a dialect, but MLIR also supports defining
185+
dialects declaratively via tablegen. Using the declarative specification is much
186+
cleaner as it removes the need for a large portion of the boilerplate when
187+
defining a new dialect. In the declarative format, the toy dialect would be
188+
specified as:
189+
190+
```tablegen
191+
// Provide a definition of the 'toy' dialect in the ODS framework so that we
192+
// can define our operations.
193+
def Toy_Dialect : Dialect {
194+
// The namespace of our dialect, this corresponds 1-1 with the string we
195+
// provided in `ToyDialect::getDialectNamespace`.
196+
let name = "toy";
197+
198+
// The C++ namespace that the dialect class definition resides in.
199+
let cppNamespace = "toy";
200+
}
201+
```
202+
203+
To see what this generates, we can run the `mlir-tblgen` command with the
204+
`gen-dialect-decls` action like so:
205+
206+
```shell
207+
${build_root}/bin/mlir-tblgen -gen-dialect-decls ${mlir_src_root}/examples/toy/Ch2/include/toy/Ops.td -I ${mlir_src_root}/include/
208+
```
209+
210+
The dialect can now be loaded into an MLIRContext:
181211

182212
```c++
183-
mlir::registerDialect<ToyDialect>();
213+
context.loadDialect<ToyDialect>();
184214
```
185215

186216
Any new `MLIRContext` created from now on will contain an instance of the Toy
@@ -249,11 +279,10 @@ class ConstantOp : public mlir::Op<ConstantOp,
249279
};
250280
```
251281
252-
and we register this operation in the `ToyDialect` constructor:
282+
and we register this operation in the `ToyDialect` initializer:
253283
254284
```c++
255-
ToyDialect::ToyDialect(mlir::MLIRContext *ctx)
256-
: mlir::Dialect(getDialectNamespace(), ctx) {
285+
void ToyDialect::initialize() {
257286
addOperations<ConstantOp>();
258287
}
259288
```
@@ -311,27 +340,9 @@ C++ API changes.
311340
312341
Lets see how to define the ODS equivalent of our ConstantOp:
313342
314-
The first thing to do is to define a link to the Toy dialect that we defined in
315-
C++. This is used to link all of the operations that we will define to our
316-
dialect:
317-
318-
```tablegen
319-
// Provide a definition of the 'toy' dialect in the ODS framework so that we
320-
// can define our operations.
321-
def Toy_Dialect : Dialect {
322-
// The namespace of our dialect, this corresponds 1-1 with the string we
323-
// provided in `ToyDialect::getDialectNamespace`.
324-
let name = "toy";
325-
326-
// The C++ namespace that the dialect class definition resides in.
327-
let cppNamespace = "toy";
328-
}
329-
```
330-
331-
Now that we have defined a link to the Toy dialect, we can start defining
332-
operations. Operations in ODS are defined by inheriting from the `Op` class. To
333-
simplify our operation definitions, we will define a base class for operations
334-
in the Toy dialect.
343+
Operations in ODS are defined by inheriting from the `Op` class. To simplify our
344+
operation definitions, we will define a base class for operations in the Toy
345+
dialect.
335346
336347
```tablegen
337348
// Base class for toy dialect operations. This operation inherits from the base

mlir/docs/Tutorials/Toy/Ch-4.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ We then register our dialect interface directly on the Toy dialect, similarly to
9999
how we did for operations.
100100
101101
```c++
102-
ToyDialect::ToyDialect(mlir::MLIRContext *ctx) : mlir::Dialect("toy", ctx) {
102+
void ToyDialect::initialize() {
103103
addInterfaces<ToyInlinerInterface>();
104104
}
105105
```

mlir/docs/Tutorials/Toy/Ch-7.md

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,11 @@ public:
177177
};
178178
```
179179

180-
We register this type in the `ToyDialect` constructor in a similar way to how we
180+
We register this type in the `ToyDialect` initializer in a similar way to how we
181181
did with operations:
182182

183183
```c++
184-
ToyDialect::ToyDialect(mlir::MLIRContext *ctx)
185-
: mlir::Dialect(getDialectNamespace(), ctx) {
184+
void ToyDialect::initialize() {
186185
addTypes<StructType>();
187186
}
188187
```
@@ -193,12 +192,32 @@ storage class must be visible.)
193192
With this we can now use our `StructType` when generating MLIR from Toy. See
194193
examples/toy/Ch7/mlir/MLIRGen.cpp for more details.
195194

195+
### Exposing to ODS
196+
197+
After defining a new type, we should make the ODS framework aware of our Type so
198+
that we can use it in the operation definitions and auto-generate utilities
199+
within the Dialect. A simple example is shown below:
200+
201+
```tablegen
202+
// Provide a definition for the Toy StructType for use in ODS. This allows for
203+
// using StructType in a similar way to Tensor or MemRef. We use `DialectType`
204+
// to demarcate the StructType as belonging to the Toy dialect.
205+
def Toy_StructType :
206+
DialectType<Toy_Dialect, CPred<"$_self.isa<StructType>()">,
207+
"Toy struct type">;
208+
209+
// Provide a definition of the types that are used within the Toy dialect.
210+
def Toy_Type : AnyTypeOf<[F64Tensor, Toy_StructType]>;
211+
```
212+
196213
### Parsing and Printing
197214

198215
At this point we can use our `StructType` during MLIR generation and
199216
transformation, but we can't output or parse `.mlir`. For this we need to add
200217
support for parsing and printing instances of the `StructType`. This can be done
201218
by overriding the `parseType` and `printType` methods on the `ToyDialect`.
219+
Declarations for these methods are automatically provided when the type is
220+
exposed to ODS as detailed in the previous section.
202221

203222
```c++
204223
class ToyDialect : public mlir::Dialect {
@@ -321,22 +340,8 @@ the IR. The next step is to add support for using it within our operations.
321340

322341
#### Updating Existing Operations
323342

324-
A few of our existing operations will need to be updated to handle `StructType`.
325-
The first step is to make the ODS framework aware of our Type so that we can use
326-
it in the operation definitions. A simple example is shown below:
327-
328-
```tablegen
329-
// Provide a definition for the Toy StructType for use in ODS. This allows for
330-
// using StructType in a similar way to Tensor or MemRef.
331-
def Toy_StructType :
332-
Type<CPred<"$_self.isa<StructType>()">, "Toy struct type">;
333-
334-
// Provide a definition of the types that are used within the Toy dialect.
335-
def Toy_Type : AnyTypeOf<[F64Tensor, Toy_StructType]>;
336-
```
337-
338-
We can then update our operations, e.g. `ReturnOp`, to also accept the
339-
`Toy_StructType`:
343+
A few of our existing operations, e.g. `ReturnOp`, will need to be updated to
344+
handle `Toy_StructType`.
340345

341346
```tablegen
342347
def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
set(LLVM_TARGET_DEFINITIONS Ops.td)
22
mlir_tablegen(Ops.h.inc -gen-op-decls)
33
mlir_tablegen(Ops.cpp.inc -gen-op-defs)
4+
mlir_tablegen(Dialect.h.inc -gen-dialect-decls)
45
add_public_tablegen_target(ToyCh2OpsIncGen)

mlir/examples/toy/Ch2/include/toy/Dialect.h

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,9 @@
1818
#include "mlir/IR/Dialect.h"
1919
#include "mlir/Interfaces/SideEffectInterfaces.h"
2020

21-
namespace mlir {
22-
namespace toy {
23-
24-
/// This is the definition of the Toy dialect. A dialect inherits from
25-
/// mlir::Dialect and registers custom attributes, operations, and types (in its
26-
/// constructor). It can also override some general behavior exposed via virtual
27-
/// methods.
28-
class ToyDialect : public mlir::Dialect {
29-
public:
30-
explicit ToyDialect(mlir::MLIRContext *ctx);
31-
32-
/// Provide a utility accessor to the dialect namespace. This is used by
33-
/// several utilities for casting between dialects.
34-
static llvm::StringRef getDialectNamespace() { return "toy"; }
35-
};
36-
37-
} // end namespace toy
38-
} // end namespace mlir
21+
/// Include the auto-generated header file containing the declaration of the toy
22+
/// dialect.
23+
#include "toy/Dialect.h.inc"
3924

4025
/// Include the auto-generated header file containing the declarations of the
4126
/// toy operations.

mlir/examples/toy/Ch2/mlir/Dialect.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@ using namespace mlir::toy;
2424
// ToyDialect
2525
//===----------------------------------------------------------------------===//
2626

27-
/// Dialect creation, the instance will be owned by the context. This is the
28-
/// point of registration of custom types and operations for the dialect.
29-
ToyDialect::ToyDialect(mlir::MLIRContext *ctx)
30-
: mlir::Dialect(getDialectNamespace(), ctx, TypeID::get<ToyDialect>()) {
27+
/// Dialect initialization, the instance will be owned by the context. This is
28+
/// the point of registration of types and operations for the dialect.
29+
void ToyDialect::initialize() {
3130
addOperations<
3231
#define GET_OP_LIST
3332
#include "toy/Ops.cpp.inc"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
set(LLVM_TARGET_DEFINITIONS Ops.td)
22
mlir_tablegen(Ops.h.inc -gen-op-decls)
33
mlir_tablegen(Ops.cpp.inc -gen-op-defs)
4+
mlir_tablegen(Dialect.h.inc -gen-dialect-decls)
45
add_public_tablegen_target(ToyCh3OpsIncGen)

mlir/examples/toy/Ch3/include/toy/Dialect.h

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,9 @@
1818
#include "mlir/IR/Dialect.h"
1919
#include "mlir/Interfaces/SideEffectInterfaces.h"
2020

21-
namespace mlir {
22-
namespace toy {
23-
24-
/// This is the definition of the Toy dialect. A dialect inherits from
25-
/// mlir::Dialect and registers custom attributes, operations, and types (in its
26-
/// constructor). It can also override some general behavior exposed via virtual
27-
/// methods.
28-
class ToyDialect : public mlir::Dialect {
29-
public:
30-
explicit ToyDialect(mlir::MLIRContext *ctx);
31-
32-
/// Provide a utility accessor to the dialect namespace. This is used by
33-
/// several utilities for casting between dialects.
34-
static llvm::StringRef getDialectNamespace() { return "toy"; }
35-
};
36-
37-
} // end namespace toy
38-
} // end namespace mlir
21+
/// Include the auto-generated header file containing the declaration of the toy
22+
/// dialect.
23+
#include "toy/Dialect.h.inc"
3924

4025
/// Include the auto-generated header file containing the declarations of the
4126
/// toy operations.

mlir/examples/toy/Ch3/mlir/Dialect.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@ using namespace mlir::toy;
2424
// ToyDialect
2525
//===----------------------------------------------------------------------===//
2626

27-
/// Dialect creation, the instance will be owned by the context. This is the
28-
/// point of registration of custom types and operations for the dialect.
29-
ToyDialect::ToyDialect(mlir::MLIRContext *ctx)
30-
: mlir::Dialect(getDialectNamespace(), ctx, TypeID::get<ToyDialect>()) {
27+
/// Dialect initialization, the instance will be owned by the context. This is
28+
/// the point of registration of types and operations for the dialect.
29+
void ToyDialect::initialize() {
3130
addOperations<
3231
#define GET_OP_LIST
3332
#include "toy/Ops.cpp.inc"

mlir/examples/toy/Ch4/include/toy/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
set(LLVM_TARGET_DEFINITIONS Ops.td)
33
mlir_tablegen(Ops.h.inc -gen-op-decls)
44
mlir_tablegen(Ops.cpp.inc -gen-op-defs)
5+
mlir_tablegen(Dialect.h.inc -gen-dialect-decls)
56
add_public_tablegen_target(ToyCh4OpsIncGen)
67

78
# Most dialects should use add_mlir_interfaces().

mlir/examples/toy/Ch4/include/toy/Dialect.h

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,9 @@
2121
#include "mlir/Interfaces/SideEffectInterfaces.h"
2222
#include "toy/ShapeInferenceInterface.h"
2323

24-
namespace mlir {
25-
namespace toy {
26-
27-
/// This is the definition of the Toy dialect. A dialect inherits from
28-
/// mlir::Dialect and registers custom attributes, operations, and types (in its
29-
/// constructor). It can also override some general behavior exposed via virtual
30-
/// methods.
31-
class ToyDialect : public mlir::Dialect {
32-
public:
33-
explicit ToyDialect(mlir::MLIRContext *ctx);
34-
35-
/// Provide a utility accessor to the dialect namespace. This is used by
36-
/// several utilities for casting between dialects.
37-
static llvm::StringRef getDialectNamespace() { return "toy"; }
38-
};
39-
40-
} // end namespace toy
41-
} // end namespace mlir
24+
/// Include the auto-generated header file containing the declaration of the toy
25+
/// dialect.
26+
#include "toy/Dialect.h.inc"
4227

4328
/// Include the auto-generated header file containing the declarations of the
4429
/// toy operations.

mlir/examples/toy/Ch4/mlir/Dialect.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,9 @@ struct ToyInlinerInterface : public DialectInlinerInterface {
7979
// ToyDialect
8080
//===----------------------------------------------------------------------===//
8181

82-
/// Dialect creation, the instance will be owned by the context. This is the
83-
/// point of registration of custom types and operations for the dialect.
84-
ToyDialect::ToyDialect(mlir::MLIRContext *ctx)
85-
: mlir::Dialect(getDialectNamespace(), ctx, TypeID::get<ToyDialect>()) {
82+
/// Dialect initialization, the instance will be owned by the context. This is
83+
/// the point of registration of types and operations for the dialect.
84+
void ToyDialect::initialize() {
8685
addOperations<
8786
#define GET_OP_LIST
8887
#include "toy/Ops.cpp.inc"

mlir/examples/toy/Ch5/include/toy/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
set(LLVM_TARGET_DEFINITIONS Ops.td)
33
mlir_tablegen(Ops.h.inc -gen-op-decls)
44
mlir_tablegen(Ops.cpp.inc -gen-op-defs)
5+
mlir_tablegen(Dialect.h.inc -gen-dialect-decls)
56
add_public_tablegen_target(ToyCh5OpsIncGen)
67

78
# Most dialects should use add_mlir_interfaces().

mlir/examples/toy/Ch5/include/toy/Dialect.h

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,9 @@
2121
#include "mlir/Interfaces/SideEffectInterfaces.h"
2222
#include "toy/ShapeInferenceInterface.h"
2323

24-
namespace mlir {
25-
namespace toy {
26-
27-
/// This is the definition of the Toy dialect. A dialect inherits from
28-
/// mlir::Dialect and registers custom attributes, operations, and types (in its
29-
/// constructor). It can also override some general behavior exposed via virtual
30-
/// methods.
31-
class ToyDialect : public mlir::Dialect {
32-
public:
33-
explicit ToyDialect(mlir::MLIRContext *ctx);
34-
35-
/// Provide a utility accessor to the dialect namespace. This is used by
36-
/// several utilities for casting between dialects.
37-
static llvm::StringRef getDialectNamespace() { return "toy"; }
38-
};
39-
40-
} // end namespace toy
41-
} // end namespace mlir
24+
/// Include the auto-generated header file containing the declaration of the toy
25+
/// dialect.
26+
#include "toy/Dialect.h.inc"
4227

4328
/// Include the auto-generated header file containing the declarations of the
4429
/// toy operations.

mlir/examples/toy/Ch5/mlir/Dialect.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,9 @@ struct ToyInlinerInterface : public DialectInlinerInterface {
7979
// ToyDialect
8080
//===----------------------------------------------------------------------===//
8181

82-
/// Dialect creation, the instance will be owned by the context. This is the
83-
/// point of registration of custom types and operations for the dialect.
84-
ToyDialect::ToyDialect(mlir::MLIRContext *ctx)
85-
: mlir::Dialect(getDialectNamespace(), ctx, TypeID::get<ToyDialect>()) {
82+
/// Dialect initialization, the instance will be owned by the context. This is
83+
/// the point of registration of types and operations for the dialect.
84+
void ToyDialect::initialize() {
8685
addOperations<
8786
#define GET_OP_LIST
8887
#include "toy/Ops.cpp.inc"

mlir/examples/toy/Ch6/include/toy/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
set(LLVM_TARGET_DEFINITIONS Ops.td)
33
mlir_tablegen(Ops.h.inc -gen-op-decls)
44
mlir_tablegen(Ops.cpp.inc -gen-op-defs)
5+
mlir_tablegen(Dialect.h.inc -gen-dialect-decls)
56
add_public_tablegen_target(ToyCh6OpsIncGen)
67

78
# Most dialects should use add_mlir_interfaces().

0 commit comments

Comments
 (0)