diff options
Diffstat (limited to 'mlir/test')
| -rw-r--r-- | mlir/test/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | mlir/test/Examples/Toy/Ch7/affine-lowering.mlir | 65 | ||||
| -rw-r--r-- | mlir/test/Examples/Toy/Ch7/ast.toy | 76 | ||||
| -rw-r--r-- | mlir/test/Examples/Toy/Ch7/codegen.toy | 31 | ||||
| -rw-r--r-- | mlir/test/Examples/Toy/Ch7/invalid.mlir | 9 | ||||
| -rw-r--r-- | mlir/test/Examples/Toy/Ch7/llvm-lowering.mlir | 23 | ||||
| -rw-r--r-- | mlir/test/Examples/Toy/Ch7/scalar.toy | 14 | ||||
| -rw-r--r-- | mlir/test/Examples/Toy/Ch7/shape_inference.mlir | 30 | ||||
| -rw-r--r-- | mlir/test/Examples/Toy/Ch7/struct-ast.toy | 61 | ||||
| -rw-r--r-- | mlir/test/Examples/Toy/Ch7/struct-codegen.toy | 44 | ||||
| -rw-r--r-- | mlir/test/Examples/Toy/Ch7/struct-opt.mlir | 16 |
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]]) |

