summaryrefslogtreecommitdiffstats
path: root/mlir/test
diff options
context:
space:
mode:
Diffstat (limited to 'mlir/test')
-rw-r--r--mlir/test/CMakeLists.txt1
-rw-r--r--mlir/test/Examples/Toy/Ch7/affine-lowering.mlir65
-rw-r--r--mlir/test/Examples/Toy/Ch7/ast.toy76
-rw-r--r--mlir/test/Examples/Toy/Ch7/codegen.toy31
-rw-r--r--mlir/test/Examples/Toy/Ch7/invalid.mlir9
-rw-r--r--mlir/test/Examples/Toy/Ch7/llvm-lowering.mlir23
-rw-r--r--mlir/test/Examples/Toy/Ch7/scalar.toy14
-rw-r--r--mlir/test/Examples/Toy/Ch7/shape_inference.mlir30
-rw-r--r--mlir/test/Examples/Toy/Ch7/struct-ast.toy61
-rw-r--r--mlir/test/Examples/Toy/Ch7/struct-codegen.toy44
-rw-r--r--mlir/test/Examples/Toy/Ch7/struct-opt.mlir16
11 files changed, 370 insertions, 0 deletions
diff --git a/mlir/test/CMakeLists.txt b/mlir/test/CMakeLists.txt
index 9c11adc95db..95792548221 100644
--- a/mlir/test/CMakeLists.txt
+++ b/mlir/test/CMakeLists.txt
@@ -50,6 +50,7 @@ if(LLVM_BUILD_EXAMPLES)
toyc-ch4
toyc-ch5
toyc-ch6
+ toyc-ch7
)
endif()
diff --git a/mlir/test/Examples/Toy/Ch7/affine-lowering.mlir b/mlir/test/Examples/Toy/Ch7/affine-lowering.mlir
new file mode 100644
index 00000000000..3d08d0c1d80
--- /dev/null
+++ b/mlir/test/Examples/Toy/Ch7/affine-lowering.mlir
@@ -0,0 +1,65 @@
+// RUN: toyc-ch7 %s -emit=mlir-affine 2>&1 | FileCheck %s
+// 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"() : () -> ()
+}
+
+// CHECK-LABEL: func @main()
+// CHECK: [[VAL_0:%.*]] = constant 1.000000e+00 : f64
+// CHECK: [[VAL_1:%.*]] = constant 2.000000e+00 : f64
+// CHECK: [[VAL_2:%.*]] = constant 3.000000e+00 : f64
+// CHECK: [[VAL_3:%.*]] = constant 4.000000e+00 : f64
+// CHECK: [[VAL_4:%.*]] = constant 5.000000e+00 : f64
+// CHECK: [[VAL_5:%.*]] = constant 6.000000e+00 : f64
+// CHECK: [[VAL_6:%.*]] = alloc() : memref<3x2xf64>
+// CHECK: [[VAL_7:%.*]] = alloc() : memref<3x2xf64>
+// CHECK: [[VAL_8:%.*]] = alloc() : memref<2x3xf64>
+// CHECK: affine.store [[VAL_0]], [[VAL_8]][0, 0] : memref<2x3xf64>
+// CHECK: affine.store [[VAL_1]], [[VAL_8]][0, 1] : memref<2x3xf64>
+// CHECK: affine.store [[VAL_2]], [[VAL_8]][0, 2] : memref<2x3xf64>
+// CHECK: affine.store [[VAL_3]], [[VAL_8]][1, 0] : memref<2x3xf64>
+// CHECK: affine.store [[VAL_4]], [[VAL_8]][1, 1] : memref<2x3xf64>
+// CHECK: affine.store [[VAL_5]], [[VAL_8]][1, 2] : memref<2x3xf64>
+// CHECK: affine.for [[VAL_9:%.*]] = 0 to 3 {
+// CHECK: affine.for [[VAL_10:%.*]] = 0 to 2 {
+// CHECK: [[VAL_11:%.*]] = affine.load [[VAL_8]]{{\[}}[[VAL_10]], [[VAL_9]]] : memref<2x3xf64>
+// CHECK: affine.store [[VAL_11]], [[VAL_7]]{{\[}}[[VAL_9]], [[VAL_10]]] : memref<3x2xf64>
+// CHECK: affine.for [[VAL_12:%.*]] = 0 to 3 {
+// CHECK: affine.for [[VAL_13:%.*]] = 0 to 2 {
+// CHECK: [[VAL_14:%.*]] = affine.load [[VAL_7]]{{\[}}[[VAL_12]], [[VAL_13]]] : memref<3x2xf64>
+// 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: dealloc [[VAL_8]] : memref<2x3xf64>
+// CHECK: dealloc [[VAL_7]] : memref<3x2xf64>
+// CHECK: dealloc [[VAL_6]] : memref<3x2xf64>
+
+// OPT-LABEL: func @main()
+// OPT: [[VAL_0:%.*]] = constant 1.000000e+00 : f64
+// OPT: [[VAL_1:%.*]] = constant 2.000000e+00 : f64
+// OPT: [[VAL_2:%.*]] = constant 3.000000e+00 : f64
+// OPT: [[VAL_3:%.*]] = constant 4.000000e+00 : f64
+// OPT: [[VAL_4:%.*]] = constant 5.000000e+00 : f64
+// OPT: [[VAL_5:%.*]] = constant 6.000000e+00 : f64
+// OPT: [[VAL_6:%.*]] = alloc() : memref<3x2xf64>
+// OPT: [[VAL_7:%.*]] = alloc() : memref<2x3xf64>
+// OPT: affine.store [[VAL_0]], [[VAL_7]][0, 0] : memref<2x3xf64>
+// OPT: affine.store [[VAL_1]], [[VAL_7]][0, 1] : memref<2x3xf64>
+// OPT: affine.store [[VAL_2]], [[VAL_7]][0, 2] : memref<2x3xf64>
+// OPT: affine.store [[VAL_3]], [[VAL_7]][1, 0] : memref<2x3xf64>
+// OPT: affine.store [[VAL_4]], [[VAL_7]][1, 1] : memref<2x3xf64>
+// OPT: affine.store [[VAL_5]], [[VAL_7]][1, 2] : memref<2x3xf64>
+// OPT: affine.for [[VAL_8:%.*]] = 0 to 3 {
+// OPT: affine.for [[VAL_9:%.*]] = 0 to 2 {
+// 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: dealloc [[VAL_7]] : memref<2x3xf64>
+// OPT: dealloc [[VAL_6]] : memref<3x2xf64>
diff --git a/mlir/test/Examples/Toy/Ch7/ast.toy b/mlir/test/Examples/Toy/Ch7/ast.toy
new file mode 100644
index 00000000000..b32410e58e7
--- /dev/null
+++ b/mlir/test/Examples/Toy/Ch7/ast.toy
@@ -0,0 +1,76 @@
+# RUN: toyc-ch7 %s -emit=ast 2>&1 | FileCheck %s
+
+# User defined generic function that operates on unknown shaped arguments.
+def multiply_transpose(a, b) {
+ return transpose(a) * transpose(b);
+}
+
+def main() {
+ # Define a variable `a` with shape <2, 3>, initialized with the literal value.
+ # The shape is inferred from the supplied literal.
+ var a = [[1, 2, 3], [4, 5, 6]];
+ # b is identical to a, the literal array is implicitly reshaped: defining new
+ # variables is the way to reshape arrays (element count in literal must match
+ # the size of specified shape).
+ var b<2, 3> = [1, 2, 3, 4, 5, 6];
+
+ # This call will specialize `multiply_transpose` with <2, 3> for both
+ # arguments and deduce a return type of <2, 2> in initialization of `c`.
+ var c = multiply_transpose(a, b);
+ # A second call to `multiply_transpose` with <2, 3> for both arguments will
+ # reuse the previously specialized and inferred version and return `<2, 2>`
+ var d = multiply_transpose(b, a);
+ # A new call with `<2, 2>` for both dimension will trigger another
+ # specialization of `multiply_transpose`.
+ var e = multiply_transpose(b, c);
+ # Finally, calling into `multiply_transpose` with incompatible shape will
+ # trigger a shape inference error.
+ var e = multiply_transpose(transpose(a), c);
+}
+
+
+# CHECK: Module:
+# CHECK-NEXT: Function
+# CHECK-NEXT: Proto 'multiply_transpose' @{{.*}}ast.toy:4:1'
+# CHECK-NEXT: Params: [a, b]
+# CHECK-NEXT: Block {
+# CHECK-NEXT: Return
+# CHECK-NEXT: BinOp: * @{{.*}}ast.toy:5:25
+# CHECK-NEXT: Call 'transpose' [ @{{.*}}ast.toy:5:10
+# CHECK-NEXT: var: a @{{.*}}ast.toy:5:20
+# CHECK-NEXT: ]
+# CHECK-NEXT: Call 'transpose' [ @{{.*}}ast.toy:5:25
+# CHECK-NEXT: var: b @{{.*}}ast.toy:5:35
+# CHECK-NEXT: ]
+# CHECK-NEXT: } // Block
+# CHECK-NEXT: Function
+# CHECK-NEXT: Proto 'main' @{{.*}}ast.toy:8:1'
+# CHECK-NEXT: Params: []
+# CHECK-NEXT: Block {
+# CHECK-NEXT: VarDecl a<> @{{.*}}ast.toy:11:3
+# CHECK-NEXT: Literal: <2, 3>[ <3>[ 1.000000e+00, 2.000000e+00, 3.000000e+00], <3>[ 4.000000e+00, 5.000000e+00, 6.000000e+00]] @{{.*}}ast.toy:11:11
+# CHECK-NEXT: VarDecl b<2, 3> @{{.*}}ast.toy:15:3
+# CHECK-NEXT: Literal: <6>[ 1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00] @{{.*}}ast.toy:15:17
+# CHECK-NEXT: VarDecl c<> @{{.*}}ast.toy:19:3
+# CHECK-NEXT: Call 'multiply_transpose' [ @{{.*}}ast.toy:19:11
+# CHECK-NEXT: var: a @{{.*}}ast.toy:19:30
+# CHECK-NEXT: var: b @{{.*}}ast.toy:19:33
+# CHECK-NEXT: ]
+# CHECK-NEXT: VarDecl d<> @{{.*}}ast.toy:22:3
+# CHECK-NEXT: Call 'multiply_transpose' [ @{{.*}}ast.toy:22:11
+# CHECK-NEXT: var: b @{{.*}}ast.toy:22:30
+# CHECK-NEXT: var: a @{{.*}}ast.toy:22:33
+# CHECK-NEXT: ]
+# CHECK-NEXT: VarDecl e<> @{{.*}}ast.toy:25:3
+# CHECK-NEXT: Call 'multiply_transpose' [ @{{.*}}ast.toy:25:11
+# CHECK-NEXT: var: b @{{.*}}ast.toy:25:30
+# CHECK-NEXT: var: c @{{.*}}ast.toy:25:33
+# CHECK-NEXT: ]
+# CHECK-NEXT: VarDecl e<> @{{.*}}ast.toy:28:3
+# CHECK-NEXT: Call 'multiply_transpose' [ @{{.*}}ast.toy:28:11
+# CHECK-NEXT: Call 'transpose' [ @{{.*}}ast.toy:28:30
+# CHECK-NEXT: var: a @{{.*}}ast.toy:28:40
+# CHECK-NEXT: ]
+# CHECK-NEXT: var: c @{{.*}}ast.toy:28:44
+# CHECK-NEXT: ]
+
diff --git a/mlir/test/Examples/Toy/Ch7/codegen.toy b/mlir/test/Examples/Toy/Ch7/codegen.toy
new file mode 100644
index 00000000000..e19500bd9ae
--- /dev/null
+++ b/mlir/test/Examples/Toy/Ch7/codegen.toy
@@ -0,0 +1,31 @@
+# RUN: toyc-ch7 %s -emit=mlir 2>&1 | FileCheck %s
+
+# 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);
+}
+
+# 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-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"() : () -> ()
diff --git a/mlir/test/Examples/Toy/Ch7/invalid.mlir b/mlir/test/Examples/Toy/Ch7/invalid.mlir
new file mode 100644
index 00000000000..5d35d95a5bf
--- /dev/null
+++ b/mlir/test/Examples/Toy/Ch7/invalid.mlir
@@ -0,0 +1,9 @@
+// RUN: not toyc-ch7 %s -emit=mlir 2>&1
+
+// The following IR is not "valid":
+// - toy.print should not return a value.
+// - toy.print should take an argument.
+// - There should be a block terminator.
+func @main() {
+ %0 = "toy.print"() : () -> tensor<2x3xf64>
+}
diff --git a/mlir/test/Examples/Toy/Ch7/llvm-lowering.mlir b/mlir/test/Examples/Toy/Ch7/llvm-lowering.mlir
new file mode 100644
index 00000000000..0009bb507eb
--- /dev/null
+++ b/mlir/test/Examples/Toy/Ch7/llvm-lowering.mlir
@@ -0,0 +1,23 @@
+// 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"() : () -> ()
+}
+
+// CHECK-LABEL: define void @main()
+// CHECK: @printf
+// CHECK-SAME: 1.000000e+00
+// CHECK: @printf
+// CHECK-SAME: 1.600000e+01
+// CHECK: @printf
+// CHECK-SAME: 4.000000e+00
+// CHECK: @printf
+// CHECK-SAME: 2.500000e+01
+// CHECK: @printf
+// CHECK-SAME: 9.000000e+00
+// CHECK: @printf
+// CHECK-SAME: 3.000000e+01
diff --git a/mlir/test/Examples/Toy/Ch7/scalar.toy b/mlir/test/Examples/Toy/Ch7/scalar.toy
new file mode 100644
index 00000000000..f917ea622e5
--- /dev/null
+++ b/mlir/test/Examples/Toy/Ch7/scalar.toy
@@ -0,0 +1,14 @@
+# RUN: toyc-ch7 %s -emit=mlir 2>&1 | FileCheck %s
+
+def main() {
+ var a<2, 2> = 5.5;
+ print(a);
+}
+
+# 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: }
+
diff --git a/mlir/test/Examples/Toy/Ch7/shape_inference.mlir b/mlir/test/Examples/Toy/Ch7/shape_inference.mlir
new file mode 100644
index 00000000000..b9355cf7e25
--- /dev/null
+++ b/mlir/test/Examples/Toy/Ch7/shape_inference.mlir
@@ -0,0 +1,30 @@
+// RUN: toyc-ch7 %s -emit=mlir -opt 2>&1 | FileCheck %s
+
+// Check the result of inlining+shape inference on an input module.
+
+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>) -> ()
+}
+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"() : () -> ()
+}
+
+// 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"() : () -> ()
diff --git a/mlir/test/Examples/Toy/Ch7/struct-ast.toy b/mlir/test/Examples/Toy/Ch7/struct-ast.toy
new file mode 100644
index 00000000000..dee0d5b0efd
--- /dev/null
+++ b/mlir/test/Examples/Toy/Ch7/struct-ast.toy
@@ -0,0 +1,61 @@
+# RUN: toyc-ch7 %s -emit=ast 2>&1 | FileCheck %s
+
+struct Struct {
+ var a;
+ var b;
+}
+
+# User defined generic function may operate on struct types as well.
+def multiply_transpose(Struct value) {
+ # We can access the elements of a struct via the '.' operator.
+ return transpose(value.a) * transpose(value.b);
+}
+
+def main() {
+ # We initialize struct values using a composite initializer.
+ Struct value = {[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]};
+
+ # We pass these arguments to functions like we do with variables.
+ var c = multiply_transpose(value);
+ print(c);
+}
+
+# CHECK: Module:
+# CHECK-NEXT: Struct: Struct @{{.*}}struct-ast.toy:3:1
+# CHECK-NEXT: Variables: [
+# CHECK-NEXT: VarDecl a<> @{{.*}}struct-ast.toy:4:3
+# CHECK-NEXT: VarDecl b<> @{{.*}}struct-ast.toy:5:3
+# CHECK-NEXT: ]
+# CHECK-NEXT:Function
+# CHECK-NEXT: Proto 'multiply_transpose' @{{.*}}struct-ast.toy:9:1'
+# CHECK-NEXT: Params: [value]
+# CHECK-NEXT: Block {
+# CHECK-NEXT: Return
+# CHECK-NEXT: BinOp: * @{{.*}}struct-ast.toy:11:31
+# CHECK-NEXT: Call 'transpose' [ @{{.*}}struct-ast.toy:11:10
+# CHECK-NEXT: BinOp: . @{{.*}}struct-ast.toy:11:26
+# CHECK-NEXT: var: value @{{.*}}struct-ast.toy:11:20
+# CHECK-NEXT: var: a @{{.*}}struct-ast.toy:11:26
+# CHECK-NEXT: ]
+# CHECK-NEXT: Call 'transpose' [ @{{.*}}struct-ast.toy:11:31
+# CHECK-NEXT: BinOp: . @{{.*}}struct-ast.toy:11:47
+# CHECK-NEXT: var: value @{{.*}}struct-ast.toy:11:41
+# CHECK-NEXT: var: b @{{.*}}struct-ast.toy:11:47
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+# CHECK-NEXT:Function
+# CHECK-NEXT: Proto 'main' @{{.*}}struct-ast.toy:14:1'
+# CHECK-NEXT: Params: []
+# CHECK-NEXT: Block {
+# CHECK-NEXT: VarDecl value<Struct> @{{.*}}struct-ast.toy:16:3
+# CHECK-NEXT: Struct Literal: Literal: <2, 3>[ <3>[ 1.000000e+00, 2.000000e+00, 3.000000e+00], <3>[ 4.000000e+00, 5.000000e+00, 6.000000e+00]] @{{.*}}struct-ast.toy:16:19
+# CHECK-NEXT: Literal: <2, 3>[ <3>[ 1.000000e+00, 2.000000e+00, 3.000000e+00], <3>[ 4.000000e+00, 5.000000e+00, 6.000000e+00]] @{{.*}}struct-ast.toy:16:43
+# CHECK-NEXT: @{{.*}}struct-ast.toy:16:18
+# CHECK-NEXT: VarDecl c<> @{{.*}}struct-ast.toy:19:3
+# CHECK-NEXT: Call 'multiply_transpose' [ @{{.*}}struct-ast.toy:19:11
+# CHECK-NEXT: var: value @{{.*}}struct-ast.toy:19:30
+# CHECK-NEXT: ]
+# CHECK-NEXT: Print [ @{{.*}}struct-ast.toy:20:3
+# CHECK-NEXT: var: c @{{.*}}struct-ast.toy:20:9
+# CHECK-NEXT: ]
+# CHECK-NEXT: } \ No newline at end of file
diff --git a/mlir/test/Examples/Toy/Ch7/struct-codegen.toy b/mlir/test/Examples/Toy/Ch7/struct-codegen.toy
new file mode 100644
index 00000000000..66eaf8a1639
--- /dev/null
+++ b/mlir/test/Examples/Toy/Ch7/struct-codegen.toy
@@ -0,0 +1,44 @@
+# RUN: toyc-ch7 %s -emit=mlir 2>&1
+# RUN: toyc-ch7 %s -emit=mlir -opt 2>&1 | FileCheck %s --check-prefix=OPT
+
+struct Struct {
+ var a;
+ var b;
+}
+
+# User defined generic function may operate on struct types as well.
+def multiply_transpose(Struct value) {
+ # We can access the elements of a struct via the '.' operator.
+ return transpose(value.a) * transpose(value.b);
+}
+
+def main() {
+ # We initialize struct values using a composite initializer.
+ Struct value = {[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]};
+
+ # We pass these arguments to functions like we do with variables.
+ var c = multiply_transpose(value);
+ print(c);
+}
+
+# CHECK-LABEL: func @multiply_transpose(
+# CHECK-SAME: [[VAL_0:%.*]]: !toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
+# 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-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"() : () -> ()
+
+# 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"() : () -> ()
diff --git a/mlir/test/Examples/Toy/Ch7/struct-opt.mlir b/mlir/test/Examples/Toy/Ch7/struct-opt.mlir
new file mode 100644
index 00000000000..8c4b055b4bf
--- /dev/null
+++ b/mlir/test/Examples/Toy/Ch7/struct-opt.mlir
@@ -0,0 +1,16 @@
+// 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"() : () -> ()
+}
+
+// CHECK-LABEL: func @main
+// CHECK-NEXT: %[[CST:.*]] = "toy.constant"
+// CHECK-SAME: dense<4.0
+// CHECK-NEXT: "toy.print"(%[[CST]])
OpenPOWER on IntegriCloud