[Mlir-commits] [mlir] 0050e8f - [mlir][Tutorial] Add a section to Toy Ch.2 detailing the custom assembly format.
River Riddle
llvmlistbot at llvm.org
Fri Feb 21 15:17:48 PST 2020
Author: River Riddle
Date: 2020-02-21T15:15:32-08:00
New Revision: 0050e8f0cf5782217ebd78fa2b58be3aa9f8d9e2
URL: https://github.com/llvm/llvm-project/commit/0050e8f0cf5782217ebd78fa2b58be3aa9f8d9e2
DIFF: https://github.com/llvm/llvm-project/commit/0050e8f0cf5782217ebd78fa2b58be3aa9f8d9e2.diff
LOG: [mlir][Tutorial] Add a section to Toy Ch.2 detailing the custom assembly format.
Summary:
This details the C++ format as well as the new declarative format. This has been one of the major missing pieces from the toy tutorial.
Differential Revision: https://reviews.llvm.org/D74938
Added:
Modified:
mlir/docs/Tutorials/Toy/Ch-2.md
mlir/docs/Tutorials/Toy/Ch-3.md
mlir/docs/Tutorials/Toy/Ch-4.md
mlir/docs/Tutorials/Toy/Ch-5.md
mlir/docs/Tutorials/Toy/Ch-6.md
mlir/docs/Tutorials/Toy/Ch-7.md
mlir/examples/toy/Ch2/include/toy/Ops.td
mlir/examples/toy/Ch2/mlir/Dialect.cpp
mlir/examples/toy/Ch3/include/toy/Ops.td
mlir/examples/toy/Ch3/mlir/Dialect.cpp
mlir/examples/toy/Ch4/include/toy/Ops.td
mlir/examples/toy/Ch4/mlir/Dialect.cpp
mlir/examples/toy/Ch5/include/toy/Ops.td
mlir/examples/toy/Ch5/mlir/Dialect.cpp
mlir/examples/toy/Ch6/include/toy/Ops.td
mlir/examples/toy/Ch6/mlir/Dialect.cpp
mlir/examples/toy/Ch7/include/toy/Ops.td
mlir/examples/toy/Ch7/mlir/Dialect.cpp
mlir/test/Examples/Toy/Ch2/codegen.toy
mlir/test/Examples/Toy/Ch2/scalar.toy
mlir/test/Examples/Toy/Ch3/codegen.toy
mlir/test/Examples/Toy/Ch3/scalar.toy
mlir/test/Examples/Toy/Ch4/codegen.toy
mlir/test/Examples/Toy/Ch4/scalar.toy
mlir/test/Examples/Toy/Ch4/shape_inference.mlir
mlir/test/Examples/Toy/Ch5/affine-lowering.mlir
mlir/test/Examples/Toy/Ch5/codegen.toy
mlir/test/Examples/Toy/Ch5/scalar.toy
mlir/test/Examples/Toy/Ch5/shape_inference.mlir
mlir/test/Examples/Toy/Ch6/affine-lowering.mlir
mlir/test/Examples/Toy/Ch6/codegen.toy
mlir/test/Examples/Toy/Ch6/llvm-lowering.mlir
mlir/test/Examples/Toy/Ch6/scalar.toy
mlir/test/Examples/Toy/Ch6/shape_inference.mlir
mlir/test/Examples/Toy/Ch7/affine-lowering.mlir
mlir/test/Examples/Toy/Ch7/codegen.toy
mlir/test/Examples/Toy/Ch7/llvm-lowering.mlir
mlir/test/Examples/Toy/Ch7/scalar.toy
mlir/test/Examples/Toy/Ch7/shape_inference.mlir
mlir/test/Examples/Toy/Ch7/struct-codegen.toy
mlir/test/Examples/Toy/Ch7/struct-opt.mlir
Removed:
################################################################################
diff --git a/mlir/docs/Tutorials/Toy/Ch-2.md b/mlir/docs/Tutorials/Toy/Ch-2.md
index 18d1ef417e9d..66a795e24ba7 100755
--- a/mlir/docs/Tutorials/Toy/Ch-2.md
+++ b/mlir/docs/Tutorials/Toy/Ch-2.md
@@ -517,12 +517,7 @@ def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {
}
```
-Above we introduce several of the concepts for defining operations in the ODS
-framework, but there are many more that we haven't had a chance to: regions,
-variadic operands, etc. Check out the
-[full specification](../../OpDefinitions.md) for more details.
-
-## Complete Toy Example
+#### Specifying a Custom Assembly Format
At this point we can generate our "Toy IR". A simplified version of the previous
example:
@@ -565,6 +560,185 @@ module {
} loc("test/codegen.toy":0:0)
```
+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
+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
+operation format that we would like to simplify.
+
+##### `toy.print`
+
+The current form of `toy.print` is a little verbose. There are a lot of
+additional characters that we would like to strip away. Let's begin by thinking
+of what a good format of `toy.print` would be, and see how we can implement it.
+Looking at the basics of `toy.print` we get:
+
+```mlir
+toy.print %5 : tensor<*xf64> loc(...)
+```
+
+Here we have stripped much of the format down to the bare essentials, and it has
+become much more readable. To provide a custom assembly format, an operation can
+either override the `parser` and `printer` fields for a C++ format, or the
+`assemblyFormat` field for the declarative format. Let's look at the C++ variant
+first, as this is what the declarative format maps to internally.
+
+```tablegen
+/// Consider a stripped definition of `toy.print` here.
+def PrintOp : Toy_Op<"print"> {
+ let arguments = (ins F64Tensor:$input);
+
+ // Divert the printer and parser to static functions in our .cpp
+ // file that correspond to 'print' and 'printPrintOp'. 'printer' and 'parser'
+ // here correspond to an instance of a 'OpAsmParser' and 'OpAsmPrinter'. More
+ // details on these classes is shown below.
+ let printer = [{ return ::print(printer, *this); }];
+ let parser = [{ return ::parse$cppClass(parser, result); }];
+}
+```
+
+A C++ implementation for the printer and parser is shown below:
+
+```c++
+/// The 'OpAsmPrinter' class is a stream that will allows for formatting
+/// strings, attributes, operands, types, etc.
+static void print(mlir::OpAsmPrinter &printer, PrintOp op) {
+ printer << "toy.print " << op.input();
+ printer.printOptionalAttrDict(op.getAttrs());
+ printer << " : " << op.input().getType();
+}
+
+/// The 'OpAsmPrinter' class provides a collection of methods for parsing
+/// various punctuation, as well as attributes, operands, types, etc. Each of
+/// these methods returns a `ParseResult`. This class is a wrapper around
+/// `LogicalResult` that can be converted to a boolean `true` value on failure,
+/// or `false` on success. This allows for easily chaining together a set of
+/// parser rules. These rules are used to populate an `mlir::OperationState`
+/// similarly to the `build` methods described above.
+static mlir::ParseResult parsePrintOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ // Parse the input operand, the attribute dictionary, and the type of the
+ // input.
+ mlir::OpAsmParser::OperandType inputOperand;
+ mlir::Type inputType;
+ if (parser.parseOperand(inputOperand) ||
+ parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
+ parser.parseType(inputType))
+ return mlir::failure();
+
+ // Resolve the input operand to the type we parsed in.
+ if (parser.resolveOperand(inputOperand, inputType, result.operands))
+ return mlir::failure();
+
+ return mlir::success();
+}
+```
+
+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 is largely composed of three
diff erent components:
+
+* Directives
+ - A type of builtin function, with an optional set of arguments.
+* Literals
+ - A keyword or punctuation surrounded by \`\`.
+* Variables
+ - An entity that has been registered on the operation itself, i.e. an
+ argument(attribute or operand), result, successor, etc. In the `PrintOp`
+ example above, a variable would be `$input`.
+
+A direct mapping of our C++ format looks something like:
+
+```tablegen
+/// Consider a stripped definition of `toy.print` here.
+def PrintOp : Toy_Op<"print"> {
+ let arguments = (ins F64Tensor:$input);
+
+ // In the following format we have two directives, `attr-dict` and `type`.
+ // These correspond to the attribute dictionary and the type of a given
+ // variable represectively.
+ let assemblyFormat = "$input attr-dict `:` type($input)";
+}
+```
+
+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:
+
+```mlir
+module {
+ func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> {
+ %0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64> loc("test/codegen.toy":5:10)
+ %1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64> loc("test/codegen.toy":5:25)
+ %2 = toy.mul %0, %1 : tensor<*xf64> loc("test/codegen.toy":5:25)
+ toy.return %2 : tensor<*xf64> loc("test/codegen.toy":5:3)
+ } loc("test/codegen.toy":4:1)
+ func @main() {
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> loc("test/codegen.toy":9:17)
+ %1 = toy.reshape(%0 : tensor<2x3xf64>) to tensor<2x3xf64> loc("test/codegen.toy":9:3)
+ %2 = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64> loc("test/codegen.toy":10:17)
+ %3 = toy.reshape(%2 : tensor<6xf64>) to tensor<2x3xf64> loc("test/codegen.toy":10:3)
+ %4 = toy.generic_call @multiply_transpose(%1, %3) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/codegen.toy":11:11)
+ %5 = toy.generic_call @multiply_transpose(%3, %1) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/codegen.toy":12:11)
+ toy.print %5 : tensor<*xf64> loc("test/codegen.toy":13:3)
+ toy.return loc("test/codegen.toy":8:1)
+ } loc("test/codegen.toy":8:1)
+} loc("test/codegen.toy":0:0)
+```
+
+Above we introduce several of the concepts for defining operations in the ODS
+framework, but there are many more that we haven't had a chance to: regions,
+variadic operands, etc. Check out the
+[full specification](../../OpDefinitions.md) for more details.
+
+## Complete Toy Example
+
+At this point we can generate our "Toy IR". A simplified version of the previous
+example:
+
+```toy
+# User defined generic function that operates on unknown shaped arguments.
+def multiply_transpose(a, b) {
+ return transpose(a) * transpose(b);
+}
+
+def main() {
+ var a<2, 3> = [[1, 2, 3], [4, 5, 6]];
+ var b<2, 3> = [1, 2, 3, 4, 5, 6];
+ var c = multiply_transpose(a, b);
+ var d = multiply_transpose(b, a);
+ print(d);
+}
+```
+
+Results in the following IR:
+
+```mlir
+module {
+ func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> {
+ %0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64> loc("test/codegen.toy":5:10)
+ %1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64> loc("test/codegen.toy":5:25)
+ %2 = toy.mul %0, %1 : tensor<*xf64> loc("test/codegen.toy":5:25)
+ toy.return %2 : tensor<*xf64> loc("test/codegen.toy":5:3)
+ } loc("test/codegen.toy":4:1)
+ func @main() {
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> loc("test/codegen.toy":9:17)
+ %1 = toy.reshape(%0 : tensor<2x3xf64>) to tensor<2x3xf64> loc("test/codegen.toy":9:3)
+ %2 = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64> loc("test/codegen.toy":10:17)
+ %3 = toy.reshape(%2 : tensor<6xf64>) to tensor<2x3xf64> loc("test/codegen.toy":10:3)
+ %4 = toy.generic_call @multiply_transpose(%1, %3) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/codegen.toy":11:11)
+ %5 = toy.generic_call @multiply_transpose(%3, %1) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/codegen.toy":12:11)
+ toy.print %5 : tensor<*xf64> loc("test/codegen.toy":13:3)
+ toy.return loc("test/codegen.toy":8:1)
+ } loc("test/codegen.toy":8:1)
+} loc("test/codegen.toy":0:0)
+```
+
You can build `toyc-ch2` and try yourself: `toyc-ch2
test/Examples/Toy/Ch2/codegen.toy -emit=mlir -mlir-print-debuginfo`. We can also
check our RoundTrip: `toyc-ch2 test/Examples/Toy/Ch2/codegen.toy -emit=mlir
diff --git a/mlir/docs/Tutorials/Toy/Ch-3.md b/mlir/docs/Tutorials/Toy/Ch-3.md
index fee947ff5fda..6e7ced2576d8 100644
--- a/mlir/docs/Tutorials/Toy/Ch-3.md
+++ b/mlir/docs/Tutorials/Toy/Ch-3.md
@@ -38,9 +38,9 @@ Which corresponds to the following IR:
```mlir
func @transpose_transpose(%arg0: tensor<*xf64>) -> tensor<*xf64> {
- %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64>
- %1 = "toy.transpose"(%0) : (tensor<*xf64>) -> tensor<*xf64>
- "toy.return"(%1) : (tensor<*xf64>) -> ()
+ %0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64>
+ %1 = toy.transpose(%0 : tensor<*xf64>) to tensor<*xf64>
+ toy.return %1 : tensor<*xf64>
}
```
@@ -133,8 +133,8 @@ observe our pattern in action:
```mlir
func @transpose_transpose(%arg0: tensor<*xf64>) -> tensor<*xf64> {
- %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64>
- "toy.return"(%arg0) : (tensor<*xf64>) -> ()
+ %0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64>
+ toy.return %arg0 : tensor<*xf64>
}
```
@@ -154,7 +154,7 @@ Let's retry now `toyc-ch3 test/transpose_transpose.toy -emit=mlir -opt`:
```mlir
func @transpose_transpose(%arg0: tensor<*xf64>) -> tensor<*xf64> {
- "toy.return"(%arg0) : (tensor<*xf64>) -> ()
+ toy.return %arg0 : tensor<*xf64>
}
```
@@ -229,13 +229,12 @@ def main() {
```mlir
module {
func @main() {
- %0 = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64>}
- : () -> tensor<2xf64>
- %1 = "toy.reshape"(%0) : (tensor<2xf64>) -> tensor<2x1xf64>
- %2 = "toy.reshape"(%1) : (tensor<2x1xf64>) -> tensor<2x1xf64>
- %3 = "toy.reshape"(%2) : (tensor<2x1xf64>) -> tensor<2x1xf64>
- "toy.print"(%3) : (tensor<2x1xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64>
+ %1 = toy.reshape(%0 : tensor<2xf64>) to tensor<2x1xf64>
+ %2 = toy.reshape(%1 : tensor<2x1xf64>) to tensor<2x1xf64>
+ %3 = toy.reshape(%2 : tensor<2x1xf64>) to tensor<2x1xf64>
+ toy.print %3 : tensor<2x1xf64>
+ toy.return
}
}
```
@@ -246,10 +245,9 @@ our pattern in action:
```mlir
module {
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00], [2.000000e+00]]> \
- : tensor<2x1xf64>} : () -> tensor<2x1xf64>
- "toy.print"(%0) : (tensor<2x1xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00], [2.000000e+00]]> : tensor<2x1xf64>
+ toy.print %0 : tensor<2x1xf64>
+ toy.return
}
}
```
diff --git a/mlir/docs/Tutorials/Toy/Ch-4.md b/mlir/docs/Tutorials/Toy/Ch-4.md
index b2882991ecdf..99f25f548ef3 100644
--- a/mlir/docs/Tutorials/Toy/Ch-4.md
+++ b/mlir/docs/Tutorials/Toy/Ch-4.md
@@ -150,20 +150,20 @@ Now let's look at a working example:
```mlir
func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> {
- %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64>
- %1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64>
- %2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
- "toy.return"(%2) : (tensor<*xf64>) -> ()
+ %0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64>
+ %1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64>
+ %2 = toy.mul %0, %1 : tensor<*xf64>
+ toy.return %2 : tensor<*xf64>
}
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %1 = "toy.reshape"(%0) : (tensor<2x3xf64>) -> tensor<2x3xf64>
- %2 = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64>
- %3 = "toy.reshape"(%2) : (tensor<6xf64>) -> tensor<2x3xf64>
- %4 = "toy.generic_call"(%1, %3) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
- %5 = "toy.generic_call"(%3, %1) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
- "toy.print"(%5) : (tensor<*xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %1 = toy.reshape(%0 : tensor<2x3xf64>) to tensor<2x3xf64>
+ %2 = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>
+ %3 = toy.reshape(%2 : tensor<6xf64>) to tensor<2x3xf64>
+ %4 = toy.generic_call @multiply_transpose(%1, %3) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+ %5 = toy.generic_call @multiply_transpose(%3, %1) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+ toy.print %5 : tensor<*xf64>
+ toy.return
}
```
@@ -226,8 +226,8 @@ func @main() {
%4 = "toy.transpose"(%2) : (tensor<*xf64>) -> tensor<*xf64>
%5 = "toy.transpose"(%3) : (tensor<*xf64>) -> tensor<*xf64>
%6 = "toy.mul"(%4, %5) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
- "toy.print"(%6) : (tensor<*xf64>) -> ()
- "toy.return"() : () -> ()
+ toy.print %6 : tensor<*xf64>
+ toy.return
}
```
@@ -374,8 +374,8 @@ func @main() {
%0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
%1 = "toy.transpose"(%0) : (tensor<2x3xf64>) -> tensor<3x2xf64>
%2 = "toy.mul"(%1, %1) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
- "toy.print"(%2) : (tensor<3x2xf64>) -> ()
- "toy.return"() : () -> ()
+ toy.print %2 : tensor<3x2xf64>
+ toy.return
}
```
diff --git a/mlir/docs/Tutorials/Toy/Ch-5.md b/mlir/docs/Tutorials/Toy/Ch-5.md
index 11ed9561d2c6..f5bee68ce676 100644
--- a/mlir/docs/Tutorials/Toy/Ch-5.md
+++ b/mlir/docs/Tutorials/Toy/Ch-5.md
@@ -239,11 +239,11 @@ Looking back at our current working example:
```mlir
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %2 = "toy.transpose"(%0) : (tensor<2x3xf64>) -> tensor<3x2xf64>
- %3 = "toy.mul"(%2, %2) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
- "toy.print"(%3) : (tensor<3x2xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %2 = toy.transpose(%0 : tensor<2x3xf64>) to tensor<3x2xf64>
+ %3 = toy.mul %2, %2 : tensor<3x2xf64>
+ toy.print %3 : tensor<3x2xf64>
+ toy.return
}
```
@@ -291,7 +291,7 @@ func @main() {
}
// Print the value held by the buffer.
- "toy.print"(%0) : (memref<3x2xf64>) -> ()
+ toy.print %0 : memref<3x2xf64>
dealloc %2 : memref<2x3xf64>
dealloc %1 : memref<3x2xf64>
dealloc %0 : memref<3x2xf64>
@@ -340,7 +340,7 @@ func @main() {
}
// Print the value held by the buffer.
- "toy.print"(%0) : (memref<3x2xf64>) -> ()
+ toy.print %0 : memref<3x2xf64>
dealloc %1 : memref<2x3xf64>
dealloc %0 : memref<3x2xf64>
return
diff --git a/mlir/docs/Tutorials/Toy/Ch-6.md b/mlir/docs/Tutorials/Toy/Ch-6.md
index e564fcce257a..bfca5c9210b4 100644
--- a/mlir/docs/Tutorials/Toy/Ch-6.md
+++ b/mlir/docs/Tutorials/Toy/Ch-6.md
@@ -115,11 +115,11 @@ Looking back at our current working example:
```mlir
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %2 = "toy.transpose"(%0) : (tensor<2x3xf64>) -> tensor<3x2xf64>
- %3 = "toy.mul"(%2, %2) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
- "toy.print"(%3) : (tensor<3x2xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %2 = toy.transpose(%0 : tensor<2x3xf64>) to tensor<3x2xf64>
+ %3 = toy.mul %2, %2 : tensor<3x2xf64>
+ toy.print %3 : tensor<3x2xf64>
+ toy.return
}
```
diff --git a/mlir/docs/Tutorials/Toy/Ch-7.md b/mlir/docs/Tutorials/Toy/Ch-7.md
index a14d65409982..64febd4c02c2 100644
--- a/mlir/docs/Tutorials/Toy/Ch-7.md
+++ b/mlir/docs/Tutorials/Toy/Ch-7.md
@@ -342,7 +342,7 @@ Which generates the following:
```mlir
module {
func @multiply_transpose(%arg0: !toy.struct<tensor<*xf64>, tensor<*xf64>>) {
- "toy.return"() : () -> ()
+ toy.return
}
}
```
@@ -391,9 +391,9 @@ modeling, we just use an [array attribute](../../LangRef.md#array-attribute)
that contains a set of constant values for each of the `struct` elements.
```mlir
- %0 = "toy.struct_constant"() {
- value = [dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64>]
- } : () -> !toy.struct<tensor<*xf64>>
+ %0 = toy.struct_constant [
+ dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64>
+ ] : !toy.struct<tensor<*xf64>>
```
##### `toy.struct_access`
@@ -401,10 +401,10 @@ that contains a set of constant values for each of the `struct` elements.
This new operation materializes the Nth element of a `struct` value.
```mlir
- %0 = "toy.struct_constant"() {
- value = [dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64>]
- } : () -> !toy.struct<tensor<*xf64>>
- %1 = "toy.struct_access"(%0) {index = 0 : i64} : (!toy.struct<tensor<*xf64>>) -> tensor<*xf64>
+ %0 = toy.struct_constant [
+ dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64>
+ ] : !toy.struct<tensor<*xf64>>
+ %1 = toy.struct_access %0[0] : !toy.struct<tensor<*xf64>> -> tensor<*xf64>
```
With these operations, we can revisit our original example:
@@ -436,18 +436,21 @@ and finally get a full MLIR module:
```mlir
module {
func @multiply_transpose(%arg0: !toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64> {
- %0 = "toy.struct_access"(%arg0) {index = 0 : i64} : (!toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
- %1 = "toy.transpose"(%0) : (tensor<*xf64>) -> tensor<*xf64>
- %2 = "toy.struct_access"(%arg0) {index = 1 : i64} : (!toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
- %3 = "toy.transpose"(%2) : (tensor<*xf64>) -> tensor<*xf64>
- %4 = "toy.mul"(%1, %3) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
- "toy.return"(%4) : (tensor<*xf64>) -> ()
+ %0 = toy.struct_access %arg0[0] : !toy.struct<tensor<*xf64>, tensor<*xf64>> -> tensor<*xf64>
+ %1 = toy.transpose(%0 : tensor<*xf64>) to tensor<*xf64>
+ %2 = toy.struct_access %arg0[1] : !toy.struct<tensor<*xf64>, tensor<*xf64>> -> tensor<*xf64>
+ %3 = toy.transpose(%2 : tensor<*xf64>) to tensor<*xf64>
+ %4 = toy.mul %1, %3 : tensor<*xf64>
+ toy.return %4 : tensor<*xf64>
}
func @main() {
- %0 = "toy.struct_constant"() {value = [dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>, dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>]} : () -> !toy.struct<tensor<*xf64>, tensor<*xf64>>
- %1 = "toy.generic_call"(%0) {callee = @multiply_transpose} : (!toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
- "toy.print"(%1) : (tensor<*xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.struct_constant [
+ dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>,
+ dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ ] : !toy.struct<tensor<*xf64>, tensor<*xf64>>
+ %1 = toy.generic_call @multiply_transpose(%0) : (!toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
+ toy.print %1 : tensor<*xf64>
+ toy.return
}
}
```
@@ -462,14 +465,17 @@ After inlining, the MLIR module in the previous section looks something like:
```mlir
module {
func @main() {
- %0 = "toy.struct_constant"() {value = [dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>, dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>]} : () -> !toy.struct<tensor<*xf64>, tensor<*xf64>>
- %1 = "toy.struct_access"(%0) {index = 0 : i64} : (!toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
- %2 = "toy.transpose"(%1) : (tensor<*xf64>) -> tensor<*xf64>
- %3 = "toy.struct_access"(%0) {index = 1 : i64} : (!toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
- %4 = "toy.transpose"(%3) : (tensor<*xf64>) -> tensor<*xf64>
- %5 = "toy.mul"(%2, %4) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
- "toy.print"(%5) : (tensor<*xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.struct_constant [
+ dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>,
+ dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ ] : !toy.struct<tensor<*xf64>, tensor<*xf64>>
+ %1 = toy.struct_access %0[0] : !toy.struct<tensor<*xf64>, tensor<*xf64>> -> tensor<*xf64>
+ %2 = toy.transpose(%1 : tensor<*xf64>) to tensor<*xf64>
+ %3 = toy.struct_access %0[1] : !toy.struct<tensor<*xf64>, tensor<*xf64>> -> tensor<*xf64>
+ %4 = toy.transpose(%3 : tensor<*xf64>) to tensor<*xf64>
+ %5 = toy.mul %2, %4 : tensor<*xf64>
+ toy.print %5 : tensor<*xf64>
+ toy.return
}
}
```
@@ -524,11 +530,11 @@ changes to our pipeline.
```mlir
module {
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %1 = "toy.transpose"(%0) : (tensor<2x3xf64>) -> tensor<3x2xf64>
- %2 = "toy.mul"(%1, %1) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
- "toy.print"(%2) : (tensor<3x2xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %1 = toy.transpose(%0 : tensor<2x3xf64>) to tensor<3x2xf64>
+ %2 = toy.mul %1, %1 : tensor<3x2xf64>
+ toy.print %2 : tensor<3x2xf64>
+ toy.return
}
}
```
diff --git a/mlir/examples/toy/Ch2/include/toy/Ops.td b/mlir/examples/toy/Ch2/include/toy/Ops.td
index 96f27ed6021b..ac5e97bbd341 100644
--- a/mlir/examples/toy/Ch2/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch2/include/toy/Ops.td
@@ -47,9 +47,8 @@ def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {
to the operation as an attribute. For example:
```mlir
- %0 = "toy.constant"()
- { value = dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64> }
- : () -> tensor<2x3xf64>
+ %0 = toy.constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]>
+ : tensor<2x3xf64>
```
}];
@@ -59,6 +58,10 @@ def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {
// The constant operation returns a single value of TensorType.
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseConstantOp(parser, result); }];
+ let printer = [{ return ::print(p, *this); }];
+
// Add custom build methods for the constant operation. These method populates
// the `state` that MLIR uses to create operations, i.e. these are used when
// using `builder.create<ConstantOp>(...)`.
@@ -87,6 +90,10 @@ def AddOp : Toy_Op<"add"> {
let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseBinaryOp(parser, result); }];
+ let printer = [{ return ::printBinaryOp(p, *this); }];
+
// Allow building an AddOp with from the two input operands.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value lhs, Value rhs">
@@ -102,7 +109,7 @@ def GenericCallOp : Toy_Op<"generic_call"> {
arguments expected by the callee. For example:
```mlir
- %4 = "toy.generic_call"(%1, %3) {callee = @my_func}
+ %4 = toy.generic_call @my_func(%1, %3)
: (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
```
@@ -117,6 +124,11 @@ def GenericCallOp : Toy_Op<"generic_call"> {
// The generic call operation returns a single value of TensorType.
let results = (outs F64Tensor);
+ // The return operation only emits the input in the format if it is present.
+ let assemblyFormat = [{
+ $callee `(` $inputs `)` attr-dict `:` functional-type($inputs, results)
+ }];
+
// Add custom build methods for the generic call operation.
let builders = [
OpBuilder<"Builder *builder, OperationState &state, "
@@ -134,6 +146,10 @@ def MulOp : Toy_Op<"mul"> {
let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseBinaryOp(parser, result); }];
+ let printer = [{ return ::printBinaryOp(p, *this); }];
+
// Allow building a MulOp with from the two input operands.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value lhs, Value rhs">
@@ -149,6 +165,8 @@ def PrintOp : Toy_Op<"print"> {
// The print operation takes an input tensor to print.
let arguments = (ins F64Tensor:$input);
+
+ let assemblyFormat = "$input attr-dict `:` type($input)";
}
def ReshapeOp : Toy_Op<"reshape"> {
@@ -158,7 +176,7 @@ def ReshapeOp : Toy_Op<"reshape"> {
the same number of elements but
diff erent shapes. For example:
```mlir
- %0 = "toy.reshape"(%arg1) : (tensor<10xf64>) -> tensor<5x2xf64>
+ %0 = toy.reshape (%arg1 : tensor<10xf64>) to tensor<5x2xf64>
```
}];
@@ -166,6 +184,10 @@ def ReshapeOp : Toy_Op<"reshape"> {
// We expect that the reshape operation returns a statically shaped tensor.
let results = (outs StaticShapeTensorOf<[F64]>);
+
+ let assemblyFormat = [{
+ `(` $input `:` type($input) `)` attr-dict `to` type(results)
+ }];
}
def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
@@ -188,6 +210,9 @@ def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
// value must match the return type of the enclosing function.
let arguments = (ins Variadic<F64Tensor>:$input);
+ // The return operation only emits the input in the format if it is present.
+ let assemblyFormat = "($input^ `:` type($input))? attr-dict ";
+
// Allow building a ReturnOp with no return operand.
let builders = [OpBuilder<
"Builder *b, OperationState &state", [{ build(b, state, llvm::None); }]
@@ -208,6 +233,10 @@ def TransposeOp : Toy_Op<"transpose"> {
let arguments = (ins F64Tensor:$input);
let results = (outs F64Tensor);
+ let assemblyFormat = [{
+ `(` $input `:` type($input) `)` attr-dict `to` type(results)
+ }];
+
// Allow building a TransposeOp with from the input operand.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value input">
diff --git a/mlir/examples/toy/Ch2/mlir/Dialect.cpp b/mlir/examples/toy/Ch2/mlir/Dialect.cpp
index c99023e215f1..4aa33c048f6e 100644
--- a/mlir/examples/toy/Ch2/mlir/Dialect.cpp
+++ b/mlir/examples/toy/Ch2/mlir/Dialect.cpp
@@ -14,6 +14,7 @@
#include "toy/Dialect.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/StandardTypes.h"
using namespace mlir;
@@ -36,6 +37,54 @@ ToyDialect::ToyDialect(mlir::MLIRContext *ctx) : mlir::Dialect("toy", ctx) {
// Toy Operations
//===----------------------------------------------------------------------===//
+/// A generalized parser for binary operations. This parses the
diff erent forms
+/// of 'printBinaryOp' below.
+static mlir::ParseResult parseBinaryOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ SmallVector<mlir::OpAsmParser::OperandType, 2> operands;
+ llvm::SMLoc operandsLoc = parser.getCurrentLocation();
+ Type type;
+ if (parser.parseOperandList(operands, /*requiredOperandCount=*/2) ||
+ parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseColonType(type))
+ return mlir::failure();
+
+ // If the type is a function type, it contains the input and result types of
+ // this operation.
+ if (FunctionType funcType = type.dyn_cast<FunctionType>()) {
+ if (parser.resolveOperands(operands, funcType.getInputs(), operandsLoc,
+ result.operands))
+ return mlir::failure();
+ result.addTypes(funcType.getResults());
+ return mlir::success();
+ }
+
+ // Otherwise, the parsed type is the type of both operands and results.
+ if (parser.resolveOperands(operands, type, result.operands))
+ return mlir::failure();
+ result.addTypes(type);
+ return mlir::success();
+}
+
+/// A generalized printer for binary operations. It prints in two
diff erent
+/// forms depending on if all of the types match.
+static void printBinaryOp(mlir::OpAsmPrinter &printer, mlir::Operation *op) {
+ printer << op->getName() << " " << op->getOperands();
+ printer.printOptionalAttrDict(op->getAttrs());
+ printer << " : ";
+
+ // If all of the types are the same, print the type directly.
+ Type resultType = *op->result_type_begin();
+ if (llvm::all_of(op->getOperandTypes(),
+ [=](Type type) { return type == resultType; })) {
+ printer << resultType;
+ return;
+ }
+
+ // Otherwise, print a functional type.
+ printer.printFunctionalType(op->getOperandTypes(), op->getResultTypes());
+}
+
//===----------------------------------------------------------------------===//
// ConstantOp
@@ -49,6 +98,32 @@ void ConstantOp::build(mlir::Builder *builder, mlir::OperationState &state,
ConstantOp::build(builder, state, dataType, dataAttribute);
}
+/// The 'OpAsmPrinter' class provides a collection of methods for parsing
+/// various punctuation, as well as attributes, operands, types, etc. Each of
+/// these methods returns a `ParseResult`. This class is a wrapper around
+/// `LogicalResult` that can be converted to a boolean `true` value on failure,
+/// or `false` on success. This allows for easily chaining together a set of
+/// parser rules. These rules are used to populate an `mlir::OperationState`
+/// similarly to the `build` methods described above.
+static mlir::ParseResult parseConstantOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ mlir::DenseElementsAttr value;
+ if (parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseAttribute(value, "value", result.attributes))
+ return failure();
+
+ result.addTypes(value.getType());
+ return success();
+}
+
+/// The 'OpAsmPrinter' class is a stream that will allows for formatting
+/// strings, attributes, operands, types, etc.
+static void print(mlir::OpAsmPrinter &printer, ConstantOp op) {
+ printer << "toy.constant ";
+ printer.printOptionalAttrDict(op.getAttrs(), /*elidedAttrs=*/{"value"});
+ printer << op.value();
+}
+
/// Verifier for the constant operation. This corresponds to the `::verify(...)`
/// in the op definition.
static mlir::LogicalResult verify(ConstantOp op) {
diff --git a/mlir/examples/toy/Ch3/include/toy/Ops.td b/mlir/examples/toy/Ch3/include/toy/Ops.td
index 80551d88e86c..2e519f391ae9 100644
--- a/mlir/examples/toy/Ch3/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch3/include/toy/Ops.td
@@ -47,9 +47,8 @@ def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {
to the operation as an attribute. For example:
```mlir
- %0 = "toy.constant"()
- { value = dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64> }
- : () -> tensor<2x3xf64>
+ %0 = toy.constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]>
+ : tensor<2x3xf64>
```
}];
@@ -59,6 +58,10 @@ def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {
// The constant operation returns a single value of TensorType.
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseConstantOp(parser, result); }];
+ let printer = [{ return ::print(p, *this); }];
+
// Add custom build methods for the constant operation. These method populates
// the `state` that MLIR uses to create operations, i.e. these are used when
// using `builder.create<ConstantOp>(...)`.
@@ -87,6 +90,10 @@ def AddOp : Toy_Op<"add", [NoSideEffect]> {
let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseBinaryOp(parser, result); }];
+ let printer = [{ return ::printBinaryOp(p, *this); }];
+
// Allow building an AddOp with from the two input operands.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value lhs, Value rhs">
@@ -102,7 +109,7 @@ def GenericCallOp : Toy_Op<"generic_call"> {
arguments expected by the callee. For example:
```mlir
- %4 = "toy.generic_call"(%1, %3) {callee = @my_func}
+ %4 = toy.generic_call @my_func(%1, %3)
: (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
```
@@ -117,6 +124,11 @@ def GenericCallOp : Toy_Op<"generic_call"> {
// The generic call operation returns a single value of TensorType.
let results = (outs F64Tensor);
+ // The return operation only emits the input in the format if it is present.
+ let assemblyFormat = [{
+ $callee `(` $inputs `)` attr-dict `:` functional-type($inputs, results)
+ }];
+
// Add custom build methods for the generic call operation.
let builders = [
OpBuilder<"Builder *builder, OperationState &state, "
@@ -134,6 +146,10 @@ def MulOp : Toy_Op<"mul", [NoSideEffect]> {
let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseBinaryOp(parser, result); }];
+ let printer = [{ return ::printBinaryOp(p, *this); }];
+
// Allow building a MulOp with from the two input operands.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value lhs, Value rhs">
@@ -149,6 +165,8 @@ def PrintOp : Toy_Op<"print"> {
// The print operation takes an input tensor to print.
let arguments = (ins F64Tensor:$input);
+
+ let assemblyFormat = "$input attr-dict `:` type($input)";
}
def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
@@ -158,17 +176,21 @@ def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
the same number of elements but
diff erent shapes. For example:
```mlir
- %0 = "toy.reshape"(%arg1) : (tensor<10xf64>) -> tensor<5x2xf64>
+ %0 = toy.reshape (%arg1 : tensor<10xf64>) to tensor<5x2xf64>
```
}];
let arguments = (ins F64Tensor:$input);
- // Enabled registering canonicalization patterns with this operation.
- let hasCanonicalizer = 1;
-
// We expect that the reshape operation returns a statically shaped tensor.
let results = (outs StaticShapeTensorOf<[F64]>);
+
+ let assemblyFormat = [{
+ `(` $input `:` type($input) `)` attr-dict `to` type(results)
+ }];
+
+ // Enable registering canonicalization patterns with this operation.
+ let hasCanonicalizer = 1;
}
def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
@@ -191,6 +213,9 @@ def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
// value must match the return type of the enclosing function.
let arguments = (ins Variadic<F64Tensor>:$input);
+ // The return operation only emits the input in the format if it is present.
+ let assemblyFormat = "($input^ `:` type($input))? attr-dict ";
+
// Allow building a ReturnOp with no return operand.
let builders = [OpBuilder<
"Builder *b, OperationState &state", [{ build(b, state, llvm::None); }]
@@ -211,7 +236,11 @@ def TransposeOp : Toy_Op<"transpose", [NoSideEffect]> {
let arguments = (ins F64Tensor:$input);
let results = (outs F64Tensor);
- // Enabled registering canonicalization patterns with this operation.
+ let assemblyFormat = [{
+ `(` $input `:` type($input) `)` attr-dict `to` type(results)
+ }];
+
+ // Enable registering canonicalization patterns with this operation.
let hasCanonicalizer = 1;
// Allow building a TransposeOp with from the input operand.
diff --git a/mlir/examples/toy/Ch3/mlir/Dialect.cpp b/mlir/examples/toy/Ch3/mlir/Dialect.cpp
index c99023e215f1..4aa33c048f6e 100644
--- a/mlir/examples/toy/Ch3/mlir/Dialect.cpp
+++ b/mlir/examples/toy/Ch3/mlir/Dialect.cpp
@@ -14,6 +14,7 @@
#include "toy/Dialect.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/StandardTypes.h"
using namespace mlir;
@@ -36,6 +37,54 @@ ToyDialect::ToyDialect(mlir::MLIRContext *ctx) : mlir::Dialect("toy", ctx) {
// Toy Operations
//===----------------------------------------------------------------------===//
+/// A generalized parser for binary operations. This parses the
diff erent forms
+/// of 'printBinaryOp' below.
+static mlir::ParseResult parseBinaryOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ SmallVector<mlir::OpAsmParser::OperandType, 2> operands;
+ llvm::SMLoc operandsLoc = parser.getCurrentLocation();
+ Type type;
+ if (parser.parseOperandList(operands, /*requiredOperandCount=*/2) ||
+ parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseColonType(type))
+ return mlir::failure();
+
+ // If the type is a function type, it contains the input and result types of
+ // this operation.
+ if (FunctionType funcType = type.dyn_cast<FunctionType>()) {
+ if (parser.resolveOperands(operands, funcType.getInputs(), operandsLoc,
+ result.operands))
+ return mlir::failure();
+ result.addTypes(funcType.getResults());
+ return mlir::success();
+ }
+
+ // Otherwise, the parsed type is the type of both operands and results.
+ if (parser.resolveOperands(operands, type, result.operands))
+ return mlir::failure();
+ result.addTypes(type);
+ return mlir::success();
+}
+
+/// A generalized printer for binary operations. It prints in two
diff erent
+/// forms depending on if all of the types match.
+static void printBinaryOp(mlir::OpAsmPrinter &printer, mlir::Operation *op) {
+ printer << op->getName() << " " << op->getOperands();
+ printer.printOptionalAttrDict(op->getAttrs());
+ printer << " : ";
+
+ // If all of the types are the same, print the type directly.
+ Type resultType = *op->result_type_begin();
+ if (llvm::all_of(op->getOperandTypes(),
+ [=](Type type) { return type == resultType; })) {
+ printer << resultType;
+ return;
+ }
+
+ // Otherwise, print a functional type.
+ printer.printFunctionalType(op->getOperandTypes(), op->getResultTypes());
+}
+
//===----------------------------------------------------------------------===//
// ConstantOp
@@ -49,6 +98,32 @@ void ConstantOp::build(mlir::Builder *builder, mlir::OperationState &state,
ConstantOp::build(builder, state, dataType, dataAttribute);
}
+/// The 'OpAsmPrinter' class provides a collection of methods for parsing
+/// various punctuation, as well as attributes, operands, types, etc. Each of
+/// these methods returns a `ParseResult`. This class is a wrapper around
+/// `LogicalResult` that can be converted to a boolean `true` value on failure,
+/// or `false` on success. This allows for easily chaining together a set of
+/// parser rules. These rules are used to populate an `mlir::OperationState`
+/// similarly to the `build` methods described above.
+static mlir::ParseResult parseConstantOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ mlir::DenseElementsAttr value;
+ if (parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseAttribute(value, "value", result.attributes))
+ return failure();
+
+ result.addTypes(value.getType());
+ return success();
+}
+
+/// The 'OpAsmPrinter' class is a stream that will allows for formatting
+/// strings, attributes, operands, types, etc.
+static void print(mlir::OpAsmPrinter &printer, ConstantOp op) {
+ printer << "toy.constant ";
+ printer.printOptionalAttrDict(op.getAttrs(), /*elidedAttrs=*/{"value"});
+ printer << op.value();
+}
+
/// Verifier for the constant operation. This corresponds to the `::verify(...)`
/// in the op definition.
static mlir::LogicalResult verify(ConstantOp op) {
diff --git a/mlir/examples/toy/Ch4/include/toy/Ops.td b/mlir/examples/toy/Ch4/include/toy/Ops.td
index 6b7c730d3d34..c805039c2f10 100644
--- a/mlir/examples/toy/Ch4/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch4/include/toy/Ops.td
@@ -48,9 +48,8 @@ def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {
to the operation as an attribute. For example:
```mlir
- %0 = "toy.constant"()
- { value = dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64> }
- : () -> tensor<2x3xf64>
+ %0 = toy.constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]>
+ : tensor<2x3xf64>
```
}];
@@ -60,6 +59,10 @@ def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {
// The constant operation returns a single value of TensorType.
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseConstantOp(parser, result); }];
+ let printer = [{ return ::print(p, *this); }];
+
// Add custom build methods for the constant operation. These method populates
// the `state` that MLIR uses to create operations, i.e. these are used when
// using `builder.create<ConstantOp>(...)`.
@@ -89,6 +92,10 @@ def AddOp : Toy_Op<"add",
let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseBinaryOp(parser, result); }];
+ let printer = [{ return ::printBinaryOp(p, *this); }];
+
// Allow building an AddOp with from the two input operands.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value lhs, Value rhs">
@@ -110,6 +117,8 @@ def CastOp : Toy_Op<"cast",
let arguments = (ins F64Tensor:$input);
let results = (outs F64Tensor:$output);
+ let assemblyFormat = "$input attr-dict `:` type($input) `to` type($output)";
+
// Set the folder bit so that we can fold redundant cast operations.
let hasFolder = 1;
}
@@ -124,7 +133,7 @@ def GenericCallOp : Toy_Op<"generic_call",
arguments expected by the callee. For example:
```mlir
- %4 = "toy.generic_call"(%1, %3) {callee = @my_func}
+ %4 = toy.generic_call @my_func(%1, %3)
: (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
```
@@ -139,6 +148,11 @@ def GenericCallOp : Toy_Op<"generic_call",
// The generic call operation returns a single value of TensorType.
let results = (outs F64Tensor);
+ // The return operation only emits the input in the format if it is present.
+ let assemblyFormat = [{
+ $callee `(` $inputs `)` attr-dict `:` functional-type($inputs, results)
+ }];
+
// Add custom build methods for the generic call operation.
let builders = [
OpBuilder<"Builder *builder, OperationState &state, "
@@ -157,6 +171,10 @@ def MulOp : Toy_Op<"mul",
let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseBinaryOp(parser, result); }];
+ let printer = [{ return ::printBinaryOp(p, *this); }];
+
// Allow building a MulOp with from the two input operands.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value lhs, Value rhs">
@@ -172,6 +190,8 @@ def PrintOp : Toy_Op<"print"> {
// The print operation takes an input tensor to print.
let arguments = (ins F64Tensor:$input);
+
+ let assemblyFormat = "$input attr-dict `:` type($input)";
}
def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
@@ -181,15 +201,21 @@ def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
the same number of elements but
diff erent shapes. For example:
```mlir
- %0 = "toy.reshape"(%arg1) : (tensor<10xf64>) -> tensor<5x2xf64>
+ %0 = toy.reshape (%arg1 : tensor<10xf64>) to tensor<5x2xf64>
```
}];
let arguments = (ins F64Tensor:$input);
- let hasCanonicalizer = 1;
// We expect that the reshape operation returns a statically shaped tensor.
let results = (outs StaticShapeTensorOf<[F64]>);
+
+ let assemblyFormat = [{
+ `(` $input `:` type($input) `)` attr-dict `to` type(results)
+ }];
+
+ // Enable registering canonicalization patterns with this operation.
+ let hasCanonicalizer = 1;
}
def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
@@ -212,6 +238,9 @@ def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
// value must match the return type of the enclosing function.
let arguments = (ins Variadic<F64Tensor>:$input);
+ // The return operation only emits the input in the format if it is present.
+ let assemblyFormat = "($input^ `:` type($input))? attr-dict ";
+
// Allow building a ReturnOp with no return operand.
let builders = [OpBuilder<
"Builder *b, OperationState &state", [{ build(b, state, llvm::None); }]
@@ -232,6 +261,12 @@ def TransposeOp : Toy_Op<"transpose",
let arguments = (ins F64Tensor:$input);
let results = (outs F64Tensor);
+
+ let assemblyFormat = [{
+ `(` $input `:` type($input) `)` attr-dict `to` type(results)
+ }];
+
+ // Enable registering canonicalization patterns with this operation.
let hasCanonicalizer = 1;
// Allow building a TransposeOp with from the input operand.
diff --git a/mlir/examples/toy/Ch4/mlir/Dialect.cpp b/mlir/examples/toy/Ch4/mlir/Dialect.cpp
index 8b4e65e6bf9c..9a0a3a6c95a6 100644
--- a/mlir/examples/toy/Ch4/mlir/Dialect.cpp
+++ b/mlir/examples/toy/Ch4/mlir/Dialect.cpp
@@ -14,6 +14,7 @@
#include "toy/Dialect.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/StandardTypes.h"
#include "mlir/Transforms/InliningUtils.h"
@@ -86,6 +87,54 @@ ToyDialect::ToyDialect(mlir::MLIRContext *ctx) : mlir::Dialect("toy", ctx) {
// Toy Operations
//===----------------------------------------------------------------------===//
+/// A generalized parser for binary operations. This parses the
diff erent forms
+/// of 'printBinaryOp' below.
+static mlir::ParseResult parseBinaryOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ SmallVector<mlir::OpAsmParser::OperandType, 2> operands;
+ llvm::SMLoc operandsLoc = parser.getCurrentLocation();
+ Type type;
+ if (parser.parseOperandList(operands, /*requiredOperandCount=*/2) ||
+ parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseColonType(type))
+ return mlir::failure();
+
+ // If the type is a function type, it contains the input and result types of
+ // this operation.
+ if (FunctionType funcType = type.dyn_cast<FunctionType>()) {
+ if (parser.resolveOperands(operands, funcType.getInputs(), operandsLoc,
+ result.operands))
+ return mlir::failure();
+ result.addTypes(funcType.getResults());
+ return mlir::success();
+ }
+
+ // Otherwise, the parsed type is the type of both operands and results.
+ if (parser.resolveOperands(operands, type, result.operands))
+ return mlir::failure();
+ result.addTypes(type);
+ return mlir::success();
+}
+
+/// A generalized printer for binary operations. It prints in two
diff erent
+/// forms depending on if all of the types match.
+static void printBinaryOp(mlir::OpAsmPrinter &printer, mlir::Operation *op) {
+ printer << op->getName() << " " << op->getOperands();
+ printer.printOptionalAttrDict(op->getAttrs());
+ printer << " : ";
+
+ // If all of the types are the same, print the type directly.
+ Type resultType = *op->result_type_begin();
+ if (llvm::all_of(op->getOperandTypes(),
+ [=](Type type) { return type == resultType; })) {
+ printer << resultType;
+ return;
+ }
+
+ // Otherwise, print a functional type.
+ printer.printFunctionalType(op->getOperandTypes(), op->getResultTypes());
+}
+
//===----------------------------------------------------------------------===//
// ConstantOp
@@ -99,6 +148,32 @@ void ConstantOp::build(mlir::Builder *builder, mlir::OperationState &state,
ConstantOp::build(builder, state, dataType, dataAttribute);
}
+/// The 'OpAsmPrinter' class provides a collection of methods for parsing
+/// various punctuation, as well as attributes, operands, types, etc. Each of
+/// these methods returns a `ParseResult`. This class is a wrapper around
+/// `LogicalResult` that can be converted to a boolean `true` value on failure,
+/// or `false` on success. This allows for easily chaining together a set of
+/// parser rules. These rules are used to populate an `mlir::OperationState`
+/// similarly to the `build` methods described above.
+static mlir::ParseResult parseConstantOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ mlir::DenseElementsAttr value;
+ if (parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseAttribute(value, "value", result.attributes))
+ return failure();
+
+ result.addTypes(value.getType());
+ return success();
+}
+
+/// The 'OpAsmPrinter' class is a stream that will allows for formatting
+/// strings, attributes, operands, types, etc.
+static void print(mlir::OpAsmPrinter &printer, ConstantOp op) {
+ printer << "toy.constant ";
+ printer.printOptionalAttrDict(op.getAttrs(), /*elidedAttrs=*/{"value"});
+ printer << op.value();
+}
+
/// Verifier for the constant operation. This corresponds to the `::verify(...)`
/// in the op definition.
static mlir::LogicalResult verify(ConstantOp op) {
diff --git a/mlir/examples/toy/Ch5/include/toy/Ops.td b/mlir/examples/toy/Ch5/include/toy/Ops.td
index d0e5317481df..84fbdb558669 100644
--- a/mlir/examples/toy/Ch5/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch5/include/toy/Ops.td
@@ -48,9 +48,8 @@ def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {
to the operation as an attribute. For example:
```mlir
- %0 = "toy.constant"()
- { value = dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64> }
- : () -> tensor<2x3xf64>
+ %0 = toy.constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]>
+ : tensor<2x3xf64>
```
}];
@@ -60,6 +59,10 @@ def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {
// The constant operation returns a single value of TensorType.
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseConstantOp(parser, result); }];
+ let printer = [{ return ::print(p, *this); }];
+
// Add custom build methods for the constant operation. These method populates
// the `state` that MLIR uses to create operations, i.e. these are used when
// using `builder.create<ConstantOp>(...)`.
@@ -89,6 +92,10 @@ def AddOp : Toy_Op<"add",
let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseBinaryOp(parser, result); }];
+ let printer = [{ return ::printBinaryOp(p, *this); }];
+
// Allow building an AddOp with from the two input operands.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value lhs, Value rhs">
@@ -110,6 +117,8 @@ def CastOp : Toy_Op<"cast",
let arguments = (ins F64Tensor:$input);
let results = (outs F64Tensor:$output);
+ let assemblyFormat = "$input attr-dict `:` type($input) `to` type($output)";
+
// Set the folder bit so that we can fold redundant cast operations.
let hasFolder = 1;
}
@@ -124,7 +133,7 @@ def GenericCallOp : Toy_Op<"generic_call",
arguments expected by the callee. For example:
```mlir
- %4 = "toy.generic_call"(%1, %3) {callee = @my_func}
+ %4 = toy.generic_call @my_func(%1, %3)
: (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
```
@@ -139,6 +148,11 @@ def GenericCallOp : Toy_Op<"generic_call",
// The generic call operation returns a single value of TensorType.
let results = (outs F64Tensor);
+ // The return operation only emits the input in the format if it is present.
+ let assemblyFormat = [{
+ $callee `(` $inputs `)` attr-dict `:` functional-type($inputs, results)
+ }];
+
// Add custom build methods for the generic call operation.
let builders = [
OpBuilder<"Builder *builder, OperationState &state, "
@@ -157,6 +171,10 @@ def MulOp : Toy_Op<"mul",
let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseBinaryOp(parser, result); }];
+ let printer = [{ return ::printBinaryOp(p, *this); }];
+
// Allow building a MulOp with from the two input operands.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value lhs, Value rhs">
@@ -173,6 +191,8 @@ def PrintOp : Toy_Op<"print"> {
// The print operation takes an input tensor to print.
// We also allow a F64MemRef to enable interop during partial lowering.
let arguments = (ins AnyTypeOf<[F64Tensor, F64MemRef]>:$input);
+
+ let assemblyFormat = "$input attr-dict `:` type($input)";
}
def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
@@ -182,15 +202,21 @@ def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
the same number of elements but
diff erent shapes. For example:
```mlir
- %0 = "toy.reshape"(%arg1) : (tensor<10xf64>) -> tensor<5x2xf64>
+ %0 = toy.reshape (%arg1 : tensor<10xf64>) to tensor<5x2xf64>
```
}];
let arguments = (ins F64Tensor:$input);
- let hasCanonicalizer = 1;
// We expect that the reshape operation returns a statically shaped tensor.
let results = (outs StaticShapeTensorOf<[F64]>);
+
+ let assemblyFormat = [{
+ `(` $input `:` type($input) `)` attr-dict `to` type(results)
+ }];
+
+ // Enable registering canonicalization patterns with this operation.
+ let hasCanonicalizer = 1;
}
def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
@@ -213,6 +239,9 @@ def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
// value must match the return type of the enclosing function.
let arguments = (ins Variadic<F64Tensor>:$input);
+ // The return operation only emits the input in the format if it is present.
+ let assemblyFormat = "($input^ `:` type($input))? attr-dict ";
+
// Allow building a ReturnOp with no return operand.
let builders = [OpBuilder<
"Builder *b, OperationState &state", [{ build(b, state, llvm::None); }]
@@ -233,6 +262,12 @@ def TransposeOp : Toy_Op<"transpose",
let arguments = (ins F64Tensor:$input);
let results = (outs F64Tensor);
+
+ let assemblyFormat = [{
+ `(` $input `:` type($input) `)` attr-dict `to` type(results)
+ }];
+
+ // Enable registering canonicalization patterns with this operation.
let hasCanonicalizer = 1;
// Allow building a TransposeOp with from the input operand.
diff --git a/mlir/examples/toy/Ch5/mlir/Dialect.cpp b/mlir/examples/toy/Ch5/mlir/Dialect.cpp
index 8b4e65e6bf9c..9a0a3a6c95a6 100644
--- a/mlir/examples/toy/Ch5/mlir/Dialect.cpp
+++ b/mlir/examples/toy/Ch5/mlir/Dialect.cpp
@@ -14,6 +14,7 @@
#include "toy/Dialect.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/StandardTypes.h"
#include "mlir/Transforms/InliningUtils.h"
@@ -86,6 +87,54 @@ ToyDialect::ToyDialect(mlir::MLIRContext *ctx) : mlir::Dialect("toy", ctx) {
// Toy Operations
//===----------------------------------------------------------------------===//
+/// A generalized parser for binary operations. This parses the
diff erent forms
+/// of 'printBinaryOp' below.
+static mlir::ParseResult parseBinaryOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ SmallVector<mlir::OpAsmParser::OperandType, 2> operands;
+ llvm::SMLoc operandsLoc = parser.getCurrentLocation();
+ Type type;
+ if (parser.parseOperandList(operands, /*requiredOperandCount=*/2) ||
+ parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseColonType(type))
+ return mlir::failure();
+
+ // If the type is a function type, it contains the input and result types of
+ // this operation.
+ if (FunctionType funcType = type.dyn_cast<FunctionType>()) {
+ if (parser.resolveOperands(operands, funcType.getInputs(), operandsLoc,
+ result.operands))
+ return mlir::failure();
+ result.addTypes(funcType.getResults());
+ return mlir::success();
+ }
+
+ // Otherwise, the parsed type is the type of both operands and results.
+ if (parser.resolveOperands(operands, type, result.operands))
+ return mlir::failure();
+ result.addTypes(type);
+ return mlir::success();
+}
+
+/// A generalized printer for binary operations. It prints in two
diff erent
+/// forms depending on if all of the types match.
+static void printBinaryOp(mlir::OpAsmPrinter &printer, mlir::Operation *op) {
+ printer << op->getName() << " " << op->getOperands();
+ printer.printOptionalAttrDict(op->getAttrs());
+ printer << " : ";
+
+ // If all of the types are the same, print the type directly.
+ Type resultType = *op->result_type_begin();
+ if (llvm::all_of(op->getOperandTypes(),
+ [=](Type type) { return type == resultType; })) {
+ printer << resultType;
+ return;
+ }
+
+ // Otherwise, print a functional type.
+ printer.printFunctionalType(op->getOperandTypes(), op->getResultTypes());
+}
+
//===----------------------------------------------------------------------===//
// ConstantOp
@@ -99,6 +148,32 @@ void ConstantOp::build(mlir::Builder *builder, mlir::OperationState &state,
ConstantOp::build(builder, state, dataType, dataAttribute);
}
+/// The 'OpAsmPrinter' class provides a collection of methods for parsing
+/// various punctuation, as well as attributes, operands, types, etc. Each of
+/// these methods returns a `ParseResult`. This class is a wrapper around
+/// `LogicalResult` that can be converted to a boolean `true` value on failure,
+/// or `false` on success. This allows for easily chaining together a set of
+/// parser rules. These rules are used to populate an `mlir::OperationState`
+/// similarly to the `build` methods described above.
+static mlir::ParseResult parseConstantOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ mlir::DenseElementsAttr value;
+ if (parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseAttribute(value, "value", result.attributes))
+ return failure();
+
+ result.addTypes(value.getType());
+ return success();
+}
+
+/// The 'OpAsmPrinter' class is a stream that will allows for formatting
+/// strings, attributes, operands, types, etc.
+static void print(mlir::OpAsmPrinter &printer, ConstantOp op) {
+ printer << "toy.constant ";
+ printer.printOptionalAttrDict(op.getAttrs(), /*elidedAttrs=*/{"value"});
+ printer << op.value();
+}
+
/// Verifier for the constant operation. This corresponds to the `::verify(...)`
/// in the op definition.
static mlir::LogicalResult verify(ConstantOp op) {
diff --git a/mlir/examples/toy/Ch6/include/toy/Ops.td b/mlir/examples/toy/Ch6/include/toy/Ops.td
index d0e5317481df..5b95e0cfb37e 100644
--- a/mlir/examples/toy/Ch6/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch6/include/toy/Ops.td
@@ -48,9 +48,8 @@ def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {
to the operation as an attribute. For example:
```mlir
- %0 = "toy.constant"()
- { value = dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64> }
- : () -> tensor<2x3xf64>
+ %0 = toy.constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]>
+ : tensor<2x3xf64>
```
}];
@@ -60,6 +59,10 @@ def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {
// The constant operation returns a single value of TensorType.
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseConstantOp(parser, result); }];
+ let printer = [{ return ::print(p, *this); }];
+
// Add custom build methods for the constant operation. These method populates
// the `state` that MLIR uses to create operations, i.e. these are used when
// using `builder.create<ConstantOp>(...)`.
@@ -89,6 +92,10 @@ def AddOp : Toy_Op<"add",
let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseBinaryOp(parser, result); }];
+ let printer = [{ return ::printBinaryOp(p, *this); }];
+
// Allow building an AddOp with from the two input operands.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value lhs, Value rhs">
@@ -110,6 +117,8 @@ def CastOp : Toy_Op<"cast",
let arguments = (ins F64Tensor:$input);
let results = (outs F64Tensor:$output);
+ let assemblyFormat = "$input attr-dict `:` type($input) `to` type($output)";
+
// Set the folder bit so that we can fold redundant cast operations.
let hasFolder = 1;
}
@@ -124,7 +133,7 @@ def GenericCallOp : Toy_Op<"generic_call",
arguments expected by the callee. For example:
```mlir
- %4 = "toy.generic_call"(%1, %3) {callee = @my_func}
+ %4 = toy.generic_call @my_func(%1, %3)
: (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
```
@@ -139,6 +148,11 @@ def GenericCallOp : Toy_Op<"generic_call",
// The generic call operation returns a single value of TensorType.
let results = (outs F64Tensor);
+ // The return operation only emits the input in the format if it is present.
+ let assemblyFormat = [{
+ $callee `(` $inputs `)` attr-dict `:` functional-type($inputs, results)
+ }];
+
// Add custom build methods for the generic call operation.
let builders = [
OpBuilder<"Builder *builder, OperationState &state, "
@@ -157,6 +171,10 @@ def MulOp : Toy_Op<"mul",
let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseBinaryOp(parser, result); }];
+ let printer = [{ return ::printBinaryOp(p, *this); }];
+
// Allow building a MulOp with from the two input operands.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value lhs, Value rhs">
@@ -173,6 +191,8 @@ def PrintOp : Toy_Op<"print"> {
// The print operation takes an input tensor to print.
// We also allow a F64MemRef to enable interop during partial lowering.
let arguments = (ins AnyTypeOf<[F64Tensor, F64MemRef]>:$input);
+
+ let assemblyFormat = "$input attr-dict `:` type($input)";
}
def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
@@ -182,11 +202,17 @@ def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
the same number of elements but
diff erent shapes. For example:
```mlir
- %0 = "toy.reshape"(%arg1) : (tensor<10xf64>) -> tensor<5x2xf64>
+ %0 = toy.reshape (%arg1 : tensor<10xf64>) to tensor<5x2xf64>
```
}];
let arguments = (ins F64Tensor:$input);
+
+ let assemblyFormat = [{
+ `(` $input `:` type($input) `)` attr-dict `to` type(results)
+ }];
+
+ // Enable registering canonicalization patterns with this operation.
let hasCanonicalizer = 1;
// We expect that the reshape operation returns a statically shaped tensor.
@@ -213,6 +239,9 @@ def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
// value must match the return type of the enclosing function.
let arguments = (ins Variadic<F64Tensor>:$input);
+ // The return operation only emits the input in the format if it is present.
+ let assemblyFormat = "($input^ `:` type($input))? attr-dict ";
+
// Allow building a ReturnOp with no return operand.
let builders = [OpBuilder<
"Builder *b, OperationState &state", [{ build(b, state, llvm::None); }]
@@ -233,6 +262,12 @@ def TransposeOp : Toy_Op<"transpose",
let arguments = (ins F64Tensor:$input);
let results = (outs F64Tensor);
+
+ let assemblyFormat = [{
+ `(` $input `:` type($input) `)` attr-dict `to` type(results)
+ }];
+
+ // Enable registering canonicalization patterns with this operation.
let hasCanonicalizer = 1;
// Allow building a TransposeOp with from the input operand.
diff --git a/mlir/examples/toy/Ch6/mlir/Dialect.cpp b/mlir/examples/toy/Ch6/mlir/Dialect.cpp
index 8b4e65e6bf9c..9a0a3a6c95a6 100644
--- a/mlir/examples/toy/Ch6/mlir/Dialect.cpp
+++ b/mlir/examples/toy/Ch6/mlir/Dialect.cpp
@@ -14,6 +14,7 @@
#include "toy/Dialect.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/StandardTypes.h"
#include "mlir/Transforms/InliningUtils.h"
@@ -86,6 +87,54 @@ ToyDialect::ToyDialect(mlir::MLIRContext *ctx) : mlir::Dialect("toy", ctx) {
// Toy Operations
//===----------------------------------------------------------------------===//
+/// A generalized parser for binary operations. This parses the
diff erent forms
+/// of 'printBinaryOp' below.
+static mlir::ParseResult parseBinaryOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ SmallVector<mlir::OpAsmParser::OperandType, 2> operands;
+ llvm::SMLoc operandsLoc = parser.getCurrentLocation();
+ Type type;
+ if (parser.parseOperandList(operands, /*requiredOperandCount=*/2) ||
+ parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseColonType(type))
+ return mlir::failure();
+
+ // If the type is a function type, it contains the input and result types of
+ // this operation.
+ if (FunctionType funcType = type.dyn_cast<FunctionType>()) {
+ if (parser.resolveOperands(operands, funcType.getInputs(), operandsLoc,
+ result.operands))
+ return mlir::failure();
+ result.addTypes(funcType.getResults());
+ return mlir::success();
+ }
+
+ // Otherwise, the parsed type is the type of both operands and results.
+ if (parser.resolveOperands(operands, type, result.operands))
+ return mlir::failure();
+ result.addTypes(type);
+ return mlir::success();
+}
+
+/// A generalized printer for binary operations. It prints in two
diff erent
+/// forms depending on if all of the types match.
+static void printBinaryOp(mlir::OpAsmPrinter &printer, mlir::Operation *op) {
+ printer << op->getName() << " " << op->getOperands();
+ printer.printOptionalAttrDict(op->getAttrs());
+ printer << " : ";
+
+ // If all of the types are the same, print the type directly.
+ Type resultType = *op->result_type_begin();
+ if (llvm::all_of(op->getOperandTypes(),
+ [=](Type type) { return type == resultType; })) {
+ printer << resultType;
+ return;
+ }
+
+ // Otherwise, print a functional type.
+ printer.printFunctionalType(op->getOperandTypes(), op->getResultTypes());
+}
+
//===----------------------------------------------------------------------===//
// ConstantOp
@@ -99,6 +148,32 @@ void ConstantOp::build(mlir::Builder *builder, mlir::OperationState &state,
ConstantOp::build(builder, state, dataType, dataAttribute);
}
+/// The 'OpAsmPrinter' class provides a collection of methods for parsing
+/// various punctuation, as well as attributes, operands, types, etc. Each of
+/// these methods returns a `ParseResult`. This class is a wrapper around
+/// `LogicalResult` that can be converted to a boolean `true` value on failure,
+/// or `false` on success. This allows for easily chaining together a set of
+/// parser rules. These rules are used to populate an `mlir::OperationState`
+/// similarly to the `build` methods described above.
+static mlir::ParseResult parseConstantOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ mlir::DenseElementsAttr value;
+ if (parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseAttribute(value, "value", result.attributes))
+ return failure();
+
+ result.addTypes(value.getType());
+ return success();
+}
+
+/// The 'OpAsmPrinter' class is a stream that will allows for formatting
+/// strings, attributes, operands, types, etc.
+static void print(mlir::OpAsmPrinter &printer, ConstantOp op) {
+ printer << "toy.constant ";
+ printer.printOptionalAttrDict(op.getAttrs(), /*elidedAttrs=*/{"value"});
+ printer << op.value();
+}
+
/// Verifier for the constant operation. This corresponds to the `::verify(...)`
/// in the op definition.
static mlir::LogicalResult verify(ConstantOp op) {
diff --git a/mlir/examples/toy/Ch7/include/toy/Ops.td b/mlir/examples/toy/Ch7/include/toy/Ops.td
index e49b5039b534..d2d369d5fccb 100644
--- a/mlir/examples/toy/Ch7/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch7/include/toy/Ops.td
@@ -57,9 +57,8 @@ def ConstantOp : Toy_Op<"constant",
to the operation as an attribute. For example:
```mlir
- %0 = "toy.constant"()
- { value = dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64> }
- : () -> tensor<2x3xf64>
+ %0 = toy.constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]>
+ : tensor<2x3xf64>
```
}];
@@ -69,6 +68,10 @@ def ConstantOp : Toy_Op<"constant",
// The constant operation returns a single value of TensorType.
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseConstantOp(parser, result); }];
+ let printer = [{ return ::print(p, *this); }];
+
// Add custom build methods for the constant operation. These method populates
// the `state` that MLIR uses to create operations, i.e. these are used when
// using `builder.create<ConstantOp>(...)`.
@@ -101,6 +104,10 @@ def AddOp : Toy_Op<"add",
let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseBinaryOp(parser, result); }];
+ let printer = [{ return ::printBinaryOp(p, *this); }];
+
// Allow building an AddOp with from the two input operands.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value lhs, Value rhs">
@@ -122,6 +129,8 @@ def CastOp : Toy_Op<"cast",
let arguments = (ins F64Tensor:$input);
let results = (outs F64Tensor:$output);
+ let assemblyFormat = "$input attr-dict `:` type($input) `to` type($output)";
+
// Set the folder bit so that we can fold redundant cast operations.
let hasFolder = 1;
}
@@ -136,7 +145,7 @@ def GenericCallOp : Toy_Op<"generic_call",
arguments expected by the callee. For example:
```mlir
- %4 = "toy.generic_call"(%1, %3) {callee = @my_func}
+ %4 = toy.generic_call @my_func(%1, %3)
: (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
```
@@ -152,6 +161,11 @@ def GenericCallOp : Toy_Op<"generic_call",
// StructType.
let results = (outs Toy_Type);
+ // The return operation only emits the input in the format if it is present.
+ let assemblyFormat = [{
+ $callee `(` $inputs `)` attr-dict `:` functional-type($inputs, results)
+ }];
+
// Add custom build methods for the generic call operation.
let builders = [
OpBuilder<"Builder *builder, OperationState &state, "
@@ -170,6 +184,10 @@ def MulOp : Toy_Op<"mul",
let arguments = (ins F64Tensor:$lhs, F64Tensor:$rhs);
let results = (outs F64Tensor);
+ // Specify a parser and printer method.
+ let parser = [{ return ::parseBinaryOp(parser, result); }];
+ let printer = [{ return ::printBinaryOp(p, *this); }];
+
// Allow building a MulOp with from the two input operands.
let builders = [
OpBuilder<"Builder *b, OperationState &state, Value lhs, Value rhs">
@@ -186,6 +204,8 @@ def PrintOp : Toy_Op<"print"> {
// The print operation takes an input tensor to print.
// We also allow a F64MemRef to enable interop during partial lowering.
let arguments = (ins AnyTypeOf<[F64Tensor, F64MemRef]>:$input);
+
+ let assemblyFormat = "$input attr-dict `:` type($input)";
}
def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
@@ -195,11 +215,17 @@ def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
the same number of elements but
diff erent shapes. For example:
```mlir
- %0 = "toy.reshape"(%arg1) : (tensor<10xf64>) -> tensor<5x2xf64>
+ %0 = toy.reshape (%arg1 : tensor<10xf64>) to tensor<5x2xf64>
```
}];
let arguments = (ins F64Tensor:$input);
+
+ let assemblyFormat = [{
+ `(` $input `:` type($input) `)` attr-dict `to` type(results)
+ }];
+
+ // Enable registering canonicalization patterns with this operation.
let hasCanonicalizer = 1;
// We expect that the reshape operation returns a statically shaped tensor.
@@ -226,6 +252,9 @@ def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
// value must match the return type of the enclosing function.
let arguments = (ins Variadic<Toy_Type>:$input);
+ // The return operation only emits the input in the format if it is present.
+ let assemblyFormat = "($input^ `:` type($input))? attr-dict ";
+
// Allow building a ReturnOp with no return operand.
let builders = [OpBuilder<
"Builder *b, OperationState &state", [{ build(b, state, llvm::None); }]
@@ -247,7 +276,11 @@ def StructAccessOp : Toy_Op<"struct_access", [NoSideEffect]> {
}];
let arguments = (ins Toy_StructType:$input, I64Attr:$index);
- let results = (outs Toy_Type);
+ let results = (outs Toy_Type:$output);
+
+ let assemblyFormat = [{
+ $input `[` $index `]` attr-dict `:` type($input) `->` type($output)
+ }];
// Allow building a StructAccessOp with just a struct value and an index.
let builders = [
@@ -268,16 +301,19 @@ def StructConstantOp : Toy_Op<"struct_constant", [NoSideEffect]> {
as an array of other constant values. For example:
```mlir
- %0 = "toy.struct_constant"() {
- value = [dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64>]
- } : () -> !toy.struct<tensor<*xf64>>
+ %0 = toy.struct_constant [
+ dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf64>
+ ] : !toy.struct<tensor<*xf64>>
```
}];
- let hasFolder = 1;
let arguments = (ins ArrayAttr:$value);
- let results = (outs Toy_StructType);
+ let results = (outs Toy_StructType:$output);
+
+ let assemblyFormat = "$value attr-dict `:` type($output)";
+
let verifier = [{ return ::verify(*this); }];
+ let hasFolder = 1;
}
def TransposeOp : Toy_Op<"transpose",
@@ -286,6 +322,12 @@ def TransposeOp : Toy_Op<"transpose",
let arguments = (ins F64Tensor:$input);
let results = (outs F64Tensor);
+
+ let assemblyFormat = [{
+ `(` $input `:` type($input) `)` attr-dict `to` type(results)
+ }];
+
+ // Enable registering canonicalization patterns with this operation.
let hasCanonicalizer = 1;
// Allow building a TransposeOp with from the input operand.
diff --git a/mlir/examples/toy/Ch7/mlir/Dialect.cpp b/mlir/examples/toy/Ch7/mlir/Dialect.cpp
index 0b4510ecec3b..dc66cebd0e5e 100644
--- a/mlir/examples/toy/Ch7/mlir/Dialect.cpp
+++ b/mlir/examples/toy/Ch7/mlir/Dialect.cpp
@@ -15,6 +15,7 @@
#include "mlir/IR/Builders.h"
#include "mlir/IR/DialectImplementation.h"
+#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/StandardTypes.h"
#include "mlir/Transforms/InliningUtils.h"
@@ -99,6 +100,54 @@ mlir::Operation *ToyDialect::materializeConstant(mlir::OpBuilder &builder,
// Toy Operations
//===----------------------------------------------------------------------===//
+/// A generalized parser for binary operations. This parses the
diff erent forms
+/// of 'printBinaryOp' below.
+static mlir::ParseResult parseBinaryOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ SmallVector<mlir::OpAsmParser::OperandType, 2> operands;
+ llvm::SMLoc operandsLoc = parser.getCurrentLocation();
+ Type type;
+ if (parser.parseOperandList(operands, /*requiredOperandCount=*/2) ||
+ parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseColonType(type))
+ return mlir::failure();
+
+ // If the type is a function type, it contains the input and result types of
+ // this operation.
+ if (FunctionType funcType = type.dyn_cast<FunctionType>()) {
+ if (parser.resolveOperands(operands, funcType.getInputs(), operandsLoc,
+ result.operands))
+ return mlir::failure();
+ result.addTypes(funcType.getResults());
+ return mlir::success();
+ }
+
+ // Otherwise, the parsed type is the type of both operands and results.
+ if (parser.resolveOperands(operands, type, result.operands))
+ return mlir::failure();
+ result.addTypes(type);
+ return mlir::success();
+}
+
+/// A generalized printer for binary operations. It prints in two
diff erent
+/// forms depending on if all of the types match.
+static void printBinaryOp(mlir::OpAsmPrinter &printer, mlir::Operation *op) {
+ printer << op->getName() << " " << op->getOperands();
+ printer.printOptionalAttrDict(op->getAttrs());
+ printer << " : ";
+
+ // If all of the types are the same, print the type directly.
+ Type resultType = *op->result_type_begin();
+ if (llvm::all_of(op->getOperandTypes(),
+ [=](Type type) { return type == resultType; })) {
+ printer << resultType;
+ return;
+ }
+
+ // Otherwise, print a functional type.
+ printer.printFunctionalType(op->getOperandTypes(), op->getResultTypes());
+}
+
//===----------------------------------------------------------------------===//
// ConstantOp
@@ -112,6 +161,32 @@ void ConstantOp::build(mlir::Builder *builder, mlir::OperationState &state,
ConstantOp::build(builder, state, dataType, dataAttribute);
}
+/// The 'OpAsmPrinter' class provides a collection of methods for parsing
+/// various punctuation, as well as attributes, operands, types, etc. Each of
+/// these methods returns a `ParseResult`. This class is a wrapper around
+/// `LogicalResult` that can be converted to a boolean `true` value on failure,
+/// or `false` on success. This allows for easily chaining together a set of
+/// parser rules. These rules are used to populate an `mlir::OperationState`
+/// similarly to the `build` methods described above.
+static mlir::ParseResult parseConstantOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ mlir::DenseElementsAttr value;
+ if (parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseAttribute(value, "value", result.attributes))
+ return failure();
+
+ result.addTypes(value.getType());
+ return success();
+}
+
+/// The 'OpAsmPrinter' class is a stream that will allows for formatting
+/// strings, attributes, operands, types, etc.
+static void print(mlir::OpAsmPrinter &printer, ConstantOp op) {
+ printer << "toy.constant ";
+ printer.printOptionalAttrDict(op.getAttrs(), /*elidedAttrs=*/{"value"});
+ printer << op.value();
+}
+
/// Verify that the given attribute value is valid for the given type.
static mlir::LogicalResult verifyConstantForType(mlir::Type type,
mlir::Attribute opaqueValue,
diff --git a/mlir/test/Examples/Toy/Ch2/codegen.toy b/mlir/test/Examples/Toy/Ch2/codegen.toy
index e4f20aa2a47f..ea1708e6fee1 100644
--- a/mlir/test/Examples/Toy/Ch2/codegen.toy
+++ b/mlir/test/Examples/Toy/Ch2/codegen.toy
@@ -15,17 +15,17 @@ def main() {
# CHECK-LABEL: func @multiply_transpose(
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>, [[VAL_1:%.*]]: tensor<*xf64>) -> tensor<*xf64>
-# CHECK: [[VAL_2:%.*]] = "toy.transpose"([[VAL_0]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_3:%.*]] = "toy.transpose"([[VAL_1]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_4:%.*]] = "toy.mul"([[VAL_2]], [[VAL_3]]) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.return"([[VAL_4]]) : (tensor<*xf64>) -> ()
+# CHECK: [[VAL_2:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_3:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_4:%.*]] = toy.mul [[VAL_2]], [[VAL_3]] : tensor<*xf64>
+# CHECK-NEXT: toy.return [[VAL_4]] : tensor<*xf64>
# CHECK-LABEL: func @main()
-# CHECK-NEXT: [[VAL_5:%.*]] = "toy.constant"() {value = dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_6:%.*]] = "toy.reshape"([[VAL_5]]) : (tensor<2x3xf64>) -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_7:%.*]] = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64>
-# CHECK-NEXT: [[VAL_8:%.*]] = "toy.reshape"([[VAL_7]]) : (tensor<6xf64>) -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_9:%.*]] = "toy.generic_call"([[VAL_6]], [[VAL_8]]) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_10:%.*]] = "toy.generic_call"([[VAL_8]], [[VAL_6]]) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.print"([[VAL_10]]) : (tensor<*xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: [[VAL_5:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_6:%.*]] = toy.reshape([[VAL_5]] : tensor<2x3xf64>) to tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_7:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>
+# CHECK-NEXT: [[VAL_8:%.*]] = toy.reshape([[VAL_7]] : tensor<6xf64>) to tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_9:%.*]] = toy.generic_call @multiply_transpose([[VAL_6]], [[VAL_8]]) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+# CHECK-NEXT: [[VAL_10:%.*]] = toy.generic_call @multiply_transpose([[VAL_8]], [[VAL_6]]) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+# CHECK-NEXT: toy.print [[VAL_10]] : tensor<*xf64>
+# CHECK-NEXT: toy.return
diff --git a/mlir/test/Examples/Toy/Ch2/scalar.toy b/mlir/test/Examples/Toy/Ch2/scalar.toy
index 0671f0501295..2d9cf2d62b81 100644
--- a/mlir/test/Examples/Toy/Ch2/scalar.toy
+++ b/mlir/test/Examples/Toy/Ch2/scalar.toy
@@ -6,9 +6,9 @@ def main() {
}
# CHECK-LABEL: func @main() {
-# CHECK-NEXT: %0 = "toy.constant"() {value = dense<5.500000e+00> : tensor<f64>} : () -> tensor<f64>
-# CHECK-NEXT: %1 = "toy.reshape"(%0) : (tensor<f64>) -> tensor<2x2xf64>
-# CHECK-NEXT: "toy.print"(%1) : (tensor<2x2xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: %0 = toy.constant dense<5.500000e+00> : tensor<f64>
+# CHECK-NEXT: %1 = toy.reshape(%0 : tensor<f64>) to tensor<2x2xf64>
+# CHECK-NEXT: toy.print %1 : tensor<2x2xf64>
+# CHECK-NEXT: toy.return
# CHECK-NEXT: }
diff --git a/mlir/test/Examples/Toy/Ch3/codegen.toy b/mlir/test/Examples/Toy/Ch3/codegen.toy
index cc9fdd4798a6..4ab63e948076 100644
--- a/mlir/test/Examples/Toy/Ch3/codegen.toy
+++ b/mlir/test/Examples/Toy/Ch3/codegen.toy
@@ -15,17 +15,17 @@ def main() {
# CHECK-LABEL: func @multiply_transpose(
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>, [[VAL_1:%.*]]: tensor<*xf64>) -> tensor<*xf64>
-# CHECK: [[VAL_2:%.*]] = "toy.transpose"([[VAL_0]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_3:%.*]] = "toy.transpose"([[VAL_1]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_4:%.*]] = "toy.mul"([[VAL_2]], [[VAL_3]]) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.return"([[VAL_4]]) : (tensor<*xf64>) -> ()
+# CHECK: [[VAL_2:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_3:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_4:%.*]] = toy.mul [[VAL_2]], [[VAL_3]] : tensor<*xf64>
+# CHECK-NEXT: toy.return [[VAL_4]] : tensor<*xf64>
# CHECK-LABEL: func @main()
-# CHECK-NEXT: [[VAL_5:%.*]] = "toy.constant"() {value = dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_6:%.*]] = "toy.reshape"([[VAL_5]]) : (tensor<2x3xf64>) -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_7:%.*]] = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64>
-# CHECK-NEXT: [[VAL_8:%.*]] = "toy.reshape"([[VAL_7]]) : (tensor<6xf64>) -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_9:%.*]] = "toy.generic_call"([[VAL_6]], [[VAL_8]]) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_10:%.*]] = "toy.generic_call"([[VAL_8]], [[VAL_6]]) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.print"([[VAL_10]]) : (tensor<*xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: [[VAL_5:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_6:%.*]] = toy.reshape([[VAL_5]] : tensor<2x3xf64>) to tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_7:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>
+# CHECK-NEXT: [[VAL_8:%.*]] = toy.reshape([[VAL_7]] : tensor<6xf64>) to tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_9:%.*]] = toy.generic_call @multiply_transpose([[VAL_6]], [[VAL_8]]) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+# CHECK-NEXT: [[VAL_10:%.*]] = toy.generic_call @multiply_transpose([[VAL_8]], [[VAL_6]]) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+# CHECK-NEXT: toy.print [[VAL_10]] : tensor<*xf64>
+# CHECK-NEXT: toy.return
diff --git a/mlir/test/Examples/Toy/Ch3/scalar.toy b/mlir/test/Examples/Toy/Ch3/scalar.toy
index dd7ec935e88b..1941806b16a4 100644
--- a/mlir/test/Examples/Toy/Ch3/scalar.toy
+++ b/mlir/test/Examples/Toy/Ch3/scalar.toy
@@ -6,9 +6,9 @@ def main() {
}
# CHECK-LABEL: func @main() {
-# CHECK-NEXT: %0 = "toy.constant"() {value = dense<5.500000e+00> : tensor<f64>} : () -> tensor<f64>
-# CHECK-NEXT: %1 = "toy.reshape"(%0) : (tensor<f64>) -> tensor<2x2xf64>
-# CHECK-NEXT: "toy.print"(%1) : (tensor<2x2xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: %0 = toy.constant dense<5.500000e+00> : tensor<f64>
+# CHECK-NEXT: %1 = toy.reshape(%0 : tensor<f64>) to tensor<2x2xf64>
+# CHECK-NEXT: toy.print %1 : tensor<2x2xf64>
+# CHECK-NEXT: toy.return
# CHECK-NEXT: }
diff --git a/mlir/test/Examples/Toy/Ch4/codegen.toy b/mlir/test/Examples/Toy/Ch4/codegen.toy
index 94ecbae38e89..785817f5c877 100644
--- a/mlir/test/Examples/Toy/Ch4/codegen.toy
+++ b/mlir/test/Examples/Toy/Ch4/codegen.toy
@@ -15,17 +15,17 @@ def main() {
# CHECK-LABEL: func @multiply_transpose(
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>, [[VAL_1:%.*]]: tensor<*xf64>) -> tensor<*xf64>
-# CHECK: [[VAL_2:%.*]] = "toy.transpose"([[VAL_0]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_3:%.*]] = "toy.transpose"([[VAL_1]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_4:%.*]] = "toy.mul"([[VAL_2]], [[VAL_3]]) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.return"([[VAL_4]]) : (tensor<*xf64>) -> ()
+# CHECK: [[VAL_2:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_3:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_4:%.*]] = toy.mul [[VAL_2]], [[VAL_3]] : tensor<*xf64>
+# CHECK-NEXT: toy.return [[VAL_4]] : tensor<*xf64>
# CHECK-LABEL: func @main()
-# CHECK-NEXT: [[VAL_5:%.*]] = "toy.constant"() {value = dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_6:%.*]] = "toy.reshape"([[VAL_5]]) : (tensor<2x3xf64>) -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_7:%.*]] = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64>
-# CHECK-NEXT: [[VAL_8:%.*]] = "toy.reshape"([[VAL_7]]) : (tensor<6xf64>) -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_9:%.*]] = "toy.generic_call"([[VAL_6]], [[VAL_8]]) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_10:%.*]] = "toy.generic_call"([[VAL_8]], [[VAL_6]]) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.print"([[VAL_10]]) : (tensor<*xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: [[VAL_5:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_6:%.*]] = toy.reshape([[VAL_5]] : tensor<2x3xf64>) to tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_7:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>
+# CHECK-NEXT: [[VAL_8:%.*]] = toy.reshape([[VAL_7]] : tensor<6xf64>) to tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_9:%.*]] = toy.generic_call @multiply_transpose([[VAL_6]], [[VAL_8]]) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+# CHECK-NEXT: [[VAL_10:%.*]] = toy.generic_call @multiply_transpose([[VAL_8]], [[VAL_6]]) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+# CHECK-NEXT: toy.print [[VAL_10]] : tensor<*xf64>
+# CHECK-NEXT: toy.return
diff --git a/mlir/test/Examples/Toy/Ch4/scalar.toy b/mlir/test/Examples/Toy/Ch4/scalar.toy
index 032b3b02b9d9..b39dd18a4b53 100644
--- a/mlir/test/Examples/Toy/Ch4/scalar.toy
+++ b/mlir/test/Examples/Toy/Ch4/scalar.toy
@@ -6,9 +6,9 @@ def main() {
}
# CHECK-LABEL: func @main() {
-# CHECK-NEXT: %0 = "toy.constant"() {value = dense<5.500000e+00> : tensor<f64>} : () -> tensor<f64>
-# CHECK-NEXT: %1 = "toy.reshape"(%0) : (tensor<f64>) -> tensor<2x2xf64>
-# CHECK-NEXT: "toy.print"(%1) : (tensor<2x2xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: %0 = toy.constant dense<5.500000e+00> : tensor<f64>
+# CHECK-NEXT: %1 = toy.reshape(%0 : tensor<f64>) to tensor<2x2xf64>
+# CHECK-NEXT: toy.print %1 : tensor<2x2xf64>
+# CHECK-NEXT: toy.return
# CHECK-NEXT: }
diff --git a/mlir/test/Examples/Toy/Ch4/shape_inference.mlir b/mlir/test/Examples/Toy/Ch4/shape_inference.mlir
index c5d38f3a44f7..7c7f2513b96d 100644
--- a/mlir/test/Examples/Toy/Ch4/shape_inference.mlir
+++ b/mlir/test/Examples/Toy/Ch4/shape_inference.mlir
@@ -4,28 +4,28 @@
func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64>
attributes { sym_visibility = "private" } {
- %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64>
- %1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64>
- %2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
- "toy.return"(%2) : (tensor<*xf64>) -> ()
+ %0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64>
+ %1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64>
+ %2 = toy.mul %0, %1 : tensor<*xf64>
+ toy.return %2 : tensor<*xf64>
}
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %1 = "toy.reshape"(%0) : (tensor<2x3xf64>) -> tensor<2x3xf64>
- %2 = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64>
- %3 = "toy.reshape"(%2) : (tensor<6xf64>) -> tensor<2x3xf64>
- %4 = "toy.generic_call"(%1, %3) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
- %5 = "toy.generic_call"(%3, %1) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
- "toy.print"(%5) : (tensor<*xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %1 = toy.reshape(%0 : tensor<2x3xf64>) to tensor<2x3xf64>
+ %2 = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>
+ %3 = toy.reshape(%2 : tensor<6xf64>) to tensor<2x3xf64>
+ %4 = toy.generic_call @multiply_transpose(%1, %3) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+ %5 = toy.generic_call @multiply_transpose(%3, %1) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+ toy.print %5 : tensor<*xf64>
+ toy.return
}
// CHECK-NOT: func @multiply_transpose
// CHECK-NOT: tensor<*xf64>
// CHECK-LABEL: func @main()
-// CHECK: [[VAL_0:%.*]] = "toy.constant"() {value = dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
-// CHECK: [[VAL_1:%.*]] = "toy.transpose"([[VAL_0]]) : (tensor<2x3xf64>) -> tensor<3x2xf64>
-// CHECK: [[VAL_2:%.*]] = "toy.mul"([[VAL_1]], [[VAL_1]]) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
-// CHECK: "toy.print"([[VAL_2]]) : (tensor<3x2xf64>) -> ()
-// CHECK: "toy.return"() : () -> ()
+// CHECK: [[VAL_0:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+// CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<2x3xf64>) to tensor<3x2xf64>
+// CHECK: [[VAL_2:%.*]] = toy.mul [[VAL_1]], [[VAL_1]] : tensor<3x2xf64>
+// CHECK: toy.print [[VAL_2]] : tensor<3x2xf64>
+// CHECK: toy.return
diff --git a/mlir/test/Examples/Toy/Ch5/affine-lowering.mlir b/mlir/test/Examples/Toy/Ch5/affine-lowering.mlir
index 07bbc22ab6ec..62fcc880e6d6 100644
--- a/mlir/test/Examples/Toy/Ch5/affine-lowering.mlir
+++ b/mlir/test/Examples/Toy/Ch5/affine-lowering.mlir
@@ -2,11 +2,11 @@
// RUN: toyc-ch5 %s -emit=mlir-affine -opt 2>&1 | FileCheck %s --check-prefix=OPT
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %2 = "toy.transpose"(%0) : (tensor<2x3xf64>) -> tensor<3x2xf64>
- %3 = "toy.mul"(%2, %2) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
- "toy.print"(%3) : (tensor<3x2xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %2 = toy.transpose(%0 : tensor<2x3xf64>) to tensor<3x2xf64>
+ %3 = toy.mul %2, %2 : tensor<3x2xf64>
+ toy.print %3 : tensor<3x2xf64>
+ toy.return
}
// CHECK-LABEL: func @main()
@@ -35,7 +35,7 @@ func @main() {
// CHECK: [[VAL_15:%.*]] = affine.load [[VAL_7]]{{\[}}[[VAL_12]], [[VAL_13]]] : memref<3x2xf64>
// CHECK: [[VAL_16:%.*]] = mulf [[VAL_14]], [[VAL_15]] : f64
// CHECK: affine.store [[VAL_16]], [[VAL_6]]{{\[}}[[VAL_12]], [[VAL_13]]] : memref<3x2xf64>
-// CHECK: "toy.print"([[VAL_6]]) : (memref<3x2xf64>) -> ()
+// CHECK: toy.print [[VAL_6]] : memref<3x2xf64>
// CHECK: dealloc [[VAL_8]] : memref<2x3xf64>
// CHECK: dealloc [[VAL_7]] : memref<3x2xf64>
// CHECK: dealloc [[VAL_6]] : memref<3x2xf64>
@@ -60,6 +60,6 @@ func @main() {
// OPT: [[VAL_10:%.*]] = affine.load [[VAL_7]]{{\[}}[[VAL_9]], [[VAL_8]]] : memref<2x3xf64>
// OPT: [[VAL_11:%.*]] = mulf [[VAL_10]], [[VAL_10]] : f64
// OPT: affine.store [[VAL_11]], [[VAL_6]]{{\[}}[[VAL_8]], [[VAL_9]]] : memref<3x2xf64>
-// OPT: "toy.print"([[VAL_6]]) : (memref<3x2xf64>) -> ()
+// OPT: toy.print [[VAL_6]] : memref<3x2xf64>
// OPT: dealloc [[VAL_7]] : memref<2x3xf64>
// OPT: dealloc [[VAL_6]] : memref<3x2xf64>
diff --git a/mlir/test/Examples/Toy/Ch5/codegen.toy b/mlir/test/Examples/Toy/Ch5/codegen.toy
index 8719ce4f4301..2083a6abb1c7 100644
--- a/mlir/test/Examples/Toy/Ch5/codegen.toy
+++ b/mlir/test/Examples/Toy/Ch5/codegen.toy
@@ -15,17 +15,17 @@ def main() {
# CHECK-LABEL: func @multiply_transpose(
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>, [[VAL_1:%.*]]: tensor<*xf64>) -> tensor<*xf64>
-# CHECK: [[VAL_2:%.*]] = "toy.transpose"([[VAL_0]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_3:%.*]] = "toy.transpose"([[VAL_1]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_4:%.*]] = "toy.mul"([[VAL_2]], [[VAL_3]]) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.return"([[VAL_4]]) : (tensor<*xf64>) -> ()
+# CHECK: [[VAL_2:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_3:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_4:%.*]] = toy.mul [[VAL_2]], [[VAL_3]] : tensor<*xf64>
+# CHECK-NEXT: toy.return [[VAL_4]] : tensor<*xf64>
# CHECK-LABEL: func @main()
-# CHECK-NEXT: [[VAL_5:%.*]] = "toy.constant"() {value = dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_6:%.*]] = "toy.reshape"([[VAL_5]]) : (tensor<2x3xf64>) -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_7:%.*]] = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64>
-# CHECK-NEXT: [[VAL_8:%.*]] = "toy.reshape"([[VAL_7]]) : (tensor<6xf64>) -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_9:%.*]] = "toy.generic_call"([[VAL_6]], [[VAL_8]]) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_10:%.*]] = "toy.generic_call"([[VAL_8]], [[VAL_6]]) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.print"([[VAL_10]]) : (tensor<*xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: [[VAL_5:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_6:%.*]] = toy.reshape([[VAL_5]] : tensor<2x3xf64>) to tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_7:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>
+# CHECK-NEXT: [[VAL_8:%.*]] = toy.reshape([[VAL_7]] : tensor<6xf64>) to tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_9:%.*]] = toy.generic_call @multiply_transpose([[VAL_6]], [[VAL_8]]) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+# CHECK-NEXT: [[VAL_10:%.*]] = toy.generic_call @multiply_transpose([[VAL_8]], [[VAL_6]]) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+# CHECK-NEXT: toy.print [[VAL_10]] : tensor<*xf64>
+# CHECK-NEXT: toy.return
diff --git a/mlir/test/Examples/Toy/Ch5/scalar.toy b/mlir/test/Examples/Toy/Ch5/scalar.toy
index 2743b5a3ac94..b8f53849a354 100644
--- a/mlir/test/Examples/Toy/Ch5/scalar.toy
+++ b/mlir/test/Examples/Toy/Ch5/scalar.toy
@@ -6,9 +6,9 @@ def main() {
}
# CHECK-LABEL: func @main() {
-# CHECK-NEXT: %0 = "toy.constant"() {value = dense<5.500000e+00> : tensor<f64>} : () -> tensor<f64>
-# CHECK-NEXT: %1 = "toy.reshape"(%0) : (tensor<f64>) -> tensor<2x2xf64>
-# CHECK-NEXT: "toy.print"(%1) : (tensor<2x2xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: %0 = toy.constant dense<5.500000e+00> : tensor<f64>
+# CHECK-NEXT: %1 = toy.reshape(%0 : tensor<f64>) to tensor<2x2xf64>
+# CHECK-NEXT: toy.print %1 : tensor<2x2xf64>
+# CHECK-NEXT: toy.return
# CHECK-NEXT: }
diff --git a/mlir/test/Examples/Toy/Ch5/shape_inference.mlir b/mlir/test/Examples/Toy/Ch5/shape_inference.mlir
index 89b427135296..37d9249281c9 100644
--- a/mlir/test/Examples/Toy/Ch5/shape_inference.mlir
+++ b/mlir/test/Examples/Toy/Ch5/shape_inference.mlir
@@ -4,28 +4,28 @@
func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64>
attributes { sym_visibility = "private" } {
- %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64>
- %1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64>
- %2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
- "toy.return"(%2) : (tensor<*xf64>) -> ()
+ %0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64>
+ %1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64>
+ %2 = toy.mul %0, %1 : tensor<*xf64>
+ toy.return %2 : tensor<*xf64>
}
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %1 = "toy.reshape"(%0) : (tensor<2x3xf64>) -> tensor<2x3xf64>
- %2 = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64>
- %3 = "toy.reshape"(%2) : (tensor<6xf64>) -> tensor<2x3xf64>
- %4 = "toy.generic_call"(%1, %3) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
- %5 = "toy.generic_call"(%3, %1) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
- "toy.print"(%5) : (tensor<*xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %1 = toy.reshape(%0 : tensor<2x3xf64>) to tensor<2x3xf64>
+ %2 = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>
+ %3 = toy.reshape(%2 : tensor<6xf64>) to tensor<2x3xf64>
+ %4 = toy.generic_call @multiply_transpose(%1, %3) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+ %5 = toy.generic_call @multiply_transpose(%3, %1) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+ toy.print %5 : tensor<*xf64>
+ toy.return
}
// CHECK-NOT: func @multiply_transpose
// CHECK-NOT: tensor<*xf64>
// CHECK-LABEL: func @main()
-// CHECK: [[VAL_0:%.*]] = "toy.constant"() {value = dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
-// CHECK: [[VAL_1:%.*]] = "toy.transpose"([[VAL_0]]) : (tensor<2x3xf64>) -> tensor<3x2xf64>
-// CHECK: [[VAL_2:%.*]] = "toy.mul"([[VAL_1]], [[VAL_1]]) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
-// CHECK: "toy.print"([[VAL_2]]) : (tensor<3x2xf64>) -> ()
-// CHECK: "toy.return"() : () -> ()
+// CHECK: [[VAL_0:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+// CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<2x3xf64>) to tensor<3x2xf64>
+// CHECK: [[VAL_2:%.*]] = toy.mul [[VAL_1]], [[VAL_1]] : tensor<3x2xf64>
+// CHECK: toy.print [[VAL_2]] : tensor<3x2xf64>
+// CHECK: toy.return
diff --git a/mlir/test/Examples/Toy/Ch6/affine-lowering.mlir b/mlir/test/Examples/Toy/Ch6/affine-lowering.mlir
index 3f546be0790f..79bdd38de6f5 100644
--- a/mlir/test/Examples/Toy/Ch6/affine-lowering.mlir
+++ b/mlir/test/Examples/Toy/Ch6/affine-lowering.mlir
@@ -2,11 +2,11 @@
// RUN: toyc-ch6 %s -emit=mlir-affine -opt 2>&1 | FileCheck %s --check-prefix=OPT
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %2 = "toy.transpose"(%0) : (tensor<2x3xf64>) -> tensor<3x2xf64>
- %3 = "toy.mul"(%2, %2) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
- "toy.print"(%3) : (tensor<3x2xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %2 = toy.transpose(%0 : tensor<2x3xf64>) to tensor<3x2xf64>
+ %3 = toy.mul %2, %2 : tensor<3x2xf64>
+ toy.print %3 : tensor<3x2xf64>
+ toy.return
}
// CHECK-LABEL: func @main()
@@ -35,7 +35,7 @@ func @main() {
// CHECK: [[VAL_15:%.*]] = affine.load [[VAL_7]]{{\[}}[[VAL_12]], [[VAL_13]]] : memref<3x2xf64>
// CHECK: [[VAL_16:%.*]] = mulf [[VAL_14]], [[VAL_15]] : f64
// CHECK: affine.store [[VAL_16]], [[VAL_6]]{{\[}}[[VAL_12]], [[VAL_13]]] : memref<3x2xf64>
-// CHECK: "toy.print"([[VAL_6]]) : (memref<3x2xf64>) -> ()
+// CHECK: toy.print [[VAL_6]] : memref<3x2xf64>
// CHECK: dealloc [[VAL_8]] : memref<2x3xf64>
// CHECK: dealloc [[VAL_7]] : memref<3x2xf64>
// CHECK: dealloc [[VAL_6]] : memref<3x2xf64>
@@ -60,6 +60,6 @@ func @main() {
// OPT: [[VAL_10:%.*]] = affine.load [[VAL_7]]{{\[}}[[VAL_9]], [[VAL_8]]] : memref<2x3xf64>
// OPT: [[VAL_11:%.*]] = mulf [[VAL_10]], [[VAL_10]] : f64
// OPT: affine.store [[VAL_11]], [[VAL_6]]{{\[}}[[VAL_8]], [[VAL_9]]] : memref<3x2xf64>
-// OPT: "toy.print"([[VAL_6]]) : (memref<3x2xf64>) -> ()
+// OPT: toy.print [[VAL_6]] : memref<3x2xf64>
// OPT: dealloc [[VAL_7]] : memref<2x3xf64>
// OPT: dealloc [[VAL_6]] : memref<3x2xf64>
diff --git a/mlir/test/Examples/Toy/Ch6/codegen.toy b/mlir/test/Examples/Toy/Ch6/codegen.toy
index 7056880eae9e..97746ceec0fc 100644
--- a/mlir/test/Examples/Toy/Ch6/codegen.toy
+++ b/mlir/test/Examples/Toy/Ch6/codegen.toy
@@ -15,17 +15,17 @@ def main() {
# CHECK-LABEL: func @multiply_transpose(
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>, [[VAL_1:%.*]]: tensor<*xf64>) -> tensor<*xf64>
-# CHECK: [[VAL_2:%.*]] = "toy.transpose"([[VAL_0]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_3:%.*]] = "toy.transpose"([[VAL_1]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_4:%.*]] = "toy.mul"([[VAL_2]], [[VAL_3]]) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.return"([[VAL_4]]) : (tensor<*xf64>) -> ()
+# CHECK: [[VAL_2:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_3:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_4:%.*]] = toy.mul [[VAL_2]], [[VAL_3]] : tensor<*xf64>
+# CHECK-NEXT: toy.return [[VAL_4]] : tensor<*xf64>
# CHECK-LABEL: func @main()
-# CHECK-NEXT: [[VAL_5:%.*]] = "toy.constant"() {value = dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_6:%.*]] = "toy.reshape"([[VAL_5]]) : (tensor<2x3xf64>) -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_7:%.*]] = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64>
-# CHECK-NEXT: [[VAL_8:%.*]] = "toy.reshape"([[VAL_7]]) : (tensor<6xf64>) -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_9:%.*]] = "toy.generic_call"([[VAL_6]], [[VAL_8]]) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_10:%.*]] = "toy.generic_call"([[VAL_8]], [[VAL_6]]) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.print"([[VAL_10]]) : (tensor<*xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: [[VAL_5:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_6:%.*]] = toy.reshape([[VAL_5]] : tensor<2x3xf64>) to tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_7:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>
+# CHECK-NEXT: [[VAL_8:%.*]] = toy.reshape([[VAL_7]] : tensor<6xf64>) to tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_9:%.*]] = toy.generic_call @multiply_transpose([[VAL_6]], [[VAL_8]]) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+# CHECK-NEXT: [[VAL_10:%.*]] = toy.generic_call @multiply_transpose([[VAL_8]], [[VAL_6]]) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+# CHECK-NEXT: toy.print [[VAL_10]] : tensor<*xf64>
+# CHECK-NEXT: toy.return
diff --git a/mlir/test/Examples/Toy/Ch6/llvm-lowering.mlir b/mlir/test/Examples/Toy/Ch6/llvm-lowering.mlir
index 12b050c3bfe8..8a9514ea95a0 100644
--- a/mlir/test/Examples/Toy/Ch6/llvm-lowering.mlir
+++ b/mlir/test/Examples/Toy/Ch6/llvm-lowering.mlir
@@ -1,11 +1,11 @@
// RUN: toyc-ch6 %s -emit=llvm -opt
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %2 = "toy.transpose"(%0) : (tensor<2x3xf64>) -> tensor<3x2xf64>
- %3 = "toy.mul"(%2, %2) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
- "toy.print"(%3) : (tensor<3x2xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %2 = toy.transpose(%0 : tensor<2x3xf64>) to tensor<3x2xf64>
+ %3 = toy.mul %2, %2 : tensor<3x2xf64>
+ toy.print %3 : tensor<3x2xf64>
+ toy.return
}
// CHECK-LABEL: define void @main()
diff --git a/mlir/test/Examples/Toy/Ch6/scalar.toy b/mlir/test/Examples/Toy/Ch6/scalar.toy
index f28bbf97e21b..0a8b1ef7ce05 100644
--- a/mlir/test/Examples/Toy/Ch6/scalar.toy
+++ b/mlir/test/Examples/Toy/Ch6/scalar.toy
@@ -6,9 +6,9 @@ def main() {
}
# CHECK-LABEL: func @main() {
-# CHECK-NEXT: %0 = "toy.constant"() {value = dense<5.500000e+00> : tensor<f64>} : () -> tensor<f64>
-# CHECK-NEXT: %1 = "toy.reshape"(%0) : (tensor<f64>) -> tensor<2x2xf64>
-# CHECK-NEXT: "toy.print"(%1) : (tensor<2x2xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: %0 = toy.constant dense<5.500000e+00> : tensor<f64>
+# CHECK-NEXT: %1 = toy.reshape(%0 : tensor<f64>) to tensor<2x2xf64>
+# CHECK-NEXT: toy.print %1 : tensor<2x2xf64>
+# CHECK-NEXT: toy.return
# CHECK-NEXT: }
diff --git a/mlir/test/Examples/Toy/Ch6/shape_inference.mlir b/mlir/test/Examples/Toy/Ch6/shape_inference.mlir
index d1c4397af851..44a8e66a58bb 100644
--- a/mlir/test/Examples/Toy/Ch6/shape_inference.mlir
+++ b/mlir/test/Examples/Toy/Ch6/shape_inference.mlir
@@ -4,28 +4,28 @@
func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64>
attributes { sym_visibility = "private" } {
- %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64>
- %1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64>
- %2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
- "toy.return"(%2) : (tensor<*xf64>) -> ()
+ %0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64>
+ %1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64>
+ %2 = toy.mul %0, %1 : tensor<*xf64>
+ toy.return %2 : tensor<*xf64>
}
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %1 = "toy.reshape"(%0) : (tensor<2x3xf64>) -> tensor<2x3xf64>
- %2 = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64>
- %3 = "toy.reshape"(%2) : (tensor<6xf64>) -> tensor<2x3xf64>
- %4 = "toy.generic_call"(%1, %3) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
- %5 = "toy.generic_call"(%3, %1) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
- "toy.print"(%5) : (tensor<*xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %1 = toy.reshape(%0 : tensor<2x3xf64>) to tensor<2x3xf64>
+ %2 = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>
+ %3 = toy.reshape(%2 : tensor<6xf64>) to tensor<2x3xf64>
+ %4 = toy.generic_call @multiply_transpose(%1, %3) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+ %5 = toy.generic_call @multiply_transpose(%3, %1) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+ toy.print %5 : tensor<*xf64>
+ toy.return
}
// CHECK-NOT: func @multiply_transpose
// CHECK-NOT: tensor<*xf64>
// CHECK-LABEL: func @main()
-// CHECK: [[VAL_0:%.*]] = "toy.constant"() {value = dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
-// CHECK: [[VAL_1:%.*]] = "toy.transpose"([[VAL_0]]) : (tensor<2x3xf64>) -> tensor<3x2xf64>
-// CHECK: [[VAL_2:%.*]] = "toy.mul"([[VAL_1]], [[VAL_1]]) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
-// CHECK: "toy.print"([[VAL_2]]) : (tensor<3x2xf64>) -> ()
-// CHECK: "toy.return"() : () -> ()
+// CHECK: [[VAL_0:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+// CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<2x3xf64>) to tensor<3x2xf64>
+// CHECK: [[VAL_2:%.*]] = toy.mul [[VAL_1]], [[VAL_1]] : tensor<3x2xf64>
+// CHECK: toy.print [[VAL_2]] : tensor<3x2xf64>
+// CHECK: toy.return
diff --git a/mlir/test/Examples/Toy/Ch7/affine-lowering.mlir b/mlir/test/Examples/Toy/Ch7/affine-lowering.mlir
index 3d08d0c1d804..4054eb0aba8e 100644
--- a/mlir/test/Examples/Toy/Ch7/affine-lowering.mlir
+++ b/mlir/test/Examples/Toy/Ch7/affine-lowering.mlir
@@ -2,11 +2,11 @@
// RUN: toyc-ch7 %s -emit=mlir-affine -opt 2>&1 | FileCheck %s --check-prefix=OPT
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %2 = "toy.transpose"(%0) : (tensor<2x3xf64>) -> tensor<3x2xf64>
- %3 = "toy.mul"(%2, %2) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
- "toy.print"(%3) : (tensor<3x2xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %2 = toy.transpose(%0 : tensor<2x3xf64>) to tensor<3x2xf64>
+ %3 = toy.mul %2, %2 : tensor<3x2xf64>
+ toy.print %3 : tensor<3x2xf64>
+ toy.return
}
// CHECK-LABEL: func @main()
@@ -35,7 +35,7 @@ func @main() {
// CHECK: [[VAL_15:%.*]] = affine.load [[VAL_7]]{{\[}}[[VAL_12]], [[VAL_13]]] : memref<3x2xf64>
// CHECK: [[VAL_16:%.*]] = mulf [[VAL_14]], [[VAL_15]] : f64
// CHECK: affine.store [[VAL_16]], [[VAL_6]]{{\[}}[[VAL_12]], [[VAL_13]]] : memref<3x2xf64>
-// CHECK: "toy.print"([[VAL_6]]) : (memref<3x2xf64>) -> ()
+// CHECK: toy.print [[VAL_6]] : memref<3x2xf64>
// CHECK: dealloc [[VAL_8]] : memref<2x3xf64>
// CHECK: dealloc [[VAL_7]] : memref<3x2xf64>
// CHECK: dealloc [[VAL_6]] : memref<3x2xf64>
@@ -60,6 +60,6 @@ func @main() {
// OPT: [[VAL_10:%.*]] = affine.load [[VAL_7]]{{\[}}[[VAL_9]], [[VAL_8]]] : memref<2x3xf64>
// OPT: [[VAL_11:%.*]] = mulf [[VAL_10]], [[VAL_10]] : f64
// OPT: affine.store [[VAL_11]], [[VAL_6]]{{\[}}[[VAL_8]], [[VAL_9]]] : memref<3x2xf64>
-// OPT: "toy.print"([[VAL_6]]) : (memref<3x2xf64>) -> ()
+// OPT: toy.print [[VAL_6]] : memref<3x2xf64>
// OPT: dealloc [[VAL_7]] : memref<2x3xf64>
// OPT: dealloc [[VAL_6]] : memref<3x2xf64>
diff --git a/mlir/test/Examples/Toy/Ch7/codegen.toy b/mlir/test/Examples/Toy/Ch7/codegen.toy
index e19500bd9ae7..3956fe668d58 100644
--- a/mlir/test/Examples/Toy/Ch7/codegen.toy
+++ b/mlir/test/Examples/Toy/Ch7/codegen.toy
@@ -15,17 +15,17 @@ def main() {
# CHECK-LABEL: func @multiply_transpose(
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>, [[VAL_1:%.*]]: tensor<*xf64>) -> tensor<*xf64>
-# CHECK: [[VAL_2:%.*]] = "toy.transpose"([[VAL_0]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_3:%.*]] = "toy.transpose"([[VAL_1]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_4:%.*]] = "toy.mul"([[VAL_2]], [[VAL_3]]) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.return"([[VAL_4]]) : (tensor<*xf64>) -> ()
+# CHECK: [[VAL_2:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_3:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_4:%.*]] = toy.mul [[VAL_2]], [[VAL_3]] : tensor<*xf64>
+# CHECK-NEXT: toy.return [[VAL_4]] : tensor<*xf64>
# CHECK-LABEL: func @main()
-# CHECK-NEXT: [[VAL_5:%.*]] = "toy.constant"() {value = dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_6:%.*]] = "toy.reshape"([[VAL_5]]) : (tensor<2x3xf64>) -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_7:%.*]] = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64>
-# CHECK-NEXT: [[VAL_8:%.*]] = "toy.reshape"([[VAL_7]]) : (tensor<6xf64>) -> tensor<2x3xf64>
-# CHECK-NEXT: [[VAL_9:%.*]] = "toy.generic_call"([[VAL_6]], [[VAL_8]]) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_10:%.*]] = "toy.generic_call"([[VAL_8]], [[VAL_6]]) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.print"([[VAL_10]]) : (tensor<*xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: [[VAL_5:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_6:%.*]] = toy.reshape([[VAL_5]] : tensor<2x3xf64>) to tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_7:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>
+# CHECK-NEXT: [[VAL_8:%.*]] = toy.reshape([[VAL_7]] : tensor<6xf64>) to tensor<2x3xf64>
+# CHECK-NEXT: [[VAL_9:%.*]] = toy.generic_call @multiply_transpose([[VAL_6]], [[VAL_8]]) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+# CHECK-NEXT: [[VAL_10:%.*]] = toy.generic_call @multiply_transpose([[VAL_8]], [[VAL_6]]) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+# CHECK-NEXT: toy.print [[VAL_10]] : tensor<*xf64>
+# CHECK-NEXT: toy.return
diff --git a/mlir/test/Examples/Toy/Ch7/llvm-lowering.mlir b/mlir/test/Examples/Toy/Ch7/llvm-lowering.mlir
index 0009bb507eb8..aff7c07f3043 100644
--- a/mlir/test/Examples/Toy/Ch7/llvm-lowering.mlir
+++ b/mlir/test/Examples/Toy/Ch7/llvm-lowering.mlir
@@ -1,11 +1,11 @@
// RUN: toyc-ch7 %s -emit=llvm -opt
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %2 = "toy.transpose"(%0) : (tensor<2x3xf64>) -> tensor<3x2xf64>
- %3 = "toy.mul"(%2, %2) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
- "toy.print"(%3) : (tensor<3x2xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %2 = toy.transpose(%0 : tensor<2x3xf64>) to tensor<3x2xf64>
+ %3 = toy.mul %2, %2 : tensor<3x2xf64>
+ toy.print %3 : tensor<3x2xf64>
+ toy.return
}
// CHECK-LABEL: define void @main()
diff --git a/mlir/test/Examples/Toy/Ch7/scalar.toy b/mlir/test/Examples/Toy/Ch7/scalar.toy
index f917ea622e5c..9ca96553646a 100644
--- a/mlir/test/Examples/Toy/Ch7/scalar.toy
+++ b/mlir/test/Examples/Toy/Ch7/scalar.toy
@@ -6,9 +6,9 @@ def main() {
}
# CHECK-LABEL: func @main() {
-# CHECK-NEXT: %0 = "toy.constant"() {value = dense<5.500000e+00> : tensor<f64>} : () -> tensor<f64>
-# CHECK-NEXT: %1 = "toy.reshape"(%0) : (tensor<f64>) -> tensor<2x2xf64>
-# CHECK-NEXT: "toy.print"(%1) : (tensor<2x2xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: %0 = toy.constant dense<5.500000e+00> : tensor<f64>
+# CHECK-NEXT: %1 = toy.reshape(%0 : tensor<f64>) to tensor<2x2xf64>
+# CHECK-NEXT: toy.print %1 : tensor<2x2xf64>
+# CHECK-NEXT: toy.return
# CHECK-NEXT: }
diff --git a/mlir/test/Examples/Toy/Ch7/shape_inference.mlir b/mlir/test/Examples/Toy/Ch7/shape_inference.mlir
index 096c04193603..8d679458aa59 100644
--- a/mlir/test/Examples/Toy/Ch7/shape_inference.mlir
+++ b/mlir/test/Examples/Toy/Ch7/shape_inference.mlir
@@ -4,28 +4,28 @@
func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64>
attributes { sym_visibility = "private" } {
- %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64>
- %1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64>
- %2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
- "toy.return"(%2) : (tensor<*xf64>) -> ()
+ %0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64>
+ %1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64>
+ %2 = toy.mul %0, %1 : tensor<*xf64>
+ toy.return %2 : tensor<*xf64>
}
func @main() {
- %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
- %1 = "toy.reshape"(%0) : (tensor<2x3xf64>) -> tensor<2x3xf64>
- %2 = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64>
- %3 = "toy.reshape"(%2) : (tensor<6xf64>) -> tensor<2x3xf64>
- %4 = "toy.generic_call"(%1, %3) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
- %5 = "toy.generic_call"(%3, %1) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
- "toy.print"(%5) : (tensor<*xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+ %1 = toy.reshape(%0 : tensor<2x3xf64>) to tensor<2x3xf64>
+ %2 = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>
+ %3 = toy.reshape(%2 : tensor<6xf64>) to tensor<2x3xf64>
+ %4 = toy.generic_call @multiply_transpose(%1, %3) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+ %5 = toy.generic_call @multiply_transpose(%3, %1) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64>
+ toy.print %5 : tensor<*xf64>
+ toy.return
}
// CHECK-NOT: func @multiply_transpose
// CHECK-NOT: tensor<*xf64>
// CHECK-LABEL: func @main()
-// CHECK: [[VAL_0:%.*]] = "toy.constant"() {value = dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
-// CHECK: [[VAL_1:%.*]] = "toy.transpose"([[VAL_0]]) : (tensor<2x3xf64>) -> tensor<3x2xf64>
-// CHECK: [[VAL_2:%.*]] = "toy.mul"([[VAL_1]], [[VAL_1]]) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
-// CHECK: "toy.print"([[VAL_2]]) : (tensor<3x2xf64>) -> ()
-// CHECK: "toy.return"() : () -> ()
+// CHECK: [[VAL_0:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+// CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<2x3xf64>) to tensor<3x2xf64>
+// CHECK: [[VAL_2:%.*]] = toy.mul [[VAL_1]], [[VAL_1]] : tensor<3x2xf64>
+// CHECK: toy.print [[VAL_2]] : tensor<3x2xf64>
+// CHECK: toy.return
diff --git a/mlir/test/Examples/Toy/Ch7/struct-codegen.toy b/mlir/test/Examples/Toy/Ch7/struct-codegen.toy
index 4c5ed13e1171..b650e3a8dc09 100644
--- a/mlir/test/Examples/Toy/Ch7/struct-codegen.toy
+++ b/mlir/test/Examples/Toy/Ch7/struct-codegen.toy
@@ -24,22 +24,22 @@ def main() {
# CHECK-LABEL: func @multiply_transpose(
# CHECK-SAME: [[VAL_0:%.*]]: !toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
# CHECK-SAME: attributes {sym_visibility = "private"}
-# CHECK-NEXT: [[VAL_1:%.*]] = "toy.struct_access"([[VAL_0]]) {index = 0 : i64} : (!toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_2:%.*]] = "toy.transpose"([[VAL_1]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_3:%.*]] = "toy.struct_access"([[VAL_0]]) {index = 1 : i64} : (!toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_4:%.*]] = "toy.transpose"([[VAL_3]]) : (tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: [[VAL_5:%.*]] = "toy.mul"([[VAL_2]], [[VAL_4]]) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.return"([[VAL_5]]) : (tensor<*xf64>) -> ()
+# CHECK-NEXT: [[VAL_1:%.*]] = toy.struct_access [[VAL_0]][0] : !toy.struct<tensor<*xf64>, tensor<*xf64>> -> tensor<*xf64>
+# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_3:%.*]] = toy.struct_access [[VAL_0]][1] : !toy.struct<tensor<*xf64>, tensor<*xf64>> -> tensor<*xf64>
+# CHECK-NEXT: [[VAL_4:%.*]] = toy.transpose([[VAL_3]] : tensor<*xf64>) to tensor<*xf64>
+# CHECK-NEXT: [[VAL_5:%.*]] = toy.mul [[VAL_2]], [[VAL_4]] : tensor<*xf64>
+# CHECK-NEXT: toy.return [[VAL_5]] : tensor<*xf64>
# CHECK-LABEL: func @main()
-# CHECK-NEXT: [[VAL_6:%.*]] = "toy.struct_constant"() {value = [dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>, dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>]} : () -> !toy.struct<tensor<*xf64>, tensor<*xf64>>
-# CHECK-NEXT: [[VAL_7:%.*]] = "toy.generic_call"([[VAL_6]]) {callee = @multiply_transpose} : (!toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
-# CHECK-NEXT: "toy.print"([[VAL_7]]) : (tensor<*xf64>) -> ()
-# CHECK-NEXT: "toy.return"() : () -> ()
+# CHECK-NEXT: [[VAL_6:%.*]] = toy.struct_constant [dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>, dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>] : !toy.struct<tensor<*xf64>, tensor<*xf64>>
+# CHECK-NEXT: [[VAL_7:%.*]] = toy.generic_call @multiply_transpose([[VAL_6]]) : (!toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
+# CHECK-NEXT: toy.print [[VAL_7]] : tensor<*xf64>
+# CHECK-NEXT: toy.return
# OPT-LABEL: func @main()
-# OPT-NEXT: [[VAL_0:%.*]] = "toy.constant"() {value = dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64>
-# OPT-NEXT: [[VAL_1:%.*]] = "toy.transpose"([[VAL_0]]) : (tensor<2x3xf64>) -> tensor<3x2xf64>
-# OPT-NEXT: [[VAL_2:%.*]] = "toy.mul"([[VAL_1]], [[VAL_1]]) : (tensor<3x2xf64>, tensor<3x2xf64>) -> tensor<3x2xf64>
-# OPT-NEXT: "toy.print"([[VAL_2]]) : (tensor<3x2xf64>) -> ()
-# OPT-NEXT: "toy.return"() : () -> ()
+# OPT-NEXT: [[VAL_0:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>
+# OPT-NEXT: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<2x3xf64>) to tensor<3x2xf64>
+# OPT-NEXT: [[VAL_2:%.*]] = toy.mul [[VAL_1]], [[VAL_1]] : tensor<3x2xf64>
+# OPT-NEXT: toy.print [[VAL_2]] : tensor<3x2xf64>
+# OPT-NEXT: toy.return
diff --git a/mlir/test/Examples/Toy/Ch7/struct-opt.mlir b/mlir/test/Examples/Toy/Ch7/struct-opt.mlir
index 8c4b055b4bf5..2bfc811b7890 100644
--- a/mlir/test/Examples/Toy/Ch7/struct-opt.mlir
+++ b/mlir/test/Examples/Toy/Ch7/struct-opt.mlir
@@ -1,16 +1,15 @@
// RUN: toyc-ch7 %s -emit=mlir -opt 2>&1 | FileCheck %s
func @main() {
- %0 = "toy.struct_constant"() {
- value = [[dense<4.000000e+00> : tensor<2x2xf64>], dense<4.000000e+00> : tensor<2x2xf64>]
- } : () -> !toy.struct<!toy.struct<tensor<*xf64>>, tensor<*xf64>>
- %1 = "toy.struct_access"(%0) {index = 0 : i64} : (!toy.struct<!toy.struct<tensor<*xf64>>, tensor<*xf64>>) -> !toy.struct<tensor<*xf64>>
- %2 = "toy.struct_access"(%1) {index = 0 : i64} : (!toy.struct<tensor<*xf64>>) -> tensor<*xf64>
- "toy.print"(%2) : (tensor<*xf64>) -> ()
- "toy.return"() : () -> ()
+ %0 = toy.struct_constant [
+ [dense<4.000000e+00> : tensor<2x2xf64>], dense<4.000000e+00> : tensor<2x2xf64>
+ ] : !toy.struct<!toy.struct<tensor<*xf64>>, tensor<*xf64>>
+ %1 = toy.struct_access %0[0] : !toy.struct<!toy.struct<tensor<*xf64>>, tensor<*xf64>> -> !toy.struct<tensor<*xf64>>
+ %2 = toy.struct_access %1[0] : !toy.struct<tensor<*xf64>> -> tensor<*xf64>
+ toy.print %2 : tensor<*xf64>
+ toy.return
}
// CHECK-LABEL: func @main
-// CHECK-NEXT: %[[CST:.*]] = "toy.constant"
-// CHECK-SAME: dense<4.0
-// CHECK-NEXT: "toy.print"(%[[CST]])
+// CHECK-NEXT: %[[CST:.*]] = toy.constant dense<4.0
+// CHECK-NEXT: toy.print %[[CST]]
More information about the Mlir-commits
mailing list