// Copyright 2026 The TensorFlow Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ============================================================================== // RUN: litert-opt -split-input-file -verify-diagnostics -tfl-runtime-verify %s | FileCheck %s // Unary math operations // ----- // CHECK-LABEL: testCos func.func @testCos(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.cos"(%arg0) %0 = "tfl.cos"(%arg0): (tensor) -> tensor func.return %0 : tensor } // ----- // test invalid Cos input func.func @testCosWithWrongInputType(tensor) -> tensor { ^bb0(%arg0: tensor): // expected-error @+1 {{tfl.cos' op operand #0 must be tensor of 32-bit float or 16-bit float values}} %0 = "tfl.cos"(%arg0): (tensor) -> tensor func.return %0#0 : tensor } // ----- // CHECK-LABEL: testExp func.func @testExp(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.exp"(%arg0) %0 = "tfl.exp"(%arg0): (tensor) -> tensor func.return %0 : tensor } // CHECK-LABEL: testFloor func.func @testFloor(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.floor"(%arg0) %0 = "tfl.floor"(%arg0): (tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testGather func.func @testGather(%arg0 : tensor, %arg1 : tensor) -> tensor { %0 = "tfl.gather"(%arg0, %arg1) {axis = 1 : i32}: (tensor,tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testGather func.func @testGather(%arg0 : tensor<2xf32>, %arg1 : tensor<2xi32>) -> tensor<2xf32> { %0 = "tfl.gather"(%arg0, %arg1) {axis = 1 : i32}: (tensor<2xf32>,tensor<2xi32>) -> tensor<2xf32> func.return %0 : tensor<2xf32> } // ----- // CHECK-LABEL: testGatherUnknownRank func.func @testGatherUnknownRank(%arg0 : tensor<*xf32>, %arg1 : tensor<1xi32>) -> tensor<*xf32> { %0 = "tfl.gather"(%arg0, %arg1) {axis = 1 : i32}: (tensor<*xf32>,tensor<1xi32>) -> tensor<*xf32> func.return %0 : tensor<*xf32> } // ----- func.func @testGatherUnsupportedType(%arg0 : tensor, %arg1 : tensor) -> tensor { // expected-error @+1 {{op failed to verify that params and output must have same element type}} %0 = "tfl.gather"(%arg0, %arg1) {axis = 1 : i32}: (tensor,tensor) -> tensor func.return %0 : tensor } // ----- func.func @testGatherUnsupportedRank(%arg0 : tensor, %arg1 : tensor<1xi32>) -> tensor { // expected-error @+1 {{op failed to verify that operand 0 is 1-D}} %0 = "tfl.gather"(%arg0, %arg1) {axis = 1 : i32}: (tensor,tensor<1xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testGatherUnsupported2DStringInput(%arg0 : tensor, %arg1 : tensor) -> tensor<*x!tf_type.string> { // expected-error @+1 {{'tfl.gather' op expect 1d input when the given type is string, got 'tensor'}} %0 = "tfl.gather"(%arg0, %arg1) {axis = 1 : i32}: (tensor,tensor) -> tensor<*x!tf_type.string> func.return %0 : tensor<*x!tf_type.string> } // ----- // CHECK-LABEL: testGatherWithBatchDims func.func @testGatherWithBatchDims(%arg0 : tensor<2xf32>, %arg1 : tensor<2xi32>) -> tensor<2xf32> { %0 = "tfl.gather"(%arg0, %arg1) {axis = 1 : i32, batch_dims = 2 : i32}: (tensor<2xf32>,tensor<2xi32>) -> tensor<2xf32> func.return %0 : tensor<2xf32> } // ----- // CHECK-LABEL: testGatherNd func.func @testGatherNd(%arg0 : tensor, %arg1 : tensor) -> tensor { %0 = "tfl.gather_nd"(%arg0, %arg1) {axis = 1 : i32}: (tensor,tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testGatherNdI16Indices func.func @testGatherNdI16Indices(%arg0 : tensor, %arg1 : tensor) -> tensor { %0 = "tfl.gather_nd"(%arg0, %arg1) {axis = 1 : i32}: (tensor,tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testAbs func.func @testAbs(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.abs"(%arg0) %0 = "tfl.abs"(%arg0): (tensor) -> tensor func.return %0 : tensor } // CHECK-LABEL: testAddN func.func @testAddN(tensor, tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor, %arg2: tensor): // CHECK: "tfl.add_n"(%arg0, %arg1, %arg2) %0 = "tfl.add_n"(%arg0, %arg1, %arg2): (tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // test invalid AddN func.func @testAddNWrongOperandResultType(tensor, tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor, %arg2: tensor): // expected-error @+1 {{'tfl.add_n' op operand #0 must be variadic of tensor of 32-bit float or 32-bit signless integer}} %0 = "tfl.add_n"(%arg0, %arg1, %arg2): (tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testLog func.func @testLog(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.log"(%arg0) %0 = "tfl.log"(%arg0): (tensor) -> tensor func.return %0 : tensor } // CHECK-LABEL: testLogStaticShapeInputAndDynamicShapeOutput func.func @testLogStaticShapeInputAndDynamicShapeOutput(tensor<8 x f32>) -> tensor { ^bb0(%arg0: tensor<8 x f32>): // CHECK: "tfl.log"(%arg0) %0 = "tfl.log"(%arg0): (tensor<8 x f32>) -> tensor func.return %0 : tensor } // CHECK-LABEL: testLogQuantInt8 func.func @testLogQuantInt8(%arg0: tensor<1x80x128x!quant.uniform>) -> tensor<1x80x128x!quant.uniform> { %0 = "tfl.log"(%arg0): (tensor<1x80x128x!quant.uniform>) -> tensor<1x80x128x!quant.uniform> func.return %0 : tensor<1x80x128x!quant.uniform> } // CHECK-LABEL: testNeg func.func @testNeg(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.neg"(%arg0) %0 = "tfl.neg"(%arg0): (tensor) -> tensor func.return %0 : tensor } // CHECK-LABEL: testRsqrt func.func @testRsqrt(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.rsqrt"(%arg0) %0 = "tfl.rsqrt"(%arg0): (tensor) -> tensor func.return %0 : tensor } // CHECK-LABEL: testRsqrtQuant func.func @testRsqrtQuant(%arg0: tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1x!quant.uniform> { %0 = "tfl.rsqrt"(%arg0) : (tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1x!quant.uniform> func.return %0 : tensor<1x80x1x!quant.uniform> } // CHECK-LABEL: testRsqrtQuantWithQI16 func.func @testRsqrtQuantWithQI16(%arg0: tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1x!quant.uniform> { %0 = "tfl.rsqrt"(%arg0) : (tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1x!quant.uniform> return %0 : tensor<1x80x1x!quant.uniform> } // CHECK-LABEL: testSin func.func @testSin(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.sin"(%arg0) %0 = "tfl.sin"(%arg0): (tensor) -> tensor func.return %0 : tensor } // ----- // test invalid Sin input func.func @testSinWithWrongInputType(tensor) -> tensor { ^bb0(%arg0: tensor): // expected-error @+1 {{tfl.sin' op operand #0 must be tensor of 32-bit float or 16-bit float values}} %0 = "tfl.sin"(%arg0): (tensor) -> tensor func.return %0#0 : tensor } // ----- // test invalid Sqrt input func.func @testSqrtWithWrongInputType(tensor) -> tensor { ^bb0(%arg0: tensor): // expected-error @+1 {{'tfl.sqrt' op operand #0 must be tensor of 32-bit float or QI8 type or QI16 type values}} %0 = "tfl.sqrt"(%arg0): (tensor) -> tensor func.return %0#0 : tensor } // ----- // test invalid Square input func.func @testSquareWithWrongInputType(tensor) -> tensor { ^bb0(%arg0: tensor): // expected-error @+1 {{tfl.square' op operand #0 must be tensor of 32-bit float values}} %0 = "tfl.square"(%arg0): (tensor) -> tensor func.return %0#0 : tensor } // ----- // CHECK-LABEL: testSquaredDifferenceQuant func.func @testSquaredDifferenceQuant(%arg0: tensor<1x80x128x!quant.uniform>, %arg1: tensor<1x80x128x!quant.uniform>) -> tensor<1x80x128x!quant.uniform> { %0 = "tfl.squared_difference"(%arg0, %arg1) : (tensor<1x80x128x!quant.uniform>, tensor<1x80x128x!quant.uniform>) -> tensor<1x80x128x!quant.uniform> func.return %0 : tensor<1x80x128x!quant.uniform> } // ----- // CHECK-LABEL: testSqrt func.func @testSqrt(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.sqrt"(%arg0) %0 = "tfl.sqrt"(%arg0): (tensor) -> tensor func.return %0 : tensor } // CHECK-LABEL: testSqrtQuant func.func @testSqrtQuant(%arg0: tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1x!quant.uniform> { %0 = "tfl.sqrt"(%arg0) : (tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1x!quant.uniform> func.return %0 : tensor<1x80x1x!quant.uniform> } // CHECK-LABEL: testSqrtQuantWithQI16 func.func @testSqrtQuantWithQI16(%arg0: tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1x!quant.uniform> { %0 = "tfl.sqrt"(%arg0) : (tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1x!quant.uniform> func.return %0 : tensor<1x80x1x!quant.uniform> } // CHECK-LABEL: testSquare func.func @testSquare(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.square"(%arg0) %0 = "tfl.square"(%arg0): (tensor) -> tensor func.return %0 : tensor } func.func @testQuantizedResizeNearestNeighbor(tensor>, tensor) -> tensor> { ^bb0(%arg0: tensor>, %arg1: tensor): %0 = "tfl.resize_nearest_neighbor"(%arg0, %arg1) { align_corners = false, half_pixel_centers = false } : (tensor>, tensor) -> tensor> func.return %0 : tensor> } // CHECK-LABEL: testTanh func.func @testTanh(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.tanh"(%arg0) %0 = "tfl.tanh"(%arg0): (tensor) -> tensor func.return %0 : tensor } // CHECK-LABEL: testTanhWithQI8 func.func @testTanhWithQI8(%arg0: tensor>) -> tensor> { %0 = "tfl.tanh"(%arg0): (tensor>) -> tensor> func.return %0 : tensor> } // CHECK-LABEL: testTanhWithQUI8 func.func @testTanhWithQUI8(%arg0: tensor>) -> tensor> { %0 = "tfl.tanh"(%arg0): (tensor>) -> tensor> func.return %0 : tensor> } // CHECK-LABEL: testZerosLike func.func @testZerosLike(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.zeros_like"(%arg0) %0 = "tfl.zeros_like"(%arg0): (tensor) -> tensor func.return %0 : tensor } // CHECK-LABEL: testDequantize func.func @testDequantize(tensor>) -> tensor { ^bb0(%arg0: tensor>): // CHECK: "tfl.dequantize"(%arg0) : (tensor>) -> tensor %0 = "tfl.dequantize"(%arg0): (tensor>) -> tensor func.return %0 : tensor } // CHECK-LABEL: testLogicalNot func.func @testLogicalNot(tensor) -> tensor { ^bb0(%arg0: tensor): // CHECK: "tfl.logical_not"(%arg0) %0 = "tfl.logical_not"(%arg0): (tensor) -> tensor func.return %0 : tensor } // CHECK-LABEL: testSign func.func @testSign(%arg0: tensor) -> tensor { %0 = "tfl.sign"(%arg0): (tensor) -> tensor func.return %0 : tensor } // ----- func.func @testLogicalNotWrongOperandType(tensor) -> tensor { ^bb0(%arg0: tensor): // expected-error @+1 {{'tfl.logical_not' op operand #0 must be tensor of 1-bit signless integer values}} %0 = "tfl.logical_not"(%arg0) : (tensor) -> tensor func.return %0 : tensor } // Binary math ops // ----- // CHECK-LABEL: testAdd func.func @testAdd(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // TODO(jpienaar): Enable specifying label of enum for parsing. // CHECK: tfl.add %arg0, %arg1 {fused_activation_function = "RELU6"} %0 = tfl.add %arg0, %arg1 {fused_activation_function = "RELU6"} : tensor func.return %0#0 : tensor } // CHECK-LABEL: testAddInt16 func.func @testAddInt16(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.add %arg0, %arg1 {fused_activation_function = "RELU6"} %0 = tfl.add %arg0, %arg1 {fused_activation_function = "RELU6"} : tensor func.return %0#0 : tensor } // CHECK-LABEL: testSub func.func @testSub(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.sub %arg0, %arg1 {fused_activation_function = "RELU6"} %0 = tfl.sub %arg0, %arg1 {fused_activation_function = "RELU6"} : tensor func.return %0#0 : tensor } // CHECK-LABEL: testSubInt64 func.func @testSubInt64(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.sub %arg0, %arg1 {fused_activation_function = "RELU6"} %0 = tfl.sub %arg0, %arg1 {fused_activation_function = "RELU6"} : tensor func.return %0#0 : tensor } // CHECK-LABEL: testMul func.func @testMul(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.mul %arg0, %arg1 {fused_activation_function = "RELU6"} %0 = tfl.mul %arg0, %arg1 {fused_activation_function = "RELU6"} : tensor func.return %0#0 : tensor } // CHECK-LABEL: testMul32BitUInt func.func @testMul32BitUInt(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.mul %arg0, %arg1 {fused_activation_function = "RELU6"} %0 = tfl.mul %arg0, %arg1 {fused_activation_function = "RELU6"} : tensor func.return %0#0 : tensor } // CHECK-LABEL: testMul16BitInt func.func @testMul16BitInt(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.mul %arg0, %arg1 {fused_activation_function = "RELU6"} %0 = tfl.mul %arg0, %arg1 {fused_activation_function = "RELU6"} : tensor func.return %0#0 : tensor } // CHECK-LABEL: testMulComplex func.func @testMulComplex(tensor>, tensor>) -> tensor> { ^bb0(%arg0: tensor>, %arg1: tensor>): // CHECK: tfl.mul %arg0, %arg1 {fused_activation_function = "NONE"} %0 = tfl.mul %arg0, %arg1 {fused_activation_function = "NONE"}: tensor> func.return %0#0 : tensor> } // CHECK-LABEL: testAddWithI64Broadcasting func.func @testAddWithI64Broadcasting(tensor< 2x3xi64>, tensor<3xi64>) -> tensor<2x3xi64> { ^bb0(%arg0: tensor<2x3xi64>, %arg1: tensor<3xi64>): // CHECK: tfl.add(%arg0, %arg1) %0 = tfl.add(%arg0, %arg1) {fused_activation_function = "RELU6"} : (tensor< 2x3xi64>, tensor<3xi64>) -> tensor<2x3xi64> func.return %0#0 : tensor<2x3xi64> } // ----- // CHECK-LABEL: add_with_i32_five_dim_broadcasting func.func @add_with_i32_five_dim_broadcasting(tensor<1x1x1x1x1xi32>, tensor<1xi32>) -> tensor<1x1x1x1x1xi32> { ^bb0(%arg0: tensor<1x1x1x1x1xi32>, %arg1: tensor<1xi32>): // CHECK: tfl.add(%arg0, %arg1) <{fused_activation_function = "RELU6"}> %0 = "tfl.add"(%arg0, %arg1) {fused_activation_function = "RELU6"} : (tensor<1x1x1x1x1xi32>, tensor<1xi32>) -> tensor<1x1x1x1x1xi32> func.return %0#0 : tensor<1x1x1x1x1xi32> } // ----- func.func @add_with_quantized_i16_broadcasting(tensor<2x2xf32>, tensor<1xf32>) -> tensor<2x2x!quant.any> { ^bb0(%arg0: tensor<2x2xf32>, %arg1: tensor<1xf32>): // expected-error @+1 {{Operands should have valid shapes and element type needs to match}} %0 = "tfl.add"(%arg0, %arg1) {fused_activation_function = "RELU6"} : (tensor<2x2xf32>, tensor<1xf32>) -> tensor<2x2x!quant.any> func.return %0#0 : tensor<2x2x!quant.any> } // ----- // CHECK-LABEL: sub_with_i32_five_dim_broadcasting func.func @sub_with_i32_five_dim_broadcasting(tensor<1x1x1x1x1xi32>, tensor<1xi32>) -> tensor<1x1x1x1x1xi32> { ^bb0(%arg0: tensor<1x1x1x1x1xi32>, %arg1: tensor<1xi32>): // CHECK: tfl.sub(%arg0, %arg1) <{fused_activation_function = "RELU6"}> %0 = "tfl.sub"(%arg0, %arg1) {fused_activation_function = "RELU6"} : (tensor<1x1x1x1x1xi32>, tensor<1xi32>) -> tensor<1x1x1x1x1xi32> func.return %0#0 : tensor<1x1x1x1x1xi32> } // ----- func.func @sub_with_quantized_i8_five_dim_broadcasting(tensor<1x1x1x1x1xf32>, tensor<1xf32>) -> tensor<1x1x1x1x1x!quant.any> { ^bb0(%arg0: tensor<1x1x1x1x1xf32>, %arg1: tensor<1xf32>): %0 = "tfl.sub"(%arg0, %arg1) {fused_activation_function = "RELU6"} : (tensor<1x1x1x1x1xf32>, tensor<1xf32>) -> tensor<1x1x1x1x1x!quant.any> func.return %0#0 : tensor<1x1x1x1x1x!quant.any> } // ----- // CHECK-LABEL: mul_with_i32_five_dim_broadcasting func.func @mul_with_i32_five_dim_broadcasting(tensor<1x1x1x1x1xi32>, tensor<1xi32>) -> tensor<1x1x1x1x1xi32> { ^bb0(%arg0: tensor<1x1x1x1x1xi32>, %arg1: tensor<1xi32>): // CHECK: tfl.mul(%arg0, %arg1) <{fused_activation_function = "RELU6"}> %0 = "tfl.mul"(%arg0, %arg1) {fused_activation_function = "RELU6"} : (tensor<1x1x1x1x1xi32>, tensor<1xi32>) -> tensor<1x1x1x1x1xi32> func.return %0#0 : tensor<1x1x1x1x1xi32> } // ----- // CHECK-LABEL: mul_with_quantized_i16_five_dim_broadcasting func.func @mul_with_quantized_i16_five_dim_broadcasting(tensor<1x1x1x1x1x!quant.any>, tensor<1x!quant.any>) -> tensor<1x1x1x1x1x!quant.any> { ^bb0(%arg0: tensor<1x1x1x1x1x!quant.any>, %arg1: tensor<1x!quant.any>): // CHECK: tfl.mul(%arg0, %arg1) <{fused_activation_function = "RELU6"}> %0 = "tfl.mul"(%arg0, %arg1) {fused_activation_function = "RELU6"} : (tensor<1x1x1x1x1x!quant.any>, tensor<1x!quant.any>) -> tensor<1x1x1x1x1x!quant.any> func.return %0#0 : tensor<1x1x1x1x1x!quant.any> } // ----- func.func @mul_with_quantized_i16_to_uint8_broadcasting(tensor<1x1x!quant.any>, tensor<1x!quant.any>) -> tensor<1x1x!quant.any> { ^bb0(%arg0: tensor<1x1x!quant.any>, %arg1: tensor<1x!quant.any>): // expected-error @+1 {{Operands do not have valid shapes}} %0 = "tfl.mul"(%arg0, %arg1) {fused_activation_function = "RELU6"} : (tensor<1x1x!quant.any>, tensor<1x!quant.any>) -> tensor<1x1x!quant.any> func.return %0#0 : tensor<1x1x!quant.any> } // ----- // CHECK-LABEL: testMulNonQuantizedOperandsandQuantizedResult func.func @testMulNonQuantizedOperandsandQuantizedResult(tensor, tensor) -> tensor> { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.mul(%arg0, %arg1) <{fused_activation_function = "RELU6"}> %0 = "tfl.mul"(%arg0, %arg1) {fused_activation_function = "RELU6"}: (tensor, tensor) -> tensor> func.return %0#0 : tensor> } // ----- func.func @testMulInvalidOperands(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // expected-error @+1 {{failed to verify that binary op operands have same element type}} %0 = "tfl.mul"(%arg0, %arg1) {fused_activation_function = "RELU6"}: (tensor, tensor) -> tensor func.return %0#0 : tensor } // ----- func.func @testMulInvalidQuantizedOperands(tensor<* x !quant.any>, tensor<* x !quant.any>) -> tensor<* x !quant.any> { ^bb0(%arg0: tensor<* x !quant.any>, %arg1: tensor<* x !quant.any>): // expected-error @+1 {{failed to verify that binary op operands have same element type}} %0 = "tfl.mul"(%arg0, %arg1) {fused_activation_function = "RELU6"}: (tensor<* x !quant.any>, tensor<* x !quant.any>) -> tensor<* x !quant.any> func.return %0#0 : tensor<* x !quant.any> } // ----- // CHECK-LABEL: testDiv func.func @testDiv(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.div %arg0, %arg1 {fused_activation_function = "RELU6"} %0 = tfl.div %arg0, %arg1 {fused_activation_function = "RELU6"} : tensor func.return %0#0 : tensor } // CHECK-LABEL: testLess func.func @testLess(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.less(%arg0, %arg1) %0 = "tfl.less"(%arg0, %arg1) : (tensor, tensor) -> tensor func.return %0#0 : tensor } // CHECK-LABEL: testLessInt16 func.func @testLessInt16(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.less(%arg0, %arg1) %0 = "tfl.less"(%arg0, %arg1) : (tensor, tensor) -> tensor func.return %0#0 : tensor } // CHECK-LABEL: testGreaterEqual func.func @testGreaterEqual(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.greater_equal(%arg0, %arg1) %0 = "tfl.greater_equal"(%arg0, %arg1) : (tensor, tensor) -> tensor func.return %0#0 : tensor } // CHECK-LABEL: testGreaterEqualInt16 func.func @testGreaterEqualInt16(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.greater_equal(%arg0, %arg1) %0 = "tfl.greater_equal"(%arg0, %arg1) : (tensor, tensor) -> tensor func.return %0#0 : tensor } // ----- // CHECK-LABEL: testFloorDivI32 func.func @testFloorDivI32(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.floor_div %arg0, %arg1 %0 = tfl.floor_div %arg0, %arg1 : tensor func.return %0#0 : tensor } // ----- // CHECK-LABEL: testFloorDivF32 func.func @testFloorDivF32(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.floor_div %arg0, %arg1 %0 = tfl.floor_div %arg0, %arg1 : tensor func.return %0#0 : tensor } // ----- func.func @testFloorDivF32(%arg0: tensor<2 x f32>, %arg1: tensor<2 x i32>) -> tensor<2 x f32> { // expected-error @+1 {{failed to verify that binary op operands have same element type}} %0 = "tfl.floor_div"(%arg0, %arg1) : (tensor<2 x f32>, tensor<2 x i32>) -> tensor<2 x f32> func.return %0#0 : tensor<2 x f32> } // ----- // CHECK-LABEL: testFloorMod func.func @testFloorMod(%arg0: tensor, %arg1: tensor) -> tensor { %0 = "tfl.floor_mod"(%arg0, %arg1) : (tensor, tensor) -> tensor func.return %0 : tensor } // CHECK-LABEL: testPow func.func @testPow(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.pow %arg0, %arg1 %0 = tfl.pow %arg0, %arg1 : tensor func.return %0#0 : tensor } // CHECK-LABEL: testAtan2 func.func @testAtan2(%arg0: tensor, %arg1: tensor) -> tensor { // CHECK: "tfl.atan2"(%arg0, %arg1) %0 = "tfl.atan2"(%arg0, %arg1): (tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testConv2D func.func @testConv2D(tensor<256x32x32x3xf32>, tensor<16x3x3x3xf32>, tensor<16xf32>) -> tensor<256x32x32x16xf32> { ^bb0(%arg0: tensor<256x32x32x3xf32>, %arg1: tensor<16x3x3x3xf32>, %arg2: tensor<16xf32>): // CHECK: "tfl.conv_2d"(%arg0, %arg1, %arg2) %0 = "tfl.conv_2d"(%arg0, %arg1, %arg2) {dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "SAME", stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "RELU6"} : (tensor<256x32x32x3xf32>, tensor<16x3x3x3xf32>, tensor<16xf32>) -> tensor<256x32x32x16xf32> func.return %0 : tensor<256x32x32x16xf32> } // CHECK-LABEL: testConv2DNoBias func.func @testConv2DNoBias(%arg0: tensor<256x32x32x3xf32>, %arg1: tensor<16x3x3x3xf32>, %arg2: none) -> tensor<256x32x32x16xf32> { // CHECK: "tfl.conv_2d"(%arg0, %arg1, %arg2) %0 = "tfl.conv_2d"(%arg0, %arg1, %arg2) {dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "SAME", stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "RELU6"} : (tensor<256x32x32x3xf32>, tensor<16x3x3x3xf32>, none) -> tensor<256x32x32x16xf32> func.return %0 : tensor<256x32x32x16xf32> } // ----- func.func @testConv2D4DBias(tensor<256x32x32x3xf32>, tensor<16x3x3x3xf32>, tensor<1x1x1x16xf32>) -> tensor<256x32x32x16xf32> { ^bb0(%arg0: tensor<256x32x32x3xf32>, %arg1: tensor<16x3x3x3xf32>, %arg2: tensor<1x1x1x16xf32>): // expected-error-re @+1 {{'tfl.conv_2d' op operand #2 must be 1D tensor of any {{(non-token )?}}type values or none type, but got 'tensor<1x1x1x16xf32>'}} %0 = "tfl.conv_2d"(%arg0, %arg1, %arg2) {dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "SAME", stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "RELU6"} : (tensor<256x32x32x3xf32>, tensor<16x3x3x3xf32>, tensor<1x1x1x16xf32>) -> tensor<256x32x32x16xf32> func.return %0 : tensor<256x32x32x16xf32> } // ----- // CHECK-LABEL: testFakeQuant func.func @testFakeQuant(tensor, f32, f32) -> tensor { ^bb0(%arg0: tensor, %arg1: f32, %arg2: f32): // CHECK: "tfl.fake_quant"(%arg0) <{max = 1.400000e+00 : f32, min = 3.000000e-01 : f32, narrow_range = false, num_bits = 6 : i32}> : (tensor) -> tensor %1 = "tfl.fake_quant"(%arg0) {num_bits = 6 : i32, narrow_range = false, min = 0.3:f32, max = 1.4:f32} : (tensor) -> tensor func.return %1 : tensor } // CHECK-LABEL: testQuantize func.func @testQuantize(tensor) -> tensor> { ^bb0(%arg0: tensor): // CHECK: %0 = "tfl.quantize"(%arg0) <{qtype = tensor>}> %0 = "tfl.quantize"(%arg0) {qtype = tensor>} : (tensor) -> tensor> func.return %0 : tensor> } // CHECK-LABEL: testLogicalAnd func.func @testLogicalAnd(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.logical_and %arg0, %arg1 %0 = "tfl.logical_and"(%arg0, %arg1) : (tensor, tensor) -> tensor func.return %0#0 : tensor } // ----- func.func @testLogicalAndWrongOperandType(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // expected-error @+1 {{'tfl.logical_and' op operand #0 must be tensor of 1-bit signless integer values}} %0 = "tfl.logical_and"(%arg0, %arg1) : (tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testLogicalOr func.func @testLogicalOr(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.logical_or %arg0, %arg1 %0 = "tfl.logical_or"(%arg0, %arg1) : (tensor, tensor) -> tensor func.return %0#0 : tensor } // ----- func.func @testLogicalOrWrongOperandType(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // expected-error @+1 {{'tfl.logical_or' op operand #0 must be tensor of 1-bit signless integer values}} %0 = "tfl.logical_or"(%arg0, %arg1) : (tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testEluF32 func.func @testEluF32(%arg0: tensor) -> tensor { // CHECK: "tfl.elu"(%arg0) %0 = "tfl.elu"(%arg0): (tensor) -> tensor func.return %0#0 : tensor } // ----- // CHECK-LABEL: testTileF32 func.func @testTileF32(%arg0: tensor<4 x 1 x f32>, %arg1: tensor<4 x i32>) -> tensor { // CHECK: "tfl.tile"(%arg0, %arg1) %0 = "tfl.tile"(%arg0, %arg1): (tensor<4 x 1 x f32>, tensor<4 x i32>) -> tensor func.return %0 : tensor } // ----- func.func @testEluI32(%arg0: tensor) -> tensor { // expected-error @+1 {{operand #0 must be tensor of 32-bit float or 8-bit signless integer values}} %0 = "tfl.elu"(%arg0): (tensor) -> tensor func.return %0#0 : tensor } // ----- func.func @testFusedActivationFunction(%arg0: tensor<4xi32>, %arg1: tensor<4xi32>) -> (tensor<4xi32>, tensor<4xi32>, tensor<4xi32>, tensor<4xi32>, tensor<4xi32>, tensor<4xi32>) { // CHECK: "NONE" %0 = tfl.add %arg0, %arg1 {fused_activation_function = "NONE"} : tensor<4xi32> // CHECK: "RELU" %1 = tfl.add %arg0, %arg1 {fused_activation_function = "RELU"} : tensor<4xi32> // CHECK: "RELU_N1_TO_1" %2 = tfl.add %arg0, %arg1 {fused_activation_function = "RELU_N1_TO_1"} : tensor<4xi32> // CHECK: "RELU6" %3 = tfl.add %arg0, %arg1 {fused_activation_function = "RELU6"} : tensor<4xi32> // CHECK: "TANH" %4 = tfl.add %arg0, %arg1 {fused_activation_function = "TANH"} : tensor<4xi32> // CHECK: "SIGN_BIT" %5 = tfl.add %arg0, %arg1 {fused_activation_function = "SIGN_BIT"} : tensor<4xi32> func.return %0, %1, %2, %3, %4, %5: tensor<4xi32>, tensor<4xi32>, tensor<4xi32>, tensor<4xi32>, tensor<4xi32>, tensor<4xi32> } // ----- func.func @testFusedActivationFunction(%arg0: tensor<4xi32>, %arg1: tensor<4xi32>) -> tensor<4xi32> { // expected-error @+1 {{attribute 'fused_activation_function' failed to satisfy constraint: string attribute whose value is NONE, or RELU, or RELU_N1_TO_1, or RELU6, or TANH, or SIGN_BIT}} %0 = tfl.add %arg0, %arg1 {fused_activation_function = "Relu6"} : tensor<4xi32> func.return %0: tensor<4xi32> } // ----- func.func @testPadding(%arg0: tensor<256x32x32x3xf32>, %arg1: tensor<16x3x3x3xf32>, %arg2: tensor<16xf32>) -> (tensor<256x32x32x16xf32>, tensor<256x30x30x16xf32>) { // CHECK: "SAME" %0 = "tfl.conv_2d"(%arg0, %arg1, %arg2) {dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, fused_activation_function = "NONE", padding = "SAME", stride_h = 1 : i32, stride_w = 1 : i32} : (tensor<256x32x32x3xf32>, tensor<16x3x3x3xf32>, tensor<16xf32>) -> tensor<256x32x32x16xf32> // CHECK: "VALID" %1 = "tfl.conv_2d"(%arg0, %arg1, %arg2) {dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, fused_activation_function = "NONE", padding = "VALID", stride_h = 1 : i32, stride_w = 1 : i32} : (tensor<256x32x32x3xf32>, tensor<16x3x3x3xf32>, tensor<16xf32>) -> tensor<256x30x30x16xf32> func.return %0, %1 : tensor<256x32x32x16xf32>, tensor<256x30x30x16xf32> } // ----- func.func @testPadding(%arg0: tensor<256x32x32x3xf32>, %arg1: tensor<16x3x3x3xf32>, %arg2: tensor<16xf32>) -> tensor<256x30x30x16xf32> { // expected-error @+1 {{op attribute 'padding' failed to satisfy constraint: string attribute whose value is SAME, or VALID}} %0 = "tfl.conv_2d"(%arg0, %arg1, %arg2) {dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, fused_activation_function = "NONE", padding = "SOMETHING", stride_h = 1 : i32, stride_w = 1 : i32} : (tensor<256x32x32x3xf32>, tensor<16x3x3x3xf32>, tensor<16xf32>) -> tensor<256x30x30x16xf32> func.return %0 : tensor<256x30x30x16xf32> } // ----- // CHECK-LABEL: testMaxPool2D func.func @testMaxPool2D(tensor<256x32x32x3xf32>) -> tensor { ^bb0(%arg0: tensor<256x32x32x3xf32>): // CHECK: "tfl.max_pool_2d"(%arg0) <{filter_height = 1 : i32, filter_width = 1 : i32, fused_activation_function = "RELU6", padding = "SAME", stride_h = 1 : i32, stride_w = 1 : i32}> : (tensor<256x32x32x3xf32>) -> tensor %0 = "tfl.max_pool_2d"(%arg0) {filter_height = 1 : i32, filter_width = 1 : i32, fused_activation_function = "RELU6", padding = "SAME", stride_h = 1 : i32, stride_w = 1 : i32} : (tensor<256x32x32x3xf32>) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testMaxPool2DQuantized func.func @testMaxPool2DQuantized(tensor<256x32x32x3x!quant.uniform>) -> tensor> { ^bb0(%arg0: tensor<256x32x32x3x!quant.uniform>): // CHECK: "tfl.max_pool_2d"(%arg0) <{filter_height = 1 : i32, filter_width = 1 : i32, fused_activation_function = "RELU6", padding = "SAME", stride_h = 1 : i32, stride_w = 1 : i32}> %0 = "tfl.max_pool_2d"(%arg0) {filter_height = 1 : i32, filter_width = 1 : i32, fused_activation_function = "RELU6", padding = "SAME", stride_h = 1 : i32, stride_w = 1 : i32} : (tensor<256x32x32x3x!quant.uniform>) -> tensor> func.return %0 : tensor> } // ----- // test invalid MaxPool2D func.func @testMaxPool2DWrongOperandResultType(tensor<1x7x7x16xi32>) -> tensor<1x7x7x16xi32> { ^bb0(%arg0: tensor<1x7x7x16xi32>): // expected-error @+1 {{'tfl.max_pool_2d' op operand #0 must be tensor of 32-bit float or QUI8 type or QI8 type or QI16 type or TFLite quint8 type values, but got 'tensor<1x7x7x16xi32>'}} %0 = "tfl.max_pool_2d"(%arg0) {filter_height = 1 : i32, filter_width = 1 : i32, fused_activation_function = "RELU6", padding = "SAME", stride_h = 1 : i32, stride_w = 1 : i32} : (tensor<1x7x7x16xi32>) -> tensor<1x7x7x16xi32> func.return %0 : tensor<1x7x7x16xi32> } // ----- // test invalid MaxPool2D func.func @testMaxPool2DWrongOperandStorageType(tensor<1x7x7x16x!quant.uniform>) -> tensor<1x7x7x16x!quant.uniform> { ^bb0(%arg0: tensor<1x7x7x16x!quant.uniform>): // expected-error @+1 {{'tfl.max_pool_2d' op operand #0 must be tensor of 32-bit float or QUI8 type or QI8 type or QI16 type or TFLite quint8 type values, but got 'tensor<1x7x7x16x!quant.uniform>'}} %0 = "tfl.max_pool_2d"(%arg0) {filter_height = 1 : i32, filter_width = 1 : i32, fused_activation_function = "RELU6", padding = "SAME", stride_h = 1 : i32, stride_w = 1 : i32} : (tensor<1x7x7x16x!quant.uniform>) -> tensor<1x7x7x16x!quant.uniform> func.return %0 : tensor<1x7x7x16x!quant.uniform> } // ----- func.func @testTFLiteDetectionPostProcess(%arg0: tensor<1x64x64x32xf32>, %arg1: tensor<1x64x64x32xf32>, %arg2: tensor<1x64x64x32xf32>) -> (tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>) { %0, %1, %2, %3 = "tfl.custom_tf"(%arg0, %arg1, %arg2) ({ ^bb0(%a0: tensor<1x64x64x32xf32>, %a1: tensor<1x64x64x32xf32>, %a2: tensor<1x64x64x32xf32>): %4, %5, %6, %7 = "tf.TFLite_Detection_PostProcess"(%a0, %a1, %a2) {_output_quantized = true, _output_types = [f32, f32, f32, f32], _support_output_type_float_in_quantized_op = true, detections_per_class = 100 : i64, device = "", h_scale = 5.000000e+00 : f32, max_classes_per_detection = 1 : i64, max_detections = 20 : i64, nms_iou_threshold = 6.000000e-01 : f32, nms_score_threshold = 3.000000e-01 : f32, num_classes = 90 : i64, use_regular_nms = false, w_scale = 5.000000e+00 : f32, x_scale = 1.000000e+01 : f32, y_scale = 1.000000e+01 : f32} : (tensor<1x64x64x32xf32>, tensor<1x64x64x32xf32>, tensor<1x64x64x32xf32>) -> (tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>) "tfl.yield"(%4, %5, %6, %7) : (tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>) -> () }) : (tensor<1x64x64x32xf32>, tensor<1x64x64x32xf32>, tensor<1x64x64x32xf32>) -> (tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>) func.return %0, %1 : tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32> } // ----- func.func @testMaxPoolingWithArgMax2D(%arg0: tensor<1x64x64x32xf32>) -> (tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>) { // custom op for "tfl.max_pooling_with_argmax_2d"(%arg0) {filter_h = 2 : i32, filter_w = 2 : i32, padding = "SAME", stride_h = 2 : i32, stride_w = 2 : i32} : (tensor<1x64x64x32xf32>) -> (tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>) %0, %1 = "tfl.custom"(%arg0) {custom_option = #tfl, custom_code = "MaxPoolingWithArgmax2D"} : (tensor<1x64x64x32xf32>) -> (tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>) func.return %0, %1 : tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32> } // ----- func.func @testMaxUnpooling2D(%arg0: tensor<1x8x8x128xf32>, %arg1: tensor<1x8x8x128xf32>) -> tensor<1x8x8x128xf32> { // custom op for "tfl.max_unpooling_2d"(%arg0, %arg1) {filter_h = 2 : i32, filter_w = 2 : i32, padding = "SAME", stride_h = 2 : i32, stride_w = 2 : i32} : (tensor<1x8x8x128xf32>, tensor<1x8x8x128xf32>) -> (tensor<1x8x8x128xf32>) %0 = "tfl.custom"(%arg0, %arg1) {custom_option = #tfl, custom_code = "MaxUnpooling2D"} : (tensor<1x8x8x128xf32>, tensor<1x8x8x128xf32>) -> (tensor<1x8x8x128xf32>) func.return %0 : tensor<1x8x8x128xf32> } // ----- // CHECK-LABEL: testLogistic func.func @testLogistic(tensor<1x2x3x4x5xf32>) -> tensor<1x2x3x4x5xf32> { ^bb0(%arg0: tensor<1x2x3x4x5xf32>): // CHECK: "tfl.logistic"(%arg0) %0 = "tfl.logistic"(%arg0): (tensor<1x2x3x4x5xf32>) -> tensor<1x2x3x4x5xf32> func.return %0 : tensor<1x2x3x4x5xf32> } // ----- // test invalid Logistic input func.func @testLogisticWithWrongInputType(tensor) -> tensor { ^bb0(%arg0: tensor): // expected-error @+1 {{'tfl.logistic' op operand #0 must be tensor of 32-bit float or QI8 type or QUI8 type or QI16 type or TFLite quint8 type values, but got 'tensor'}} %0 = "tfl.logistic"(%arg0): (tensor) -> tensor func.return %0#0 : tensor } // ----- // CHECK-LABEL: testUnidirectionalSequenceRnn func.func @testUnidirectionalSequenceRnn(%arg0: tensor, %arg1: tensor, %arg2: tensor, %arg3: tensor, %arg4: tensor) -> tensor { // CHECK: "tfl.unidirectional_sequence_rnn"(%arg0, %arg1, %arg2, %arg3, %arg4) <{fused_activation_function = "NONE", time_major = false}> : (tensor, tensor, tensor, tensor, tensor) -> tensor %0 = "tfl.unidirectional_sequence_rnn"(%arg0, %arg1, %arg2, %arg3, %arg4) {fused_activation_function = "NONE", time_major = false} : (tensor, tensor, tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testUnidirectionalSequenceLstmWithoutProjection func.func @testUnidirectionalSequenceLstmWithoutProjection(%arg0: tensor, %arg1: tensor, %arg2: tensor, %arg3: tensor, %arg4: tensor, %arg5: tensor, %arg6: tensor, %arg7: tensor, %arg8: tensor, %arg9: tensor, %arg10: tensor, %arg11: tensor, %arg12: tensor, %arg13: tensor, %arg14: tensor, %arg15: tensor, %arg16: none, %arg17: none, %arg18: tensor, %arg19: tensor, %arg20: tensor, %arg21: tensor, %arg22: tensor, %arg23: tensor) -> tensor { // CHECK: "tfl.unidirectional_sequence_lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) <{fused_activation_function = "NONE", time_major = false}> : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, none, none, tensor, tensor, tensor, tensor, tensor, tensor) -> tensor %0 = "tfl.unidirectional_sequence_lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) {fused_activation_function = "NONE", time_major = false} : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, none, none, tensor, tensor, tensor, tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testUnidirectionalSequenceLstm func.func @testUnidirectionalSequenceLstm(%arg0: tensor, %arg1: tensor, %arg2: tensor, %arg3: tensor, %arg4: tensor, %arg5: tensor, %arg6: tensor, %arg7: tensor, %arg8: tensor, %arg9: tensor, %arg10: tensor, %arg11: tensor, %arg12: tensor, %arg13: tensor, %arg14: tensor, %arg15: tensor, %arg16: tensor, %arg17: tensor, %arg18: tensor, %arg19: tensor, %arg20: tensor, %arg21: tensor, %arg22: tensor, %arg23: tensor) -> tensor { // CHECK: "tfl.unidirectional_sequence_lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) <{fused_activation_function = "NONE", time_major = false}> : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor) -> tensor %0 = "tfl.unidirectional_sequence_lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) {fused_activation_function = "NONE", time_major = false} : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testUnidirectionalSequenceLstmWithNoneTypeAndOverrideAttr func.func @testUnidirectionalSequenceLstmWithNoneTypeAndOverrideAttr(%arg0: tensor, %arg1: none, %arg2: tensor, %arg3: tensor, %arg4: tensor, %arg5: none, %arg6: tensor, %arg7: tensor, %arg8: tensor, %arg9: none, %arg10: tensor, %arg11: tensor, %arg12: none, %arg13: tensor, %arg14: tensor, %arg15: tensor, %arg16: tensor, %arg17: tensor, %arg18: tensor, %arg19: tensor, %arg20: none, %arg21: tensor, %arg22: tensor, %arg23: tensor) -> tensor { // CHECK: "tfl.unidirectional_sequence_lstm"(%arg0, // CHECK-SAME: %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, // CHECK-SAME: %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) <{cell_clip = 1.000000e+00 : f32, fused_activation_function = "NONE", time_major = false}> : // CHECK-SAME: (tensor, // CHECK-SAME: none, tensor, tensor, tensor, none, tensor, tensor, tensor, // CHECK-SAME: none, tensor, tensor, none, tensor, tensor, tensor, tensor, tensor, tensor, tensor, // CHECK-SAME: none, tensor, tensor, tensor) -> tensor %0 = "tfl.unidirectional_sequence_lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) {cell_clip = 1.000000e+00 : f32, fused_activation_function = "NONE", time_major = false} : (tensor, none, tensor, tensor, tensor, none, tensor, tensor, tensor, none, tensor, tensor, none, tensor, tensor, tensor, tensor, tensor, tensor, tensor, none, tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testUnidirectionalSequenceLstmWithIntermediates func.func @testUnidirectionalSequenceLstmWithIntermediates(%arg0: tensor, %arg1: tensor, %arg2: tensor, %arg3: tensor, %arg4: tensor, %arg5: tensor, %arg6: tensor, %arg7: tensor, %arg8: tensor, %arg9: tensor, %arg10: tensor, %arg11: tensor, %arg12: tensor, %arg13: tensor, %arg14: tensor, %arg15: tensor, %arg16: tensor, %arg17: tensor, %arg18: tensor, %arg19: tensor, %arg20: tensor, %arg21: tensor, %arg22: tensor, %arg23: tensor) -> tensor { // CHECK: "tfl.unidirectional_sequence_lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) <{cell_clip = 1.000000e+01 : f32, effective_hidden_scale_intermediate = tensor<0x!quant.uniform:f32, 0.0077881771139800549>>, fused_activation_function = "TANH", input_to_cell_intermediate = tensor<0xf32>, input_to_forget_intermediate = tensor<0xf32>, input_to_input_intermediate = tensor<0xf32>, input_to_output_intermediate = tensor<0xf32>, proj_clip = 0.000000e+00 : f32, time_major = false}> : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor) -> tensor %0 = "tfl.unidirectional_sequence_lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) {cell_clip = 1.000000e+01 : f32, effective_hidden_scale_intermediate = tensor<0x!quant.uniform:f32, 0.0077881771139800549>>, fused_activation_function = "TANH", input_to_cell_intermediate = tensor<0xf32>, input_to_forget_intermediate = tensor<0xf32>, input_to_input_intermediate = tensor<0xf32>, input_to_output_intermediate = tensor<0xf32>, proj_clip = 0.000000e+00 : f32, time_major = false} : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // test violation of projection weight and projection bias pred op trait func.func @testUnidirectionalSequenceLstmWithInvalidNoneType(%arg0: tensor, %arg1: tensor, %arg2: tensor, %arg3: tensor, %arg4: tensor, %arg5: tensor, %arg6: tensor, %arg7: tensor, %arg8: tensor, %arg9: tensor, %arg10: tensor, %arg11: tensor, %arg12: tensor, %arg13: tensor, %arg14: tensor, %arg15: tensor, %arg16: none, %arg17: tensor, %arg18: tensor, %arg19: tensor, %arg20: tensor, %arg21: tensor, %arg22: tensor, %arg23: tensor) -> tensor { // expected-error @+1 {{'tfl.unidirectional_sequence_lstm' op failed to verify that either projection weight must be specified or both projection weight and projection bias must not be specified}} %0 = "tfl.unidirectional_sequence_lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) {fused_activation_function = "NONE", time_major = false} : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, none, tensor, tensor, tensor, tensor, tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testLstmIntermediates func.func @testLstmIntermediates(%arg0: tensor<1x528x!quant.uniform>, %arg1: tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, %arg2: tensor<2048x528x!quant.uniform:f32, 0.031925998628139496>>, %arg3: tensor<2048x528x!quant.uniform:f32, 0.056272000074386597>>, %arg4: tensor<2048x528x!quant.uniform:f32, 0.063763998448848724>>, %arg5: tensor<2048x640x!quant.uniform:f32, 0.013358999975025654>>, %arg6: tensor<2048x640x!quant.uniform:f32, 0.022830000147223473>>, %arg7: tensor<2048x640x!quant.uniform:f32, 0.032276000827550888>>, %arg8: tensor<2048x640x!quant.uniform:f32, 0.035427000373601913>>, %arg9: tensor<2048x!quant.uniform>, %arg10: tensor<2048x!quant.uniform>, %arg11: tensor<2048x!quant.uniform>, %arg12: tensor<2048x!quant.uniform>, %arg13: tensor<640x2048x!quant.uniform:f32, 0.021174000576138496>>, %arg14: tensor<640x!quant.uniform>, %arg15: tensor<2048x!quant.uniform>, %arg16: tensor<2048x!quant.uniform>, %arg17: tensor<2048x!quant.uniform>, %arg18: tensor<2048x!quant.uniform>, %arg19: tensor<1x640x!quant.uniform>, %arg20: tensor<1x2048x!quant.uniform>) -> tensor<1x640x!quant.uniform> { %cst = "tfl.no_value"() {value = unit} : () -> none %0 = "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %cst, %cst, %cst, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg19, %arg20, %arg15, %arg16, %arg17, %arg18) ({}) {cell_clip = 1.000000e+01 : f32, fused_activation_function = "TANH", input_to_input_intermediate = tensor<0x!quant.uniform>, input_to_forget_intermediate = tensor<0x!quant.uniform>, input_to_cell_intermediate = tensor<0x!quant.uniform>, input_to_output_intermediate = tensor<0x!quant.uniform>, effective_hidden_scale_intermediate = tensor<0x!quant.uniform:f32, 0.0075630000792443752:2>>, kernel_type = #tfl, proj_clip = 0.01 : f32} : (tensor<1x528x!quant.uniform>, tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x528x!quant.uniform:f32, 0.031925998628139496>>, tensor<2048x528x!quant.uniform:f32, 0.056272000074386597>>, tensor<2048x528x!quant.uniform:f32, 0.063763998448848724>>, tensor<2048x640x!quant.uniform:f32, 0.013358999975025654>>, tensor<2048x640x!quant.uniform:f32, 0.022830000147223473>>, tensor<2048x640x!quant.uniform:f32, 0.032276000827550888>>, tensor<2048x640x!quant.uniform:f32, 0.035427000373601913>>, none, none, none, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<640x2048x!quant.uniform:f32, 0.021174000576138496>>, tensor<640x!quant.uniform>, tensor<1x640x!quant.uniform>, tensor<1x2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>) -> tensor<1x640x!quant.uniform> func.return %0 : tensor<1x640x!quant.uniform> // CHECK: %[[RES0:.*]] = "tfl.no_value"() <{value}> : () -> none // CHECK: %[[RES1:.*]] = "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %[[RES0]], %[[RES0]], %[[RES0]], %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg19, %arg20, %arg15, %arg16, %arg17, %arg18) // CHECK-SAME: <{cell_clip = 1.000000e+01 : f32, effective_hidden_scale_intermediate = tensor<0x!quant.uniform:f32, 0.0075630000792443752:2>>, fused_activation_function = "TANH", input_to_cell_intermediate = tensor<0x!quant.uniform>, input_to_forget_intermediate = tensor<0x!quant.uniform>, input_to_input_intermediate = tensor<0x!quant.uniform>, input_to_output_intermediate = tensor<0x!quant.uniform>, kernel_type = #tfl, proj_clip = 0.00999999977 : f32}> ({ // CHECK: }) : (tensor<1x528x!quant.uniform>, tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x528x!quant.uniform:f32, 0.031925998628139496>>, tensor<2048x528x!quant.uniform:f32, 0.056272000074386597>>, tensor<2048x528x!quant.uniform:f32, 0.063763998448848724>>, tensor<2048x640x!quant.uniform:f32, 0.013358999975025654>>, tensor<2048x640x!quant.uniform:f32, 0.022830000147223473>>, tensor<2048x640x!quant.uniform:f32, 0.032276000827550888>>, tensor<2048x640x!quant.uniform:f32, 0.035427000373601913>>, none, none, none, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<640x2048x!quant.uniform:f32, 0.021174000576138496>>, tensor<640x!quant.uniform>, tensor<1x640x!quant.uniform>, tensor<1x2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>) -> tensor<1x640x!quant.uniform> } // ----- // CHECK-LABEL: testBidirectionalSequenceLstm func.func @testBidirectionalSequenceLstm(%arg0: tensor, %arg1: tensor, %arg2: tensor, %arg3: tensor, %arg4: tensor, %arg5: tensor, %arg6: tensor, %arg7: tensor, %arg8: tensor, %arg9: tensor, %arg10: tensor, %arg11: tensor, %arg12: tensor, %arg13: tensor, %arg14: tensor, %arg15: tensor, %arg16: tensor, %arg17: tensor, %arg18: tensor, %arg19: tensor, %arg20: tensor, %arg21: tensor, %arg22: tensor, %arg23: tensor, %arg24: tensor, %arg25: tensor, %arg26: tensor, %arg27: tensor, %arg28: tensor, %arg29: tensor, %arg30: tensor, %arg31: tensor, %arg32: tensor, %arg33: tensor, %arg34: tensor, %arg35: tensor, %arg36: tensor, %arg37: tensor, %arg38: tensor, %arg39: tensor, %arg40: tensor, %arg41: tensor, %arg42: tensor, %arg43: tensor, %arg44: tensor, %arg45: tensor, %arg46: tensor, %arg47: tensor) -> tensor { // CHECK: "tfl.bidirectional_sequence_lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23, %arg24, %arg25, %arg26, %arg27, %arg28, %arg29, %arg30, %arg31, %arg32, %arg33, %arg34, %arg35, %arg36, %arg37, %arg38, %arg39, %arg40, %arg41, %arg42, %arg43, %arg44, %arg45, %arg46, %arg47) <{cell_clip = 1.000000e+00 : f32, fused_activation_function = "NONE", merge_outputs = true, time_major = false}> : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor) -> (tensor, tensor) %0:2 = "tfl.bidirectional_sequence_lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23, %arg24, %arg25, %arg26, %arg27, %arg28, %arg29, %arg30, %arg31, %arg32, %arg33, %arg34, %arg35, %arg36, %arg37, %arg38, %arg39, %arg40, %arg41, %arg42, %arg43, %arg44, %arg45, %arg46, %arg47) {cell_clip = 1.000000e+00 : f32, fused_activation_function = "NONE", merge_outputs = true, time_major = false} : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor) -> (tensor, tensor) func.return %0#0 : tensor } // ----- // CHECK-LABEL: testLstmQuantizedType func.func @testLstmQuantizedType(%arg0: tensor<1x528x!quant.uniform>, %arg1: tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, %arg2: tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, %arg3: tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, %arg4: tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, %arg5: tensor<2048x640x!quant.uniform:f32, 0.059801999479532242>>, %arg6: tensor<2048x640x!quant.uniform:f32, 0.059801999479532242>>, %arg7: tensor<2048x640x!quant.uniform:f32, 0.059801999479532242>>, %arg8: tensor<2048x640x!quant.uniform:f32, 0.059801999479532242>>, %arg9: tensor<2048x!quant.uniform>, %arg10: tensor<2048x!quant.uniform>, %arg11: tensor<2048x!quant.uniform>, %arg12: tensor<2048x!quant.uniform>, %arg13: tensor<640x2048x!quant.uniform:f32, 0.021174000576138496>>, %arg14: tensor<640x!quant.uniform>, %arg15: tensor<2048x!quant.uniform>, %arg16: tensor<2048x!quant.uniform>, %arg17: tensor<2048x!quant.uniform>, %arg18: tensor<2048x!quant.uniform>, %arg19: tensor<1x640x!quant.uniform>, %arg20: tensor<1x2048x!quant.uniform>) -> tensor<1x640x!quant.uniform> { %cst = "tfl.no_value"() {value = unit} : () -> none %0 = "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %cst, %cst, %cst, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg19, %arg20, %arg15, %arg16, %arg17, %arg18) ({ }) {cell_clip = 1.000000e+01 : f32, fused_activation_function = "TANH", kernel_type = #tfl, proj_clip = 0.01 : f32} : (tensor<1x528x!quant.uniform>, tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x640x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x640x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x640x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x640x!quant.uniform:f32, 0.059801999479532242>>, none, none, none, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<640x2048x!quant.uniform:f32, 0.021174000576138496>>, tensor<640x!quant.uniform>, tensor<1x640x!quant.uniform>, tensor<1x2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>) -> tensor<1x640x!quant.uniform> func.return %0 : tensor<1x640x!quant.uniform> // CHECK: %[[RES0:.*]] = "tfl.no_value"() <{value}> : () -> none // CHECK: %[[RES1:.*]] = "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %[[RES0]], %[[RES0]], %[[RES0]], %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg19, %arg20, %arg15, %arg16, %arg17, %arg18) // CHECK-SAME: <{cell_clip = 1.000000e+01 : f32, fused_activation_function = "TANH", kernel_type = #tfl, proj_clip = 0.00999999977 : f32}> ({ // CHECK-NEXT: }) : (tensor<1x528x!quant.uniform>, tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x528x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x640x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x640x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x640x!quant.uniform:f32, 0.059801999479532242>>, tensor<2048x640x!quant.uniform:f32, 0.059801999479532242>>, none, none, none, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<640x2048x!quant.uniform:f32, 0.021174000576138496>>, tensor<640x!quant.uniform>, tensor<1x640x!quant.uniform>, tensor<1x2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>, tensor<2048x!quant.uniform>) -> tensor<1x640x!quant.uniform> // CHECK: return %[[RES1]] } // ----- // CHECK-LABEL: testLstm func.func @testLstm(%arg0: tensor, %arg1: tensor, %arg2: tensor, %arg3: tensor, %arg4: tensor, %arg5: tensor, %arg6: tensor, %arg7: tensor, %arg8: tensor, %arg9: tensor, %arg10: tensor, %arg11: tensor, %arg12: tensor, %arg13: tensor, %arg14: tensor, %arg15: tensor, %arg16: tensor, %arg17: tensor, %arg18: tensor, %arg19: tensor, %arg20: tensor, %arg21: tensor, %arg22: tensor, %arg23: tensor) -> tensor { // CHECK: "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) // CHECK-SAME: <{fused_activation_function = "NONE", kernel_type = #tfl}> ({ // CHECK-NEXT: }) : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor) -> tensor %0 = "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) ({}) {fused_activation_function = "NONE", kernel_type = #tfl} : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testBasicLstm func.func @testBasicLstm(%arg0: tensor<1x384xf32>, %arg1: tensor<1x96xf32>, %arg2: tensor<384x480xf32>, %arg3: tensor<384xf32>, %arg4: tensor<1x96xf32>) -> (tensor<1x96xf32>, tensor<1x96xf32>) { %0:4 = "tfl.basic_lstm"(%arg0, %arg1, %arg2, %arg3, %arg4) {fused_activation_function = "TANH", kernel_type = #tfl} : (tensor<1x384xf32>, tensor<1x96xf32>, tensor<384x480xf32>, tensor<384xf32>, tensor<1x96xf32>) -> (tensor<1x96xf32>, tensor<1x96xf32>, tensor<1x480xf32>, tensor<1x384xf32>) func.return %0#0, %0#1 : tensor<1x96xf32>, tensor<1x96xf32> } // ----- // CHECK-LABEL: testQuantizedBasicLstm func.func @testQuantizedBasicLstm(%arg0: tensor<1x384x!quant.uniform>, %arg1: tensor<1x96x!quant.uniform>, %arg2: tensor<384x480x!quant.uniform:f32, 0.070853792130947113:163>>, %arg3: tensor<384x!quant.uniform>, %arg4: tensor<1x96x!quant.uniform>) -> (tensor<1x96x!quant.uniform>, tensor<1x96x!quant.uniform>) { %0:4 = "tfl.basic_lstm"(%arg0, %arg1, %arg2, %arg3, %arg4) : (tensor<1x384x!quant.uniform>, tensor<1x96x!quant.uniform>, tensor<384x480x!quant.uniform:f32, 0.070853792130947113:163>>, tensor<384x!quant.uniform>, tensor<1x96x!quant.uniform>) -> (tensor<1x96x!quant.uniform>, tensor<1x96x!quant.uniform>, tensor<1x480x!quant.uniform>, tensor<1x384x!quant.uniform>) func.return %0#0, %0#1 : tensor<1x96x!quant.uniform>, tensor<1x96x!quant.uniform> } // ----- // CHECK-LABEL: testLstmWithNoneTypeAndOverrideAttr func.func @testLstmWithNoneTypeAndOverrideAttr(%arg0: tensor, %arg1: none, %arg2: tensor, %arg3: tensor, %arg4: tensor, %arg5: none, %arg6: tensor, %arg7: tensor, %arg8: tensor, %arg9: none, %arg10: tensor, %arg11: tensor, %arg12: none, %arg13: tensor, %arg14: tensor, %arg15: tensor, %arg16: tensor, %arg17: tensor, %arg18: tensor, %arg19: tensor, %arg20: none, %arg21: tensor, %arg22: tensor, %arg23: tensor) -> tensor { // CHECK: "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) // CHECK-SAME: <{cell_clip = 1.000000e+00 : f32, fused_activation_function = "NONE", kernel_type = #tfl}> ({ // CHECK-NEXT: }) : (tensor, // CHECK-SAME: none, tensor, tensor, tensor, none, tensor, tensor, tensor, // CHECK-SAME: none, tensor, tensor, none, tensor, tensor, tensor, tensor, tensor, tensor, tensor, // CHECK-SAME: none, tensor, tensor, tensor) -> tensor %0 = "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) ({}) {cell_clip = 1.000000e+00 : f32, fused_activation_function = "NONE", kernel_type = #tfl} : (tensor, none, tensor, tensor, tensor, none, tensor, tensor, tensor, none, tensor, tensor, none, tensor, tensor, tensor, tensor, tensor, tensor, tensor, none, tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // test violation of projection weight and projection bias pred op trait func.func @testLstmWithInvalidNoneType(%arg0: tensor, %arg1: tensor, %arg2: tensor, %arg3: tensor, %arg4: tensor, %arg5: tensor, %arg6: tensor, %arg7: tensor, %arg8: tensor, %arg9: tensor, %arg10: tensor, %arg11: tensor, %arg12: tensor, %arg13: tensor, %arg14: tensor, %arg15: tensor, %arg16: none, %arg17: tensor, %arg18: tensor, %arg19: tensor, %arg20: tensor, %arg21: tensor, %arg22: tensor, %arg23: tensor) -> tensor { // expected-error @+1 {{'tfl.lstm' op failed to verify that either projection weight must be specified or both projection weight and projection bias must not be specified}} %0 = "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) ({}) {fused_activation_function = "NONE"} : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, none, tensor, tensor, tensor, tensor, tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // test invalid input dimension, the third input operand for lstm op should be 2-D tensor. func.func @testLstmWithInvalidInputDimension(%arg0: tensor<4 x f32>, %arg1: tensor<4 x f32>, %arg2: tensor<4 x f32>, %arg3: tensor<4 x f32>, %arg4: tensor<4 x f32>, %arg5: tensor<4 x f32>, %arg6: tensor<4 x f32>, %arg7: tensor<4 x f32>, %arg8: tensor<4 x f32>, %arg9: tensor<4 x f32>, %arg10: tensor<4 x f32>, %arg11: tensor<4 x f32>, %arg12: tensor<4 x f32>, %arg13: tensor<4 x f32>, %arg14: tensor<4 x f32>, %arg15: tensor<4 x f32>, %arg16: tensor<4 x f32>, %arg17: tensor<4 x f32>, %arg18: tensor<4 x f32>, %arg19: tensor<4 x f32>, %arg20: tensor<4 x f32>, %arg21: tensor<4 x f32>) -> tensor<4 x f32> { %cst0 = "tfl.pseudo_const" () {value = dense<0.0> : tensor<4xf32>} : () -> tensor<4xf32> loc("Const") %cst1 = "tfl.pseudo_const" () {value = dense<0.0> : tensor<4xf32>} : () -> tensor<4xf32> loc("Const") // expected-error @+1 {{'tfl.lstm' op failed to verify that operand 2 is 2-D}} %24 = "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %cst0, %cst1, %arg18, %arg19, %arg20, %arg21) ({}) {fused_activation_function = "NONE", kernel_type = #tfl} : (tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32> func.return %24 : tensor<4xf32> } // ----- // 'input_to_output_weights' input for lstm op has unmatched rank with `input`. func.func @testLstmWithInvalidInputsRankMatch(%arg0: tensor<1x4xf32>, %arg1: tensor<4x2xf32>, %arg2: tensor<4x2xf32>, %arg3: tensor<4x2xf32>, %arg4: tensor<4x2xf32>, %arg5: tensor<4x4xf32>, %arg6: tensor<4x4xf32>, %arg7: tensor<4x4xf32>, %arg8: tensor<4x4xf32>, %arg9: tensor<4xf32>, %arg10: tensor<4xf32>, %arg11: tensor<4xf32>, %arg12: tensor<1x4xf32>, %arg13: tensor<4xf32>, %arg14: tensor<4xf32>, %arg15: tensor<4xf32>, %arg16: tensor<4x4xf32>, %arg17: tensor<4xf32>, %arg18: tensor<4xf32>, %arg19: tensor<4xf32>, %arg20: tensor<4xf32>, %arg21: tensor<4xf32>) -> tensor<1x4xf32> { %cst0 = "tfl.pseudo_const" () {value = dense<0.0> : tensor<1x4xf32>} : () -> tensor<1x4xf32> loc("Const") %cst1 = "tfl.pseudo_const" () {value = dense<0.0> : tensor<1x4xf32>} : () -> tensor<1x4xf32> loc("Const") // expected-error @+1 {{'tfl.lstm' op inputs don't match with the dimensions.}} %24 = "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %cst0, %cst1, %arg18, %arg19, %arg20, %arg21) ({}) {cell_clip = 0.000000e+00 : f32, fused_activation_function = "NONE", kernel_type = #tfl, proj_clip = 0.000000e+00 : f32} : (tensor<1x4xf32>, tensor<4x2xf32>, tensor<4x2xf32>, tensor<4x2xf32>, tensor<4x2xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<1x4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4x4xf32>, tensor<4xf32>, tensor<1x4xf32>, tensor<1x4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>) -> tensor<1x4xf32> func.return %24 : tensor<1x4xf32> } // ----- // Coefficient inputs of LSTM op don't match the dimension with input operand `input_to_output_weights`. func.func @testLstmWithInvalidInputsRankMatch(%arg0: tensor<1x4xf32>, %arg1: tensor<4x4xf32>, %arg2: tensor<4x4xf32>, %arg3: tensor<4x4xf32>, %arg4: tensor<4x4xf32>, %arg5: tensor<4x4xf32>, %arg6: tensor<4x4xf32>, %arg7: tensor<4x4xf32>, %arg8: tensor<4x4xf32>, %arg9: tensor<4xf32>, %arg10: tensor<4xf32>, %arg11: tensor<4xf32>, %arg12: tensor<1x4xf32>, %arg13: tensor<4xf32>, %arg14: tensor<4xf32>, %arg15: tensor<4xf32>, %arg16: tensor<4x4xf32>, %arg17: tensor<4xf32>, %arg18: tensor<3xf32>, %arg19: tensor<3xf32>, %arg20: tensor<3xf32>, %arg21: tensor<3xf32>) -> tensor<1x4xf32> { %cst0 = "tfl.pseudo_const" () {value = dense<0.0> : tensor<1x4xf32>} : () -> tensor<1x4xf32> loc("Const") %cst1 = "tfl.pseudo_const" () {value = dense<0.0> : tensor<1x4xf32>} : () -> tensor<1x4xf32> loc("Const") // expected-error @+1 {{'tfl.lstm' op coefficient inputs have more than 2 dimensions or don't match the dimension with input operand `input_to_output_weights`.}} %24 = "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %cst0, %cst1, %arg18, %arg19, %arg20, %arg21) ({}) {cell_clip = 0.000000e+00 : f32, fused_activation_function = "NONE", kernel_type = #tfl, proj_clip = 0.000000e+00 : f32} : (tensor<1x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<1x4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4x4xf32>, tensor<4xf32>, tensor<1x4xf32>, tensor<1x4xf32>, tensor<3xf32>, tensor<3xf32>, tensor<3xf32>, tensor<3xf32>) -> tensor<1x4xf32> func.return %24 : tensor<1x4xf32> } // ----- // Coefficient inputs of LSTM op have unknown rank. func.func @testLstmWithInvalidInputsRankMatch(%arg0: tensor<1x4xf32>, %arg1: tensor<4x4xf32>, %arg2: tensor<4x4xf32>, %arg3: tensor<4x4xf32>, %arg4: tensor<4x4xf32>, %arg5: tensor<4x4xf32>, %arg6: tensor<4x4xf32>, %arg7: tensor<4x4xf32>, %arg8: tensor<4x4xf32>, %arg9: tensor<4xf32>, %arg10: tensor<4xf32>, %arg11: tensor<4xf32>, %arg12: tensor<1x4xf32>, %arg13: tensor<4xf32>, %arg14: tensor<4xf32>, %arg15: tensor<4xf32>, %arg16: tensor<4x4xf32>, %arg17: tensor<4xf32>, %arg18: tensor<3xf32>, %arg19: tensor<3xf32>, %arg20: tensor<3xf32>, %arg21: tensor<*xf32>) -> tensor<1x4xf32> { %cst0 = "tfl.pseudo_const" () {value = dense<0.0> : tensor<1x4xf32>} : () -> tensor<1x4xf32> loc("Const") %cst1 = "tfl.pseudo_const" () {value = dense<0.0> : tensor<1x4xf32>} : () -> tensor<1x4xf32> loc("Const") // expected-error @+1 {{'tfl.lstm' op coefficient inputs have more than 2 dimensions or don't match the dimension with input operand `input_to_output_weights`.}} %24 = "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %cst0, %cst1, %arg18, %arg19, %arg20, %arg21) ({}) {cell_clip = 0.000000e+00 : f32, fused_activation_function = "NONE", kernel_type = #tfl, proj_clip = 0.000000e+00 : f32} : (tensor<1x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4x4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<1x4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4x4xf32>, tensor<4xf32>, tensor<1x4xf32>, tensor<1x4xf32>, tensor<3xf32>, tensor<3xf32>, tensor<3xf32>, tensor<*xf32>) -> tensor<1x4xf32> func.return %24 : tensor<1x4xf32> } // ----- // test invalid kernel type func.func @testLstmWithInvalidKernelType(%arg0: tensor, %arg1: tensor, %arg2: tensor, %arg3: tensor, %arg4: tensor, %arg5: tensor, %arg6: tensor, %arg7: tensor, %arg8: tensor, %arg9: tensor, %arg10: tensor, %arg11: tensor, %arg12: tensor, %arg13: tensor, %arg14: tensor, %arg15: tensor, %arg16: tensor, %arg17: tensor, %arg18: tensor, %arg19: tensor, %arg20: tensor, %arg21: tensor, %arg22: tensor, %arg23: tensor) -> tensor { // expected-error @+1 {{'tfl.lstm' op attribute 'kernel_type' failed to satisfy constraint: lstm_kernel_type whose value is mlir::TFL::LSTMKernelType::FULL}} %0 = "tfl.lstm"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11, %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21, %arg22, %arg23) ({}) {cell_clip = 1.000000e+00 : f32, fused_activation_function = "NONE", kernel_type = #tfl} : (tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testReverseV2 func.func @testReverseV2(%arg0: tensor<1x2x3x4xf32>, %arg1 : tensor<2xi32>) -> tensor<1x2x3x4xf32> { // CHECK: "tfl.reverse_v2"(%arg0, %arg1) %0 = "tfl.reverse_v2"(%arg0, %arg1): (tensor<1x2x3x4xf32>, tensor<2xi32>) -> tensor<1x2x3x4xf32> func.return %0 : tensor<1x2x3x4xf32> } // ----- // test select // CHECK-LABEL: testSelect func.func @testSelect(%cond : tensor, %arg0 : tensor, %arg1 : tensor) -> tensor { %0 = "tfl.select"(%cond, %arg0, %arg1): (tensor,tensor,tensor) -> tensor func.return %0 : tensor } // ----- // test select with multi-dim inputs // CHECK-LABEL: testSelectMultiDim func.func @testSelectMultiDim(%cond : tensor, %arg0 : tensor, %arg1 : tensor) -> tensor { %0 = "tfl.select"(%cond, %arg0, %arg1): (tensor,tensor,tensor) -> tensor func.return %0 : tensor } // ----- func.func @testSelectWithUnsupportedType(%cond : tensor, %arg0 : tensor, %arg1 : tensor) -> tensor { // expected-error @+1 {{op operand #0 must be tensor of 1-bit signless integer values}} %0 = "tfl.select"(%cond, %arg0, %arg1): (tensor,tensor,tensor) -> tensor func.return %0 : tensor } // ----- func.func @testSelectWithUnsupportedType(%cond : tensor, %arg0 : tensor, %arg1 : tensor) -> tensor { // expected-error @+1 {{failed to verify that operands have same element type}} %0 = "tfl.select"(%cond, %arg0, %arg1): (tensor,tensor,tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testSelectV2 func.func @testSelectV2(%cond : tensor<*xi1>, %arg0 : tensor<*xf32>, %arg1 : tensor<*xf32>) -> tensor<*xf32> { // CHECK: "tfl.select_v2"(%arg0, %arg1, %arg2) %0 = "tfl.select_v2"(%cond, %arg0, %arg1): (tensor<*xi1>, tensor<*xf32>, tensor<*xf32>) -> tensor<*xf32> func.return %0 : tensor<*xf32> } // ----- // CHECK-LABEL: testSelectV2WithHighDimInputs func.func @testSelectV2WithHighDimInputs(%cond : tensor<1x2x3x4x5x6xi1>, %arg0 : tensor<1x2x3x4x5x6xf32>, %arg1 : tensor<1x2x3x4x5x6xf32>) -> tensor<1x2x3x4x5x6xf32> { // CHECK: "tfl.select_v2"(%arg0, %arg1, %arg2) %0 = "tfl.select_v2"(%cond, %arg0, %arg1): (tensor<1x2x3x4x5x6xi1>, tensor<1x2x3x4x5x6xf32>, tensor<1x2x3x4x5x6xf32>) -> tensor<1x2x3x4x5x6xf32> func.return %0 : tensor<1x2x3x4x5x6xf32> } // ----- // CHECK-LABEL: testSelectV2With4DBroadcasting func.func @testSelectV2With4DBroadcasting(%cond : tensor<1x1x3x1xi1>, %arg0 : tensor<1x1x1x4xf32>, %arg1 : tensor<1x2x1x1xf32>) -> tensor<1x2x3x4xf32> { // CHECK: "tfl.select_v2"(%arg0, %arg1, %arg2) %0 = "tfl.select_v2"(%cond, %arg0, %arg1): (tensor<1x1x3x1xi1>, tensor<1x1x1x4xf32>, tensor<1x2x1x1xf32>) -> tensor<1x2x3x4xf32> func.return %0 : tensor<1x2x3x4xf32> } // ----- func.func @testSelectV2WithWrongBroadcastableArguments(%cond : tensor<3x4xi1>, %arg0 : tensor<2x3x4xf32>, %arg1 : tensor<4x3xf32>) -> tensor<2x3x4xf32> { // expected-error @+1 {{'tfl.select_v2' op operands don't have broadcast-compatible shapes}} %0 = "tfl.select_v2"(%cond, %arg0, %arg1): (tensor<3x4xi1>, tensor<2x3x4xf32>, tensor<4x3xf32>) -> tensor<2x3x4xf32> func.return %0 : tensor<2x3x4xf32> } // ----- // CHECK-LABEL: topk func.func @topk(%arg0: tensor<8xf32>, %arg1: tensor) -> (tensor, tensor) { %0, %1 = "tfl.topk_v2"(%arg0, %arg1) : (tensor<8xf32>, tensor) -> (tensor, tensor) func.return %0, %1: tensor, tensor } // ----- // CHECK-LABEL: topk func.func @topk(%arg0: tensor<*xf32>, %arg1: tensor) -> (tensor<*xf32>, tensor<*xi32>) { %0, %1 = "tfl.topk_v2"(%arg0, %arg1) : (tensor<*xf32>, tensor) -> (tensor<*xf32>, tensor<*xi32>) func.return %0, %1: tensor<*xf32>, tensor<*xi32> } // ----- // CHECK-LABEL: topk_2 func.func @topk_2(%arg0: tensor<3x4x8xf32>) -> (tensor<3x4x2xf32>, tensor<3x4x2xi32>) { %0 = arith.constant dense<2> : tensor %1:2 = "tfl.topk_v2"(%arg0, %0) : (tensor<3x4x8xf32>, tensor) -> (tensor<3x4x2xf32>, tensor<3x4x2xi32>) func.return %1#0, %1#1: tensor<3x4x2xf32>, tensor<3x4x2xi32> } // ----- // CHECK-LABEL: topk_d func.func @topk_d(%arg0: tensor) -> (tensor, tensor) { %0 = arith.constant dense<2> : tensor %1:2 = "tfl.topk_v2"(%arg0, %0) : (tensor, tensor) -> (tensor, tensor) func.return %1#0, %1#1: tensor, tensor } // ----- // CHECK-LABEL: topk_d // TODO(jpienaar): This should fail but doesn't as the op definition does not // include shape verification. func.func @topk_d(%arg0: tensor) -> (tensor, tensor) { %0 = arith.constant dense<2> : tensor %1:2 = "tfl.topk_v2"(%arg0, %0) : (tensor, tensor) -> (tensor, tensor) func.return %1#0, %1#1: tensor, tensor } // ----- // CHECK-LABEL: topk_d func.func @topk_d(%arg0: tensor) -> (tensor<*xf32>, tensor<*xi32>) { %0 = arith.constant dense<2> : tensor %1:2 = "tfl.topk_v2"(%arg0, %0) : (tensor, tensor) -> (tensor<*xf32>, tensor<*xi32>) func.return %1#0, %1#1: tensor<*xf32>, tensor<*xi32> } // ----- // CHECK-LABEL: testEqual func.func @testEqual(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: "tfl.equal"(%arg0, %arg1) %0 = "tfl.equal"(%arg0, %arg1) : (tensor, tensor) -> tensor func.return %0#0 : tensor } // CHECK-LABEL: testEqualInt16 func.func @testEqualInt16(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: "tfl.equal"(%arg0, %arg1) %0 = "tfl.equal"(%arg0, %arg1) : (tensor, tensor) -> tensor func.return %0#0 : tensor } // CHECK-LABEL: testEqualQuant func.func @testEqualQuant(%arg0: tensor<1x80x1x!quant.uniform>, %arg1: tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1xi1> { %0 = "tfl.equal"(%arg0, %arg1) : (tensor<1x80x1x!quant.uniform>, tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1xi1> func.return %0 : tensor<1x80x1xi1> } // CHECK-LABEL: testEqualQuantWithQI16 func.func @testEqualQuantWithQI16(%arg0: tensor<1x80x1x!quant.uniform>, %arg1: tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1xi1> { %0 = "tfl.equal"(%arg0, %arg1) : (tensor<1x80x1x!quant.uniform>, tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1xi1> func.return %0 : tensor<1x80x1xi1> } // ----- // CHECK-LABEL: testNotEqual func.func @testNotEqual(tensor, tensor) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor): // CHECK: tfl.not_equal(%arg0, %arg1) %0 = "tfl.not_equal"(%arg0, %arg1) : (tensor, tensor) -> tensor func.return %0#0 : tensor } // CHECK-LABEL: testNotEqualQuant func.func @testNotEqualQuant(%arg0: tensor<1x80x1x!quant.uniform>, %arg1: tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1xi1> { %0 = "tfl.not_equal"(%arg0, %arg1) : (tensor<1x80x1x!quant.uniform>, tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1xi1> func.return %0 : tensor<1x80x1xi1> } // CHECK-LABEL: testNotEqualQuantWithQI16 func.func @testNotEqualQuantWithQI16(%arg0: tensor<1x80x1x!quant.uniform>, %arg1: tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1xi1> { %0 = "tfl.not_equal"(%arg0, %arg1) : (tensor<1x80x1x!quant.uniform>, tensor<1x80x1x!quant.uniform>) -> tensor<1x80x1xi1> func.return %0 : tensor<1x80x1xi1> } // ----- // CHECK-LABEL: testPad func.func @testPad(tensor<2x1x3xf32>, tensor<3x2xi32>) -> tensor { ^bb0(%arg0: tensor<2x1x3xf32>, %arg1: tensor<3x2xi32>): // CHECK: "tfl.pad"(%arg0, %arg1) %0 = "tfl.pad"(%arg0, %arg1) : (tensor<2x1x3xf32>, tensor<3x2xi32>) -> tensor func.return %0#0 : tensor } // ----- // CHECK-LABEL: testPad5D func.func @testPad5D(tensor<*xf32>, tensor<5x3xi32>) -> tensor { ^bb0(%arg0: tensor<*xf32>, %arg1: tensor<5x3xi32>): // CHECK: "tfl.pad"(%arg0, %arg1) %0 = "tfl.pad"(%arg0, %arg1) : (tensor<*xf32>, tensor<5x3xi32>) -> tensor func.return %0#0 : tensor } // ----- // test Pad with invalid paddings size func.func @testPadWithInvalidPaddingsDim(tensor<2x1x3xf32>, tensor<2x2xi32>) -> tensor { ^bb0(%arg0: tensor<2x1x3xf32>, %arg1: tensor<2x2xi32>): // expected-error @+1 {{'tfl.pad' op failed to verify that operand 0's rank equals operand 1's size}} %0 = "tfl.pad"(%arg0, %arg1) : (tensor<2x1x3xf32>, tensor<2x2xi32>) -> tensor func.return %0#0 : tensor } // ----- // test Pad with invalid paddings rank func.func @testPadWithInvalidPaddingsRank(tensor<2x1x3xf32>, tensor<1x3x2xi32>) -> tensor { ^bb0(%arg0: tensor<2x1x3xf32>, %arg1: tensor<1x3x2xi32>): // expected-error @+1 {{'tfl.pad' op failed to verify that operand 1 is 2-D}} %0 = "tfl.pad"(%arg0, %arg1) : (tensor<2x1x3xf32>, tensor<1x3x2xi32>) -> tensor func.return %0#0 : tensor } // ----- func.func @testPadUnknownPaddings(tensor<2x1x3xf32>, tensor<*xi32>) -> tensor { ^bb0(%arg0: tensor<2x1x3xf32>, %arg1: tensor<*xi32>): %0 = "tfl.pad"(%arg0, %arg1) : (tensor<2x1x3xf32>, tensor<*xi32>) -> tensor func.return %0#0 : tensor // CHECK-LABEL: testPadUnknownPaddings // CHECK: "tfl.pad"(%arg0, %arg1) : (tensor<2x1x3xf32>, tensor<*xi32>) -> tensor // CHECK: return } // ----- func.func @testPadUnsupportedPaddings(tensor<*xf32>, tensor<6x3xi32>) -> tensor { ^bb0(%arg0: tensor<*xf32>, %arg1: tensor<6x3xi32>): // expected-error @+1 {{'tfl.pad' op failed to verify that the first dim size of the padding argument must be at most 5}} %0 = "tfl.pad"(%arg0, %arg1) : (tensor<*xf32>, tensor<6x3xi32>) -> tensor func.return %0#0 : tensor } // ----- // CHECK-LABEL: testPadQuantizedU8 func.func @testPadQuantizedU8(%arg0: tensor<2x1x3x!quant.uniform>, %arg1: tensor<3x2xi32>) -> tensor> { // CHECK: "tfl.pad"(%arg0, %arg1) %0 = "tfl.pad"(%arg0, %arg1) : (tensor<2x1x3x!quant.uniform>, tensor<3x2xi32>) -> tensor> func.return %0#0 : tensor> } // CHECK-LABEL: testPadQuantizedI8 func.func @testPadQuantizedI8(%arg0: tensor<2x1x3x!quant.uniform>, %arg1: tensor<3x2xi32>) -> tensor> { // CHECK: "tfl.pad"(%arg0, %arg1) %0 = "tfl.pad"(%arg0, %arg1) : (tensor<2x1x3x!quant.uniform>, tensor<3x2xi32>) -> tensor> func.return %0#0 : tensor> } // ----- // CHECK-LABEL: testPadV2 func.func @testPadV2(tensor<2x1x3xf32>, tensor<3x2xi32>) -> tensor { ^bb0(%arg0: tensor<2x1x3xf32>, %arg1: tensor<3x2xi32>): %cst = arith.constant dense<2.0> : tensor // CHECK: "tfl.padv2"(%arg0, %arg1, %cst) %0 = "tfl.padv2"(%arg0, %arg1, %cst) : (tensor<2x1x3xf32>, tensor<3x2xi32>, tensor) -> tensor func.return %0#0 : tensor } // ----- // CHECK-LABEL: testPadV25D func.func @testPadV25D(tensor<*xf32>, tensor<5x3xi32>) -> tensor { ^bb0(%arg0: tensor<*xf32>, %arg1: tensor<5x3xi32>): %cst = arith.constant dense<2.0> : tensor // CHECK: "tfl.padv2"(%arg0, %arg1, %cst) %0 = "tfl.padv2"(%arg0, %arg1, %cst) : (tensor<*xf32>, tensor<5x3xi32>, tensor) -> tensor func.return %0#0 : tensor } // ----- // test PadV2 with invalid paddings size func.func @testPadV2WithInvalidPaddingsDim(tensor<2x1x3xf32>, tensor<2x2xi32>) -> tensor { ^bb0(%arg0: tensor<2x1x3xf32>, %arg1: tensor<2x2xi32>): %cst = arith.constant dense<2.0> : tensor //// expected-error @+1 {{'tfl.padv2' op failed to verify that operand 0's rank equals operand 1's size}} %0 = "tfl.padv2"(%arg0, %arg1, %cst) : (tensor<2x1x3xf32>, tensor<2x2xi32>, tensor) -> tensor func.return %0#0 : tensor } // ----- // test PadV2 with invalid paddings rank func.func @testPadV2WithInvalidPaddingsRank(tensor<2x1x3xf32>, tensor<1x3x2xi32>) -> tensor { ^bb0(%arg0: tensor<2x1x3xf32>, %arg1: tensor<1x3x2xi32>): %cst = arith.constant dense<2.0> : tensor // expected-error @+1 {{'tfl.padv2' op failed to verify that operand 1 is 2-D}} %0 = "tfl.padv2"(%arg0, %arg1, %cst) : (tensor<2x1x3xf32>, tensor<1x3x2xi32>, tensor) -> tensor func.return %0#0 : tensor } // ----- // test PadV2 with invalid constant rank func.func @testPadV2WithInvalidConstantScalar(tensor<2x1x3xf32>, tensor<3x2xi32>) -> tensor { ^bb0(%arg0: tensor<2x1x3xf32>, %arg1: tensor<3x2xi32>): %cst = arith.constant dense<[2.0]> : tensor<1xf32> //// expected-error @+1 {{'tfl.padv2' op failed to verify that operand 2 is 0-D}} %0 = "tfl.padv2"(%arg0, %arg1, %cst) : (tensor<2x1x3xf32>, tensor<3x2xi32>, tensor<1xf32>) -> tensor func.return %0#0 : tensor } // ----- // test PadV2 with invalid constant data type func.func @testPadV2WithInvalidConstantScalar(tensor<2x1x3xf32>, tensor<3x2xi32>) -> tensor { ^bb0(%arg0: tensor<2x1x3xf32>, %arg1: tensor<3x2xi32>): %cst = arith.constant dense<2> : tensor //// expected-error @+1 {{'tfl.padv2' op failed to verify that input and constant value operands must have same element type}} %0 = "tfl.padv2"(%arg0, %arg1, %cst) : (tensor<2x1x3xf32>, tensor<3x2xi32>, tensor) -> tensor func.return %0#0 : tensor } // ----- func.func @testPadV2UnknownPaddings(tensor<2x1x3xf32>, tensor<*xi32>) -> tensor { ^bb0(%arg0: tensor<2x1x3xf32>, %arg1: tensor<*xi32>): %cst = arith.constant dense<2.0> : tensor %0 = "tfl.padv2"(%arg0, %arg1, %cst) : (tensor<2x1x3xf32>, tensor<*xi32>, tensor) -> tensor func.return %0#0 : tensor // CHECK-LABEL: testPadV2UnknownPaddings // CHECK: "tfl.padv2"(%arg0, %arg1, %cst) : (tensor<2x1x3xf32>, tensor<*xi32>, tensor) -> tensor // CHECK: return } // ----- func.func @testPadV2UnsupportedPaddings(tensor<*xf32>, tensor<6x3xi32>) -> tensor { ^bb0(%arg0: tensor<*xf32>, %arg1: tensor<6x3xi32>): %cst = arith.constant dense<2.0> : tensor // expected-error @+1 {{'tfl.padv2' op failed to verify that the first dim size of the padding argument must be at most 5}} %0 = "tfl.padv2"(%arg0, %arg1, %cst) : (tensor<*xf32>, tensor<6x3xi32>, tensor) -> tensor func.return %0#0 : tensor } // ----- func.func @packQuantizedU8(%arg0: tensor<2x!quant.uniform>, %arg1: tensor<2x!quant.uniform>) -> tensor<2x2x!quant.uniform> { // CHECK: "tfl.pack"(%arg0, %arg1) <{axis = 0 : i32, values_count = 2 : i32}> %0 = "tfl.pack"(%arg0, %arg1) {axis = 0 : i32, values_count = 2 : i32} : (tensor<2x!quant.uniform>, tensor<2x!quant.uniform>) -> tensor<2x2x!quant.uniform> func.return %0 : tensor<2x2x!quant.uniform> } func.func @packQuantizedI8(%arg0: tensor<2x!quant.uniform>, %arg1: tensor<2x!quant.uniform>) -> tensor<2x2x!quant.uniform> { // CHECK: "tfl.pack"(%arg0, %arg1) <{axis = 0 : i32, values_count = 2 : i32}> %0 = "tfl.pack"(%arg0, %arg1) {axis = 0 : i32, values_count = 2 : i32} : (tensor<2x!quant.uniform>, tensor<2x!quant.uniform>) -> tensor<2x2x!quant.uniform> func.return %0 : tensor<2x2x!quant.uniform> } // ----- func.func @pack(%arg0: tensor<2xi32>, %arg1: tensor<2xi32>) -> tensor<2x2xi32> { // CHECK: "tfl.pack"(%arg0, %arg1) <{axis = 0 : i32, values_count = 2 : i32}> %0 = "tfl.pack"(%arg0, %arg1) {axis = 0 : i32, values_count = 2 : i32} : (tensor<2xi32>, tensor<2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @packUnranked(%arg0: tensor<2xi32>, %arg1: tensor<*xi32>) -> tensor<2x2xi32> { // CHECK: "tfl.pack"(%arg0, %arg1) <{axis = 0 : i32, values_count = 2 : i32}> %0 = "tfl.pack"(%arg0, %arg1) {axis = 0 : i32, values_count = 2 : i32} : (tensor<2xi32>, tensor<*xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @packInputRank(%arg0: tensor<1x4xi32>, %arg1: tensor<1x4xi32>) -> tensor<1x4x2xi32> { // CHECK: "tfl.pack"(%arg0, %arg1) <{axis = 2 : i32, values_count = 2 : i32}> %0 = "tfl.pack"(%arg0, %arg1) {axis = 2 : i32, values_count = 2 : i32} : (tensor<1x4xi32>, tensor<1x4xi32>) -> tensor<1x4x2xi32> func.return %0 : tensor<1x4x2xi32> } // ----- func.func @packNegInputAxis2(%arg0: tensor<1x4xi32>, %arg1: tensor<1x4xi32>) -> tensor<1x2x4xi32> { // CHECK: "tfl.pack"(%arg0, %arg1) <{axis = -2 : i32, values_count = 2 : i32}> %0 = "tfl.pack"(%arg0, %arg1) {axis = -2 : i32, values_count = 2 : i32} : (tensor<1x4xi32>, tensor<1x4xi32>) -> tensor<1x2x4xi32> func.return %0 : tensor<1x2x4xi32> } func.func @packNegInputAxis3(%arg0: tensor<1x4xi32>, %arg1: tensor<1x4xi32>) -> tensor<2x1x4xi32> { // CHECK: "tfl.pack"(%arg0, %arg1) <{axis = -3 : i32, values_count = 2 : i32}> %0 = "tfl.pack"(%arg0, %arg1) {axis = -3 : i32, values_count = 2 : i32} : (tensor<1x4xi32>, tensor<1x4xi32>) -> tensor<2x1x4xi32> func.return %0 : tensor<2x1x4xi32> } // ----- func.func @packInputUnranked(%arg0: tensor<*xi32>, %arg1: tensor<*xi32>) -> tensor<*xi32> { // CHECK: "tfl.pack"(%arg0, %arg1) <{axis = -2 : i32, values_count = 2 : i32}> %0 = "tfl.pack"(%arg0, %arg1) {axis = -2 : i32, values_count = 2 : i32} : (tensor<*xi32>, tensor<*xi32>) -> tensor<*xi32> func.return %0 : tensor<*xi32> } // ----- func.func @pack(%arg0: tensor<2xi32>, %arg1: tensor<2xi32>) -> tensor<2x2xi32> { // expected-error @+1 {{input count should match 'values_count' attribute}} %0 = "tfl.pack"(%arg0, %arg1) {axis = 0 : i32, values_count = 1 : i32} : (tensor<2xi32>, tensor<2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @pack(%arg0: tensor<1xi32>, %arg1: tensor<2xi32>) -> tensor<2x2xi32> { // expected-error @+1 {{operands should be of the same type}} %0 = "tfl.pack"(%arg0, %arg1) {axis = 0 : i32, values_count = 2 : i32} : (tensor<1xi32>, tensor<2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @pack(%arg0: tensor<2xi32>, %arg1: tensor<2xi32>) -> tensor<2x2xi32> { // expected-error @+1 {{op attribute 'axis' should be in range [-rank - 1, rank + 1), got rank = 1, and axis = 3}} %0 = "tfl.pack"(%arg0, %arg1) {axis = 3 : i32, values_count = 2 : i32} : (tensor<2xi32>, tensor<2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @unpack(%arg0: tensor<2x3xi32>) -> tensor<2xi32> { // CHECK: "tfl.unpack"(%arg0) <{axis = 1 : i32, num = 3 : i32}> %0:3 = "tfl.unpack"(%arg0) {axis = 1 : i32, num = 3 : i32} : (tensor<2x3xi32>) -> (tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) func.return %0#0 : tensor<2xi32> } // ----- func.func @unpack(%arg0: tensor<2x3xi32>) -> tensor<2xi32> { // CHECK: "tfl.unpack"(%arg0) <{axis = -1 : i32, num = 3 : i32}> %0:3 = "tfl.unpack"(%arg0) {axis = -1 : i32, num = 3 : i32} : (tensor<2x3xi32>) -> (tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) func.return %0#0 : tensor<2xi32> } // ----- func.func @unpack(%arg0: tensor<2x3xi32>) -> tensor<3xi32> { // CHECK: "tfl.unpack"(%arg0) <{axis = -2 : i32, num = 2 : i32}> %0:2 = "tfl.unpack"(%arg0) {axis = -2 : i32, num = 2 : i32} : (tensor<2x3xi32>) -> (tensor<3xi32>, tensor<3xi32>) func.return %0#0 : tensor<3xi32> } // ----- func.func @unpackQuantized(%arg0: tensor<2x3x!quant.uniform>) -> tensor<2x!quant.uniform> { %0:3 = "tfl.unpack"(%arg0) {axis = 1 : i32, num = 3 : i32} : (tensor<2x3x!quant.uniform>) -> (tensor<2x!quant.uniform>, tensor<2x!quant.uniform>, tensor<2x!quant.uniform>) func.return %0#0 : tensor<2x!quant.uniform> } // ----- func.func @unpack(%arg0: tensor<2x3xi32>) -> tensor<2xi32> { // expected-error @+2 {{failed to infer returned types}} // expected-error @+1 {{output count should match 'num' attribute}} %0:3 = "tfl.unpack"(%arg0) {axis = 1 : i32, num = 2 : i32} : (tensor<2x3xi32>) -> (tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) func.return %0#0 : tensor<2xi32> } // ----- func.func @unpack(%arg0: tensor<2x3xi32>) -> tensor<2xi32> { // expected-error @+2 {{failed to infer returned types}} // expected-error @+1 {{attribute 'axis' should be in range [-rank, rank), got axis = 2, and rank = 2}} %0:3 = "tfl.unpack"(%arg0) {axis = 2 : i32, num = 3 : i32} : (tensor<2x3xi32>) -> (tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) func.return %0#0 : tensor<2xi32> } // ----- func.func @unpack(%arg0: tensor<2x3xi32>) -> tensor<2xi32> { // expected-error @+2 {{failed to infer returned types}} // expected-error @+1 {{attribute 'axis' should be in range [-rank, rank), got axis = -3, and rank = 2}} %0:3 = "tfl.unpack"(%arg0) {axis = -3 : i32, num = 3 : i32} : (tensor<2x3xi32>) -> (tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) func.return %0#0 : tensor<2xi32> } // ----- func.func @unpack(%arg0: tensor) -> tensor<2xi32> { // expected-error @+2 {{failed to infer returned types}} // expected-error @+1 {{input should be of rank larger than 0}} %0:3 = "tfl.unpack"(%arg0) {axis = 0 : i32, num = 3 : i32} : (tensor) -> (tensor<2xi32>, tensor<2xi32>, tensor<2xi32>) func.return %0#0 : tensor<2xi32> } // ----- func.func @unpack(%arg0: tensor<2x3xi32>) -> tensor<2xi32> { // expected-error @+2 {{failed to infer returned types}} // expected-error @+1 {{op inferred type(s) 'tensor<2xi32>', 'tensor<2xi32>', 'tensor<2xi32>' are incompatible with return type(s) of operation 'tensor<2xi32>', 'tensor<2x1xi32>', 'tensor<2xi32>'}} %0:3 = "tfl.unpack"(%arg0) {axis = 1 : i32, num = 3 : i32} : (tensor<2x3xi32>) -> (tensor<2xi32>, tensor<2x1xi32>, tensor<2xi32>) func.return %0#0 : tensor<2xi32> } // ----- func.func @unpack(%arg0: tensor<*xi32>) -> (tensor<*xi32>, tensor<*xi32>) { %0:2 = "tfl.unpack"(%arg0) {axis = 1 : i32, num = 2 : i32} : (tensor<*xi32>) -> (tensor<*xi32>, tensor<*xi32>) func.return %0#0, %0#1 : tensor<*xi32>, tensor<*xi32> } // ----- func.func @unpack(%arg0: tensor) -> () { %0:2 = "tfl.unpack"(%arg0) {axis = 1 : i32, num = 2 : i32} : (tensor) -> (tensor<5x5x3xf32>, tensor<5x5x3xf32>) func.return } // ----- // CHECK-LABEL: testMean func.func @testMean(%arg0: tensor<2x2xf32>, %arg1 : tensor<1xi32>) -> tensor<1x2xf32> { // CHECK: "tfl.mean"(%arg0, %arg1) <{keep_dims = false}> %0 = "tfl.mean"(%arg0, %arg1) {keep_dims = false}: (tensor<2x2xf32>, tensor<1xi32>) -> tensor<1x2xf32> func.return %0 : tensor<1x2xf32> } // ----- // CHECK-LABEL: testMean_true func.func @testMean_true(%arg0: tensor<2x2xf32>, %arg1 : tensor<1xi32>) -> tensor<1x2xf32> { // CHECK: "tfl.mean"(%arg0, %arg1) <{keep_dims = true}> %0 = "tfl.mean"(%arg0, %arg1) {keep_dims = true}: (tensor<2x2xf32>, tensor<1xi32>) -> tensor<1x2xf32> func.return %0 : tensor<1x2xf32> } // ----- func.func @testMean_missing_keep_dims(%arg0: tensor<2x2xf32>, %arg1 : tensor<1xi32>) -> tensor<1x2xf32> { // expected-error @+1 {{'tfl.mean' op requires attribute 'keep_dims'}} %0 = "tfl.mean"(%arg0, %arg1): (tensor<2x2xf32>, tensor<1xi32>) -> tensor<1x2xf32> func.return %0 : tensor<1x2xf32> } // ----- // CHECK-LABEL: testBatchToSpaceND func.func @testBatchToSpaceND(%arg0 : tensor<4x2x2x3xf32>, %arg1 : tensor<2xi32>, %arg2 : tensor<2x2xi32>) -> tensor { // CHECK: "tfl.batch_to_space_nd"(%arg0, %arg1, %arg2) %0 = "tfl.batch_to_space_nd"(%arg0, %arg1, %arg2) : (tensor<4x2x2x3xf32>, tensor<2xi32>, tensor<2x2xi32>) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testSpaceToBatchND func.func @testSpaceToBatchND(%arg0 : tensor<1x4x4x3xf32>, %arg1 : tensor<2xi32>, %arg2 : tensor<2x2xi32>) -> tensor { // CHECK: "tfl.space_to_batch_nd"(%arg0, %arg1, %arg2) %0 = "tfl.space_to_batch_nd"(%arg0, %arg1, %arg2) : (tensor<1x4x4x3xf32>, tensor<2xi32>, tensor<2x2xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testBatchMatmulQuant(%arg0 : tensor<1x4x384x32x!quant.uniform>, %arg1 : tensor<1x4x384x32x!quant.uniform>) -> tensor<1x4x384x384x!quant.uniform> { // CHECK: "tfl.batch_matmul"(%arg0, %arg1) %0 = "tfl.batch_matmul"(%arg0, %arg1) {adj_x = false, adj_y = true} : (tensor<1x4x384x32x!quant.uniform>, tensor<1x4x384x32x!quant.uniform>) -> tensor<1x4x384x384x!quant.uniform> func.return %0 : tensor<1x4x384x384x!quant.uniform> } // ----- func.func @testBatchMatmulHybridQuant(%arg0 : tensor<1x4x384x32xf32>, %arg1 : tensor<1x4x384x32x!quant.uniform>) -> tensor<1x4x384x384xf32> { // CHECK: "tfl.batch_matmul"(%arg0, %arg1) %0 = "tfl.batch_matmul"(%arg0, %arg1) {adj_x = false, adj_y = true} : (tensor<1x4x384x32xf32>, tensor<1x4x384x32x!quant.uniform>) -> tensor<1x4x384x384xf32> func.return %0 : tensor<1x4x384x384xf32> } // ----- func.func @testBatchMatmulHybridBf16F32(%arg0 : tensor<1x4x384x32xbf16>, %arg1 : tensor<1x4x384x32xbf16>) -> tensor<1x4x384x384xf32> { // expected-error @+1 {{'tfl.batch_matmul' op operand #0 must be tensor of 32-bit float or 16-bit float or QI8 type or QI16 type or 8-bit signless integer values}} %0 = "tfl.batch_matmul"(%arg0, %arg1) {adj_x = false, adj_y = true} : (tensor<1x4x384x32xbf16>, tensor<1x4x384x32xbf16>) -> tensor<1x4x384x384xf32> func.return %0 : tensor<1x4x384x384xf32> } // ----- func.func @testConcat(%arg0: tensor<1x2xi32>, %arg1: tensor<1x2xi32>) -> tensor<2x2xi32> { // CHECK: "tfl.concatenation"(%arg0, %arg1) <{axis = 0 : i32, fused_activation_function = "NONE"}> %0 = "tfl.concatenation"(%arg0, %arg1) {axis = 0 : i32, fused_activation_function = "NONE"} : (tensor<1x2xi32>, tensor<1x2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @testConcatQuantized(%arg0: tensor<1x2x!quant.uniform>, %arg1: tensor<1x2x!quant.uniform>) -> tensor<2x2x!quant.uniform> { // CHECK: "tfl.concatenation"(%arg0, %arg1) <{axis = 0 : i32, fused_activation_function = "NONE"}> %0 = "tfl.concatenation"(%arg0, %arg1) {axis = 0 : i32, fused_activation_function = "NONE"} : (tensor<1x2x!quant.uniform>, tensor<1x2x!quant.uniform>) -> tensor<2x2x!quant.uniform> func.return %0 : tensor<2x2x!quant.uniform> } // ----- func.func @testConcatInvalidOutputElementalType(%arg0: tensor<2xi32>, %arg1: tensor<2xi32>) -> tensor { // expected-error @+1 {{'tfl.concatenation' op failed to verify that values and output must have same element type}} %0 = "tfl.concatenation"(%arg0, %arg1) {axis = 0 : i32, fused_activation_function = "NONE"} : (tensor<2xi32>, tensor<2xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testConcatInvalidAxis(%arg0: tensor<1x2xi32>, %arg1: tensor<1x2xi32>) -> tensor<2x2xi32> { // expected-error @+1 {{'tfl.concatenation' op concatenation dimension must be in [-rank, rank)}} %0 = "tfl.concatenation"(%arg0, %arg1) {axis = 2 : i32, fused_activation_function = "NONE"} : (tensor<1x2xi32>, tensor<1x2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @testConcatInvalidAxisUnderflow(%arg0: tensor<1x2xi32>, %arg1: tensor<1x2xi32>) -> tensor<2x2xi32> { // expected-error @+1 {{'tfl.concatenation' op concatenation dimension must be in [-rank, rank)}} %0 = "tfl.concatenation"(%arg0, %arg1) {axis = -4 : i32, fused_activation_function = "NONE"} : (tensor<1x2xi32>, tensor<1x2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @testConcatInvalidOperandRankLess(%arg0: tensor<2xi32>, %arg1: tensor<2xi32>) -> tensor<2x2xi32> { // expected-error @+1 {{'tfl.concatenation' op rank of operand #0 must be equal to rank of output, expected 2, got 1}} %0 = "tfl.concatenation"(%arg0, %arg1) {axis = 0 : i32, fused_activation_function = "NONE"} : (tensor<2xi32>, tensor<2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @testConcatInvalidOperandRankGreater(%arg0: tensor<1x1x2xi32>, %arg1: tensor<1x1x2xi32>) -> tensor<2x2xi32> { // expected-error @+1 {{'tfl.concatenation' op rank of operand #0 must be equal to rank of output, expected 2, got 3}} %0 = "tfl.concatenation"(%arg0, %arg1) {axis = 0 : i32, fused_activation_function = "NONE"} : (tensor<1x1x2xi32>, tensor<1x1x2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @testConcatInvalidOperandDimSize(%arg0: tensor<1x2xi32>, %arg1: tensor<1x3xi32>) -> tensor<2x2xi32> { // expected-error @+1 {{'tfl.concatenation' op dimension size of dimension #1 of operand #1 must be equal to dimension size of dimension #1 of output, expected 2, got 3}} %0 = "tfl.concatenation"(%arg0, %arg1) {axis = 0 : i32, fused_activation_function = "NONE"} : (tensor<1x2xi32>, tensor<1x3xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @testConcatInvalidOperandDimSizeComparedToPrevInput(%arg0: tensor<1x2xi32>, %arg1: tensor<1x3xi32>) -> tensor { // expected-error @+1 {{'tfl.concatenation' op dimension size of dimension #1 of operand #1 must be equal to dimension size of dimension #1 of operand #0, expected 2, got 3}} %0 = "tfl.concatenation"(%arg0, %arg1) {axis = 0 : i32, fused_activation_function = "NONE"} : (tensor<1x2xi32>, tensor<1x3xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testConcatInvalidScales(%arg0: tensor<*x!quant.uniform>, %arg1: tensor<*x!quant.uniform>) -> tensor<*x!quant.uniform> { // expected-error @+1 {{'tfl.concatenation' op quantization parameters violate the same scale constraint: !quant.uniform vs. !quant.uniform}} %0 = "tfl.concatenation"(%arg0, %arg1) {axis = 3 : i32, fused_activation_function = "NONE"} : (tensor<*x!quant.uniform>, tensor<*x!quant.uniform>) -> tensor<*x!quant.uniform> func.return %0 : tensor<*x!quant.uniform> } // ----- func.func @testConcatBenignUnrankedOperand(%arg0: tensor<*xi32>, %arg1: tensor<1x2xi32>) -> tensor<2x2xi32> { %0 = "tfl.concatenation"(%arg0, %arg1) {axis = 0 : i32, fused_activation_function = "NONE"} : (tensor<*xi32>, tensor<1x2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @testConcatBenignDynamicDimSizeOperand(%arg0: tensor<1x?xi32>, %arg1: tensor) -> tensor<2x2xi32> { %0 = "tfl.concatenation"(%arg0, %arg1) {axis = 0 : i32, fused_activation_function = "NONE"} : (tensor<1x?xi32>, tensor) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- // CHECK-LABEL: testResizeBilinear func.func @testResizeBilinear(%arg0 : tensor<1x100x100x3xf32>, %arg1 : tensor<2xi32>) -> tensor { // CHECK: "tfl.resize_bilinear"(%arg0, %arg1) <{align_corners = false, half_pixel_centers = false}> %0 = "tfl.resize_bilinear"(%arg0, %arg1) {align_corners = false, half_pixel_centers = false} : (tensor<1x100x100x3xf32>, tensor<2xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testResizeBilinearInvalidOutputType(%arg0 : tensor<1x100x100x3xf32>, %arg1 : tensor<2xi32>) -> tensor { // expected-error @+1 {{'tfl.resize_bilinear' op failed to verify that input and output must have same element type}} %0 = "tfl.resize_bilinear"(%arg0, %arg1) {align_corners = false} : (tensor<1x100x100x3xf32>, tensor<2xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testResizeBilinearInvalidSize(%arg0 : tensor<1x100x100x3xf32>, %arg1 : tensor<4xi32>) -> tensor { // expected-error @+1 {{'tfl.resize_bilinear' op failed to verify that operand 1's dimension 0 is dynamic or equals 2}} %0 = "tfl.resize_bilinear"(%arg0, %arg1) {align_corners = false} : (tensor<1x100x100x3xf32>, tensor<4xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testResizeNearestNeighborInvalidSize(%arg0 : tensor<1x100x100x3xf32>, %arg1 : tensor<4xi32>) -> tensor { // expected-error @+1 {{'tfl.resize_nearest_neighbor' op failed to verify that operand 1's dimension 0 is dynamic or equals 2}} %0 = "tfl.resize_nearest_neighbor"(%arg0, %arg1) {align_corners = false, half_pixel_centers = false} : (tensor<1x100x100x3xf32>, tensor<4xi32>) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testStridedSlice func.func @testStridedSlice(%arg0: tensor<12x2x2x5xf32>, %arg1: tensor<1xi32>, %arg2: tensor<1xi32>, %arg3: tensor<1xi32>) -> tensor<1x2x2x5xf32> { // CHECK: "tfl.strided_slice"(%arg0, %arg1, %arg2, %arg3) <{begin_mask = 0 : i32, ellipsis_mask = 0 : i32, end_mask = 0 : i32, new_axis_mask = 0 : i32, offset = false, shrink_axis_mask = 0 : i32}> : (tensor<12x2x2x5xf32>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>) -> tensor<1x2x2x5xf32> %0 = "tfl.strided_slice"(%arg0, %arg1, %arg2, %arg3) {begin_mask = 0 : i32, ellipsis_mask = 0 : i32, end_mask = 0 : i32, new_axis_mask = 0 : i32, shrink_axis_mask = 0 : i32, offset = false} : (tensor<12x2x2x5xf32>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>) -> tensor<1x2x2x5xf32> func.return %0 : tensor<1x2x2x5xf32> } // CHECK-LABEL: testStridedSliceWithQI8 func.func @testStridedSliceWithQI8(%arg0: tensor<12x2x2x5x!quant.uniform>, %arg1: tensor<1xi32>, %arg2: tensor<1xi32>, %arg3: tensor<1xi32>) -> tensor<1x2x2x5x!quant.uniform> { %0 = "tfl.strided_slice"(%arg0, %arg1, %arg2, %arg3) {begin_mask = 0 : i32, ellipsis_mask = 0 : i32, end_mask = 0 : i32, new_axis_mask = 0 : i32, shrink_axis_mask = 0 : i32, offset = false} : (tensor<12x2x2x5x!quant.uniform>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>) -> tensor<1x2x2x5x!quant.uniform> func.return %0 : tensor<1x2x2x5x!quant.uniform> } // CHECK-LABEL: testStridedSliceWithQUI8 func.func @testStridedSliceWithQUI8(%arg0: tensor<12x2x2x5x!quant.uniform>, %arg1: tensor<1xi32>, %arg2: tensor<1xi32>, %arg3: tensor<1xi32>) -> tensor<1x2x2x5x!quant.uniform> { %0 = "tfl.strided_slice"(%arg0, %arg1, %arg2, %arg3) {begin_mask = 0 : i32, ellipsis_mask = 0 : i32, end_mask = 0 : i32, new_axis_mask = 0 : i32, shrink_axis_mask = 0 : i32, offset = false} : (tensor<12x2x2x5x!quant.uniform>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>) -> tensor<1x2x2x5x!quant.uniform> func.return %0 : tensor<1x2x2x5x!quant.uniform> } // CHECK-LABEL: testStridedSliceTFType func.func @testStridedSliceTFType(%arg0: tensor<12x2x2x5xui8>, %arg1: tensor<1xi32>, %arg2: tensor<1xi32>, %arg3: tensor<1xi32>) -> tensor<1x2x2x5x!tf_type.quint8> { %0 = "tfl.strided_slice"(%arg0, %arg1, %arg2, %arg3) {begin_mask = 0 : i32, ellipsis_mask = 0 : i32, end_mask = 0 : i32, new_axis_mask = 0 : i32, shrink_axis_mask = 0 : i32, offset = false} : (tensor<12x2x2x5xui8>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>) -> tensor<1x2x2x5x!tf_type.quint8> func.return %0 : tensor<1x2x2x5x!tf_type.quint8> } // CHECK-LABEL: testStridedSliceWithString func.func @testStridedSliceWithString(%arg0: tensor<12x2x2x5x!tf_type.string>, %arg1: tensor<1xi32>, %arg2: tensor<1xi32>, %arg3: tensor<1xi32>) -> tensor<1x2x2x5x!tf_type.string> { %0 = "tfl.strided_slice"(%arg0, %arg1, %arg2, %arg3) {begin_mask = 0 : i32, ellipsis_mask = 0 : i32, end_mask = 0 : i32, new_axis_mask = 0 : i32, shrink_axis_mask = 0 : i32, offset = false} : (tensor<12x2x2x5x!tf_type.string>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>) -> tensor<1x2x2x5x!tf_type.string> func.return %0 : tensor<1x2x2x5x!tf_type.string> } // ----- func.func @testStridedSliceWithInvalidOutputType(%arg0: tensor<12x2x2x5xf32>, %arg1: tensor<1xi32>, %arg2: tensor<1xi32>, %arg3: tensor<1xi32>) -> tensor<1x2x2x5xi32> { // expected-error @+1 {{op failed to verify that input and output must have same element type}} %0 = "tfl.strided_slice"(%arg0, %arg1, %arg2, %arg3) {begin_mask = 0 : i32, ellipsis_mask = 0 : i32, end_mask = 0 : i32, new_axis_mask = 0 : i32, shrink_axis_mask = 0 : i32, offset = false} : (tensor<12x2x2x5xf32>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>) -> tensor<1x2x2x5xi32> func.return %0 : tensor<1x2x2x5xi32> } // ----- // CHECK-LABEL: testStridedSliceWith6DInputRank func.func @testStridedSliceWith6DInputRank(%arg0: tensor<12x2x2x5xf32>, %arg1: tensor<1xi32>, %arg2: tensor<1xi32>, %arg3: tensor<1xi32>) -> tensor<1x1x12x2x2x5xf32> { // CHECK: "tfl.strided_slice" %0 = "tfl.strided_slice"(%arg0, %arg1, %arg2, %arg3) {begin_mask = 0 : i32, ellipsis_mask = 0 : i32, end_mask = 0 : i32, new_axis_mask = 3 : i32, shrink_axis_mask = 0 : i32, offset = false} : (tensor<12x2x2x5xf32>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>) -> tensor<1x1x12x2x2x5xf32> func.return %0 : tensor<1x1x12x2x2x5xf32> } // ----- // test invalid strided slice input rank (exceeds 6) func.func @testStridedSliceWithInvalidInputRank(%arg0: tensor<12x2x2x5xf32>, %arg1: tensor<1xi32>, %arg2: tensor<1xi32>, %arg3: tensor<1xi32>) -> tensor<1x1x1x12x2x2x5xf32> { // expected-error @+1 {{op failed to verify that input (with new_axis) must have rank at most 6}} %0 = "tfl.strided_slice"(%arg0, %arg1, %arg2, %arg3) {begin_mask = 0 : i32, ellipsis_mask = 0 : i32, end_mask = 0 : i32, new_axis_mask = 7 : i32, shrink_axis_mask = 0 : i32, offset = false} : (tensor<12x2x2x5xf32>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>) -> tensor<1x1x1x12x2x2x5xf32> func.return %0 : tensor<1x1x1x12x2x2x5xf32> } // ----- // CHECK-LABEL: testOneHot func.func @testOneHot(%arg0: tensor<3xi32>, %arg1: tensor, %arg2: tensor, %arg3: tensor) -> tensor<*xf32> { // CHECK: "tfl.one_hot"(%arg0, %arg1, %arg2, %arg3) <{axis = -1 : i32}> : (tensor<3xi32>, tensor, tensor, tensor) -> tensor<*xf32> %0 = "tfl.one_hot"(%arg0, %arg1, %arg2, %arg3) {axis = -1 : i32} : (tensor<3xi32>, tensor, tensor, tensor) -> tensor<*xf32> func.return %0 : tensor<*xf32> } // ----- func.func @testOneHotWithInvalidOutputType(%arg0: tensor<3xi32>, %arg1: tensor, %arg2: tensor, %arg3: tensor) -> tensor<*xi16> { // expected-error @+1 {{'tfl.one_hot' op result #0 must be tensor of 32-bit float or 32-bit signless integer or 64-bit signless integer or 1-bit signless integer or 8-bit signless integer or 8-bit unsigned integer values, but got 'tensor<*xi16>'}} %0 = "tfl.one_hot"(%arg0, %arg1, %arg2, %arg3) {axis = -1 : i32} : (tensor<3xi32>, tensor, tensor, tensor) -> tensor<*xi16> func.return %0 : tensor<*xi16> } // ----- func.func @testArgMax(%arg0: tensor<3xi32>, %arg1: tensor) -> tensor { // CHECK: "tfl.arg_max"(%arg0, %arg1) {output_type = 2 : i32} : (tensor<3xi32>, tensor) -> tensor %0 = "tfl.arg_max"(%arg0, %arg1) {output_type = 2 : i32} : (tensor<3xi32>, tensor) -> tensor func.return %0 : tensor } // ----- func.func @testArgMin(%arg0: tensor<3xi32>, %arg1: tensor) -> tensor { // CHECK: "tfl.arg_min"(%arg0, %arg1) {output_type = 2 : i32} : (tensor<3xi32>, tensor) -> tensor %0 = "tfl.arg_min"(%arg0, %arg1) {output_type = 2 : i32} : (tensor<3xi32>, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testSpaceToDepth func.func @testSpaceToDepthF32(%arg0: tensor<1x2x2x1xf32>) -> tensor<1x1x1x4xf32> { // CHECK: %[[ARG:.*]]: tensor<1x2x2x1xf32> // CHECK: "tfl.space_to_depth"(%[[ARG]]) <{block_size = 2 : i32}> : (tensor<1x2x2x1xf32>) -> tensor<1x1x1x4xf32> %0 = "tfl.space_to_depth"(%arg0) {block_size = 2: i32} : (tensor<1x2x2x1xf32>) -> tensor<1x1x1x4xf32> func.return %0 : tensor<1x1x1x4xf32> } // ----- func.func @testSpaceToDepthInvalidOutputType(%arg0: tensor<1x2x2x1xf32>) -> tensor<1x1x1x4xi32> { // expected-error @+1 {{'tfl.space_to_depth' op failed to verify that input and output must have same element type}} %0 = "tfl.space_to_depth"(%arg0) {block_size = 2: i32} : (tensor<1x2x2x1xf32>) -> tensor<1x1x1x4xi32> func.return %0 : tensor<1x1x1x4xi32> } // ----- func.func @testRange(%arg0 : tensor, %arg1 : tensor, %arg2 : tensor) -> tensor { %0 = "tfl.range"(%arg0, %arg1, %arg2) : (tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- func.func @testRangeNonScalarTensorInput(%arg0 : tensor<1xi32>, %arg1 : tensor, %arg2 : tensor) -> tensor { // expected-error @+1 {{op failed to verify that operand 0 is 0-D}} %0 = "tfl.range"(%arg0, %arg1, %arg2) : (tensor<1xi32>, tensor, tensor) -> tensor func.return %0 : tensor } // ----- func.func @testRangeOutputTypeMismatch(%arg0 : tensor, %arg1 : tensor, %arg2 : tensor) -> tensor { // expected-error @+1 {{op failed to verify that operands and output must have same element type}} %0 = "tfl.range"(%arg0, %arg1, %arg2) : (tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- func.func @transpose(%arg0 : tensor<2x2xi32>, %arg1 : tensor<2xi32>) -> tensor<2x2xi32> { %0 = "tfl.transpose"(%arg0, %arg1) : (tensor<2x2xi32>, tensor<2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- // CHECK-LABEL: transpose_int4 func.func @transpose_int4(%arg0 : tensor<2x2xi4>, %arg1 : tensor<2xi32>) -> tensor<2x2xi4> { // CHECK: "tfl.transpose"(%arg0, %arg1) %0 = "tfl.transpose"(%arg0, %arg1) : (tensor<2x2xi4>, tensor<2xi32>) -> tensor<2x2xi4> func.return %0 : tensor<2x2xi4> } // ----- // CHECK-LABEL: transpose_with_output_that_has_dynamic_sizes func.func @transpose_with_output_that_has_dynamic_sizes(%arg0 : tensor<2x2xi32>, %arg1 : tensor<2xi32>) -> tensor { // CHECK: "tfl.transpose"(%arg0, %arg1) %0 = "tfl.transpose"(%arg0, %arg1) : (tensor<2x2xi32>, tensor<2xi32>) -> tensor func.return %0 : tensor } // ----- func.func @transpose_perm_not_i32(%arg0 : tensor<2x2xi32>, %arg1 : tensor<2xf32>) -> tensor<2x2xi32> { // expected-error @+1 {{op operand #1 must be tensor of 32-bit signless integer values}} %0 = "tfl.transpose"(%arg0, %arg1) : (tensor<2x2xi32>, tensor<2xf32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @transpose_perm_size(%arg0 : tensor<2x2xi32>, %arg1 : tensor<3xi32>) -> tensor<2x2xi32> { // expected-error @+1 {{perm tensor elements size is not equal to input tensor rank}} %0 = "tfl.transpose"(%arg0, %arg1) : (tensor<2x2xi32>, tensor<3xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @transpose_unranked_shape(%arg0 : tensor<*xi32>) -> tensor<2x2xi32> { %cst = arith.constant dense<[1, 0]> : tensor<2xi32> %0 = "tfl.transpose"(%arg0, %cst) : (tensor<*xi32>, tensor<2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @transpose_dynamic_shape(%arg0 : tensor<2x?xi32>) -> tensor { %cst = arith.constant dense<[1, 0]> : tensor<2xi32> %0 = "tfl.transpose"(%arg0, %cst) : (tensor<2x?xi32>, tensor<2xi32>) -> tensor func.return %0 : tensor } // ----- func.func @transpose_perm_axis_duplicated(%arg0 : tensor<2x2xi32>) -> tensor<2x2xi32> { %cst = arith.constant dense<[1, 1]> : tensor<2xi32> // expected-error @+1 {{perm[1] cannot have duplicated axis}} %0 = "tfl.transpose"(%arg0, %cst) : (tensor<2x2xi32>, tensor<2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @transpose_output_type_bad(%arg0 : tensor<3x4x5x6xi32>) -> tensor<3x4x5x6xi32> { %cst = arith.constant dense<[0, 3, 1, 2]> : tensor<4xi32> // expected-error @+1 {{expect output type tensor<3x6x4x5xi32>, got tensor<3x4x5x6xi32>}} %0 = "tfl.transpose"(%arg0, %cst) : (tensor<3x4x5x6xi32>, tensor<4xi32>) -> tensor<3x4x5x6xi32> func.return %0 : tensor<3x4x5x6xi32> } // ----- func.func @transpose_element_type(%arg0 : tensor<2x2xf32>, %arg1 : tensor<2xi32>) -> tensor<2x2xi32> { // expected-error @+1 {{input and output must have same element type}} %0 = "tfl.transpose"(%arg0, %arg1) : (tensor<2x2xf32>, tensor<2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @transpose_1d_perm(%arg0 : tensor<2x2xi32>, %arg1 : tensor<2x2xi32>) -> tensor<2x2xi32> { // expected-error @+1 {{op failed to verify that operand 1 is 1-D}} %0 = "tfl.transpose"(%arg0, %arg1) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32> func.return %0 : tensor<2x2xi32> } // ----- func.func @transpose_uniform_qtype(%arg0 : tensor<1x3x4x3xf32>) -> tensor<3x4x3x1x!quant.uniform> { %cst = arith.constant dense<[1, 2, 3, 0]> : tensor<4xi32> %0 = "tfl.quantize"(%arg0) {qtype = tensor<1x3x4x3x!quant.uniform>} : (tensor<1x3x4x3xf32>) -> tensor<1x3x4x3x!quant.uniform> // CHECK: "tfl.transpose" %1 = "tfl.transpose"(%0, %cst) : (tensor<1x3x4x3x!quant.uniform>, tensor<4xi32>) -> tensor<3x4x3x1x!quant.uniform> func.return %1 : tensor<3x4x3x1x!quant.uniform> } // ----- func.func @transpose_uniform_per_axis_qtype(%arg0 : tensor<2x1x1x3x!quant.uniform:f32:0, {0.072314441204071045,0.050758145749568939}>>) -> tensor<1x1x3x2x!quant.uniform:f32:3, {0.072314441204071045,0.050758145749568939}>> { %cst = arith.constant dense<[1, 2, 3, 0]> : tensor<4xi32> // CHECK: "tfl.transpose" %0 = "tfl.transpose"(%arg0, %cst) : (tensor<2x1x1x3x!quant.uniform:f32:0, {0.072314441204071045,0.050758145749568939}>>, tensor<4xi32>) -> tensor<1x1x3x2x!quant.uniform:f32:3, {0.072314441204071045,0.050758145749568939}>> func.return %0 : tensor<1x1x3x2x!quant.uniform:f32:3, {0.072314441204071045,0.050758145749568939}>> } // ----- func.func @transpose_uniform_qtype_int4(%arg0 : tensor<1x3x4x3xf32>) -> tensor<3x4x3x1x!quant.uniform> { %cst = arith.constant dense<[1, 2, 3, 0]> : tensor<4xi32> %0 = "tfl.quantize"(%arg0) {qtype = tensor<1x3x4x3x!quant.uniform>} : (tensor<1x3x4x3xf32>) -> tensor<1x3x4x3x!quant.uniform> // CHECK: "tfl.transpose" %1 = "tfl.transpose"(%0, %cst) : (tensor<1x3x4x3x!quant.uniform>, tensor<4xi32>) -> tensor<3x4x3x1x!quant.uniform> func.return %1 : tensor<3x4x3x1x!quant.uniform> } // ----- func.func @transpose_uniform_per_axis_qtype_int4(%arg0 : tensor<2x1x1x3x!quant.uniform:f32:0, {0.072314441204071045,0.050758145749568939}>>) -> tensor<1x1x3x2x!quant.uniform:f32:3, {0.072314441204071045,0.050758145749568939}>> { %cst = arith.constant dense<[1, 2, 3, 0]> : tensor<4xi32> // CHECK: "tfl.transpose" %0 = "tfl.transpose"(%arg0, %cst) : (tensor<2x1x1x3x!quant.uniform:f32:0, {0.072314441204071045,0.050758145749568939}>>, tensor<4xi32>) -> tensor<1x1x3x2x!quant.uniform:f32:3, {0.072314441204071045,0.050758145749568939}>> func.return %0 : tensor<1x1x3x2x!quant.uniform:f32:3, {0.072314441204071045,0.050758145749568939}>> } // ----- func.func @transpose_uniform_per_axis_qtype_mismatch_axis(%arg0 : tensor<2x1x1x3x!quant.uniform:f32:0, {0.072314441204071045,0.050758145749568939}>>) -> tensor<1x1x3x2x!quant.uniform:f32:0, {0.072314441204071045,0.050758145749568939}>> { %cst = arith.constant dense<[1, 2, 3, 0]> : tensor<4xi32> // expected-error @+1 {{op has mismatched quantized axes of input and output}} %0 = "tfl.transpose"(%arg0, %cst) : (tensor<2x1x1x3x!quant.uniform:f32:0, {0.072314441204071045,0.050758145749568939}>>, tensor<4xi32>) -> tensor<1x1x3x2x!quant.uniform:f32:0, {0.072314441204071045,0.050758145749568939}>> func.return %0 : tensor<1x1x3x2x!quant.uniform:f32:0, {0.072314441204071045,0.050758145749568939}>> } // ----- func.func @anyWithI64Axis(%arg0: tensor<2x2xi1>, %arg1: tensor) -> tensor { // expected-error @+1 {{tfl.reduce_any' op operand #1 must be tensor of 32-bit signless integer values}} %0 = "tfl.reduce_any"(%arg0, %arg1) {keep_dims = false} : (tensor<2x2xi1>, tensor) -> tensor func.return %0 : tensor } // ----- func.func @testRoundInvalidInputType(%arg: tensor) -> tensor { // expected-error @+1 {{'tfl.round' op operand #0 must be tensor of 32-bit float values}} %0 = "tfl.round"(%arg) : (tensor) -> tensor func.return %0 : tensor } // ----- func.func @testSplitWithQuantizedTypes(%arg0 : tensor, %arg1 : tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> { %0 = "tfl.split"(%arg0, %arg1) {num_splits = 1 : i32} : (tensor, tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> func.return %0 : tensor<10x!quant.uniform> } // ----- func.func @testSplitVWithQuantizedTypes(%arg0 : tensor<10x!quant.uniform>, %arg1 : tensor<1xi32>, %arg2 : tensor) -> tensor<10x!quant.uniform> { %0 = "tfl.split_v"(%arg0, %arg1, %arg2) {num_splits = 1 : i32} : (tensor<10x!quant.uniform>, tensor<1xi32>, tensor) -> tensor<10x!quant.uniform> func.return %0 : tensor<10x!quant.uniform> } // ----- func.func @whereWithI32Input(%arg0: tensor<3x5xf64>) -> tensor { // expected-error @+1 {{'tfl.where' op operand #0 must be tensor of 1-bit signless integer}} %0 = "tfl.where"(%arg0) : (tensor<3x5xf64>) -> tensor func.return %0 : tensor } // ----- func.func @testMinimumWithQuantizedTypes(%arg0 : tensor<10x!quant.uniform>, %arg1 : tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> { %0 = "tfl.minimum"(%arg0, %arg1) : (tensor<10x!quant.uniform>, tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> func.return %0 : tensor<10x!quant.uniform> } // ----- func.func @testMaximumWithQuantizedTypes(%arg0 : tensor<10x!quant.uniform>, %arg1 : tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> { %0 = "tfl.maximum"(%arg0, %arg1) : (tensor<10x!quant.uniform>, tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> func.return %0 : tensor<10x!quant.uniform> } // ----- func.func @testReluWithQuantizedTypes(%arg0 : tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> { %0 = "tfl.relu"(%arg0) : (tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> func.return %0 : tensor<10x!quant.uniform> } // ----- func.func @testRelu6WithQuantizedTypes(%arg0 : tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> { %0 = "tfl.relu6"(%arg0) : (tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> func.return %0 : tensor<10x!quant.uniform> } // ----- func.func @testRelu0To1WithQuantizedTypes(%arg0 : tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> { %0 = "tfl.relu_0_to_1"(%arg0) : (tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> func.return %0 : tensor<10x!quant.uniform> } // ----- func.func @testReluWithDifferentScales(%arg0 : tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> { %0 = "tfl.relu"(%arg0) : (tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> %1 = "tfl.relu_n1_to_1"(%0) : (tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> %2 = "tfl.relu6"(%1) : (tensor<10x!quant.uniform>) -> tensor<10x!quant.uniform> func.return %2 : tensor<10x!quant.uniform> } // ----- func.func @testEmbeddingLookup(%arg0 : tensor, %arg1 : tensor) -> tensor { %0 = "tfl.embedding_lookup"(%arg0, %arg1) : (tensor,tensor) -> tensor func.return %0 : tensor } // ----- func.func @testWrongQuantizedLocalResponseNormalization(%arg0 : tensor<1x56x56x192x!quant.uniform>) -> tensor<1x56x56x192x!quant.uniform> { // expected-error @+1 {{'tfl.local_response_normalization' op operand #0 must be tensor of 32-bit float values, but got 'tensor<1x56x56x192x!quant.uniform>'}} %0 = "tfl.local_response_normalization"(%arg0) {alpha = 9.99999974E-5 : f32, beta = 5.000000e-01 : f32, bias = 2.000000e+00 : f32, radius = 5 : i32} : (tensor<1x56x56x192x!quant.uniform>) -> tensor<1x56x56x192x!quant.uniform> func.return %0 : tensor<1x56x56x192x!quant.uniform> } // ----- // CHECK-LABEL: testSvdf func.func @testSvdf(%arg0: tensor, %arg1: tensor, %arg2: tensor, %arg3: tensor, %arg4: tensor) -> tensor { // CHECK: "tfl.svdf"(%arg0, %arg1, %arg2, %arg3, %arg4) <{fused_activation_function = "RELU", rank = 2 : i32}> : (tensor, tensor, tensor, tensor, tensor) -> tensor %0 = "tfl.svdf"(%arg0, %arg1, %arg2, %arg3, %arg4) {fused_activation_function = "RELU", rank = 2 : i32} : (tensor, tensor, tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testDepthToSpace func.func @testDepthToSpaceF32(%arg0: tensor<1x1x1x4xf32>) -> tensor<1x2x2x1xf32> { // CHECK: %[[ARG:.*]]: tensor<1x1x1x4xf32> // CHECK: "tfl.depth_to_space"(%[[ARG]]) <{block_size = 2 : i32}> : (tensor<1x1x1x4xf32>) -> tensor<1x2x2x1xf32> %0 = "tfl.depth_to_space"(%arg0) {block_size = 2: i32} : (tensor<1x1x1x4xf32>) -> tensor<1x2x2x1xf32> func.return %0 : tensor<1x2x2x1xf32> } // ----- func.func @testDepthToSpaceInvalidOutputType(%arg0: tensor<1x1x1x4xf32>) -> tensor<1x2x2x1xi32> { // expected-error @+1 {{'tfl.depth_to_space' op failed to verify that input and output must have same element type}} %0 = "tfl.depth_to_space"(%arg0) {block_size = 2: i32} : (tensor<1x1x1x4xf32>) -> tensor<1x2x2x1xi32> func.return %0 : tensor<1x2x2x1xi32> } // ----- func.func @testPReluWrongOutputRank(%arg0: tensor<10x10x10x10xf32>, %arg1: tensor<10x10x10x10xf32>) -> tensor<10x10xf32> { // expected-error @+1 {{'tfl.prelu' op result type '10x10' not broadcast compatible with broadcasted operands's shapes '10x10x10x10'}} %0 = "tfl.prelu"(%arg0, %arg1) : (tensor<10x10x10x10xf32>, tensor<10x10x10x10xf32>) -> tensor<10x10xf32> func.return %0 : tensor<10x10xf32> } // ----- func.func @testPReluWrongOutputShape(%arg0: tensor<1x2x3x4xf32>, %arg1: tensor<2x3x4xf32>) -> tensor<1x2x3x5xf32> { // expected-error @+1 {{'tfl.prelu' op result type '1x2x3x5' not broadcast compatible with broadcasted operands's shapes '1x2x3x4'}} %0 = "tfl.prelu"(%arg0, %arg1) : (tensor<1x2x3x4xf32>, tensor<2x3x4xf32>) -> tensor<1x2x3x5xf32> func.return %0 : tensor<1x2x3x5xf32> } // ----- func.func @testPReluWrongAlphaRank(%arg0: tensor<7x3x2x14xf32>, %arg1: tensor<7x3x2x14xf32>) -> tensor<7x3x2x14xf32> { // expected-error @+1 {{'alpha' should have one less rank than 'input'.}} %0 = "tfl.prelu"(%arg0, %arg1) : (tensor<7x3x2x14xf32>, tensor<7x3x2x14xf32>) -> tensor<7x3x2x14xf32> func.return %0 : tensor<7x3x2x14xf32> } // ----- func.func @testPReluInvalidBroadcast(%arg0: tensor<15x14x2x14xf32>, %arg1: tensor<1x1x3xf32>) -> tensor<15x14x2x14xf32> { // expected-error @+1 {{'tfl.prelu' op operands don't have broadcast-compatible shapes}} %0 = "tfl.prelu"(%arg0, %arg1) : (tensor<15x14x2x14xf32>, tensor<1x1x3xf32>) -> tensor<15x14x2x14xf32> func.return %0 : tensor<15x14x2x14xf32> } // ----- func.func @testPReluValidSameSize(%arg0: tensor<16x20x20x13xf32>, %arg1: tensor<20x20x13xf32>) -> tensor<16x20x20x13xf32> { %0 = "tfl.prelu"(%arg0, %arg1) : (tensor<16x20x20x13xf32>, tensor<20x20x13xf32>) -> tensor<16x20x20x13xf32> func.return %0 : tensor<16x20x20x13xf32> } // ----- func.func @testPReluValidBroadcast(%arg0: tensor<19x7x12x14xf32>, %arg1: tensor<1x1x14xf32>) -> tensor<19x7x12x14xf32> { %0 = "tfl.prelu"(%arg0, %arg1) : (tensor<19x7x12x14xf32>, tensor<1x1x14xf32>) -> tensor<19x7x12x14xf32> func.return %0 : tensor<19x7x12x14xf32> } // ----- func.func @testPReluValidFullBroadcast(%arg0: tensor<7x8x9x10xf32>, %arg1: tensor<1x1x1xf32>) -> tensor<7x8x9x10xf32> { %0 = "tfl.prelu"(%arg0, %arg1) : (tensor<7x8x9x10xf32>, tensor<1x1x1xf32>) -> tensor<7x8x9x10xf32> func.return %0 : tensor<7x8x9x10xf32> } // ----- func.func @testPReluValidQuantized(%arg0: tensor<1x96x96x16x!quant.uniform>, %arg1: tensor<1x1x16x!quant.uniform:f32, 0.004846:14>>) -> tensor<1x96x96x16x!quant.uniform> { %0 = "tfl.prelu"(%arg0, %arg1) : (tensor<1x96x96x16x!quant.uniform>, tensor<1x1x16x!quant.uniform:f32, 0.004846:14>>) -> tensor<1x96x96x16x!quant.uniform> func.return %0 : tensor<1x96x96x16x!quant.uniform> } // ----- func.func @testSlice(%arg0: tensor<2x3x5xf32>, %arg1: tensor<3xi32>, %arg2: tensor<3xi32>) -> tensor { %0 = "tfl.slice"(%arg0, %arg1, %arg2) : (tensor<2x3x5xf32>, tensor<3xi32>, tensor<3xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testSliceBadBeginDimension(%arg0: tensor<2x3x5xf32>, %arg1: tensor<2xi32>, %arg2: tensor<3xi32>) -> tensor { // expected-error @+1 {{begin tensor elements size is not equal to input tensor rank}} %0 = "tfl.slice"(%arg0, %arg1, %arg2) : (tensor<2x3x5xf32>, tensor<2xi32>, tensor<3xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testSliceBadSizeDimension(%arg0: tensor<2x3x5xf32>, %arg1: tensor<3xi32>, %arg2: tensor<2xi32>) -> tensor { // expected-error @+1 {{size tensor elements size is not equal to input tensor rank}} %0 = "tfl.slice"(%arg0, %arg1, %arg2) : (tensor<2x3x5xf32>, tensor<3xi32>, tensor<2xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testSliceBadBegin(%arg0: tensor<2x3x5xf32>, %arg1: tensor<3xi32>) -> tensor { %cst = arith.constant dense<[2, -1, 5]> : tensor<3xi32> // expected-error @+1 {{begin[1] cannot be negative}} %0 = "tfl.slice"(%arg0, %cst, %arg1) : (tensor<2x3x5xf32>, tensor<3xi32>, tensor<3xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testSliceNegativeSize(%arg0: tensor<2x3x5xf32>, %arg1: tensor<3xi32>) -> tensor { %cst = arith.constant dense<[-2, -1, 5]> : tensor<3xi32> // expected-error @+1 {{size[0] cannot be negative other than -1}} %0 = "tfl.slice"(%arg0, %arg1, %cst) : (tensor<2x3x5xf32>, tensor<3xi32>, tensor<3xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testSliceSizeOutOfRange(%arg0: tensor<2x3x5xf32>, %arg1: tensor<3xi32>) -> tensor { %cst = arith.constant dense<[2, 1, 5]> : tensor<3xi32> %cst_1 = arith.constant dense<[0, 1, 1]> : tensor<3xi32> // expected-error @+1 {{begin[2] + size[2] cannot exceed dimension length: 5}} %0 = "tfl.slice"(%arg0, %cst_1, %cst) : (tensor<2x3x5xf32>, tensor<3xi32>, tensor<3xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testSliceBeginOutOfRange(%arg0: tensor<2x3x5xf32>, %arg1: tensor<3xi32>) -> tensor { %cst = arith.constant dense<[1, 1, 1]> : tensor<3xi32> %cst_1 = arith.constant dense<[3, 1, 3]> : tensor<3xi32> // expected-error @+1 {{begin[0] cannot exceed dimension length: 2}} %0 = "tfl.slice"(%arg0, %cst_1, %cst) : (tensor<2x3x5xf32>, tensor<3xi32>, tensor<3xi32>) -> tensor func.return %0 : tensor } // ----- func.func @testSplitOpWithBadNumSplits(%arg0 : tensor<16xf32>) -> () { %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split' op attribute 'num_splits' failed to satisfy constraint: 32-bit signless integer attribute whose value is positive}} "tfl.split"(%split_dim, %arg0) {num_splits = 0 : i32} : (tensor, tensor<16xf32>) -> () func.return } // ----- func.func @testSplitOpWithMismatchedNumResults(%arg0 : tensor<16xf32>) -> (tensor<8xf32>, tensor<8xf32>) { %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split' op output count should match 'num_splits' attribute}} %0, %1 = "tfl.split"(%split_dim, %arg0) {num_splits = 4 : i32} : (tensor, tensor<16xf32>) -> (tensor<8xf32>, tensor<8xf32>) func.return %0, %1 : tensor<8xf32>, tensor<8xf32> } // ----- func.func @testSplitOpWithBadSplitDimTensorType(%arg0: tensor<16x4x4xf32>) -> tensor<16x4x4xf32> { %split_dim = arith.constant dense<0> : tensor<2x2xi32> // expected-error @+1 {{'tfl.split' op failed to verify that operand #0 is an 0-d tensor or 1-d tensor w/ 1 element}} %0 = "tfl.split"(%split_dim, %arg0) {num_splits = 1 : i32} : (tensor<2x2xi32>, tensor<16x4x4xf32>) -> tensor<16x4x4xf32> func.return %0 : tensor<16x4x4xf32> } // ----- func.func @testSplitOpWithBadSplitDimUnrankedTensorType(%arg0: tensor<16x4x4xf32>, %split_dim : tensor<*xi32>) -> tensor<16x4x4xf32> { // expected-error @+1 {{'tfl.split' op failed to verify that operand #0 is an 0-d tensor or 1-d tensor w/ 1 element}} %0 = "tfl.split"(%split_dim, %arg0) {num_splits = 1 : i32} : (tensor<*xi32>, tensor<16x4x4xf32>) -> tensor<16x4x4xf32> func.return %0 : tensor<16x4x4xf32> } // ----- func.func @testSplitOpWithOutOfRangeSplitDim(%arg0 : tensor<16xf32>) -> (tensor<8xf32>, tensor<8xf32>) { %split_dim = arith.constant dense<1> : tensor // expected-error @+1 {{'tfl.split' op 'split_dim' should be in [-rank, rank)}} %0, %1 = "tfl.split"(%split_dim, %arg0) {num_splits = 2 : i32} : (tensor, tensor<16xf32>) -> (tensor<8xf32>, tensor<8xf32>) func.return %0, %1 : tensor<8xf32>, tensor<8xf32> } // ----- func.func @testSplitOpWithOutOfRangeSplitDimTFLConst(%arg0 : tensor<16xf32>) -> (tensor<8xf32>, tensor<8xf32>) { %split_dim = "tfl.pseudo_const"() {value = dense<1> : tensor} : () -> tensor // expected-error @+1 {{'tfl.split' op 'split_dim' should be in [-rank, rank)}} %0, %1 = "tfl.split"(%split_dim, %arg0) {num_splits = 2 : i32} : (tensor, tensor<16xf32>) -> (tensor<8xf32>, tensor<8xf32>) func.return %0, %1 : tensor<8xf32>, tensor<8xf32> } // ----- func.func @testSplitOpWithOutOfRangeSplitDimNegative(%arg0 : tensor<16xf32>) -> (tensor<8xf32>, tensor<8xf32>) { %split_dim = arith.constant dense<-2> : tensor // expected-error @+1 {{'tfl.split' op 'split_dim' should be in [-rank, rank)}} %0, %1 = "tfl.split"(%split_dim, %arg0) {num_splits = 2 : i32} : (tensor, tensor<16xf32>) -> (tensor<8xf32>, tensor<8xf32>) func.return %0, %1 : tensor<8xf32>, tensor<8xf32> } // ----- func.func @testSplitOpWithUnevenDivision(%arg0 : tensor<16xf32>) -> (tensor<6xf32>, tensor<5xf32>, tensor<5xf32>) { %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split' op 'num_splits' should evenly divide 'split_dim' axis}} %0, %1, %2 = "tfl.split"(%split_dim, %arg0) {num_splits = 3 : i32} : (tensor, tensor<16xf32>) -> (tensor<6xf32>, tensor<5xf32>, tensor<5xf32>) func.return %0, %1, %2 : tensor<6xf32>, tensor<5xf32>, tensor<5xf32> } // ----- func.func @testSplitOpWithMismatchTensorTypeSplitDimOut0(%arg0 : tensor<16xf32>) -> (tensor<4xf32>, tensor<4xf32>) { %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split' op output #0 should be 'tensor<8xf32>'}} %0, %1 = "tfl.split"(%split_dim, %arg0) {num_splits = 2 : i32} : (tensor, tensor<16xf32>) -> (tensor<4xf32>, tensor<4xf32>) func.return %0, %1 : tensor<4xf32>, tensor<4xf32> } // ----- func.func @testSplitOpWithMismatchTensorTypeSplitDimOut1(%arg0 : tensor<16xf32>) -> (tensor<8xf32>, tensor<4xf32>) { %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split' op output #1 should be 'tensor<8xf32>'}} %0, %1 = "tfl.split"(%split_dim, %arg0) {num_splits = 2 : i32} : (tensor, tensor<16xf32>) -> (tensor<8xf32>, tensor<4xf32>) func.return %0, %1 : tensor<8xf32>, tensor<4xf32> } // ----- func.func @testSplitOpWithMismatchTensorTypeNonSplitDim(%arg0 : tensor<16x4xf32>) -> (tensor<8x2xf32>, tensor<8x2xf32>) { %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split' op output #0 should be 'tensor<8x4xf32>'}} %0, %1 = "tfl.split"(%split_dim, %arg0) {num_splits = 2 : i32} : (tensor, tensor<16x4xf32>) -> (tensor<8x2xf32>, tensor<8x2xf32>) func.return %0, %1 : tensor<8x2xf32>, tensor<8x2xf32> } // ----- // CHECK-LABEL:testSplitOpWithValidTensorType func.func @testSplitOpWithValidTensorType(%arg0 : tensor<16x4xf32>) -> (tensor<8x4xf32>, tensor<8x4xf32>, tensor<16x2xf32>, tensor<16x2xf32>, tensor<16x2xf32>) { %split_dim_0 = arith.constant dense<0> : tensor %0, %1 = "tfl.split"(%split_dim_0, %arg0) {num_splits = 2 : i32} : (tensor, tensor<16x4xf32>) -> (tensor<8x4xf32>, tensor<8x4xf32>) %split_dim_1 = arith.constant dense<1> : tensor %2, %3 = "tfl.split"(%split_dim_1, %arg0) {num_splits = 2 : i32} : (tensor, tensor<16x4xf32>) -> (tensor<16x2xf32>, tensor<16x2xf32>) %split_dim_2 = arith.constant dense<1> : tensor<1xi32> %4, %5 = "tfl.split"(%split_dim_2, %arg0) {num_splits = 2 : i32} : (tensor<1xi32>, tensor<16x4xf32>) -> (tensor<16x2xf32>, tensor<16x2xf32>) %6:2 = "tfl.split"(%split_dim_2, %arg0) {num_splits = 2 : i32} : (tensor<1xi32>, tensor<16x4xf32>) -> (tensor<16x2xf32>, tensor<16x?xf32>) %7:2 = "tfl.split"(%split_dim_2, %arg0) {num_splits = 2 : i32} : (tensor<1xi32>, tensor<16x4xf32>) -> (tensor, tensor<16x?xf32>) %8:2 = "tfl.split"(%split_dim_2, %arg0) {num_splits = 2 : i32} : (tensor<1xi32>, tensor<16x4xf32>) -> (tensor<16x2xf32>, tensor<*xf32>) func.return %0, %1, %2, %3, %4 : tensor<8x4xf32>, tensor<8x4xf32>, tensor<16x2xf32>, tensor<16x2xf32>, tensor<16x2xf32> } // ----- func.func @testSplitOpWithValidTensorTypeDynamic(%arg0 : tensor<16x?xf32>) -> (tensor<8x?xf32>, tensor<8x?xf32>) { %split_dim = arith.constant dense<0> : tensor %0, %1 = "tfl.split"(%split_dim, %arg0) {num_splits = 2 : i32} : (tensor, tensor<16x?xf32>) -> (tensor<8x?xf32>, tensor<8x?xf32>) func.return %0, %1 : tensor<8x?xf32>, tensor<8x?xf32> } // ----- func.func @testSplitVOpWithBadNumSplits(%arg0 : tensor<16xf32>) -> () { %size_splits = arith.constant dense<[]> : tensor<0xi32> %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split_v' op attribute 'num_splits' failed to satisfy constraint: 32-bit signless integer attribute whose value is positive}} "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 0 : i32} : (tensor<16xf32>, tensor<0xi32>, tensor) -> () func.return } // ----- func.func @testSplitVOpWithMismatchedNumResults(%arg0 : tensor<16xf32>) -> (tensor<8xf32>, tensor<8xf32>) { %size_splits = arith.constant dense<[4, 4, 4, 4]> : tensor<4xi32> %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split_v' op output count should match 'num_splits' attribute}} %0, %1 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 4 : i32} : (tensor<16xf32>, tensor<4xi32>, tensor) -> (tensor<8xf32>, tensor<8xf32>) func.return %0, %1 : tensor<8xf32>, tensor<8xf32> } // ----- func.func @testSplitVOpWithBadSizeSplitsTensorType(%arg0: tensor<16x4x4xf32>) -> tensor<16x4x4xf32> { %size_splits = arith.constant dense<[[8, 8], [2, 2]]> : tensor<2x2xi32> %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split_v' op operand #1 must be 1D tensor of 32-bit signless integer values}} %0 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 1 : i32} : (tensor<16x4x4xf32>, tensor<2x2xi32>, tensor) -> tensor<16x4x4xf32> func.return %0 : tensor<16x4x4xf32> } // ----- func.func @testSplitVOpWithBadSizeSplitsUnrankedTensorType(%arg0: tensor<16x4x4xf32>, %size_splits: tensor<*xi32>) -> tensor<16x4x4xf32> { %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split_v' op operand #1 must be 1D tensor of 32-bit signless integer values}} %0 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 1 : i32} : (tensor<16x4x4xf32>, tensor<*xi32>, tensor) -> tensor<16x4x4xf32> func.return %0 : tensor<16x4x4xf32> } // ----- func.func @testSplitVOpWithBadSizeSplitsConstant(%arg0: tensor<16x4x4xf32>) -> tensor<16x4x4xf32> { %size_splits = arith.constant dense<[-2]> : tensor<1xi32> %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split_v' op elements of 'size_splits' should be greater than or equal to -1}} %0 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 1 : i32} : (tensor<16x4x4xf32>, tensor<1xi32>, tensor) -> tensor<16x4x4xf32> func.return %0 : tensor<16x4x4xf32> } // ----- func.func @testSplitVOpWithBadSizeSplitsConstantMultipleNegativeOne(%arg0: tensor<16x4x4xf32>) -> (tensor<1x4x4xf32>, tensor<1x4x4xf32>, tensor<14x4x4xf32>) { %size_splits = arith.constant dense<[-1, -1, 14]> : tensor<3xi32> %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split_v' op 'size_splits' can only have one -1}} %0, %1, %2 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 3 : i32} : (tensor<16x4x4xf32>, tensor<3xi32>, tensor) -> (tensor<1x4x4xf32>, tensor<1x4x4xf32>, tensor<14x4x4xf32>) func.return %0, %1, %2 : tensor<1x4x4xf32>, tensor<1x4x4xf32>, tensor<14x4x4xf32> } // ----- func.func @testSplitVOpWithBadSizeSplitsConstantSum(%arg0: tensor<16x4x4xf32>) -> (tensor<0x4x4xf32>, tensor<16x4x4xf32>) { %size_splits = arith.constant dense<[-1, 17]> : tensor<2xi32> %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split_v' op sum of non-negative elements of 'size_splits' is greater than the dimension size of 'split_dim' axis}} %0, %1 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 2 : i32} : (tensor<16x4x4xf32>, tensor<2xi32>, tensor) -> (tensor<0x4x4xf32>, tensor<16x4x4xf32>) func.return %0, %1 : tensor<0x4x4xf32>, tensor<16x4x4xf32> } // ----- func.func @testSplitVOpWithBadSizeSplitsSize(%arg0: tensor<16x4x4xf32>) -> tensor<15x4x4xf32> { %size_splits = arith.constant dense<[15, 1]> : tensor<2xi32> %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split_v' op 'size_splits' should be 'tensor<1xi32>'}} %0 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 1 : i32} : (tensor<16x4x4xf32>, tensor<2xi32>, tensor) -> tensor<15x4x4xf32> func.return %0 : tensor<15x4x4xf32> } // ----- func.func @testSplitVOpWithBadSplitDimTensorType(%arg0: tensor<16x4x4xf32>) -> tensor<16x4x4xf32> { %size_splits = arith.constant dense<[16]> : tensor<1xi32> %split_dim = arith.constant dense<0> : tensor<2x2xi32> // expected-error @+1 {{'tfl.split_v' op operand #2 must be 0D tensor of 32-bit signless integer values}} %0 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 1 : i32} : (tensor<16x4x4xf32>, tensor<1xi32>, tensor<2x2xi32>) -> tensor<16x4x4xf32> func.return %0 : tensor<16x4x4xf32> } // ----- func.func @testSplitVOpWithBadSplitDimUnrankedTensorType(%arg0: tensor<16x4x4xf32>, %split_dim : tensor<*xi32>) -> tensor<16x4x4xf32> { %size_splits = arith.constant dense<[16]> : tensor<1xi32> // expected-error @+1 {{'tfl.split_v' op operand #2 must be 0D tensor of 32-bit signless integer values}} %0 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 1 : i32} : (tensor<16x4x4xf32>, tensor<1xi32>, tensor<*xi32>) -> tensor<16x4x4xf32> func.return %0 : tensor<16x4x4xf32> } // ----- func.func @testSplitVOpWithOutOfRangeSplitDim(%arg0 : tensor<16xf32>) -> (tensor<8xf32>, tensor<8xf32>) { %size_splits = arith.constant dense<[8, 8]> : tensor<2xi32> %split_dim = arith.constant dense<1> : tensor // expected-error @+1 {{'tfl.split_v' op 'split_dim' should be in [-rank, rank)}} %0, %1 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 2 : i32} : (tensor<16xf32>, tensor<2xi32>, tensor) -> (tensor<8xf32>, tensor<8xf32>) func.return %0, %1 : tensor<8xf32>, tensor<8xf32> } // ----- func.func @testSplitVOpWithOutOfRangeSplitDimTFLConst(%arg0 : tensor<16xf32>) -> (tensor<8xf32>, tensor<8xf32>) { %size_splits = arith.constant dense<[8, 8]> : tensor<2xi32> %split_dim = "tfl.pseudo_const"() {value = dense<1> : tensor} : () -> tensor // expected-error @+1 {{'tfl.split_v' op 'split_dim' should be in [-rank, rank)}} %0, %1 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 2 : i32} : (tensor<16xf32>, tensor<2xi32>, tensor) -> (tensor<8xf32>, tensor<8xf32>) func.return %0, %1 : tensor<8xf32>, tensor<8xf32> } // ----- func.func @testSplitVOpWithOutOfRangeSplitDimNegative(%arg0 : tensor<16xf32>) -> (tensor<8xf32>, tensor<8xf32>) { %size_splits = arith.constant dense<[8, 8]> : tensor<2xi32> %split_dim = arith.constant dense<-2> : tensor // expected-error @+1 {{'tfl.split_v' op 'split_dim' should be in [-rank, rank)}} %0, %1 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 2 : i32} : (tensor<16xf32>, tensor<2xi32>, tensor) -> (tensor<8xf32>, tensor<8xf32>) func.return %0, %1 : tensor<8xf32>, tensor<8xf32> } // ----- func.func @testSplitVOpWithMismatchSizeSplitsSum(%arg0 : tensor<16xf32>) -> (tensor<8xf32>, tensor<4xf32>) { %size_splits = arith.constant dense<[8, 4]> : tensor<2xi32> %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split_v' op sum of 'size_splits' should match the dimension size of 'split_dim' axis}} %0, %1 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 2 : i32} : (tensor<16xf32>, tensor<2xi32>, tensor) -> (tensor<8xf32>, tensor<4xf32>) func.return %0, %1 : tensor<8xf32>, tensor<4xf32> } // ----- func.func @testSplitVOpWithMismatchTensorTypeSplitDimOut0(%arg0 : tensor<16xf32>) -> (tensor<4xf32>, tensor<4xf32>) { %size_splits = arith.constant dense<[8, 8]> : tensor<2xi32> %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split_v' op output #0 should be 'tensor<8xf32>'}} %0, %1 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 2 : i32} : (tensor<16xf32>, tensor<2xi32>, tensor) -> (tensor<4xf32>, tensor<4xf32>) func.return %0, %1 : tensor<4xf32>, tensor<4xf32> } // ----- func.func @testSplitVOpWithMismatchTensorTypeSplitDimOut1(%arg0 : tensor<16xf32>) -> (tensor<8xf32>, tensor<4xf32>) { %size_splits = arith.constant dense<[8, 8]> : tensor<2xi32> %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split_v' op output #1 should be 'tensor<8xf32>'}} %0, %1 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 2 : i32} : (tensor<16xf32>, tensor<2xi32>, tensor) -> (tensor<8xf32>, tensor<4xf32>) func.return %0, %1 : tensor<8xf32>, tensor<4xf32> } // ----- func.func @testSplitVOpWithMismatchTensorTypeNonSplitDim(%arg0 : tensor<16x4xf32>) -> (tensor<8x2xf32>, tensor<8x2xf32>) { %size_splits = arith.constant dense<[8, 8]> : tensor<2xi32> %split_dim = arith.constant dense<0> : tensor // expected-error @+1 {{'tfl.split_v' op output #0 should be 'tensor<8x4xf32>'}} %0, %1 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 2 : i32} : (tensor<16x4xf32>, tensor<2xi32>, tensor) -> (tensor<8x2xf32>, tensor<8x2xf32>) func.return %0, %1 : tensor<8x2xf32>, tensor<8x2xf32> } // ----- func.func @testSplitVOpWithValidTensorType(%arg0 : tensor<16x4xf32>) -> (tensor<8x4xf32>, tensor<8x4xf32>, tensor<16x2xf32>, tensor<16x2xf32>) { %size_splits_0 = arith.constant dense<[8, 8]> : tensor<2xi32> %split_dim_0 = arith.constant dense<0> : tensor %0, %1 = "tfl.split_v"(%arg0, %size_splits_0, %split_dim_0) {num_splits = 2 : i32} : (tensor<16x4xf32>, tensor<2xi32>, tensor) -> (tensor<8x4xf32>, tensor<8x4xf32>) %size_splits_1 = arith.constant dense<[2, 2]> : tensor<2xi32> %split_dim_1 = arith.constant dense<1> : tensor %2, %3 = "tfl.split_v"(%arg0, %size_splits_1, %split_dim_1) {num_splits = 2 : i32} : (tensor<16x4xf32>, tensor<2xi32>, tensor) -> (tensor<16x2xf32>, tensor<16x2xf32>) func.return %0, %1, %2, %3 : tensor<8x4xf32>, tensor<8x4xf32>, tensor<16x2xf32>, tensor<16x2xf32> } // ----- func.func @testSplitVOpWithValidTensorTypeDynamic(%arg0 : tensor<16x?xf32>) -> (tensor<8x?xf32>, tensor<8x?xf32>) { %size_splits = arith.constant dense<[8, 8]> : tensor<2xi32> %split_dim = arith.constant dense<0> : tensor %0, %1 = "tfl.split_v"(%arg0, %size_splits, %split_dim) {num_splits = 2 : i32} : (tensor<16x?xf32>, tensor<2xi32>, tensor) -> (tensor<8x?xf32>, tensor<8x?xf32>) func.return %0, %1 : tensor<8x?xf32>, tensor<8x?xf32> } // ----- func.func @testSplitVOpWithValidSizeSplitsUneven(%arg0 : tensor<16x4xf32>) -> (tensor<7x4xf32>, tensor<3x4xf32>, tensor<6x4xf32>, tensor<16x1xf32>, tensor<16x3xf32>) { %size_splits_0 = arith.constant dense<[7, 3, 6]> : tensor<3xi32> %split_dim_0 = arith.constant dense<0> : tensor %0, %1, %2 = "tfl.split_v"(%arg0, %size_splits_0, %split_dim_0) {num_splits = 3 : i32} : (tensor<16x4xf32>, tensor<3xi32>, tensor) -> (tensor<7x4xf32>, tensor<3x4xf32>, tensor<6x4xf32>) %size_splits_1 = arith.constant dense<[1, 3]> : tensor<2xi32> %split_dim_1 = arith.constant dense<1> : tensor %3, %4 = "tfl.split_v"(%arg0, %size_splits_1, %split_dim_1) {num_splits = 2 : i32} : (tensor<16x4xf32>, tensor<2xi32>, tensor) -> (tensor<16x1xf32>, tensor<16x3xf32>) func.return %0, %1, %2, %3, %4 : tensor<7x4xf32>, tensor<3x4xf32>, tensor<6x4xf32>, tensor<16x1xf32>, tensor<16x3xf32> } // ----- func.func @testSplitVOpWithValidSizeSplitsNegative(%arg0 : tensor<16x4xf32>) -> (tensor<7x4xf32>, tensor<3x4xf32>, tensor<6x4xf32>, tensor<16x0xf32>, tensor<16x4xf32>) { %size_splits_0 = arith.constant dense<[7, -1, 6]> : tensor<3xi32> %split_dim_0 = arith.constant dense<0> : tensor %0, %1, %2 = "tfl.split_v"(%arg0, %size_splits_0, %split_dim_0) {num_splits = 3 : i32} : (tensor<16x4xf32>, tensor<3xi32>, tensor) -> (tensor<7x4xf32>, tensor<3x4xf32>, tensor<6x4xf32>) %size_splits_1 = arith.constant dense<[-1, 4]> : tensor<2xi32> %split_dim_1 = arith.constant dense<1> : tensor %3, %4 = "tfl.split_v"(%arg0, %size_splits_1, %split_dim_1) {num_splits = 2 : i32} : (tensor<16x4xf32>, tensor<2xi32>, tensor) -> (tensor<16x0xf32>, tensor<16x4xf32>) func.return %0, %1, %2, %3, %4 : tensor<7x4xf32>, tensor<3x4xf32>, tensor<6x4xf32>, tensor<16x0xf32>, tensor<16x4xf32> } // ----- func.func @testNonMaxSuppressionV4WithCorrectBoxShape(%arg0: tensor<3x4xf32>, %arg1: tensor<3xf32>, %arg2: tensor, %arg3: tensor, %arg4: tensor) -> (tensor<2xi32>, tensor) { %0, %1 = "tfl.non_max_suppression_v4"(%arg0, %arg1, %arg2, %arg3, %arg4) : (tensor<3x4xf32>, tensor<3xf32>, tensor, tensor, tensor) -> (tensor<2xi32>, tensor) func.return %0, %1 : tensor<2xi32>, tensor } // ----- func.func @testNonMaxSuppressionV4WithWrongBoxShape(%arg0: tensor<3x2xf32>, %arg1: tensor<3xf32>, %arg2: tensor, %arg3: tensor, %arg4: tensor) -> (tensor<2xi32>, tensor) { // expected-error @+1 {{'tfl.non_max_suppression_v4' op failed to verify that boxes should have dim[1] == 4}} %0, %1 = "tfl.non_max_suppression_v4"(%arg0, %arg1, %arg2, %arg3, %arg4) : (tensor<3x2xf32>, tensor<3xf32>, tensor, tensor, tensor) -> (tensor<2xi32>, tensor) func.return %0, %1 : tensor<2xi32>, tensor } // ----- func.func @testNonMaxSuppressionV5WithCorrectBoxShape(%arg0: tensor<3x4xf32>, %arg1: tensor<3xf32>, %arg2: tensor, %arg3: tensor, %arg4: tensor, %arg5: tensor) -> (tensor<2xi32>, tensor<2xf32>, tensor) { %0, %1, %2 = "tfl.non_max_suppression_v5"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5) : (tensor<3x4xf32>, tensor<3xf32>, tensor, tensor, tensor, tensor) -> (tensor<2xi32>, tensor<2xf32>, tensor) func.return %0, %1, %2 : tensor<2xi32>, tensor<2xf32>, tensor } // ----- func.func @testNonMaxSuppressionV5WithWrongBoxShape(%arg0: tensor<3x2xf32>, %arg1: tensor<3xf32>, %arg2: tensor, %arg3: tensor, %arg4: tensor, %arg5: tensor) -> (tensor<2xi32>, tensor<2xf32>, tensor) { // expected-error @+1 {{'tfl.non_max_suppression_v5' op failed to verify that boxes should have dim[1] == 4}} %0, %1, %2 = "tfl.non_max_suppression_v5"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5) : (tensor<3x2xf32>, tensor<3xf32>, tensor, tensor, tensor, tensor) -> (tensor<2xi32>, tensor<2xf32>, tensor) func.return %0, %1, %2 : tensor<2xi32>, tensor<2xf32>, tensor } // ----- func.func @fully_connected(%arg0: tensor<1x37xf32>, %arg1: tensor<40x37xf32>, %arg2: tensor<40xf32>) -> tensor<1x40xf32> { %0 = "tfl.fully_connected"(%arg0, %arg1, %arg2) {fused_activation_function = "NONE", keep_num_dims = false, weights_format = "DEFAULT"} : (tensor<1x37xf32>, tensor<40x37xf32>, tensor<40xf32>) -> tensor<1x40xf32> func.return %0 : tensor<1x40xf32> } // ----- func.func @fully_connected_with_int64_num_elements(%arg0: tensor<2048x128xf32>, %arg1: tensor<1049088x128xf32>, %arg2: none) -> tensor<2048x1049088xf32> { %0 = "tfl.fully_connected"(%arg0, %arg1, %arg2) <{fused_activation_function = "NONE", keep_num_dims = true, weights_format = "DEFAULT"}> : (tensor<2048x128xf32>, tensor<1049088x128xf32>, none) -> tensor<2048x1049088xf32> func.return %0 : tensor<2048x1049088xf32> } // ----- func.func @fully_connected_no_bias(%arg0: tensor<2x2x10xf32>, %arg1: tensor<40x40xf32>, %arg2: none) -> tensor<1x40xf32> { %0 = "tfl.fully_connected"(%arg0, %arg1, %arg2) {fused_activation_function = "NONE", keep_num_dims = false, weights_format = "DEFAULT"} : (tensor<2x2x10xf32>, tensor<40x40xf32>, none) -> tensor<1x40xf32> func.return %0 : tensor<1x40xf32> } // ----- func.func @testFullyConnectedWith3DFilter(%arg0: tensor<1x37xf32>, %arg1: tensor<40x2x37xf32>, %arg2: tensor<40xf32>) -> tensor<1x40xf32> { // expected-error @+1 {{expect 2d filter, got 'tensor<40x2x37xf32>'}} %0 = "tfl.fully_connected"(%arg0, %arg1, %arg2) {fused_activation_function = "NONE", keep_num_dims = false, weights_format = "DEFAULT"} : (tensor<1x37xf32>, tensor<40x2x37xf32>, tensor<40xf32>) -> tensor<1x40xf32> func.return %0 : tensor<1x40xf32> } // ----- func.func @testFullyConnectedWithBadInputShape(%arg0: tensor<2x2x11xf32>, %arg1: tensor<40x40xf32>, %arg2: none) -> tensor<1x40xf32> { // expected-error @+1 {{expect 'input' num_elements % 40 == 0, got input type 'tensor<2x2x11xf32>'}} %0 = "tfl.fully_connected"(%arg0, %arg1, %arg2) {fused_activation_function = "NONE", keep_num_dims = false, weights_format = "DEFAULT"} : (tensor<2x2x11xf32>, tensor<40x40xf32>, none) -> tensor<1x40xf32> func.return %0 : tensor<1x40xf32> } // ----- func.func @testFullyConnectedWithBadBatch(%arg0: tensor<1x37xf32>, %arg1: tensor<40x37xf32>, %arg2: tensor<40xf32>) -> tensor<2x40xf32> { // expected-error @+1 {{num_input_elements / z_in != num_output_elements / z_out}} %0 = "tfl.fully_connected"(%arg0, %arg1, %arg2) {fused_activation_function = "NONE", keep_num_dims = false, weights_format = "DEFAULT"} : (tensor<1x37xf32>, tensor<40x37xf32>, tensor<40xf32>) -> tensor<2x40xf32> func.return %0 : tensor<2x40xf32> } // ----- func.func @testFullyConnectedWithBadOutputShape(%arg0: tensor<1x37xf32>, %arg1: tensor<40x37xf32>, %arg2: tensor<40xf32>) -> tensor<1x41xf32> { // expected-error @+1 {{expect 'output' num_elements % 40 == 0, got 'tensor<1x41xf32>'}} %0 = "tfl.fully_connected"(%arg0, %arg1, %arg2) {fused_activation_function = "NONE", keep_num_dims = false, weights_format = "DEFAULT"} : (tensor<1x37xf32>, tensor<40x37xf32>, tensor<40xf32>) -> tensor<1x41xf32> func.return %0 : tensor<1x41xf32> } // ----- func.func @testTransposeConv(%arg0: tensor<4xi32>, %arg1: tensor<32x4x4x128xf32>, %arg2: tensor<1x32x42x128xf32>) -> tensor<1x64x84x32xf32> { %cst = "tfl.no_value"() {value = unit} : () -> none %0 = "tfl.transpose_conv"(%arg0, %arg1, %arg2, %cst) {padding = "SAME", stride_h = 2 : i32, stride_w = 2 : i32, fused_activation_function = "NONE"} : (tensor<4xi32>, tensor<32x4x4x128xf32>, tensor<1x32x42x128xf32>, none) -> tensor<1x64x84x32xf32> func.return %0 : tensor<1x64x84x32xf32> } // ----- // CHECK-LABEL: testTransposeConvWithOutputThatHasDynamicSizes func.func @testTransposeConvWithOutputThatHasDynamicSizes(%arg0: tensor<4xi32>, %arg1: tensor<32x4x4x128xf32>, %arg2: tensor<1x32x42x128xf32>) -> tensor { // CHECK: %[[NONE:.*]] = "tfl.no_value"() <{value}> : () -> none // CHECK: "tfl.transpose_conv"(%arg0, %arg1, %arg2, %[[NONE]]) %cst = "tfl.no_value"() {value = unit} : () -> none %0 = "tfl.transpose_conv"(%arg0, %arg1, %arg2, %cst) {padding = "SAME", stride_h = 2 : i32, stride_w = 2 : i32, fused_activation_function = "NONE"} : (tensor<4xi32>, tensor<32x4x4x128xf32>, tensor<1x32x42x128xf32>, none) -> tensor func.return %0 : tensor } // ----- func.func @testConvolution2DTransposeBias(%arg0: tensor<32x4x4x128xf32>, %arg1: tensor<1x32x42x128xf32>, %arg2: tensor<4xi32>) -> tensor<1x64x84x32xf32> { // custom op for "tfl.convolution_2d_transpose_bias"(%arg0, %arg1, %arg2) {padding = "SAME", stride_h = 2 : i32, stride_w = 2 : i32} : (tensor<32x4x4x128xf32>, tensor<1x32x42x128xf32>, tensor<4xi32>) -> tensor<1x64x84x32xf32> %0 = "tfl.custom"(%arg0, %arg1, %arg2) {custom_option = #tfl, custom_code = "Convolution2DTransposeBias"} : (tensor<32x4x4x128xf32>, tensor<1x32x42x128xf32>, tensor<4xi32>) -> tensor<1x64x84x32xf32> func.return %0 : tensor<1x64x84x32xf32> } // ----- func.func @testConvolution2DTransposeNoBias(%arg0: tensor<32x4x4x128xf32>, %arg1: tensor<1x32x42x128xf32>) -> tensor<1x64x84x32xf32> { %cst = "tfl.no_value"() {value = unit} : () -> none // custom op for "tfl.convolution_2d_transpose_bias"(%arg0, %arg1, %cst) {padding = "SAME", stride_h = 2 : i32, stride_w = 2 : i32} : (tensor<32x4x4x128xf32>, tensor<1x32x42x128xf32>, none) -> tensor<1x64x84x32xf32> %0 = "tfl.custom"(%arg0, %arg1, %cst) {custom_option = #tfl, custom_code = "Convolution2DTransposeBias"} : (tensor<32x4x4x128xf32>, tensor<1x32x42x128xf32>, none) -> tensor<1x64x84x32xf32> func.return %0 : tensor<1x64x84x32xf32> } // ----- func.func @testTransposeConvBadOutputRank(%arg0: tensor<4xi32>, %arg1: tensor<32x4x4x128xf32>, %arg2: tensor<1x32x42x128xf32>) -> tensor<64x84x32xf32> { %cst = "tfl.no_value"() {value = unit} : () -> none // expected-error @+1 {{expect output type has rank = 4, got output type tensor<64x84x32xf32>}} %0 = "tfl.transpose_conv"(%arg0, %arg1, %arg2, %cst) {padding = "SAME", stride_h = 2 : i32, stride_w = 2 : i32, fused_activation_function = "NONE"} : (tensor<4xi32>, tensor<32x4x4x128xf32>, tensor<1x32x42x128xf32>, none) -> tensor<64x84x32xf32> func.return %0 : tensor<64x84x32xf32> } // ----- func.func @testTransposeConvBadOutputShape(%arg1: tensor<32x4x4x128xf32>, %arg2: tensor<1x32x42x128xf32>) -> tensor<1x64x84x31xf32> { %cst = arith.constant dense<[1, 64, 84, 32]> : tensor<4xi32> %cst_1 = "tfl.no_value"() {value = unit} : () -> none // expected-error @+1 {{expect output type tensor<1x64x84x32xf32>, got tensor<1x64x84x31xf32>}} %0 = "tfl.transpose_conv"(%cst, %arg1, %arg2, %cst_1) {padding = "SAME", stride_h = 2 : i32, stride_w = 2 : i32, fused_activation_function = "NONE"} : (tensor<4xi32>, tensor<32x4x4x128xf32>, tensor<1x32x42x128xf32>, none) -> tensor<1x64x84x31xf32> func.return %0 : tensor<1x64x84x31xf32> } // ----- // CHECK-LABEL: testDensify func.func @testDensify(%arg0: tensor) -> tensor { // CHECK: "tfl.densify"(%arg0) : (tensor) -> tensor %0 = "tfl.densify"(%arg0): (tensor) -> tensor func.return %0 : tensor } // ----- func.func @WhileOp_cond(%arg0: tensor<*xi32>, %arg1: tensor<*xf32>) -> tensor { %cst = arith.constant dense<0> : tensor loc("Const") %0 = "tfl.greater"(%arg0, %cst) : (tensor<*xi32>, tensor) -> tensor func.return %0 : tensor } func.func @WhileOp_body(%arg0: tensor<*xi32>, %arg1: tensor<*xf32>) -> (tensor<*xi32>, tensor<*xf32>) { %cst = arith.constant dense<1> : tensor loc("Const1") %0 = "tfl.sub"(%arg0, %cst) {fused_activation_function = "NONE"} : (tensor<*xi32>, tensor) -> tensor<*xi32> %1 = tfl.add %arg1, %arg1 {fused_activation_function = "NONE"} : tensor<*xf32> func.return %0, %1 : tensor<*xi32>, tensor<*xf32> } func.func @main(%arg0: tensor, %arg1: tensor<1xf32>) -> tensor { // expected-error @+1 {{number of operands does not match number of results}} %0:1 = "tfl.while"(%arg0, %arg1) ({ ^bb0(%arg2: tensor<*xi32>, %arg3: tensor<*xf32>): %1 = func.call @WhileOp_cond(%arg2, %arg3) : (tensor<*xi32>, tensor<*xf32>) -> tensor "tfl.yield"(%1) : (tensor) -> () }, { ^bb0(%arg2: tensor<*xi32>, %arg3: tensor<*xf32>): %1:2 = func.call @WhileOp_body(%arg2, %arg3) : (tensor<*xi32>, tensor<*xf32>) -> (tensor<*xi32>, tensor<*xf32>) "tfl.yield"(%1#0, %1#1) : (tensor<*xi32>, tensor<*xf32>) -> () }) : (tensor, tensor<1xf32>) -> (tensor) func.return %0#0 : tensor } // ----- func.func @WhileOp_cond(%arg0: tensor<*xi32>) -> tensor { %cst = arith.constant dense<0> : tensor loc("Const") %0 = "tfl.greater"(%arg0, %cst) : (tensor<*xi32>, tensor) -> tensor func.return %0 : tensor } func.func @WhileOp_body(%arg0: tensor<*xi32>, %arg1: tensor<*xf32>) -> (tensor<*xi32>, tensor<*xf32>) { %cst = arith.constant dense<1> : tensor loc("Const1") %0 = "tfl.sub"(%arg0, %cst) {fused_activation_function = "NONE"} : (tensor<*xi32>, tensor) -> tensor<*xi32> %1 = tfl.add %arg1, %arg1 {fused_activation_function = "NONE"} : tensor<*xf32> func.return %0, %1 : tensor<*xi32>, tensor<*xf32> } func.func @main(%arg0: tensor, %arg1: tensor<*xf32>) -> tensor { // expected-error @+1 {{number of arguments in condition function does not match number of arguments in body function}} %0:2 = "tfl.while"(%arg0, %arg1) ({ ^bb0(%arg2: tensor<*xi32>): %1 = func.call @WhileOp_cond(%arg2) : (tensor<*xi32>) -> tensor "tfl.yield"(%1) : (tensor) -> () }, { ^bb0(%arg2: tensor<*xi32>, %arg3: tensor<*xf32>): %1:2 = func.call @WhileOp_body(%arg2, %arg3) : (tensor<*xi32>, tensor<*xf32>) -> (tensor<*xi32>, tensor<*xf32>) "tfl.yield"(%1#0, %1#1) : (tensor<*xi32>, tensor<*xf32>) -> () }) : (tensor, tensor<*xf32>) -> (tensor, tensor<*xf32>) func.return %0#0 : tensor } // ----- func.func @WhileOp_cond(%arg0: tensor<*xi32>, %arg1: tensor<1xf32>, %arg2: tensor<2xf32>) -> tensor { %cst = arith.constant dense<0> : tensor loc("Const") %0 = "tfl.greater"(%arg0, %cst) : (tensor<*xi32>, tensor) -> tensor func.return %0 : tensor } func.func @WhileOp_body(%arg0: tensor<*xi32>, %arg1: tensor<2xf32>, %arg2: tensor<1xf32>) -> (tensor<*xi32>, tensor<2xf32>, tensor<1xf32>) { %cst = arith.constant dense<1> : tensor loc("Const1") %0 = "tfl.sub"(%arg0, %cst) {fused_activation_function = "NONE"} : (tensor<*xi32>, tensor) -> tensor<*xi32> %1 = tfl.add %arg1, %arg1 {fused_activation_function = "NONE"} : tensor<2xf32> func.return %0, %1, %arg2 : tensor<*xi32>, tensor<2xf32>, tensor<1xf32> } func.func @main(%arg0: tensor, %arg1: tensor<1xf32>, %arg2: tensor<2xf32>) -> tensor { // expected-error @+1 {{condition function's argument type does not match body function's argument type}} %0:3 = "tfl.while"(%arg0, %arg1, %arg2) ({ ^bb0(%arg3: tensor<*xi32>, %arg4: tensor<1xf32>, %arg5: tensor<2xf32>): %1 = func.call @WhileOp_cond(%arg3, %arg4, %arg5) : (tensor<*xi32>, tensor<1xf32>, tensor<2xf32>) -> tensor "tfl.yield"(%1) : (tensor) -> () }, { ^bb0(%arg3: tensor<*xi32>, %arg4: tensor<2xf32>, %arg5: tensor<1xf32>): %1:3 = func.call @WhileOp_body(%arg3, %arg4, %arg5) : (tensor<*xi32>, tensor<2xf32>, tensor<1xf32>) -> (tensor<*xi32>, tensor<2xf32>, tensor<1xf32>) "tfl.yield"(%1#0, %1#1, %1#2) : (tensor<*xi32>, tensor<2xf32>, tensor<1xf32>) -> () }) : (tensor, tensor<1xf32>, tensor<2xf32>) -> (tensor, tensor<2xf32>, tensor<1xf32>) func.return %0#0 : tensor } // ----- func.func @if_then_else(%arg0: tensor, %arg1: tensor<1xf32>) -> tensor<1xf32> { %0 = "tfl.if"(%arg0) ({ "tfl.yield"(%arg1) : (tensor<1xf32>) -> () }, { %1 = "tfl.sub"(%arg1, %arg1) {fused_activation_function = "NONE"} : (tensor<1xf32>, tensor<1xf32>) -> tensor<1xf32> "tfl.yield"(%1) : (tensor<1xf32>) -> () }) : (tensor) -> (tensor<1xf32>) func.return %0 : tensor<1xf32> } func.func @if_then(%arg0: tensor, %arg1: tensor<1xf32>) -> tensor<1xf32> { // expected-error @+1 {{'tfl.if' op expected 2 regions}} %0 = "tfl.if"(%arg0) ({ %1 = "tfl.sub"(%arg1, %arg1) {fused_activation_function = "NONE"} : (tensor<1xf32>, tensor<1xf32>) -> tensor<1xf32> "tfl.yield"(%1) : (tensor<1xf32>) -> () }) : (tensor) -> (tensor<1xf32>) func.return %0 : tensor<1xf32> } // ----- func.func @test_reshape_with_per_axis_quant_dim(%arg0: tensor<1x2x3x4x5x!quant.uniform>) -> tensor<24x5x!quant.uniform> { %cst = arith.constant dense<[24, 5]> : tensor<2xi32> // CHECK: "tfl.reshape"(%arg0, %cst) %0 = "tfl.reshape"(%arg0, %cst) : (tensor<1x2x3x4x5x!quant.uniform>, tensor<2xi32>) -> tensor<24x5x!quant.uniform> func.return %0 : tensor<24x5x!quant.uniform> } // ----- func.func @test_reshape_with_per_axis_quant_dim_1(%arg0: tensor<1x2x3x4x5x!quant.uniform:f32:4, {0.2345, 0.2345, 0.2345, 0.2345, 0.2345}>>) -> tensor<24x5x!quant.uniform:f32:1, {0.2345, 0.2345, 0.2345, 0.2345, 0.2345}>> { %cst = arith.constant dense<[24, 5]> : tensor<2xi32> // CHECK: "tfl.reshape"(%arg0, %cst) %0 = "tfl.reshape"(%arg0, %cst) : (tensor<1x2x3x4x5x!quant.uniform:f32:4, {0.2345, 0.2345, 0.2345, 0.2345, 0.2345}>>, tensor<2xi32>) -> tensor<24x5x!quant.uniform:f32:1, {0.2345, 0.2345, 0.2345, 0.2345, 0.2345}>> func.return %0 : tensor<24x5x!quant.uniform:f32:1, {0.2345, 0.2345, 0.2345, 0.2345, 0.2345}>> } // ----- // CHECK-LABEL: valid_unranked_inputs_on_reshape func.func @valid_unranked_inputs_on_reshape(%arg0: tensor<3x4xi32>, %arg1: tensor<*xi32>) -> tensor<3x4xi32> { // CHECK: "tfl.reshape"(%arg0, %arg1) %0 = "tfl.reshape"(%arg0, %arg1) : (tensor<3x4xi32>, tensor<*xi32>) -> tensor<3x4xi32> func.return %0 : tensor<3x4xi32> } // ----- // CHECK-LABEL: valid_one_dynamic_dim_on_reshape func.func @valid_one_dynamic_dim_on_reshape(%arg0: tensor<3x4xi32>) -> tensor<1x3x4xi32> { %cst = arith.constant dense<[1, -1, 4]> : tensor<3xi32> // CHECK: "tfl.reshape"(%arg0, %cst) %0 = "tfl.reshape"(%arg0, %cst) : (tensor<3x4xi32>, tensor<3xi32>) -> tensor<1x3x4xi32> func.return %0 : tensor<1x3x4xi32> } // ----- func.func @invalid_two_dynamic_dims_on_reshape(%arg0: tensor<3x4xi32>) -> tensor<1x3x4xi32> { %cst = arith.constant dense<[-1, -1, 4]> : tensor<3xi32> // expected-error @+1 {{tfl.reshape' op requires 'shape' to have at most one dynamic dimension, but got multiple dynamic dimensions at indices 0 and 1. You need to set up the unspecified size(s) to avoid this problem, for example,setting batch size in keras model or setting unspecified input size(s) with fixed ones.}} %0 = "tfl.reshape"(%arg0, %cst) : (tensor<3x4xi32>, tensor<3xi32>) -> tensor<1x3x4xi32> func.return %0 : tensor<1x3x4xi32> } // ----- // CHECK-LABEL: testBroadcastToWithI32ShapeTensor func.func @testBroadcastToWithI32ShapeTensor(tensor, tensor<8xi32>) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor<8xi32>): // CHECK: "tfl.broadcast_to"(%arg0, %arg1) %0 = "tfl.broadcast_to"(%arg0, %arg1): (tensor, tensor<8xi32>) -> tensor func.return %0 : tensor } // CHECK-LABEL: testBroadcastToWithI64ShapeTensor func.func @testBroadcastToWithI64ShapeTensor(tensor, tensor<8xi64>) -> tensor { ^bb0(%arg0: tensor, %arg1: tensor<8xi64>): // CHECK: "tfl.broadcast_to"(%arg0, %arg1) %0 = "tfl.broadcast_to"(%arg0, %arg1): (tensor, tensor<8xi64>) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testFillWithQI8 func.func @testFillWithQI8(%arg0: tensor<1x4xi32>, %arg1: tensor>) -> tensor> { %0 = "tfl.fill"(%arg0, %arg1): (tensor<1x4xi32>, tensor>) -> tensor> func.return %0 : tensor> } // ----- // CHECK-LABEL: testConv3dWithFloatInput func.func @testConv3dWithFloatInput(%arg0: tensor,%arg1: tensor,%arg2: tensor) -> tensor { // CHECK: "tfl.conv_3d"(%arg0, %arg1, %arg2) %0 = "tfl.conv_3d"(%arg0, %arg1, %arg2) {dilation_d_factor = 1 : i32, dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "SAME", stride_d = 1 : i32, stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "NONE"}: (tensor, tensor, tensor) -> tensor func.return %0 : tensor } // CHECK-LABEL: testConv3dNoBiasInput func.func @testConv3dNoBiasInput(%arg0: tensor,%arg1: tensor,%arg2: none) -> tensor { // CHECK: "tfl.conv_3d"(%arg0, %arg1, %arg2) %0 = "tfl.conv_3d"(%arg0, %arg1, %arg2) {dilation_d_factor = 1 : i32, dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "SAME", stride_d = 1 : i32, stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "NONE"}: (tensor, tensor, none) -> tensor func.return %0 : tensor } // ----- func.func @testConv3dInvalidFilterShape(%arg0: tensor<2x3x4x5x2xf32>,%arg1: tensor<2x2x2x3x3xf32>,%arg2: tensor) -> tensor { // expected-error @+1 {{failed to verify that dim 4 of operand 0 equals to dim 3 of operand 1}} %0 = "tfl.conv_3d"(%arg0, %arg1, %arg2) {dilation_d_factor = 1 : i32, dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "SAME", stride_d = 1 : i32, stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "NONE"}: (tensor<2x3x4x5x2xf32>, tensor<2x2x2x3x3xf32>, tensor) -> tensor func.return %0 : tensor } // ----- func.func @testConv3dInvalidBiasShape(%arg0: tensor<2x3x4x5x2xf32>,%arg1: tensor<2x2x2x2x3xf32>,%arg2: tensor<4xf32>) -> tensor { // expected-error @+1 {{failed to verify that bias must has num of elements equals to 4th dim of filter}} %0 = "tfl.conv_3d"(%arg0, %arg1, %arg2) {dilation_d_factor = 1 : i32, dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "SAME", stride_d = 1 : i32, stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "NONE"}: (tensor<2x3x4x5x2xf32>, tensor<2x2x2x2x3xf32>, tensor<4xf32>) -> tensor func.return %0 : tensor } // ----- func.func @testConv3dMisMatchInputType(%arg0: tensor<2x3x4x5x2xi32>,%arg1: tensor<2x2x2x2x3xf32>,%arg2: tensor<3xf32>) -> tensor { // expected-error @+1 {{op failed to verify that input and output must have same element type}} %0 = "tfl.conv_3d"(%arg0, %arg1, %arg2) {dilation_d_factor = 1 : i32, dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "SAME", stride_d = 1 : i32, stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "NONE"}: (tensor<2x3x4x5x2xi32>, tensor<2x2x2x2x3xf32>, tensor<3xf32>) -> tensor func.return %0 : tensor } // ----- func.func @testConv3dMisMatchBiasType(%arg0: tensor<2x3x4x5x2xf32>,%arg1: tensor<2x2x2x2x3xf32>,%arg2: tensor<3xi32>) -> tensor { // expected-error @+1 {{failed to verify that bias and output must have same element type}} %0 = "tfl.conv_3d"(%arg0, %arg1, %arg2) {dilation_d_factor = 1 : i32, dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "SAME", stride_d = 1 : i32, stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "NONE"}: (tensor<2x3x4x5x2xf32>, tensor<2x2x2x2x3xf32>, tensor<3xi32>) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testComplexAbs func.func @testComplexAbs(%arg0: tensor>) -> tensor { // CHECK: "tfl.complex_abs"(%arg0) %0 = "tfl.complex_abs"(%arg0): (tensor>) -> tensor func.return %0 : tensor } // ----- func.func @testComplexAbsUnsupportedType(%arg0: tensor) -> tensor { // expected-error @+1 {{operand #0 must be tensor of complex type with 32-bit float elements or complex type with 64-bit float elements values}} %0 = "tfl.complex_abs"(%arg0): (tensor) -> tensor func.return %0 : tensor } // ----- func.func @testComplexAbsWrongShape(%arg0: tensor<2 x complex>) -> tensor<3xf32> { // expected-error @+1 {{requires the same shape for all operands and results}} %0 = "tfl.complex_abs"(%arg0): (tensor<2 x complex>) -> tensor<3xf32> func.return %0 : tensor<3xf32> } // ----- // CHECK-LABEL: testReal func.func @testReal(%arg0: tensor>) -> tensor { // CHECK: "tfl.real"(%arg0) %0 = "tfl.real"(%arg0): (tensor>) -> tensor func.return %0 : tensor } // ----- func.func @testRealWrongShape(%arg0: tensor<3 x complex>) -> tensor<4xf32> { // expected-error @+1 {{requires the same shape for all operands and results}} %0 = "tfl.real"(%arg0): (tensor<3 x complex>) -> tensor<4xf32> func.return %0 : tensor<4xf32> } // ----- // CHECK-LABEL: testImag func.func @testImag(%arg0: tensor>) -> tensor { // CHECK: "tfl.imag"(%arg0) %0 = "tfl.imag"(%arg0): (tensor>) -> tensor func.return %0 : tensor } // ----- func.func @testImagWrongType(%arg0: tensor<3 x complex>) -> tensor<4xi32> { // expected-error @+1 {{requires the same shape for all operands and results}} %0 = "tfl.imag"(%arg0): (tensor<3 x complex>) -> tensor<4xi32> func.return %0 : tensor<4xi32> } // ----- func.func @all(%arg0: tensor<2x2xi1>, %arg1: tensor) -> tensor { // CHECK: "tfl.reduce_all"(%arg0, %arg1) %0 = "tfl.reduce_all"(%arg0, %arg1) {keep_dims = false} : (tensor<2x2xi1>, tensor) -> tensor func.return %0 : tensor } // ----- func.func @conv3d_transpose(%arg0: tensor<5xi32>, %arg1: tensor, %arg2: tensor, %arg3: none) -> tensor { // CHECK: "tfl.conv_3d_transpose"(%arg0, %arg1, %arg2, %arg3) %0 = "tfl.conv_3d_transpose"(%arg0, %arg1, %arg2, %arg3) {data_format = "NDHWC", dilation_d_factor = 1 : i32, dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "VALID", stride_d = 1 : i32, stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "NONE"} : (tensor<5xi32>, tensor, tensor, none) -> tensor func.return %0 : tensor } // ----- func.func @conv3d_transpose_with_bias(%arg0: tensor<5xi32>, %arg1: tensor, %arg2: tensor, %arg3: tensor<2xf32>) -> tensor { // CHECK: "tfl.conv_3d_transpose"(%arg0, %arg1, %arg2, %arg3) %0 = "tfl.conv_3d_transpose"(%arg0, %arg1, %arg2, %arg3) {data_format = "NDHWC", dilation_d_factor = 1 : i32, dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "VALID", stride_d = 1 : i32, stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "NONE"} : (tensor<5xi32>, tensor, tensor, tensor<2xf32>) -> tensor func.return %0 : tensor } // ----- func.func @conv3d_transpose_channel_dim_not_match(%arg0: tensor<5xi32>, %arg1: tensor<1x2x2x3x2xf32>, %arg2: tensor<2x5x6x8x3xf32>, %arg3: tensor<2xf32>) -> tensor { // expected-error @+1 {{op failed to verify that dim 4 of operand 2 equals to dim 4 of operand 1}} %0 = "tfl.conv_3d_transpose"(%arg0, %arg1, %arg2, %arg3) {data_format = "NDHWC", dilation_d_factor = 1 : i32, dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "VALID", stride_d = 1 : i32, stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "NONE"} : (tensor<5xi32>, tensor<1x2x2x3x2xf32>, tensor<2x5x6x8x3xf32>, tensor<2xf32>) -> tensor func.return %0 : tensor } // ----- func.func @conv3d_transpose_bias_size_not_match(%arg0: tensor<5xi32>, %arg1: tensor<1x2x2x3x2xf32>, %arg2: tensor<2x5x6x8x2xf32>, %arg3: tensor<3xf32>) -> tensor { // expected-error @+1 {{bias must has num of elements equals to 4th dim of filter}} %0 = "tfl.conv_3d_transpose"(%arg0, %arg1, %arg2, %arg3) {data_format = "NDHWC", dilation_d_factor = 1 : i32, dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, padding = "VALID", stride_d = 1 : i32, stride_h = 1 : i32, stride_w = 1 : i32, fused_activation_function = "NONE"} : (tensor<5xi32>, tensor<1x2x2x3x2xf32>, tensor<2x5x6x8x2xf32>, tensor<3xf32>) -> tensor func.return %0 : tensor } // ----- func.func @broadcast_args(%arg0: tensor<5xi32>, %arg1: tensor<2xi32>) -> tensor<5xi32> { // CHECK: "tfl.broadcast_args"(%arg0, %arg1) %0 = "tfl.broadcast_args"(%arg0, %arg1) {} : (tensor<5xi32>, tensor<2xi32>) -> tensor<5xi32> func.return %0 : tensor<5xi32> } // ----- func.func @broadcast_args_unmatch_types(%arg0: tensor<5xi32>, %arg1: tensor<2xi64>) -> tensor<5xi32> { // expected-error @+1 {{failed to verify that BroadcastArgs op operands have same element type}} %0 = "tfl.broadcast_args"(%arg0, %arg1) {} : (tensor<5xi32>, tensor<2xi64>) -> tensor<5xi32> func.return %0 : tensor<5xi32> } // ----- func.func @mul_with_dynamic_shape_from_broadcast_args(%arg0: tensor<8x7x6x5x?x3x2x1xf32>, %arg1: tensor) -> tensor<8x7x6x5x?x3x2x1xf32> { %0 = "tfl.shape"(%arg0) : (tensor<8x7x6x5x?x3x2x1xf32>) -> tensor<8xi64> %1 = "tfl.shape"(%arg1) : (tensor) -> tensor<4xi64> %2 = "tfl.broadcast_args"(%0, %1) : (tensor<8xi64>, tensor<4xi64>) -> tensor<8xi64> %3 = "tfl.broadcast_to"(%arg0, %2) : (tensor<8x7x6x5x?x3x2x1xf32>, tensor<8xi64>) -> tensor<8x7x6x5x?x3x2x1xf32> %4 = "tfl.broadcast_to"(%arg1, %2) : (tensor, tensor<8xi64>) -> tensor<8x7x6x5x?x3x2x1xf32> %5 = "tfl.mul"(%3, %4) {fused_activation_function = "NONE"} : (tensor<8x7x6x5x?x3x2x1xf32>, tensor<8x7x6x5x?x3x2x1xf32>) -> tensor<8x7x6x5x?x3x2x1xf32> func.return %5 : tensor<8x7x6x5x?x3x2x1xf32> // CHECK: tfl.mul } // ----- func.func @mul_with_dynamic_shape_not_from_broadcast_args(%arg0: tensor<8x7x6x5x?x3x2x1xf32>, %arg1: tensor<8x7x6x5x?x3x2x1xf32>) -> tensor<8x7x6x5x?x3x2x1xf32> { // expected-error @+1 {{'tfl.mul' op failed to verify that Operands do not have valid shapes}} %0 = "tfl.mul"(%arg0, %arg1) {fused_activation_function = "NONE"} : (tensor<8x7x6x5x?x3x2x1xf32>, tensor<8x7x6x5x?x3x2x1xf32>) -> tensor<8x7x6x5x?x3x2x1xf32> func.return %0 : tensor<8x7x6x5x?x3x2x1xf32> } // ----- func.func @select_v2_with_dynamic_shape_from_broadcast_args(%arg0: tensor<8x7x6x5x?x3x2x1xi1>, %arg1: tensor<8x7x6x5x?x3x2x1xf32>, %arg2: tensor) -> tensor<8x7x6x5x?x3x2x1xf32> { %0 = "tfl.shape"(%arg1) : (tensor<8x7x6x5x?x3x2x1xf32>) -> tensor<8xi64> %1 = "tfl.shape"(%arg2) : (tensor) -> tensor<4xi64> %2 = "tfl.broadcast_args"(%0, %1) : (tensor<8xi64>, tensor<4xi64>) -> tensor<8xi64> %3 = "tfl.shape"(%arg0) : (tensor<8x7x6x5x?x3x2x1xi1>) -> tensor<8xi64> %4 = "tfl.broadcast_args"(%2, %3) : (tensor<8xi64>, tensor<8xi64>) -> tensor<8xi64> %5 = "tfl.broadcast_to"(%arg0, %4) : (tensor<8x7x6x5x?x3x2x1xi1>, tensor<8xi64>) -> tensor<8x7x6x5x?x3x2x1xi1> %6 = "tfl.broadcast_to"(%arg1, %4) : (tensor<8x7x6x5x?x3x2x1xf32>, tensor<8xi64>) -> tensor<8x7x6x5x?x3x2x1xf32> %7 = "tfl.broadcast_to"(%arg2, %4) : (tensor, tensor<8xi64>) -> tensor<8x7x6x5x?x3x2x1xf32> %8 = "tfl.select_v2"(%5, %6, %7) : (tensor<8x7x6x5x?x3x2x1xi1>, tensor<8x7x6x5x?x3x2x1xf32>, tensor<8x7x6x5x?x3x2x1xf32>) -> tensor<8x7x6x5x?x3x2x1xf32> func.return %8 : tensor<8x7x6x5x?x3x2x1xf32> } // ----- func.func @select_v2_with_dynamic_shape_not_from_broadcast_args(%arg0: tensor<8x7x6x5x?x3x2x1xi1>, %arg1: tensor<8x7x6x5x?x3x2x1xf32>, %arg2: tensor, %arg3: tensor<8xi64>) -> tensor<8x7x6x5x?x3x2x1xf32> { %0 = "tfl.broadcast_to"(%arg1, %arg3) : (tensor<8x7x6x5x?x3x2x1xf32>, tensor<8xi64>) -> tensor<8x7x6x5x?x3x2x1xf32> %1 = "tfl.broadcast_to"(%arg2, %arg3) : (tensor, tensor<8xi64>) -> tensor<8x7x6x5x?x3x2x1xf32> // expected-error @+1 {{'tfl.select_v2' op failed to verify that operands do not have the same shape or broadcastable shapes within the rank 5}} %2 = "tfl.select_v2"(%arg0, %0, %1) : (tensor<8x7x6x5x?x3x2x1xi1>, tensor<8x7x6x5x?x3x2x1xf32>, tensor<8x7x6x5x?x3x2x1xf32>) -> tensor<8x7x6x5x?x3x2x1xf32> func.return %2 : tensor<8x7x6x5x?x3x2x1xf32> } // ----- func.func @depthwise_conv_2D_invalid_bias(%arg0: tensor<1x224x224x3xf32>) -> tensor<1x112x112x32xf32> { %w = arith.constant dense<127.0> : tensor<32x3x3x3xf32> %b = arith.constant dense<0.0> : tensor<32x1xf32> // expected-error-re @+1 {{'tfl.depthwise_conv_2d' op operand #2 must be 1D tensor of any {{(non-token )?}}type values or none type, but got 'tensor<32x1xf32>'}} %dc = "tfl.depthwise_conv_2d"(%arg0, %w, %b) {depth_multiplier = 4 : i32, dilation_h_factor = 1 : i32, dilation_w_factor = 1 : i32, fused_activation_function = "NONE", padding = "VALID", stride_h = 4 : i32, stride_w = 5 : i32} : (tensor<1x224x224x3xf32>, tensor<32x3x3x3xf32>, tensor<32x1xf32>) -> tensor<1x112x112x32xf32> func.return %dc : tensor<1x112x112x32xf32> } // ----- // CHECK-LABEL: testRandomUniform func.func @testRandomUniform(%arg0: tensor<3xi32>) -> tensor { // CHECK: "tfl.random_uniform"(%arg0) %0 = "tfl.random_uniform"(%arg0) {seed = 0 : i64, seed2 = 0 : i64} : (tensor<3xi32>) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testRandomStandardNormal func.func @testRandomStandardNormal(%arg0: tensor<3xi32>) -> tensor { // CHECK: "tfl.random_standard_normal"(%arg0) %0 = "tfl.random_standard_normal"(%arg0) {seed = 0 : i64, seed2 = 0 : i64} : (tensor<3xi32>) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testMultinomial func.func @testMultinomial(%arg0: tensor<2xf32>, %arg1: tensor<1xi32>) -> tensor<10xi64> { // CHECK: "tfl.multinomial"(%arg0, %arg1) %0 = "tfl.multinomial"(%arg0, %arg1) {seed = 0 : i64, seed2 = 0: i64} : (tensor<2xf32>, tensor<1xi32>) -> tensor<10xi64> func.return %0 : tensor<10xi64> } // ----- // CHECK-LABEL: testMultinomialInt32 func.func @testMultinomialInt32(%arg0: tensor<2xf32>, %arg1: tensor<1xi32>) -> tensor<10xi32> { // CHECK: "tfl.multinomial"(%arg0, %arg1) %0 = "tfl.multinomial"(%arg0, %arg1) {seed = 0 : i64, seed2 = 0: i64} : (tensor<2xf32>, tensor<1xi32>) -> tensor<10xi32> func.return %0 : tensor<10xi32> } // ----- // CHECK-LABEL: testGelu func.func @testGelu(%arg0: tensor<1x2x3x4x5xf32>) -> tensor<1x2x3x4x5xf32> { // CHECK: "tfl.gelu"(%arg0) %0 = "tfl.gelu"(%arg0) {approximate = false}: (tensor<1x2x3x4x5xf32>) -> tensor<1x2x3x4x5xf32> func.return %0 : tensor<1x2x3x4x5xf32> } // ----- // test invalid GELU input func.func @testGeluWithWrongInputType(%arg0: tensor) -> tensor { // expected-error @+1 {{'tfl.gelu' op failed to verify that input and output must have same element type}} %0 = "tfl.gelu"(%arg0) {approximate = false}: (tensor) -> tensor func.return %0#0 : tensor } // ----- // CHECK-LABEL: scatter_nd_i1 func.func @scatter_nd_i1(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // CHECK: "tfl.scatter_nd"(%arg0, %arg1, %arg2) %0 = "tfl.scatter_nd"(%arg0, %arg1, %arg2): (tensor, tensor, tensor) -> tensor func.return %0 : tensor } // ----- // CHECK-LABEL: testUnsortedSegmentSum func.func @testUnsortedSegmentSum(%arg0: tensor<8xf32>, %arg1: tensor<8xi32>, %arg2: tensor) -> tensor<8xf32> { // CHECK: "tfl.unsorted_segment_sum"(%arg0, %arg1, %arg2) %0 = "tfl.unsorted_segment_sum"(%arg0, %arg1, %arg2) : (tensor<8xf32>, tensor<8xi32>, tensor) -> tensor<8xf32> func.return %0 : tensor<8xf32> // CHECK: return %0 : tensor<8xf32> } // ----- // CHECK-LABEL: testUnsortedSegmentProd func.func @testUnsortedSegmentProd(%arg0: tensor<8xf32>, %arg1: tensor<8xi32>, %arg2: tensor) -> tensor<8xf32> { // CHECK: "tfl.unsorted_segment_prod"(%arg0, %arg1, %arg2) %0 = "tfl.unsorted_segment_prod"(%arg0, %arg1, %arg2) : (tensor<8xf32>, tensor<8xi32>, tensor) -> tensor<8xf32> func.return %0 : tensor<8xf32> // CHECK: return %0 : tensor<8xf32> } // ----- // CHECK-LABEL: testUnsortedSegmentMax func.func @testUnsortedSegmentMax(%arg0: tensor<8xf32>, %arg1: tensor<8xi32>, %arg2: tensor) -> tensor<8xf32> { // CHECK: "tfl.unsorted_segment_max"(%arg0, %arg1, %arg2) %0 = "tfl.unsorted_segment_max"(%arg0, %arg1, %arg2) : (tensor<8xf32>, tensor<8xi32>, tensor) -> tensor<8xf32> func.return %0 : tensor<8xf32> // CHECK: return %0 : tensor<8xf32> } // ----- // CHECK-LABEL: testControlNodeLongForm func.func @testControlNodeLongForm(%arg0: tensor<8xf32>, %arg1: tensor<8xf32>)->tensor<8xf32> { %0, %c0 = "tfl.control_node"() ({ %1 = "tfl.add"(%arg0, %arg1) {fused_activation_function = "RELU6"} : (tensor<8xf32>, tensor<8xf32>)->tensor<8xf32> "tfl.yield"(%1) : (tensor<8xf32>) -> () }) : () -> (tensor<8xf32>, !tfl.control) func.return %0 : tensor<8xf32> } // ----- // CHECK-LABEL: testControlNodeShortForm func.func @testControlNodeShortForm(%arg0: tensor<8xf32>, %arg1: tensor<8xf32>)->tensor<8xf32> { %0, %c0 = tfl.control_node() controls "tfl.add"(%arg0, %arg1) {fused_activation_function = "RELU6"} : (tensor<8xf32>, tensor<8xf32>)->tensor<8xf32> func.return %0 : tensor<8xf32> } // ----- // CHECK-LABEL: testUnsortedSegmentMin func.func @testUnsortedSegmentMin(%arg0: tensor<8xf32>, %arg1: tensor<8xi32>, %arg2: tensor) -> tensor<8xf32> { // CHECK: "tfl.unsorted_segment_min"(%arg0, %arg1, %arg2) %0 = "tfl.unsorted_segment_min"(%arg0, %arg1, %arg2) : (tensor<8xf32>, tensor<8xi32>, tensor) -> tensor<8xf32> func.return %0 : tensor<8xf32> // CHECK: return %0 : tensor<8xf32> } // ----- // CHECK-LABEL: testBitcast func.func @testBitcast(%arg0: tensor<8xui32>) -> tensor<8xi32> { // CHECK: "tfl.bitcast"(%arg0) %0 = "tfl.bitcast"(%arg0) : (tensor<8xui32>) -> tensor<8xi32> func.return %0 : tensor<8xi32> // CHECK: return %0 : tensor<8xi32> } // ----- // CHECK-LABEL: testBitwiseXor func.func @testBitwiseXor(%arg0: tensor<8xui32>, %arg1: tensor<8xui32>) -> tensor<8xui32> { // CHECK: "tfl.bitwise_xor"(%arg0, %arg1) %0 = "tfl.bitwise_xor"(%arg0, %arg1) : (tensor<8xui32>, tensor<8xui32>) -> tensor<8xui32> func.return %0 : tensor<8xui32> // CHECK: return %0 : tensor<8xui32> } // ----- // CHECK-LABEL: testRightShift func.func @testRightShift(%arg0: tensor<8xui32>, %arg1: tensor<8xui32>) -> tensor<8xui32> { // CHECK: "tfl.right_shift"(%arg0, %arg1) %0 = "tfl.right_shift"(%arg0, %arg1) : (tensor<8xui32>, tensor<8xui32>) -> tensor<8xui32> func.return %0 : tensor<8xui32> // CHECK: return %0 : tensor<8xui32> } // ----- // CHECK-LABEL: testDilate func.func @testDilate(%arg0: tensor<3x4x5xf32>) -> tensor<5x7x9xf32> { // CHECK: "tfl.dilate"(%arg0, %cst, %cst_0) %cst = arith.constant dense<1> : tensor<3xi32> %cst_0 = arith.constant dense<-1.0> : tensor %0 = "tfl.dilate"(%arg0, %cst, %cst_0) : (tensor<3x4x5xf32>, tensor<3xi32>, tensor) -> tensor<5x7x9xf32> func.return %0 : tensor<5x7x9xf32> // CHECK: return %0 : tensor<5x7x9xf32> }