[MLIR] Update tutorial to add missing tests and bring directory paths and code snippets up to date.

Summary:
The tests referred to in Chapter 3 of the tutorial were missing from the tutorial test
directory; this adds those missing tests. This also cleans up some stale directory paths and code
snippets used throughout the tutorial.

Subscribers: mehdi_amini, rriddle, jpienaar, burmako, shauheen, antiagainst, nicolasvasilache, arpith-jacob, mgester, aartbik, liufengdb, Joonsoo, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D76809
This commit is contained in:
Lucy Fox 2020-03-25 15:10:31 -07:00
parent 41ad8b7388
commit 495cf27291
15 changed files with 287 additions and 121 deletions

View File

@ -109,48 +109,48 @@ The AST from the above code is fairly straightforward; here is a dump of it:
```
Module:
Function
Proto 'multiply_transpose' @test/ast.toy:5:1'
Args: [a, b]
Function
Proto 'multiply_transpose' @test/Examples/Toy/Ch1/ast.toy:4:1'
Params: [a, b]
Block {
Return
BinOp: * @test/ast.toy:6:25
Call 'transpose' [ @test/ast.toy:6:10
var: a @test/ast.toy:6:20
BinOp: * @test/Examples/Toy/Ch1/ast.toy:5:25
Call 'transpose' [ @test/Examples/Toy/Ch1/ast.toy:5:10
var: a @test/Examples/Toy/Ch1/ast.toy:5:20
]
Call 'transpose' [ @test/ast.toy:6:25
var: b @test/ast.toy:6:35
Call 'transpose' [ @test/Examples/Toy/Ch1/ast.toy:5:25
var: b @test/Examples/Toy/Ch1/ast.toy:5:35
]
} // Block
Function
Proto 'main' @test/ast.toy:9:1'
Args: []
Function
Proto 'main' @test/Examples/Toy/Ch1/ast.toy:8:1'
Params: []
Block {
VarDecl a<> @test/ast.toy:11:3
Literal: <2, 3>[<3>[1.000000e+00, 2.000000e+00, 3.000000e+00], <3>[4.000000e+00, 5.000000e+00, 6.000000e+00]] @test/ast.toy:11:17
VarDecl b<2, 3> @test/ast.toy:12:3
Literal: <6>[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00] @test/ast.toy:12:17
VarDecl c<> @test/ast.toy:15:3
Call 'multiply_transpose' [ @test/ast.toy:15:11
var: a @test/ast.toy:15:30
var: b @test/ast.toy:15:33
VarDecl a<> @test/Examples/Toy/Ch1/ast.toy:11:3
Literal: <2, 3>[ <3>[ 1.000000e+00, 2.000000e+00, 3.000000e+00], <3>[ 4.000000e+00, 5.000000e+00, 6.000000e+00]] @test/Examples/Toy/Ch1/ast.toy:11:11
VarDecl b<2, 3> @test/Examples/Toy/Ch1/ast.toy:15:3
Literal: <6>[ 1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00] @test/Examples/Toy/Ch1/ast.toy:15:17
VarDecl c<> @test/Examples/Toy/Ch1/ast.toy:19:3
Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:19:11
var: a @test/Examples/Toy/Ch1/ast.toy:19:30
var: b @test/Examples/Toy/Ch1/ast.toy:19:33
]
VarDecl d<> @test/ast.toy:18:3
Call 'multiply_transpose' [ @test/ast.toy:18:11
var: b @test/ast.toy:18:30
var: a @test/ast.toy:18:33
VarDecl d<> @test/Examples/Toy/Ch1/ast.toy:22:3
Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:22:11
var: b @test/Examples/Toy/Ch1/ast.toy:22:30
var: a @test/Examples/Toy/Ch1/ast.toy:22:33
]
VarDecl e<> @test/ast.toy:21:3
Call 'multiply_transpose' [ @test/ast.toy:21:11
var: b @test/ast.toy:21:30
var: c @test/ast.toy:21:33
VarDecl e<> @test/Examples/Toy/Ch1/ast.toy:25:3
Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:25:11
var: b @test/Examples/Toy/Ch1/ast.toy:25:30
var: c @test/Examples/Toy/Ch1/ast.toy:25:33
]
VarDecl f<> @test/ast.toy:24:3
Call 'multiply_transpose' [ @test/ast.toy:24:11
Call 'transpose' [ @test/ast.toy:24:30
var: a @test/ast.toy:24:40
VarDecl f<> @test/Examples/Toy/Ch1/ast.toy:28:3
Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:28:11
Call 'transpose' [ @test/Examples/Toy/Ch1/ast.toy:28:30
var: a @test/Examples/Toy/Ch1/ast.toy:28:40
]
var: c @test/ast.toy:24:44
var: c @test/Examples/Toy/Ch1/ast.toy:28:44
]
} // Block
```

View File

@ -491,8 +491,7 @@ def ConstantOp : Toy_Op<"constant"> {
#### Specifying a Custom Assembly Format
At this point we can generate our "Toy IR". A simplified version of the previous
example:
At this point we can generate our "Toy IR". For example, the following:
```toy
# User defined generic function that operates on unknown shaped arguments.
@ -514,22 +513,22 @@ Results in the following IR:
```mlir
module {
func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> {
%0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64> loc("test/codegen.toy":5:10)
%1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64> loc("test/codegen.toy":5:25)
%2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> 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)
%0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:10)
%1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:25)
%2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:25)
"toy.return"(%2) : (tensor<*xf64>) -> () loc("test/Examples/Toy/Ch2/codegen.toy":5:3)
} loc("test/Examples/Toy/Ch2/codegen.toy":4:1)
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> loc("test/codegen.toy":9:17)
%1 = "toy.reshape"(%0) : (tensor<2x3xf64>) -> tensor<2x3xf64> loc("test/codegen.toy":9:3)
%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> loc("test/codegen.toy":10:17)
%3 = "toy.reshape"(%2) : (tensor<6xf64>) -> tensor<2x3xf64> loc("test/codegen.toy":10:3)
%4 = "toy.generic_call"(%1, %3) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/codegen.toy":11:11)
%5 = "toy.generic_call"(%3, %1) {callee = @multiply_transpose} : (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)
%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> loc("test/Examples/Toy/Ch2/codegen.toy":9:17)
%1 = "toy.reshape"(%0) : (tensor<2x3xf64>) -> tensor<2x3xf64> loc("test/Examples/Toy/Ch2/codegen.toy":9:3)
%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> loc("test/Examples/Toy/Ch2/codegen.toy":10:17)
%3 = "toy.reshape"(%2) : (tensor<6xf64>) -> tensor<2x3xf64> loc("test/Examples/Toy/Ch2/codegen.toy":10:3)
%4 = "toy.generic_call"(%1, %3) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":11:11)
%5 = "toy.generic_call"(%3, %1) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":12:11)
"toy.print"(%5) : (tensor<*xf64>) -> () loc("test/Examples/Toy/Ch2/codegen.toy":13:3)
"toy.return"() : () -> () loc("test/Examples/Toy/Ch2/codegen.toy":8:1)
} loc("test/Examples/Toy/Ch2/codegen.toy":8:1)
} loc(unknown)
```
One thing to notice here is that all of our Toy operations are printed using the
@ -645,22 +644,22 @@ 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)
%0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:10)
%1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:25)
%2 = toy.mul %0, %1 : tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:25)
toy.return %2 : tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:3)
} loc("test/Examples/Toy/Ch2/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)
%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/Examples/Toy/Ch2/codegen.toy":9:17)
%1 = toy.reshape(%0 : tensor<2x3xf64>) to tensor<2x3xf64> loc("test/Examples/Toy/Ch2/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/Examples/Toy/Ch2/codegen.toy":10:17)
%3 = toy.reshape(%2 : tensor<6xf64>) to tensor<2x3xf64> loc("test/Examples/Toy/Ch2/codegen.toy":10:3)
%4 = toy.generic_call @multiply_transpose(%1, %3) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":11:11)
%5 = toy.generic_call @multiply_transpose(%3, %1) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":12:11)
toy.print %5 : tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":13:3)
toy.return loc("test/Examples/Toy/Ch2/codegen.toy":8:1)
} loc("test/Examples/Toy/Ch2/codegen.toy":8:1)
} loc(unknown)
```
Above we introduce several of the concepts for defining operations in the ODS
@ -670,53 +669,12 @@ variadic operands, etc. Check out the
## 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
-mlir-print-debuginfo 2> codegen.mlir` followed by `toyc-ch2 codegen.mlir
-emit=mlir`. You should also use `mlir-tblgen` on the final definition file and
study the generated C++ code.
We can now generate our "Toy IR". You can build `toyc-ch2` and try yourself on
the above example: `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 -mlir-print-debuginfo 2>
codegen.mlir` followed by `toyc-ch2 codegen.mlir -emit=mlir`. You should also
use `mlir-tblgen` on the final definition file and study the generated C++ code.
At this point, MLIR knows about our Toy dialect and operations. In the
[next chapter](Ch-3.md), we will leverage our new dialect to implement some

View File

@ -129,8 +129,8 @@ similar way to LLVM:
pm.addNestedPass<mlir::FuncOp>(mlir::createCanonicalizerPass());
```
Finally, we can run `toyc-ch3 test/transpose_transpose.toy -emit=mlir -opt` and
observe our pattern in action:
Finally, we can run `toyc-ch3 test/Examples/Toy/Ch3/transpose_transpose.toy
-emit=mlir -opt` and observe our pattern in action:
```mlir
func @transpose_transpose(%arg0: tensor<*xf64>) -> tensor<*xf64> {
@ -216,7 +216,7 @@ def FoldConstantReshapeOptPattern : Pat<
```
We demonstrate these reshape optimizations using the following
trivialReshape.toy program:
trivial_reshape.toy program:
```c++
def main() {
@ -240,8 +240,8 @@ module {
}
```
We can try to run `toyc-ch3 test/trivialReshape.toy -emit=mlir -opt` and observe
our pattern in action:
We can try to run `toyc-ch3 test/Examples/Toy/Ch3/trivial_reshape.toy -emit=mlir
-opt` and observe our pattern in action:
```mlir
module {

View File

@ -222,7 +222,7 @@ def PrintOp : Toy_Op<"print"> {
## Complete Toy Example
Looking back at our current working example:
Let's take a concrete example:
```mlir
func @main() {
@ -336,8 +336,8 @@ func @main() {
Here, we can see that a redundant allocation was removed, the two loop nests
were fused, and some unnecessary `load`s were removed. You can build `toyc-ch5`
and try yourself: `toyc-ch5 test/lowering.toy -emit=mlir-affine`. We can also
check our optimizations by adding `-opt`.
and try yourself: `toyc-ch5 test/Examples/Toy/Ch5/affine-lowering.mlir
-emit=mlir-affine`. We can also check our optimizations by adding `-opt`.
In this chapter we explored some aspects of partial lowering, with the intent to
optimize. In the [next chapter](Ch-6.md) we will continue the discussion about

View File

@ -239,8 +239,8 @@ define void @main()
}
```
The full code listing for dumping LLVM IR can be found in `Ch6/toy.cpp` in the
`dumpLLVMIR()` function:
The full code listing for dumping LLVM IR can be found in
`examples/toy/Ch6/toy.cpp` in the `dumpLLVMIR()` function:
```c++
@ -318,5 +318,8 @@ You can also play with `-emit=mlir`, `-emit=mlir-affine`, `-emit=mlir-llvm`, and
[`--print-ir-after-all`](../../WritingAPass.md#ir-printing) to track the
evolution of the IR throughout the pipeline.
The example code used throughout this section can be found in
test/Examples/Toy/Ch6/llvm-lowering.mlir.
So far, we have worked with primitive data types. In the
[next chapter](Ch-7.md), we will add a composite `struct` type.

View File

@ -0,0 +1,25 @@
# RUN: toyc-ch3 %s -emit=mlir 2>&1 | FileCheck %s
# User defined generic function that operates on unknown shaped arguments
def transpose_transpose(x) {
return transpose(transpose(x));
}
def main() {
var a<2, 3> = [[1, 2, 3], [4, 5, 6]];
var b = transpose_transpose(a);
print(b);
}
# CHECK-LABEL: func @transpose_transpose(
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64>
# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64>
# CHECK-LABEL: func @main()
# CHECK-NEXT: [[VAL_3:%.*]] = 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_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64>
# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64>
# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64>
# CHECK-NEXT: toy.return

View File

@ -0,0 +1,16 @@
# RUN: toyc-ch3 %s -emit=mlir 2>&1 | FileCheck %s
def main() {
var a<2,1> = [1, 2];
var b<2,1> = a;
var c<2,1> = b;
print(c);
}
# CHECK-LABEL: func @main()
# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64>
# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64>
# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64>
# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64>
# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64>
# CHECK-NEXT: toy.return

View File

@ -0,0 +1,25 @@
# RUN: toyc-ch4 %s -emit=mlir 2>&1 | FileCheck %s
# User defined generic function that operates on unknown shaped arguments
def transpose_transpose(x) {
return transpose(transpose(x));
}
def main() {
var a<2, 3> = [[1, 2, 3], [4, 5, 6]];
var b = transpose_transpose(a);
print(b);
}
# CHECK-LABEL: func @transpose_transpose(
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64>
# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64>
# CHECK-LABEL: func @main()
# CHECK-NEXT: [[VAL_3:%.*]] = 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_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64>
# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64>
# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64>
# CHECK-NEXT: toy.return

View File

@ -0,0 +1,16 @@
# RUN: toyc-ch4 %s -emit=mlir 2>&1 | FileCheck %s
def main() {
var a<2,1> = [1, 2];
var b<2,1> = a;
var c<2,1> = b;
print(c);
}
# CHECK-LABEL: func @main()
# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64>
# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64>
# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64>
# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64>
# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64>
# CHECK-NEXT: toy.return

View File

@ -0,0 +1,25 @@
# RUN: toyc-ch5 %s -emit=mlir 2>&1 | FileCheck %s
# User defined generic function that operates on unknown shaped arguments
def transpose_transpose(x) {
return transpose(transpose(x));
}
def main() {
var a<2, 3> = [[1, 2, 3], [4, 5, 6]];
var b = transpose_transpose(a);
print(b);
}
# CHECK-LABEL: func @transpose_transpose(
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64>
# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64>
# CHECK-LABEL: func @main()
# CHECK-NEXT: [[VAL_3:%.*]] = 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_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64>
# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64>
# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64>
# CHECK-NEXT: toy.return

View File

@ -0,0 +1,16 @@
# RUN: toyc-ch5 %s -emit=mlir 2>&1 | FileCheck %s
def main() {
var a<2,1> = [1, 2];
var b<2,1> = a;
var c<2,1> = b;
print(c);
}
# CHECK-LABEL: func @main()
# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64>
# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64>
# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64>
# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64>
# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64>
# CHECK-NEXT: toy.return

View File

@ -0,0 +1,25 @@
# RUN: toyc-ch6 %s -emit=mlir 2>&1 | FileCheck %s
# User defined generic function that operates on unknown shaped arguments
def transpose_transpose(x) {
return transpose(transpose(x));
}
def main() {
var a<2, 3> = [[1, 2, 3], [4, 5, 6]];
var b = transpose_transpose(a);
print(b);
}
# CHECK-LABEL: func @transpose_transpose(
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64>
# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64>
# CHECK-LABEL: func @main()
# CHECK-NEXT: [[VAL_3:%.*]] = 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_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64>
# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64>
# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64>
# CHECK-NEXT: toy.return

View File

@ -0,0 +1,16 @@
# RUN: toyc-ch6 %s -emit=mlir 2>&1 | FileCheck %s
def main() {
var a<2,1> = [1, 2];
var b<2,1> = a;
var c<2,1> = b;
print(c);
}
# CHECK-LABEL: func @main()
# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64>
# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64>
# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64>
# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64>
# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64>
# CHECK-NEXT: toy.return

View File

@ -0,0 +1,25 @@
# RUN: toyc-ch7 %s -emit=mlir 2>&1 | FileCheck %s
# User defined generic function that operates on unknown shaped arguments
def transpose_transpose(x) {
return transpose(transpose(x));
}
def main() {
var a<2, 3> = [[1, 2, 3], [4, 5, 6]];
var b = transpose_transpose(a);
print(b);
}
# CHECK-LABEL: func @transpose_transpose(
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64>
# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64>
# CHECK-LABEL: func @main()
# CHECK-NEXT: [[VAL_3:%.*]] = 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_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64>
# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64>
# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64>
# CHECK-NEXT: toy.return

View File

@ -0,0 +1,16 @@
# RUN: toyc-ch7 %s -emit=mlir 2>&1 | FileCheck %s
def main() {
var a<2,1> = [1, 2];
var b<2,1> = a;
var c<2,1> = b;
print(c);
}
# CHECK-LABEL: func @main()
# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64>
# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64>
# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64>
# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64>
# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64>
# CHECK-NEXT: toy.return