//-------------------------------------------------------------------------------------------------- // Test expected errors generated by verifier checks. //-------------------------------------------------------------------------------------------------- // RUN: mlir-opt %s -split-input-file -verify-diagnostics // ----- func.func @test_transpose_io_rank_mismatch(%arg0: tensor<13x21x3xf32>, %arg1: tensor<3xi32>) -> tensor<3x13x21x1xf32> { // expected-error@+1 {{'tosa.transpose' op expected input tensor rank to equal result tensor rank}} %0 = tosa.transpose %arg0 {perms = array}: (tensor<13x21x3xf32>) -> tensor<3x13x21x1xf32> return %0 : tensor<3x13x21x1xf32> } // ----- func.func @test_transpose_rank0_perms() { %14 = tensor.empty() : tensor<5x27xi64> // expected-error@+1 {{'tosa.transpose' op expected perms attribute to have size 2 (input rank) but got size 0}} %72 = tosa.transpose %14 {perms = array }: (tensor<5x27xi64>) -> tensor return } // ----- func.func @test_transpose_invalid_perms_size(%arg0: tensor<13x21x3xf32>) -> tensor<3x13x21xf32> { // expected-error@+1 {{'tosa.transpose' op expected perms attribute to have size 3 (input rank) but got size 7}} %0 = tosa.transpose %arg0 {perms = array }: (tensor<13x21x3xf32>) -> tensor<3x13x21xf32> return %0 : tensor<3x13x21xf32> } // ----- func.func @test_transpose_invalid_permutation_tensor(%arg0: tensor<13x21x3xf32>) -> tensor { // expected-error@+1 {{'tosa.transpose' op expected valid permutation indices}} %0 = tosa.transpose %arg0 {perms = array }: (tensor<13x21x3xf32>) -> tensor return %0 : tensor } // ----- func.func @test_transpose_invalid_permutation_negative(%arg0: tensor<3x2xi32>) -> tensor<*xi32> { // expected-error@+1 {{'tosa.transpose' op expected valid permutation indices}} %1 = tosa.transpose %arg0 {perms = array }: (tensor<3x2xi32>) -> tensor<*xi32> return %1 : tensor<*xi32> } // ----- func.func @test_transpose_invalid_permutation_tensor_above_range(%arg0: tensor<3x2xi32>) -> tensor<*xi32> { // expected-error@+1 {{'tosa.transpose' op expected valid permutation indices}} %1 = tosa.transpose %arg0 {perms = array }: (tensor<3x2xi32>) -> tensor<*xi32> return %1 : tensor<*xi32> } // ----- func.func @test_transpose_invalid_num_elements(%arg0: tensor<3x2xi32>) -> tensor<3x4xi32> { // expected-error@+1 {{'tosa.transpose' op expected input1 and output to have same numbers of elements, got 6 and 12}} %1 = tosa.transpose %arg0 {perms = array }: (tensor<3x2xi32>) -> tensor<3x4xi32> return %1 : tensor<3x4xi32> } // ----- func.func @test_transpose_invalid_permutation_types(%arg0: tensor<3x2xi32>) -> tensor<3x2xi32> { // expected-error@+1 {{'tosa.transpose' op expected output tensor dim 0 to match input dim 1 with value of 2}} %1 = tosa.transpose %arg0 {perms = array }: (tensor<3x2xi32>) -> tensor<3x2xi32> return %1 : tensor<3x2xi32> } // ----- func.func @test_transpose_invalid_permutation_types_dynamic_dim_ok(%arg0: tensor<2x?xi32>) -> tensor<3x4xi32> { // expected-error@+1 {{'tosa.transpose' op expected output tensor dim 1 to match input dim 0 with value of 2}} %1 = tosa.transpose %arg0 {perms = array }: (tensor<2x?xi32>) -> tensor<3x4xi32> return %1 : tensor<3x4xi32> } // ----- func.func @test_transpose_element_type_mismatch(%arg0: tensor<2x3xi32>) -> tensor<3x2xf32> { // expected-error@+1 {{'tosa.transpose' op failed to verify that all of {input1, output} have same element type}} %1 = tosa.transpose %arg0 {perms = array} : (tensor<2x3xi32>) -> tensor<3x2xf32> return %1 : tensor<3x2xf32> } // ----- // CHECK-LABEL: @test_invalid_constant_permutation func.func @test_invalid_constant_permutation() { %0 = tensor.empty() : tensor<3x4x5xi32> // expected-error@+1 {{'tosa.transpose' op expected valid permutation indices}} %2 = tosa.transpose %0 {perms = array}: (tensor<3x4x5xi32>) -> tensor<3x4x5xi32> return } // ----- // CHECK-LABEL: test_rank_size_constant_permutation func.func @test_rank_size_constant_permutation() { %0 = arith.constant 6 : index %2 = tensor.empty(%0) : tensor // expected-error@+1 {{'tosa.transpose' op expected valid permutation indices}} %3 = tosa.transpose %2 {perms = array}: (tensor) -> tensor return } // ----- // CHECK-LABEL: test_large_constant_permutation func.func @test_large_constant_permutation() { %0 = arith.constant 6 : index %2 = tensor.empty(%0) : tensor // expected-error@+1 {{'tosa.transpose' op expected valid permutation indices}} %3 = tosa.transpose %2 {perms = array}: (tensor) -> tensor return } // ----- func.func @test_scalar_output_transpose(%arg0: tensor<*xf32>) -> tensor { // expected-error@+1 {{'tosa.transpose' op result #0 must be tosa-conformant tensor of at least rank 1, but got 'tensor'}} %1 = tosa.transpose %arg0 {perms = array} : (tensor<*xf32>) -> tensor return %1 : tensor } // ----- func.func @test_reverse_element_type_mismatch(%arg0: tensor<2x3xi32>) -> tensor<2x3xf32> { // expected-error@+1 {{'tosa.reverse' op requires the same element type for all operands and results}} %0 = tosa.reverse %arg0 {axis = 1 : i32} : (tensor<2x3xi32>) -> tensor<2x3xf32> return %0 : tensor<2x3xf32> } // ----- func.func @test_reverse_shape_mismatch(%arg0: tensor<2x3xi32>) -> tensor<2x4xi32> { // expected-error@+1 {{'tosa.reverse' op requires the same shape for all operands and results}} %0 = tosa.reverse %arg0 {axis = 1 : i32} : (tensor<2x3xi32>) -> tensor<2x4xi32> return %0 : tensor<2x4xi32> } // ----- func.func @test_reverse_rank_mismatch(%arg0: tensor<2x3xi32>) -> tensor<1x2x3xi32> { // expected-error@+1 {{'tosa.reverse' op result type has different rank than operands}} %0 = tosa.reverse %arg0 {axis = 1 : i32} : (tensor<2x3xi32>) -> tensor<1x2x3xi32> return %0 : tensor<1x2x3xi32> } // ----- func.func @test_slice_invalid_output_rank() { %0 = tensor.empty() : tensor<4x31x31xf32> %start = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %size = tosa.const_shape {values = dense<[1, 1, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.slice' op expect input1 and output to have the same ranks, got 3 and 4}} %3 = tosa.slice %0, %start, %size : (tensor<4x31x31xf32>, !tosa.shape<2>, !tosa.shape<3>) -> tensor return } // ----- func.func @test_slice_invalid_start() { %0 = tensor.empty() : tensor<4x31x31xf32> %start = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %size = tosa.const_shape {values = dense<[1, 1, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.slice' op length of start is not equal to rank of input shape}} %3 = tosa.slice %0, %start, %size : (tensor<4x31x31xf32>, !tosa.shape<2>, !tosa.shape<3>) -> tensor<*xf32> return } // ----- func.func @test_slice_invalid_size() { %0 = tensor.empty() : tensor<4x31x31xf32> %start = tosa.const_shape {values = dense<[1, 1, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> %size = tosa.const_shape {values = dense<[1]> : tensor<1xindex>} : () -> !tosa.shape<1> // expected-error@+1 {{'tosa.slice' op length of size is not equal to rank of input shape}} %3 = tosa.slice %0, %start, %size : (tensor<4x31x31xf32>, !tosa.shape<3>, !tosa.shape<1>) -> tensor<*xf32> return } // ----- func.func @test_scalar_slice(%arg0: tensor) -> tensor { %0 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0> %1 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0> // expected-error@+1 {{'tosa.slice' op operand #0 must be tosa-conformant tensor of at least rank 1, but got 'tensor'}} %2 = tosa.slice %arg0, %0, %1 : (tensor, !tosa.shape<0>, !tosa.shape<0>) -> tensor return %2 : tensor } // ----- func.func @test_slice_invalid_start_values(%arg0: tensor<4x31x31xf32>) { %start = tosa.const_shape {values = dense<[-2, 0, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> %size = tosa.const_shape {values = dense<[1, 1, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.slice' op start values must be non-negative, got [-2, 0, 0]}} %1 = tosa.slice %arg0, %start, %size : (tensor<4x31x31xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<1x1x1xf32> return } // ----- func.func @test_slice_invalid_size_values(%arg0: tensor<4x31x31xf32>) { %start = tosa.const_shape {values = dense<[0, 0, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> %size = tosa.const_shape {values = dense<[1, 0, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.slice' op size values must be > 0, got [1, 0, 1]}} %1 = tosa.slice %arg0, %start, %size : (tensor<4x31x31xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor return } // ----- func.func @test_slice_output_shape_mismatch(%arg0: tensor<4x5x6xf32>) { %start = tosa.const_shape {values = dense<[0, 0, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> %size = tosa.const_shape {values = dense<[1, 2, 3]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.slice' op expected output shape to match size values, got 'tensor<1x2x4xf32>' vs [1, 2, 3]}} %1 = tosa.slice %arg0, %start, %size : (tensor<4x5x6xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<1x2x4xf32> return } // ----- func.func @test_slice_invalid_start_plus_size(%arg0: tensor) { %start = tosa.const_shape {values = dense<[-1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %size = tosa.const_shape {values = dense<[3, 2]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.slice' op start + size must be less than or equal to input dimension size, got start=1, size=2 vs input dim size=2 at dimension 1}} %1 = tosa.slice %arg0, %start, %size : (tensor, !tosa.shape<2>, !tosa.shape<2>) -> tensor return } // ----- func.func @test_slice_output_shape_mismatch_dynamic(%arg0: tensor) { %start = tosa.const_shape {values = dense<[0, 0, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> %size = tosa.const_shape {values = dense<[1, 2, 3]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.slice' op expected output shape to match size values, got 'tensor' vs [1, 2, 3]}} %1 = tosa.slice %arg0, %start, %size : (tensor, !tosa.shape<3>, !tosa.shape<3>) -> tensor return } // ----- func.func @test_depthwise_conv2d_invalid_padding(%arg0: tensor<1x4x4x4xf32>, %arg1: tensor<1x1x8x4xf32>, %arg2: tensor<8xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x4x8xf32> { // expected-error@+1 {{'tosa.depthwise_conv2d' op expect all padding values to be >= 0, got 0, 0, -1, 0}} %0 = tosa.depthwise_conv2d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array, local_bound = true} : (tensor<1x4x4x4xf32>, tensor<1x1x8x4xf32>, tensor<8xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x4x8xf32> return %0 : tensor<1x4x4x8xf32> } // ----- func.func @test_depthwise_conv2d_invalid_stride(%arg0: tensor<1x4x4x4xf32>, %arg1: tensor<1x1x8x4xf32>, %arg2: tensor<8xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x4x8xf32> { // expected-error@+1 {{'tosa.depthwise_conv2d' op expect all stride values to be >= 1, got 0, 1}} %0 = tosa.depthwise_conv2d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array, local_bound = true} : (tensor<1x4x4x4xf32>, tensor<1x1x8x4xf32>, tensor<8xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x4x8xf32> return %0 : tensor<1x4x4x8xf32> } // ----- func.func @test_depthwise_conv2d_invalid_dilation(%arg0: tensor<1x4x4x4xf32>, %arg1: tensor<1x1x8x4xf32>, %arg2: tensor<8xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x4x8xf32> { // expected-error@+1 {{'tosa.depthwise_conv2d' op expect all dilation values to be >= 1, got 1, 0}} %0 = tosa.depthwise_conv2d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array, local_bound = true} : (tensor<1x4x4x4xf32>, tensor<1x1x8x4xf32>, tensor<8xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x4x8xf32> return %0 : tensor<1x4x4x8xf32> } // ----- func.func @test_depthwise_conv2d_wholly_divisible_height(%arg0: tensor<1x4x4x4xf32>, %arg1: tensor<1x1x8x4xf32>, %arg2: tensor<8xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x4x8xf32> { // expected-error@+1 {{'tosa.depthwise_conv2d' op expected input_height - 1 + pad_top + pad_bottom - (kernel_height - 1) * dilation_y to be wholly divisible by stride_y, got (4 - 1 + 0 + 0 - (1 - 1) * 1) / 2}} %0 = tosa.depthwise_conv2d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array, local_bound = true} : (tensor<1x4x4x4xf32>, tensor<1x1x8x4xf32>, tensor<8xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x4x8xf32> return %0 : tensor<1x4x4x8xf32> } // ----- func.func @test_depthwise_conv2d_wholly_divisible_width(%arg0: tensor<1x4x4x4xf32>, %arg1: tensor<1x1x8x4xf32>, %arg2: tensor<8xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x4x8xf32> { // expected-error@+1 {{'tosa.depthwise_conv2d' op expected input_width - 1 + pad_left + pad_right - (kernel_width - 1) * dilation_x to be wholly divisible by stride_x, got (4 - 1 + 0 + 0 - (1 - 1) * 1) / 2}} %0 = tosa.depthwise_conv2d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array, local_bound = true} : (tensor<1x4x4x4xf32>, tensor<1x1x8x4xf32>, tensor<8xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x4x8xf32> return %0 : tensor<1x4x4x8xf32> } // ----- func.func @test_depthwise_conv2d_unexpected_output_height(%arg0: tensor<1x4x4x4xf32>, %arg1: tensor<1x1x8x4xf32>, %arg2: tensor<8xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x6x4x8xf32> { // expected-error@+1 {{'tosa.depthwise_conv2d' op calculated output height did not match expected: calculated=4, expected=6}} %0 = tosa.depthwise_conv2d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array, local_bound = true} : (tensor<1x4x4x4xf32>, tensor<1x1x8x4xf32>, tensor<8xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x6x4x8xf32> return %0 : tensor<1x6x4x8xf32> } // ----- func.func @test_depthwise_conv2d_unexpected_output_width(%arg0: tensor<1x4x4x4xf32>, %arg1: tensor<1x1x8x4xf32>, %arg2: tensor<8xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x6x8xf32> { // expected-error@+1 {{'tosa.depthwise_conv2d' op calculated output width did not match expected: calculated=4, expected=6}} %0 = tosa.depthwise_conv2d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array, local_bound = true} : (tensor<1x4x4x4xf32>, tensor<1x1x8x4xf32>, tensor<8xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x6x8xf32> return %0 : tensor<1x4x6x8xf32> } // ----- func.func @test_depthwise_conv2d_invalid_bias_size(%arg0: tensor<1x4x4x4xf32>, %arg1: tensor<1x1x8x4xf32>, %arg2: tensor<7xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x4x8xf32> { // expected-error@+1 {{'tosa.depthwise_conv2d' op bias channels expected to be equal to output channels (8) or 1, got 7}} %0 = tosa.depthwise_conv2d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array, local_bound = true} : (tensor<1x4x4x4xf32>, tensor<1x1x8x4xf32>, tensor<7xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x4x8xf32> return %0 : tensor<1x4x4x8xf32> } // ----- func.func @test_conv3d_invalid_padding(%arg0: tensor<1x4x8x21x17xf32>, %arg1: tensor<34x1x1x1x17xf32>, %arg2: tensor<21xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x8x21x34xf32> { // expected-error@+1 {{'tosa.conv3d' op expect all padding values to be >= 0, got 0, -1, 0, -1, 0, 0}} %0 = tosa.conv3d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array} : (tensor<1x4x8x21x17xf32>, tensor<34x1x1x1x17xf32>, tensor<21xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x8x21x34xf32> return %0 : tensor<1x4x8x21x34xf32> } // ----- func.func @test_conv3d_invalid_stride(%arg0: tensor<1x4x8x21x17xf32>, %arg1: tensor<34x1x1x1x17xf32>, %arg2: tensor<21xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x8x21x34xf32> { // expected-error@+1 {{'tosa.conv3d' op expect all stride values to be >= 1, got 0, 1, 1}} %0 = tosa.conv3d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array} : (tensor<1x4x8x21x17xf32>, tensor<34x1x1x1x17xf32>, tensor<21xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x8x21x34xf32> return %0 : tensor<1x4x8x21x34xf32> } // ----- func.func @test_conv3d_invalid_dilation(%arg0: tensor<1x4x8x21x17xf32>, %arg1: tensor<34x1x1x1x17xf32>, %arg2: tensor<21xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x8x21x34xf32> { // expected-error@+1 {{'tosa.conv3d' op expect all dilation values to be >= 1, got 1, 0, 1}} %0 = tosa.conv3d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array} : (tensor<1x4x8x21x17xf32>, tensor<34x1x1x1x17xf32>, tensor<21xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x8x21x34xf32> return %0 : tensor<1x4x8x21x34xf32> } // ----- func.func @test_conv3d_wholly_divisible_input_depth(%arg0: tensor<1x4x16x21x17xf32>, %arg1: tensor<34x1x1x1x17xf32>, %arg2: tensor<21xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x8x21x34xf32> { // expected-error@+1 {{'tosa.conv3d' op expected input_depth - 1 + pad_front + pad_back - (kernel_depth - 1) * dilation_d to be wholly divisible by stride_d, got (4 - 1 + 0 + 0 - (1 - 1) * 1) / 2}} %0 = tosa.conv3d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array} : (tensor<1x4x16x21x17xf32>, tensor<34x1x1x1x17xf32>, tensor<21xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x8x21x34xf32> return %0 : tensor<1x4x8x21x34xf32> } // ----- func.func @test_conv3d_wholly_divisible_input_height(%arg0: tensor<1x4x10x21x17xf32>, %arg1: tensor<34x1x1x1x17xf32>, %arg2: tensor<21xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x8x21x34xf32> { // expected-error@+1 {{'tosa.conv3d' op expected input_height - 1 + pad_top + pad_bottom - (kernel_height - 1) * dilation_y to be wholly divisible by stride_y, got (10 - 1 + 0 + 0 - (1 - 1) * 1) / 4}} %0 = tosa.conv3d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array} : (tensor<1x4x10x21x17xf32>, tensor<34x1x1x1x17xf32>, tensor<21xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x8x21x34xf32> return %0 : tensor<1x4x8x21x34xf32> } // ----- func.func @test_conv3d_wholly_divisible_input_width(%arg0: tensor<1x4x8x21x19xf32>, %arg1: tensor<34x1x1x1x17xf32>, %arg2: tensor<21xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x8x21x34xf32> { // expected-error@+1 {{'tosa.conv3d' op expected input_width - 1 + pad_left + pad_right - (kernel_width - 1) * dilation_x to be wholly divisible by stride_x, got (21 - 1 + 0 + 0 - (1 - 1) * 1) / 8}} %0 = tosa.conv3d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array} : (tensor<1x4x8x21x19xf32>, tensor<34x1x1x1x17xf32>, tensor<21xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x8x21x34xf32> return %0 : tensor<1x4x8x21x34xf32> } // ----- func.func @test_conv3d_wholly_divisible_output_depth(%arg0: tensor<1x4x10x21x17xf32>, %arg1: tensor<34x1x1x1x17xf32>, %arg2: tensor<21xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x3x10x21x34xf32> { // expected-error@+1 {{'tosa.conv3d' op calculated output depth did not match expected: calculated=4, expected=3}} %0 = tosa.conv3d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array} : (tensor<1x4x10x21x17xf32>, tensor<34x1x1x1x17xf32>, tensor<21xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x3x10x21x34xf32> return %0 : tensor<1x3x10x21x34xf32> } // ----- func.func @test_conv3d_wholly_divisible_output_height(%arg0: tensor<1x4x16x21x17xf32>, %arg1: tensor<34x1x1x1x17xf32>, %arg2: tensor<21xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x8x21x34xf32> { // expected-error@+1 {{'tosa.conv3d' op calculated output height did not match expected: calculated=16, expected=8}} %0 = tosa.conv3d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array} : (tensor<1x4x16x21x17xf32>, tensor<34x1x1x1x17xf32>, tensor<21xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x8x21x34xf32> return %0 : tensor<1x4x8x21x34xf32> } // ----- func.func @test_conv3d_wholly_divisible_output_width(%arg0: tensor<1x4x8x21x19xf32>, %arg1: tensor<34x1x1x1x17xf32>, %arg2: tensor<21xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x8x19x34xf32> { // expected-error@+1 {{'tosa.conv3d' op calculated output width did not match expected: calculated=21, expected=19}} %0 = tosa.conv3d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array} : (tensor<1x4x8x21x19xf32>, tensor<34x1x1x1x17xf32>, tensor<21xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x4x8x19x34xf32> return %0 : tensor<1x4x8x19x34xf32> } // ----- func.func @test_concat_element_type_mismatch(%arg0 : tensor<1x2xf32>, %arg1 : tensor<2x2xf32>) -> tensor { // expected-error@+1 {{'tosa.concat' op expect input and output to have same element type, got 'f32' and 'i8'}} %0 = tosa.concat %arg0, %arg1 {axis = 0 : i32} : (tensor<1x2xf32>, tensor<2x2xf32>) -> tensor return %0 : tensor } // ----- func.func @test_concat_zero_inputs() { // expected-error@+1 {{'tosa.concat' op expect at least one input}} %0 = tosa.concat {axis = 0 : i32} : () -> tensor<*xf32> } // ----- func.func @test_concat_axis_negative(%arg0: tensor<1x2xf32>, %arg1: tensor<2x2xf32>) -> tensor<2x2xf32> { // expected-error@+1 {{'tosa.concat' op expect axis to be within range 0 < axis < rank(input1[firstRankedTensorIdx]), got -1}} %0 = tosa.concat %arg0, %arg1 {axis = -1 : i32} : (tensor<1x2xf32>, tensor<2x2xf32>) -> tensor<2x2xf32> return %0 : tensor<2x2xf32> } // ----- func.func @test_concat_axis_out_of_range(%arg0: tensor<1x2xf32>, %arg1: tensor<2x2xf32>) -> tensor<2x2xf32> { // expected-error@+1 {{'tosa.concat' op expect axis to be within range 0 < axis < rank(input1[firstRankedTensorIdx]), got 3}} %0 = tosa.concat %arg0, %arg1 {axis = 3 : i32} : (tensor<1x2xf32>, tensor<2x2xf32>) -> tensor<2x2xf32> return %0 : tensor<2x2xf32> } // ----- func.func @test_concat_axis_sum_error(%arg0: tensor<1x2xf32>, %arg1: tensor<2x?xf32>) -> tensor<2x?xf32> { // expected-error@+1 {{'tosa.concat' op requires sum of axis dimensions of input1 equal to output axis dimension, got 3 and 2}} %0 = tosa.concat %arg0, %arg1 {axis = 0 : i32} : (tensor<1x2xf32>, tensor<2x?xf32>) -> tensor<2x?xf32> return %0 : tensor<2x?xf32> } // ----- func.func @test_error_scalar_input_with_per_channel(%arg0: tensor) -> tensor { %multiplier = "tosa.const"() {values = dense<4> : tensor<1xi32> } : () -> tensor<1xi32> %shift = "tosa.const"() {values = dense<2> : tensor<1xi8> } : () -> tensor<1xi8> %input_zp = "tosa.const"() {values = dense<0> : tensor<1xi8>} : () -> tensor<1xi8> %output_zp = "tosa.const"() {values = dense<0> : tensor<1xi16>} : () -> tensor<1xi16> // expected-error@+1 {{'tosa.rescale' op requires input to be at least rank 1 when per_channel is true, but got rank 0}} %0 = tosa.rescale %arg0, %multiplier, %shift, %input_zp, %output_zp {scale32 = true, rounding_mode = SINGLE_ROUND, per_channel = true, input_unsigned = false, output_unsigned = false} : (tensor, tensor<1xi32>, tensor<1xi8>, tensor<1xi8>, tensor<1xi16>) -> tensor return %0 : tensor } // ----- func.func @test_rescale_invalid_static_output_shape(%arg0: tensor<13x21x3xi8>) -> tensor<13x21x4xi8> { %multiplier = "tosa.const"() <{values = dense<42> : tensor<1xi16>}> : () -> tensor<1xi16> %shift = "tosa.const"() <{values = dense<0> : tensor<1xi8>}> : () -> tensor<1xi8> %input_zp = "tosa.const"() <{values = dense<0> : tensor<1xi8>}> : () -> tensor<1xi8> %output_zp = "tosa.const"() <{values = dense<0> : tensor<1xi8>}> : () -> tensor<1xi8> // expected-error@+1 {{'tosa.rescale' op expected output shape 13, 21, 4 to be compatible with inferred shape 13, 21, 3}} %0 = tosa.rescale %arg0, %multiplier, %shift, %input_zp, %output_zp {scale32 = false, rounding_mode = SINGLE_ROUND, per_channel = false, input_unsigned = false, output_unsigned = false} : (tensor<13x21x3xi8>, tensor<1xi16>, tensor<1xi8>, tensor<1xi8>, tensor<1xi8>) -> tensor<13x21x4xi8> return %0 : tensor<13x21x4xi8> } // ----- func.func @test_mul_invalid_static_output_shape(%arg0: tensor, %arg1: tensor) -> tensor { %shift = "tosa.const"() <{values = dense<0> : tensor<1xi8>}> : () -> tensor<1xi8> // expected-error@+1 {{'tosa.mul' op expected output shape ?, 21, 2 to be compatible with inferred shape ?, 21, 3}} %0 = tosa.mul %arg0, %arg1, %shift : (tensor, tensor, tensor<1xi8>) -> tensor return %0 : tensor } // ----- // CHECK-LABEL: @test_gather_invalid_indices_N func.func @test_gather_invalid_indices_N(%arg0: tensor<13x21x3xf32>, %arg1: tensor<12x26xi32>) -> tensor<13x26x3xf32> { // expected-error@+1 {{'tosa.gather' op requires indices dimension 0 to have size 13, got 12}} %0 = tosa.gather %arg0, %arg1 : (tensor<13x21x3xf32>, tensor<12x26xi32>) -> tensor<13x26x3xf32> return %0 : tensor<13x26x3xf32> } // ----- // CHECK-LABEL: test_gather_invalid_out_N func.func @test_gather_invalid_out_N(%arg0: tensor<13x21x3xf32>, %arg1: tensor<13x26xi32>) -> tensor<12x26x3xf32> { // expected-error@+1 {{'tosa.gather' op requires output dimension 0 to have size 13, got 12}} %0 = tosa.gather %arg0, %arg1 : (tensor<13x21x3xf32>, tensor<13x26xi32>) -> tensor<12x26x3xf32> return %0 : tensor<12x26x3xf32> } // ----- // CHECK-LABEL: test_gather_invalid_out_W func.func @test_gather_invalid_out_W(%arg0: tensor<13x21x3xf32>, %arg1: tensor<13x26xi32>) -> tensor<13x28x3xf32> { // expected-error@+1 {{'tosa.gather' op requires output dimension 1 to have size 26, got 28}} %0 = tosa.gather %arg0, %arg1 : (tensor<13x21x3xf32>, tensor<13x26xi32>) -> tensor<13x28x3xf32> return %0 : tensor<13x28x3xf32> } // ----- // CHECK-LABEL: test_gather_invalid_out_C func.func @test_gather_invalid_out_C(%arg0: tensor<13x21x3xf32>, %arg1: tensor<13x26xi32>) -> tensor<13x26x8xf32> { // expected-error@+1 {{'tosa.gather' op requires output dimension 2 to have size 3, got 8}} %0 = tosa.gather %arg0, %arg1 : (tensor<13x21x3xf32>, tensor<13x26xi32>) -> tensor<13x26x8xf32> return %0 : tensor<13x26x8xf32> } // ----- // CHECK-LABEL: test_row_gather_block_scaled_output_count_mismatch func.func @test_row_gather_block_scaled_output_count_mismatch(%arg0: tensor<13x21x3xf32>, %arg1: tensor<13x26xi32>) -> (tensor<13x52x3xf32>, tensor<13x52x3xf32>) { %row_count = "tosa.const"() {values = dense<2> : tensor<1xi32>} : () -> tensor<1xi32> // expected-error@+1 {{'tosa.row_gather_block_scaled' op expects output tensor list length to match values tensor list length, got 2 results for 1 input tensors}} %0:2 = tosa.row_gather_block_scaled %arg0, %arg1, %row_count {block_size = #tosa.block_size} : (tensor<13x21x3xf32>, tensor<13x26xi32>, tensor<1xi32>) -> (tensor<13x52x3xf32>, tensor<13x52x3xf32>) return %0#0, %0#1 : tensor<13x52x3xf32>, tensor<13x52x3xf32> } // ----- // CHECK-LABEL: test_row_gather_block_scaled_block_size_one_required func.func @test_row_gather_block_scaled_block_size_one_required(%arg0: tensor<13x21x3xf32>, %arg1: tensor<13x26xi32>) -> tensor<13x52x3xf32> { %row_count = "tosa.const"() {values = dense<2> : tensor<1xi32>} : () -> tensor<1xi32> // expected-error@+1 {{'tosa.row_gather_block_scaled' op requires block_size to be BLOCK_SIZE_1 when values tensor list length is 1}} %0 = tosa.row_gather_block_scaled %arg0, %arg1, %row_count {block_size = #tosa.block_size} : (tensor<13x21x3xf32>, tensor<13x26xi32>, tensor<1xi32>) -> (tensor<13x52x3xf32>) return %0 : tensor<13x52x3xf32> } // ----- // CHECK-LABEL: test_row_gather_block_scaled_output_rows_mismatch func.func @test_row_gather_block_scaled_output_rows_mismatch(%arg0: tensor<13x21x3xf32>, %arg1: tensor<13x26xi32>) -> tensor<13x53x3xf32> { %row_count = "tosa.const"() {values = dense<2> : tensor<1xi32>} : () -> tensor<1xi32> // expected-error@+1 {{'tosa.row_gather_block_scaled' op requires output[0] dimension 1 to have size 52, got 53}} %0 = tosa.row_gather_block_scaled %arg0, %arg1, %row_count {block_size = #tosa.block_size} : (tensor<13x21x3xf32>, tensor<13x26xi32>, tensor<1xi32>) -> (tensor<13x53x3xf32>) return %0 : tensor<13x53x3xf32> } // ----- // CHECK-LABEL: test_row_gather_block_scaled_scale_channel_mismatch func.func @test_row_gather_block_scaled_scale_channel_mismatch(%arg0: tensor<13x21x32xf4E2M1FN>, %arg1: tensor<13x21x2xf8E8M0FNU>, %arg2: tensor<13x26xi32>) -> (tensor<13x52x32xf4E2M1FN>, tensor<13x52x2xf8E8M0FNU>) { %row_count = "tosa.const"() {values = dense<2> : tensor<1xi32>} : () -> tensor<1xi32> // expected-error@+1 {{'tosa.row_gather_block_scaled' op expects channels of scale tensors to equal C/block_size (32/32), got 2}} %0:2 = tosa.row_gather_block_scaled %arg0, %arg1, %arg2, %row_count {block_size = #tosa.block_size} : (tensor<13x21x32xf4E2M1FN>, tensor<13x21x2xf8E8M0FNU>, tensor<13x26xi32>, tensor<1xi32>) -> (tensor<13x52x32xf4E2M1FN>, tensor<13x52x2xf8E8M0FNU>) return %0#0, %0#1 : tensor<13x52x32xf4E2M1FN>, tensor<13x52x2xf8E8M0FNU> } // ----- func.func @test_pad_padding_shape_mismatch(%arg0: tensor<13x21x3xf32>) -> tensor<13x21x3xf32> { %0 = tosa.const_shape {values = dense<1> : tensor<4xindex>} : () -> !tosa.shape<4> %pad_const = "tosa.const"() {values = dense<3.14> : tensor<1xf32>} : () -> tensor<1xf32> // expected-error@+1 {{'tosa.pad' op padding tensor must have 3 * 2 = 6 elements, but got 4}} %1 = tosa.pad %arg0, %0, %pad_const : (tensor<13x21x3xf32>, !tosa.shape<4>, tensor<1xf32>) -> tensor<13x21x3xf32> return %1 : tensor<13x21x3xf32> } // ----- func.func @test_pad_invalid_padding_rank(%arg0: tensor<13x21xf32>) { %0 = tosa.const_shape {values = dense<1> : tensor<6xindex>} : () -> !tosa.shape<6> %pad_const = "tosa.const"() {values = dense<3.14> : tensor<1xf32>} : () -> tensor<1xf32> // expected-error@+1 {{'tosa.pad' op padding tensor must have 2 * 2 = 4 elements, but got 6}} %1 = tosa.pad %arg0, %0, %pad_const : (tensor<13x21xf32>, !tosa.shape<6>, tensor<1xf32>) -> tensor<13x21xf32> return } // ----- func.func @test_pad_output_mismatch(%arg0: tensor<13x21x3xi8>, %arg1: tensor<1xi8>) -> tensor<13x21x3xi8> { %0 = tosa.const_shape {values = dense<[0, 0, 0, 1, 0, 1]> : tensor<6xindex>} : () -> !tosa.shape<6> // expected-error@+1 {{mismatch in output shape at dimension 1: expected 21 + 0 + 1 = 22, but got 21}} %1 = tosa.pad %arg0, %0, %arg1 : (tensor<13x21x3xi8>, !tosa.shape<6>, tensor<1xi8>) -> tensor<13x21x3xi8> return %1 : tensor<13x21x3xi8> } // ----- func.func @test_pad_invalid_padding_value(%arg0: tensor<10xi8>, %arg1: tensor<1xi8>) -> tensor<10xi8> { %0 = tosa.const_shape {values = dense<[-2, 2]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{invalid padding values at dimension 0: values must be non-negative or -1 for dynamic padding, got [-2, 2]}} %1 = tosa.pad %arg0, %0, %arg1 : (tensor<10xi8>, !tosa.shape<2>, tensor<1xi8>) -> tensor<10xi8> return %1 : tensor<10xi8> } // ----- func.func @test_cond_if_wrong_terminator_op(%arg0: tensor) -> tensor { %0 = "tosa.cond_if"(%arg0) ({ %1 = "tosa.const"() <{values = dense<1> : tensor}> : () -> tensor "tosa.yield"(%1) : (tensor) -> () }, { // expected-error@+2 {{'func.return' op expects parent op 'func.func'}} %2 = "tosa.const"() <{values = dense<2> : tensor}> : () -> tensor "func.return"(%2) : (tensor) -> () }) : (tensor) -> tensor return %0 : tensor } // ----- func.func @test_cond_if_missing_then_terminator(%arg0: tensor) -> tensor { %0 = "tosa.cond_if"(%arg0) ({ // expected-error@+1 {{block with no terminator}} %1 = "tosa.const"() <{values = dense<1> : tensor}> : () -> tensor }, { %2 = "tosa.const"() <{values = dense<2> : tensor}> : () -> tensor "tosa.yield"(%2) : (tensor) -> () }) : (tensor) -> tensor return %0 : tensor } // ----- func.func @test_cond_if_missing_else_terminator(%arg0: tensor) -> tensor { %0 = "tosa.cond_if"(%arg0) ({ %1 = "tosa.const"() <{values = dense<1> : tensor}> : () -> tensor "tosa.yield"(%1) : (tensor) -> () }, { // expected-error@+1 {{block with no terminator}} %2 = "tosa.const"() <{values = dense<2> : tensor}> : () -> tensor }) : (tensor) -> tensor return %0 : tensor } // ----- func.func @test_cond_if_input_list_mismatch_then_block(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+1 {{'tosa.cond_if' op require same number of values in 'then_graph' arguments (1) and 'input_list' (2)}} %0 = "tosa.cond_if"(%arg2, %arg0, %arg1) ({ ^bb0(%arg3: tensor): tosa.yield %arg3 : tensor }, { ^bb0(%arg4: tensor): tosa.yield %arg4 : tensor }) : (tensor, tensor, tensor) -> tensor return %0 : tensor } // ----- func.func @test_cond_if_input_list_mismatch_then_block_2(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+1 {{'tosa.cond_if' op require same number of values in 'then_graph' arguments (2) and 'input_list' (1)}} %0 = "tosa.cond_if"(%arg2, %arg0) ({ ^bb0(%arg3: tensor, %arg4: tensor): tosa.yield %arg3 : tensor }, { ^bb0(%arg4: tensor): tosa.yield %arg4 : tensor }) : (tensor, tensor) -> tensor return %0 : tensor } // ----- func.func @test_cond_if_input_list_mismatch_else_block(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+1 {{'tosa.cond_if' op require same number of values in 'else_graph' arguments (1) and 'input_list' (2)}} %0 = "tosa.cond_if"(%arg2, %arg0, %arg1) ({ ^bb0(%arg3: tensor, %arg4: tensor): tosa.yield %arg3 : tensor }, { ^bb0(%arg4: tensor): tosa.yield %arg4 : tensor }) : (tensor, tensor, tensor) -> tensor return %0 : tensor } // ----- func.func @test_cond_if_input_list_mismatch_else_block_2(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+1 {{'tosa.cond_if' op require same number of values in 'else_graph' arguments (2) and 'input_list' (1)}} %0 = "tosa.cond_if"(%arg2, %arg0) ({ ^bb0(%arg3: tensor): tosa.yield %arg3 : tensor }, { ^bb0(%arg4: tensor, %arg3: tensor): tosa.yield %arg4 : tensor }) : (tensor, tensor) -> tensor return %0 : tensor } // ----- func.func @test_cond_if_input_list_mismatch_else_block_simple(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+1 {{'tosa.cond_if' op require same number of values in 'else_graph' arguments (1) and 'input_list' (2)}} %0 = tosa.cond_if %arg2 (%arg3 = %arg0, %arg4 = %arg1) : tensor (tensor, tensor) -> tensor { ^bb0(%arg3: tensor, %arg4: tensor): %1 = tosa.add %arg3, %arg4 : (tensor, tensor) -> tensor tosa.yield %1 : tensor } else { ^bb0(%arg3: tensor): tosa.yield %arg3 : tensor } return %0 : tensor } // ----- func.func @test_cond_if_input_list_mismatch_else_block_simple_2(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+1 {{'tosa.cond_if' op require same number of values in 'else_graph' arguments (2) and 'input_list' (1)}} %0 = tosa.cond_if %arg2 (%arg3 = %arg0) : tensor (tensor) -> tensor { ^bb0(%arg3: tensor): tosa.yield %arg3 : tensor } else { ^bb0(%arg3: tensor, %arg4: tensor): %1 = tosa.sub %arg3, %arg4 : (tensor, tensor) -> tensor tosa.yield %1 : tensor } return %0 : tensor } // ----- func.func @test_cond_if_output_list_mismatch_then_block(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+1 {{'tosa.cond_if' op require same number of values in 'then_graph' results (2) and 'output_list' (1)}} %0 = tosa.cond_if %arg2 : tensor -> tensor { %1 = tosa.add %arg0, %arg1 : (tensor, tensor) -> tensor %2 = tosa.add %1, %arg1 : (tensor, tensor) -> tensor tosa.yield %1, %2 : tensor, tensor } else { %1 = tosa.sub %arg0, %arg1 : (tensor, tensor) -> tensor tosa.yield %1 : tensor } return %0 : tensor } // ----- func.func @test_cond_if_output_list_mismatch_then_block_2(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+1 {{'tosa.cond_if' op require same number of values in 'then_graph' results (1) and 'output_list' (2)}} %0, %2 = tosa.cond_if %arg2 : tensor -> (tensor, tensor) { %1 = tosa.add %arg0, %arg1 : (tensor, tensor) -> tensor tosa.yield %1 : tensor } else { %1 = tosa.sub %arg0, %arg1 : (tensor, tensor) -> tensor tosa.yield %1 : tensor } return %0 : tensor } // ----- func.func @test_cond_if_output_list_mismatch_else_block(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+1 {{'tosa.cond_if' op require same number of values in 'else_graph' results (2) and 'output_list' (1)}} %0 = tosa.cond_if %arg2 : tensor -> tensor { %1 = tosa.add %arg0, %arg1 : (tensor, tensor) -> tensor tosa.yield %1 : tensor } else { %1 = tosa.sub %arg0, %arg1 : (tensor, tensor) -> tensor %2 = tosa.add %1, %arg1 : (tensor, tensor) -> tensor tosa.yield %1, %2 : tensor, tensor } return %0 : tensor } // ----- func.func @test_cond_if_output_list_mismatch_else_block_2(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+1 {{'tosa.cond_if' op require same number of values in 'else_graph' results (1) and 'output_list' (2)}} %0, %2 = tosa.cond_if %arg2 : tensor -> (tensor, tensor) { %1 = tosa.add %arg0, %arg1 : (tensor, tensor) -> tensor %2 = tosa.sub %arg0, %arg1 : (tensor, tensor) -> tensor tosa.yield %1, %2 : tensor, tensor } else { %1 = tosa.sub %arg0, %arg1 : (tensor, tensor) -> tensor tosa.yield %1 : tensor } return %0 : tensor } // ----- func.func @test_cond_if_cond_input_not_size_one(%arg0: tensor, %arg1: tensor, %arg2: tensor<2xi1>) -> tensor { // expected-error@+1 {{'tosa.cond_if' op 'condition' must be a size 1 tensor, got 'tensor<2xi1>'}} %0 = "tosa.cond_if"(%arg2, %arg0, %arg1) ({ ^bb0(%arg3: tensor, %arg4: tensor): tosa.yield %arg3 : tensor }, { ^bb0(%arg3: tensor, %arg4: tensor): tosa.yield %arg4 : tensor }) : (tensor<2xi1>, tensor, tensor) -> tensor return %0 : tensor } // ----- // CHECK-LABEL: cond_if_cond_type func.func @test_cond_if_cond_type(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+2 {{expected ':'}} // expected-error@+1 {{custom op 'tosa.cond_if' expected type for condition operand}} %0 = tosa.cond_if %arg2 -> (tensor) { tosa.yield %arg0 : tensor } else { tosa.yield %arg1 : tensor } return %0 : tensor } // ----- func.func @test_cond_if_input_list_type_mismatch_simple(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+1 {{custom op 'tosa.cond_if' expected as many input types as operands (expected 2 got 0)}} %0 = tosa.cond_if %arg2 (%arg3 = %arg0, %arg4 = %arg1) : tensor () -> tensor { ^bb0(%arg3: tensor, %arg4: tensor): %1 = tosa.add %arg3, %arg4 : (tensor, tensor) -> tensor tosa.yield %1 : tensor } else { ^bb0(%arg3: tensor, %arg4: tensor): %1 = tosa.sub %arg3, %arg4 : (tensor, tensor) -> tensor tosa.yield %1 : tensor } return %0 : tensor } // ----- func.func @test_cond_if_incorrect_type_simple(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // expected-error@+2 {{expected non-function type}} // expected-error@+1 {{custom op 'tosa.cond_if' expected list of types for block arguments followed by arrow type and list of return types}} %0 = tosa.cond_if %arg2 (%arg3 = %arg0, %arg4 = %arg1) : tensor (%arg3) -> tensor { ^bb0(%arg3: tensor, %arg4: tensor): %1 = tosa.add %arg3, %arg4 : (tensor, tensor) -> tensor tosa.yield %1 : tensor } else { ^bb0(%arg3: tensor, %arg4: tensor): %1 = tosa.sub %arg3, %arg4 : (tensor, tensor) -> tensor tosa.yield %1 : tensor } return %0 : tensor } // ----- func.func @test_while_loop_wrong_terminator(%arg0: tensor, %arg1: tensor) -> tensor { %0 = tosa.while_loop (%arg2 = %arg0) : (tensor) -> tensor { // expected-error@+2 {{'func.return' op expects parent op 'func.func'}} %1 = tosa.greater_equal %arg1, %arg2 : (tensor, tensor) -> tensor "func.return"(%arg2) : (tensor) -> () } do { ^bb0(%arg2: tensor): %1 = "tosa.const"() <{values = dense<1> : tensor}> : () -> tensor %2 = tosa.add %arg2, %1 : (tensor, tensor) -> tensor tosa.yield %2 : tensor } return %0 : tensor } // ----- func.func @test_while_loop_missing_cond_terminator(%arg0: tensor, %arg1: tensor) -> tensor { %0 = tosa.while_loop (%arg2 = %arg0) : (tensor) -> tensor { // expected-error@+1 {{block with no terminator}} %1 = tosa.greater_equal %arg1, %arg2 : (tensor, tensor) -> tensor } do { ^bb0(%arg2: tensor): %1 = "tosa.const"() <{values = dense<1> : tensor}> : () -> tensor %2 = tosa.add %arg2, %1 : (tensor, tensor) -> tensor tosa.yield %2 : tensor } return %0 : tensor } // ----- func.func @test_while_loop_missing_body_terminator(%arg0: tensor, %arg1: tensor) -> tensor { %0 = tosa.while_loop (%arg2 = %arg0) : (tensor) -> tensor { %1 = tosa.greater_equal %arg1, %arg2 : (tensor, tensor) -> tensor tosa.yield %1 : tensor } do { ^bb0(%arg2: tensor): // expected-error@+1 {{block with no terminator}} %1 = "tosa.const"() <{values = dense<1> : tensor}> : () -> tensor } return %0 : tensor } // ----- func.func @test_while_loop_input_list_mismatch_body_block_in(%arg0: tensor<10xi32>, %arg1: tensor) { %0 = "tosa.const"() {values = dense<0> : tensor} : () -> tensor // expected-error@+1 {{'tosa.while_loop' op require same number of values in 'body_graph' arguments (3) and 'input_list' (2)}} %1:2 = tosa.while_loop (%arg2 = %0, %arg3 = %arg0) : (tensor, tensor<10xi32>) -> (tensor, tensor<10xi32>) { %2 = tosa.greater_equal %arg2, %arg1 : (tensor, tensor) -> tensor tosa.yield %2 : tensor } do { ^bb0(%arg2: tensor, %arg3: tensor, %arg4: tensor<10xi32>): %2 = "tosa.const"() {values = dense<1> : tensor} : () -> tensor %3 = tosa.add %arg2, %2 : (tensor, tensor) -> tensor tosa.yield %3, %arg4 : tensor, tensor<10xi32> } return } // ----- func.func @test_while_loop_input_list_mismatch_body_block_in_2(%arg0: tensor<10xi32>, %arg1: tensor) { %0 = "tosa.const"() {values = dense<0> : tensor} : () -> tensor // expected-error@+1 {{'tosa.while_loop' op require same number of values in 'body_graph' arguments (2) and 'input_list' (3)}} %1:3 = tosa.while_loop (%arg2 = %0, %arg3 = %arg0, %arg4 = %arg0) : (tensor, tensor<10xi32>, tensor<10xi32>) -> (tensor, tensor<10xi32>, tensor<10xi32>) { %2 = tosa.greater_equal %arg2, %arg1 : (tensor, tensor) -> tensor tosa.yield %2 : tensor } do { ^bb0(%arg2: tensor, %arg3: tensor): %2 = "tosa.const"() {values = dense<1> : tensor} : () -> tensor %3 = tosa.add %arg2, %2 : (tensor, tensor) -> tensor tosa.yield %3, %arg3 : tensor, tensor } return } // ----- func.func @test_while_loop_input_list_mismatch_output_list(%arg0: tensor<10xi32>, %arg1: tensor) { %0 = "tosa.const"() {values = dense<0> : tensor} : () -> tensor // expected-error@+1 {{'tosa.while_loop' op require same number of values in 'input_list' (3) and 'output_list' (2)}} %1:2 = tosa.while_loop (%arg2 = %0, %arg3 = %arg0, %arg4 = %arg0) : (tensor, tensor<10xi32>, tensor<10xi32>) -> (tensor, tensor<10xi32>) { %2 = tosa.greater_equal %arg2, %arg1 : (tensor, tensor) -> tensor tosa.yield %2 : tensor } do { ^bb0(%arg2: tensor, %arg3: tensor): %2 = "tosa.const"() {values = dense<1> : tensor} : () -> tensor %3 = tosa.add %arg2, %2 : (tensor, tensor) -> tensor tosa.yield %3, %arg3 : tensor, tensor } return } // ----- func.func @test_while_loop_input_list_mismatch_output_list_2(%arg0: tensor<10xi32>, %arg1: tensor) { %0 = "tosa.const"() {values = dense<0> : tensor} : () -> tensor // expected-error@+1 {{'tosa.while_loop' op require same number of values in 'input_list' (2) and 'output_list' (3)}} %1:3 = tosa.while_loop (%arg2 = %0, %arg3 = %arg0) : (tensor, tensor<10xi32>) -> (tensor, tensor<10xi32>, tensor<10xi32>) { %2 = tosa.greater_equal %arg2, %arg1 : (tensor, tensor) -> tensor tosa.yield %2 : tensor } do { ^bb0(%arg2: tensor, %arg3: tensor): %2 = "tosa.const"() {values = dense<1> : tensor} : () -> tensor %3 = tosa.add %arg2, %2 : (tensor, tensor) -> tensor tosa.yield %3, %arg3 : tensor, tensor } return } // ----- func.func @test_while_loop_input_list_mismatch_cond_block(%arg0: tensor<2xf32>, %arg1: tensor) { %0 = "tosa.const"() {values = dense<0> : tensor} : () -> tensor // expected-error@+1 {{'tosa.while_loop' op require same number of values in 'cond_graph' arguments (3) and 'input_list' (2)}} %1:2 = "tosa.while_loop"(%0, %arg0) ({ ^bb0(%arg3: tensor, %arg4: tensor<2xf32>, %arg5: tensor<2xf32>): %2 = "tosa.greater_equal"(%arg3, %arg1) : (tensor, tensor) -> tensor "tosa.yield"(%2) : (tensor) -> () }, { ^bb0(%arg3: tensor, %arg4: tensor<2xf32>): %2 = "tosa.const"() {values = dense<1> : tensor} : () -> tensor %3 = "tosa.const"() {values = dense<2> : tensor<1xi8>} : () -> tensor<1xi8> %4 = "tosa.mul"(%arg3, %2, %3) : (tensor, tensor, tensor<1xi8>) -> tensor "tosa.yield"(%4, %arg4) : (tensor, tensor<2xf32>) -> () }) : (tensor, tensor<2xf32>) -> (tensor, tensor<2xf32>) return } // ----- func.func @test_while_loop_input_list_mismatch_cond_block_2(%arg0: tensor<2xf32>, %arg1: tensor) { %0 = "tosa.const"() {values = dense<0> : tensor} : () -> tensor // expected-error@+1 {{'tosa.while_loop' op require same number of values in 'cond_graph' arguments (1) and 'input_list' (3)}} %1:3 = "tosa.while_loop"(%0, %arg0, %arg1) ({ ^bb0(%arg3: tensor): %2 = "tosa.greater_equal"(%arg3, %arg1) : (tensor, tensor) -> tensor "tosa.yield"(%2) : (tensor) -> () }, { ^bb0(%arg3: tensor, %arg4: tensor<2xf32>): %2 = "tosa.const"() {values = dense<1> : tensor} : () -> tensor %3 = "tosa.const"() {values = dense<2> : tensor<1xi8>} : () -> tensor<1xi8> %4 = "tosa.mul"(%arg3, %2, %3) : (tensor, tensor, tensor<1xi8>) -> tensor "tosa.yield"(%4, %arg4) : (tensor, tensor<2xf32>) -> () }) : (tensor, tensor<2xf32>, tensor) -> (tensor, tensor<2xf32>, tensor) return } // ----- func.func @test_while_loop_input_list_mismatch_body_block_out(%arg0: tensor<10xi32>, %arg1: tensor) { %0 = "tosa.const"() {values = dense<0> : tensor} : () -> tensor // expected-error@+1 {{'tosa.while_loop' op require same number of values in 'body_graph' results (3) and 'input_list' (2)}} %1:2 = tosa.while_loop (%arg2 = %0, %arg3 = %arg0) : (tensor, tensor<10xi32>) -> (tensor, tensor<10xi32>) { %2 = tosa.greater_equal %arg2, %arg1 : (tensor, tensor) -> tensor tosa.yield %2 : tensor } do { ^bb0(%arg2: tensor, %arg4: tensor<10xi32>): %2 = "tosa.const"() {values = dense<1> : tensor} : () -> tensor %3 = tosa.add %arg2, %2 : (tensor, tensor) -> tensor tosa.yield %2, %3, %arg4 : tensor, tensor, tensor<10xi32> } return } // ----- func.func @test_while_loop_input_list_mismatch_body_block_out_2(%arg0: tensor<10xi32>, %arg1: tensor) { %0 = "tosa.const"() {values = dense<0> : tensor} : () -> tensor // expected-error@+1 {{'tosa.while_loop' op require same number of values in 'body_graph' results (1) and 'input_list' (2)}} %1:2 = tosa.while_loop (%arg2 = %0, %arg3 = %arg0) : (tensor, tensor<10xi32>) -> (tensor, tensor<10xi32>) { %2 = tosa.greater_equal %arg2, %arg1 : (tensor, tensor) -> tensor tosa.yield %2 : tensor } do { ^bb0(%arg2: tensor, %arg4: tensor<10xi32>): %2 = "tosa.const"() {values = dense<1> : tensor} : () -> tensor %3 = tosa.add %arg2, %2 : (tensor, tensor) -> tensor tosa.yield %3 : tensor } return } // ----- func.func @test_while_loop_type_mismatch(%arg0: tensor<10xi32>, %arg1: tensor) { %0 = "tosa.const"() {values = dense<0> : tensor} : () -> tensor // expected-error@+1 {{'tosa.while_loop' op require same element type for 'body_graph' arguments ('f32') and 'input_list' ('i32')}} %1:3 = tosa.while_loop (%arg2 = %0, %arg3 = %0, %arg4 = %arg0) : (tensor, tensor, tensor<10xi32>) -> (tensor, tensor, tensor<10xi32>) { %2 = tosa.greater_equal %arg3, %arg1 : (tensor, tensor) -> tensor %3 = tosa.logical_not %2 : (tensor) -> tensor tosa.yield %3 : tensor } do { ^bb0(%arg2: tensor, %arg3: tensor, %arg4: tensor<10xi32>): %2 = "tosa.const"() {values = dense<1> : tensor} : () -> tensor %6 = tosa.add %arg2, %2 : (tensor, tensor) -> tensor tosa.yield %6, %2, %arg4 : tensor, tensor, tensor<10xi32> } return } // ----- func.func @test_while_loop_type_mismatch_2(%arg0: tensor<10xi32>, %arg1: tensor) { %0 = "tosa.const"() {values = dense<0> : tensor} : () -> tensor // expected-error@+1 {{'tosa.while_loop' op require same shapes for 'body_graph' arguments ('tensor<10xi32>') and 'input_list' ('tensor')}} %1:3 = tosa.while_loop (%arg2 = %0, %arg3 = %0, %arg4 = %arg0) : (tensor, tensor, tensor<10xi32>) -> (tensor, tensor, tensor<10xi32>) { %2 = tosa.greater_equal %arg3, %arg1 : (tensor, tensor) -> tensor %3 = tosa.logical_not %2 : (tensor) -> tensor tosa.yield %3 : tensor } do { ^bb0(%arg2: tensor<10xi32>, %arg3: tensor, %arg4: tensor<10xi32>): %2 = "tosa.const"() {values = dense<1> : tensor} : () -> tensor %6 = tosa.add %arg2, %2 : (tensor<10xi32>, tensor) -> tensor tosa.yield %6, %2, %arg4 : tensor, tensor, tensor<10xi32> } return } // ----- func.func @test_while_loop_cond_output_not_size_one(%arg0: tensor<10xi32>, %arg1: tensor<2xi32>) { %0 = "tosa.const"() {values = dense<[4, 1]> : tensor<2xi32>} : () -> tensor<2xi32> // expected-error@+1 {{'tosa.while_loop' op 'cond_graph' result must be a size 1 tensor, got 'tensor<2xi1>'}} %1:3 = tosa.while_loop (%arg2 = %arg0, %arg3 = %0, %arg4 = %arg0) : (tensor<10xi32>, tensor<2xi32>, tensor<10xi32>) -> (tensor<10xi32>, tensor<2xi32>, tensor<10xi32>) { %2 = tosa.greater_equal %arg3, %arg1 : (tensor<2xi32>, tensor<2xi32>) -> tensor<2xi1> tosa.yield %2 : tensor<2xi1> } do { ^bb0(%arg2: tensor<10xi32>, %arg3: tensor<2xi32>, %arg4: tensor<10xi32>): %2 = "tosa.const"() {values = dense<1> : tensor} : () -> tensor %3 = "tosa.const"() {values = dense<[3, 5]> : tensor<2xi32>} : () -> tensor<2xi32> %4 = tosa.add %arg2, %2 : (tensor<10xi32>, tensor) -> tensor<10xi32> tosa.yield %4, %3, %arg4 : tensor<10xi32>, tensor<2xi32>, tensor<10xi32> } return } // ----- func.func @test_while_loop_cond_output_not_bool(%arg0: tensor<10xi32>, %arg1: tensor) { %0 = "tosa.const"() {values = dense<9> : tensor} : () -> tensor // expected-error@+1 {{'tosa.while_loop' op 'cond_graph' result must be a boolean tensor, got 'tensor'}} %1:3 = tosa.while_loop (%arg2 = %arg0, %arg3 = %0, %arg4 = %arg0) : (tensor<10xi32>, tensor, tensor<10xi32>) -> (tensor<10xi32>, tensor, tensor<10xi32>) { %2 = tosa.add %arg3, %arg1 : (tensor, tensor) -> tensor tosa.yield %2 : tensor } do { ^bb0(%arg2: tensor<10xi32>, %arg3: tensor, %arg4: tensor<10xi32>): %2 = "tosa.const"() {values = dense<1> : tensor} : () -> tensor %4 = tosa.add %arg2, %2 : (tensor<10xi32>, tensor) -> tensor<10xi32> tosa.yield %4, %2, %arg4 : tensor<10xi32>, tensor, tensor<10xi32> } return } // ----- module { // expected-note@below {{see existing symbol definition here}} tosa.variable @stored_var = dense<-1> : tensor<2x4x8xi32> // expected-error@+1 {{redefinition of symbol named 'stored_var'}} tosa.variable @stored_var = dense<-3> : tensor<2x4x8xi32> } // ----- module { // expected-error@+1 {{inferred shape of elements literal ([2]) does not match type ([3])}} tosa.variable @stored_var = dense<[3.14, 2.14]> : tensor<3xf32> // expected-error@+1 {{custom op 'tosa.variable' expected attribute}} } // ----- module { // expected-error@+1 {{expected integer elements, but parsed floating-point}} tosa.variable @stored_var = dense<-1.2> : tensor<2x4x8xi32> // expected-error@+1 {{custom op 'tosa.variable' expected attribute}} } // ----- func.func @test_variable_read_no_declaration() -> () { // expected-error@+1 {{'tosa.variable_read' op 'stored_var' has not been declared by 'tosa.variable'}} %0 = tosa.variable_read @stored_var : tensor return } // ----- module { tosa.variable @stored_var = dense<-1.2> : tensor<2x4x8xf32> func.func @test_variable_read_type_mismatch() -> () { // expected-error@+1 {{'tosa.variable_read' op require same element type for 'output1' ('i32') and the input tensor ('f32')}} %0 = tosa.variable_read @stored_var : tensor<2x4x8xi32> return } } // ----- module { tosa.variable @stored_var = dense<-1.2> : tensor<8x4x2xf32> func.func @test_variable_read_shape_mismatch() -> () { // expected-error@+1 {{'tosa.variable_read' op require same shapes for 'output1' ('tensor<2x4x8xf32>') and the input tensor ('tensor<8x4x2xf32>')}} %0 = tosa.variable_read @stored_var : tensor<2x4x8xf32> return } } // ----- func.func @test_variable_write_no_declaration(%arg0: tensor) -> () { // expected-error@+1 {{'tosa.variable_write' op 'stored_var' has not been declared by 'tosa.variable'}} tosa.variable_write @stored_var, %arg0 : tensor return } // ----- module { tosa.variable @stored_var = dense<-1.2> : tensor<2x4x8xf32> func.func @test_variable_write_type_mismatch(%arg0: tensor<2x4x8xi32>) -> () { // expected-error@+1 {{'tosa.variable_write' op require same element type for 'input1' ('i32') and the input tensor ('f32')}} tosa.variable_write @stored_var, %arg0 : tensor<2x4x8xi32> return } } // ----- module { tosa.variable @stored_var = dense<-1.2> : tensor<8x4x2xf32> func.func @test_variable_write_shape_mismatch(%arg0: tensor<2x4x8xf32>) -> () { // expected-error@+1 {{'tosa.variable_write' op require same shapes for 'input1' ('tensor<2x4x8xf32>') and the input tensor ('tensor<8x4x2xf32>')}} tosa.variable_write @stored_var, %arg0 : tensor<2x4x8xf32> return } } // ----- func.func @scatter_invalid_indices_N(%arg0 : tensor<2x4x5xi32>, %arg1 : tensor<3x2xi32>, %arg2 : tensor<2x2x5xi32>) { // expected-error@+1 {{'tosa.scatter' op requires indices dimension 0 to have size 2, got 3}} %1 = tosa.scatter %arg0, %arg1, %arg2 : (tensor<2x4x5xi32>, tensor<3x2xi32>, tensor<2x2x5xi32>) -> tensor<2x4x5xi32> return } // ----- func.func @scatter_invalid_input_N(%arg0 : tensor, %arg1 : tensor<2x2xi32>, %arg2 : tensor<3x2x5xi32>) { // expected-error@+1 {{'tosa.scatter' op requires input dimension 0 to have size 2, got 3}} %2 = tosa.scatter %arg0, %arg1, %arg2 : (tensor, tensor<2x2xi32>, tensor<3x2x5xi32>) -> tensor<2x4x5xi32> return } // ----- func.func @scatter_invalid_out_N(%arg0 : tensor, %arg1 : tensor, %arg2 : tensor<2x2x5xi32>) { // expected-error@+1 {{'tosa.scatter' op requires values_out dimension 0 to have size 2, got 3}} %2 = tosa.scatter %arg0, %arg1, %arg2 : (tensor, tensor, tensor<2x2x5xi32>) -> tensor<3x4x5xi32> return } // ----- func.func @scatter_invalid_out_K(%arg0 : tensor, %arg1 : tensor, %arg2 : tensor<2x2x5xi32>) { // expected-error@+1 {{'tosa.scatter' op requires values_out dimension 1 to have size 4, got 3}} %2 = tosa.scatter %arg0, %arg1, %arg2 : (tensor, tensor, tensor<2x2x5xi32>) -> tensor<2x3x5xi32> return } // ----- func.func @scatter_invalid_input_W(%arg0 : tensor, %arg1 : tensor, %arg2 : tensor<2x3x5xi32>) { // expected-error@+1 {{'tosa.scatter' op requires input dimension 1 to have size 2, got 3}} %2 = tosa.scatter %arg0, %arg1, %arg2 : (tensor, tensor, tensor<2x3x5xi32>) -> tensor<2x4x5xi32> return } // ----- func.func @scatter_invalid_input_C(%arg0 : tensor, %arg1 : tensor, %arg2 : tensor<2x2x6xi32>) { // expected-error@+1 {{'tosa.scatter' op requires input dimension 2 to have size 5, got 6}} %2 = tosa.scatter %arg0, %arg1, %arg2 : (tensor, tensor, tensor<2x2x6xi32>) -> tensor<2x4x5xi32> return } // ----- func.func @scatter_invalid_out_C(%arg0 : tensor, %arg1 : tensor, %arg2 : tensor<2x2x5xi32>) { // expected-error@+1 {{'tosa.scatter' op requires values_out dimension 2 to have size 5, got 6}} %2 = tosa.scatter %arg0, %arg1, %arg2 : (tensor, tensor, tensor<2x2x5xi32>) -> tensor<2x4x6xi32> return } // ----- func.func @scatter_invalid_K_W(%arg0 : tensor<2x4x5xi32>, %arg1 : tensor<2x6xi32>, %arg2 : tensor<2x6x5xi32>) { // expected-error@+1 {{'tosa.scatter' op requires dimensions K >= W, got K=4 and W=6}} %2 = tosa.scatter %arg0, %arg1, %arg2 : (tensor<2x4x5xi32>, tensor<2x6xi32>, tensor<2x6x5xi32>) -> tensor<2x4x5xi32> return } // ----- func.func @test_matmul_output_batch_mismatch(%arg0: tensor<2x3x4xf32>, %arg1: tensor<5x4x6xf32>) -> tensor<2x3x6xf32> { %azp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> %bzp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> // expected-error@+1 {{'tosa.matmul' op expected batch of b to match size 2, got 5}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<2x3x4xf32>, tensor<5x4x6xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<2x3x6xf32> return %0 : tensor<2x3x6xf32> } // ----- func.func @test_matmul_output_channel_mismatch(%arg0: tensor<2x3x4xf32>, %arg1: tensor<2x7x6xf32>) -> tensor<2x3x6xf32> { %azp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> %bzp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> // expected-error@+1 {{'tosa.matmul' op expected channels of b to match size 4, got 7}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<2x3x4xf32>, tensor<2x7x6xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<2x3x6xf32> return %0 : tensor<2x3x6xf32> } // ----- func.func @test_matmul_output_shape_mismatch(%arg0: tensor<2x3x4xf32>, %arg1: tensor<2x4x6xf32>) -> tensor<2x5x6xf32> { %azp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> %bzp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> // expected-error@+1 {{'tosa.matmul' op expected output shape 2, 5, 6 to be compatible with expected output shape 2, 3, 6}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<2x3x4xf32>, tensor<2x4x6xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<2x5x6xf32> return %0 : tensor<2x5x6xf32> } // ----- func.func @test_matmul_dynamic_batch_mismatch(%arg0: tensor<2x?x4xf32>, %arg1: tensor<5x4x6xf32>) -> tensor<2x?x6xf32> { %azp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> %bzp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> // expected-error@+1 {{'tosa.matmul' op expected batch of b to match size 2, got 5}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<2x?x4xf32>, tensor<5x4x6xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<2x?x6xf32> return %0 : tensor<2x?x6xf32> } // ----- func.func @test_matmul_dynamic_channel_mismatch(%arg0: tensor, %arg1: tensor) -> tensor { %azp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> %bzp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> // expected-error@+1 {{'tosa.matmul' op expected channels of b to match size 4, got 7}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor, tensor, tensor<1xf32>, tensor<1xf32>) -> tensor return %0 : tensor } // ----- func.func @test_matmul_dynamic_output_shape_mismatch(%arg0: tensor, %arg1: tensor<2x4x6xf32>) -> tensor<5x3x6xf32> { %azp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> %bzp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> // expected-error@+1 {{'tosa.matmul' op expected output shape 5, 3, 6 to be compatible with expected output shape 2, 3, 6}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor, tensor<2x4x6xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<5x3x6xf32> return %0 : tensor<5x3x6xf32> } // ----- func.func @test_matmul_unranked_b_output_shape_mismatch(%arg0: tensor<2x3x4xf32>, %arg1: tensor<*xf32>) -> tensor<2x5x?xf32> { %azp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> %bzp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> // expected-error@+1 {{'tosa.matmul' op expected output shape 2, 5, ? to be compatible with expected output shape 2, 3, ?}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<2x3x4xf32>, tensor<*xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<2x5x?xf32> return %0 : tensor<2x5x?xf32> } // ----- func.func @test_matmul_quantized_mixed_operands(%arg0: tensor<2x3x4x!quant.uniform>, %arg1: tensor<2x4x6xf32>) -> tensor<2x3x6xi32> { %azp0 = "tosa.const"() {values = dense<0> : tensor<1xi8>} : () -> tensor<1xi8> %bzp0 = "tosa.const"() {values = dense<0.0> : tensor<1xf32>} : () -> tensor<1xf32> // expected-error@+1 {{'tosa.matmul' op expect operands to be both quantized or both not quantized, got '!quant.uniform' and 'f32'}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<2x3x4x!quant.uniform>, tensor<2x4x6xf32>, tensor<1xi8>, tensor<1xf32>) -> tensor<2x3x6xi32> return %0 : tensor<2x3x6xi32> } // ----- func.func @test_matmul_quantized_width_mismatch(%arg0: tensor<2x3x4x!quant.uniform>, %arg1: tensor<2x4x6x!quant.uniform>) -> tensor<2x3x6xi32> { %azp0 = "tosa.const"() {values = dense<0> : tensor<1xi8>} : () -> tensor<1xi8> %bzp0 = "tosa.const"() {values = dense<0> : tensor<1xi16>} : () -> tensor<1xi16> // expected-error@+1 {{'tosa.matmul' op expect quantized operands to have same widths, got 8 and 16}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<2x3x4x!quant.uniform>, tensor<2x4x6x!quant.uniform>, tensor<1xi8>, tensor<1xi16>) -> tensor<2x3x6xi32> return %0 : tensor<2x3x6xi32> } // ----- // CHECK-LABEL: test_matmul_a_zp_same_element_type func.func @test_matmul_a_zp_same_element_type(%arg0: tensor<1x14x19xf32>, %arg1: tensor<1x19x28xf32>) -> tensor<1x14x28xf32> { %azp0 = "tosa.const"() <{values = dense<0.0> : tensor<1xf16>}> : () -> tensor<1xf16> %bzp0 = "tosa.const"() <{values = dense<0.0> : tensor<1xf32>}> : () -> tensor<1xf32> // expected-error@+1 {{'tosa.matmul' op expect input a and a_zp have the same element type, got 'f32' and 'f16'}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<1x14x19xf32>, tensor<1x19x28xf32>, tensor<1xf16>, tensor<1xf32>) -> tensor<1x14x28xf32> return %0 : tensor<1x14x28xf32> } // ----- // CHECK-LABEL: test_matmul_b_zp_same_element_type func.func @test_matmul_b_zp_same_element_type(%arg0: tensor<1x14x19xf32>, %arg1: tensor<1x19x28xf32>) -> tensor<1x14x28xf32> { %azp0 = "tosa.const"() <{values = dense<0.0> : tensor<1xf32>}> : () -> tensor<1xf32> %bzp0 = "tosa.const"() <{values = dense<0.0> : tensor<1xf16>}> : () -> tensor<1xf16> // expected-error@+1 {{'tosa.matmul' op expect input b and b_zp have the same element type, got 'f32' and 'f16'}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<1x14x19xf32>, tensor<1x19x28xf32>, tensor<1xf32>, tensor<1xf16>) -> tensor<1x14x28xf32> return %0 : tensor<1x14x28xf32> } // ----- // CHECK-LABEL: test_matmul_a_zp_non_zero func.func @test_matmul_a_zp_non_zero(%arg0: tensor<1x14x19xf32>, %arg1: tensor<1x19x28xf32>) -> tensor<1x14x28xf32> { %azp0 = "tosa.const"() <{values = dense<1.0> : tensor<1xf32>}> : () -> tensor<1xf32> %bzp0 = "tosa.const"() <{values = dense<0.0> : tensor<1xf32>}> : () -> tensor<1xf32> // expected-error@+1 {{'tosa.matmul' op a zero point must be zero for non-int8 integer types}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<1x14x19xf32>, tensor<1x19x28xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x14x28xf32> return %0 : tensor<1x14x28xf32> } // ----- // CHECK-LABEL: test_matmul_b_zp_non_zero func.func @test_matmul_b_zp_non_zero(%arg0: tensor<1x14x19xf32>, %arg1: tensor<1x19x28xf32>) -> tensor<1x14x28xf32> { %azp0 = "tosa.const"() <{values = dense<0.0> : tensor<1xf32>}> : () -> tensor<1xf32> %bzp0 = "tosa.const"() <{values = dense<-1.0> : tensor<1xf32>}> : () -> tensor<1xf32> // expected-error@+1 {{'tosa.matmul' op b zero point must be zero for non-int8 integer types}} %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<1x14x19xf32>, tensor<1x19x28xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<1x14x28xf32> return %0 : tensor<1x14x28xf32> } // ----- func.func @test_matmul_t_block_scaled_data_mismatch(%arg0: tensor<4x8x32xf8E4M3FN>, %arg1: tensor<4x8x1xf8E8M0FNU>, %arg2: tensor<4x16x32xf8E5M2>, %arg3: tensor<4x16x1xf8E8M0FNU>) -> tensor<4x8x16xf32> { // expected-error@+1 {{'tosa.matmul_t_block_scaled' op expect A_data and B_data to have same element type, got 'f8E4M3FN' and 'f8E5M2'}} %0 = tosa.matmul_t_block_scaled %arg0, %arg1, %arg2, %arg3 {block_size = #tosa.block_size : i32} : (tensor<4x8x32xf8E4M3FN>, tensor<4x8x1xf8E8M0FNU>, tensor<4x16x32xf8E5M2>, tensor<4x16x1xf8E8M0FNU>) -> tensor<4x8x16xf32> return %0 : tensor<4x8x16xf32> } // ----- func.func @test_matmul_t_block_scaled_output_batch_mismatch(%arg0: tensor<*xf8E4M3FN>, %arg1: tensor, %arg2: tensor<*xf8E4M3FN>, %arg3: tensor<4x?x?xf8E8M0FNU>) -> tensor<5x?x?xf32> { // expected-error@+1 {{'tosa.matmul_t_block_scaled' op expected output shape 5, ?, ? to be compatible with expected output shape 4, 8, ?}} %0 = tosa.matmul_t_block_scaled %arg0, %arg1, %arg2, %arg3 {block_size = #tosa.block_size : i32} : (tensor<*xf8E4M3FN>, tensor, tensor<*xf8E4M3FN>, tensor<4x?x?xf8E8M0FNU>) -> tensor<5x?x?xf32> return %0 : tensor<5x?x?xf32> } // ----- func.func @test_matmul_t_block_scaled_output_height_mismatch(%arg0: tensor<*xf8E4M3FN>, %arg1: tensor, %arg2: tensor<*xf8E4M3FN>, %arg3: tensor<4x?x?xf8E8M0FNU>) -> tensor<4x8x?xf32> { // expected-error@+1 {{'tosa.matmul_t_block_scaled' op expected output shape 4, 8, ? to be compatible with expected output shape 4, 9, ?}} %0 = tosa.matmul_t_block_scaled %arg0, %arg1, %arg2, %arg3 {block_size = #tosa.block_size : i32} : (tensor<*xf8E4M3FN>, tensor, tensor<*xf8E4M3FN>, tensor<4x?x?xf8E8M0FNU>) -> tensor<4x8x?xf32> return %0 : tensor<4x8x?xf32> } // ----- func.func @test_matmul_t_block_scaled_output_width_mismatch(%arg0: tensor<*xf8E4M3FN>, %arg1: tensor, %arg2: tensor, %arg3: tensor<*xf8E8M0FNU>) -> tensor { // expected-error@+1 {{'tosa.matmul_t_block_scaled' op expected output shape ?, ?, 10 to be compatible with expected output shape ?, ?, 1}} %0 = tosa.matmul_t_block_scaled %arg0, %arg1, %arg2, %arg3 {block_size = #tosa.block_size : i32} : (tensor<*xf8E4M3FN>, tensor, tensor, tensor<*xf8E8M0FNU>) -> tensor return %0 : tensor } // ----- func.func @test_matmul_t_block_scaled_channel_not_multiple_of_block_size(%arg0: tensor<4x8x55xf8E4M3FN>, %arg1: tensor<4x8x1xf8E8M0FNU>, %arg2: tensor<4x16x32xf8E4M3FN>, %arg3: tensor<4x16x1xf8E8M0FNU>) -> tensor<4x8x16xf32> { // expected-error@+1 {{'tosa.matmul_t_block_scaled' op expected channels of b_data to match size 55, got 32}} %0 = tosa.matmul_t_block_scaled %arg0, %arg1, %arg2, %arg3 {block_size = #tosa.block_size : i32} : (tensor<4x8x55xf8E4M3FN>, tensor<4x8x1xf8E8M0FNU>, tensor<4x16x32xf8E4M3FN>, tensor<4x16x1xf8E8M0FNU>) -> tensor<4x8x16xf32> return %0 : tensor<4x8x16xf32> } // ----- func.func @test_matmul_t_block_scaled_batch_mismatch(%arg0: tensor<4x8x32xf8E4M3FN>, %arg1: tensor<4x8x1xf8E8M0FNU>, %arg2: tensor<2x16x32xf8E4M3FN>, %arg3: tensor<2x16x1xf8E8M0FNU>) -> tensor<4x8x16xf32> { // expected-error@+1 {{'tosa.matmul_t_block_scaled' op expect B matrix batch size to be broadcast compatible with A, got D=2 vs N=4}} %0 = tosa.matmul_t_block_scaled %arg0, %arg1, %arg2, %arg3 {block_size = #tosa.block_size : i32} : (tensor<4x8x32xf8E4M3FN>, tensor<4x8x1xf8E8M0FNU>, tensor<2x16x32xf8E4M3FN>, tensor<2x16x1xf8E8M0FNU>) -> tensor<4x8x16xf32> return %0 : tensor<4x8x16xf32> } // ----- func.func @test_matmul_t_block_scaled_block_size_mismatch(%arg0: tensor<4x8x32xf8E4M3FN>, %arg1: tensor<4x8x1xf8E8M0FNU>, %arg2: tensor<4x16x32xf8E4M3FN>, %arg3: tensor<4x16x1xf8E8M0FNU>) -> tensor<4x8x16xf32> { // expected-error@+1 {{'tosa.matmul_t_block_scaled' op expect block size to be 32, got 1}} %0 = tosa.matmul_t_block_scaled %arg0, %arg1, %arg2, %arg3 {block_size = #tosa.block_size} : (tensor<4x8x32xf8E4M3FN>, tensor<4x8x1xf8E8M0FNU>, tensor<4x16x32xf8E4M3FN>, tensor<4x16x1xf8E8M0FNU>) -> tensor<4x8x16xf32> return %0 : tensor<4x8x16xf32> } // ----- func.func @cast_from_block_scaled_incompatible_input_output_shape(%arg0: tensor<4x32xf4E2M1FN>, %arg1: tensor<4x1xf8E8M0FNU>) -> tensor<5x32xf32> { // expected-error@+1 {{'tosa.cast_from_block_scaled' op require compatible shapes for input_data ('tensor<4x32xf4E2M1FN>') and output_data ('tensor<5x32xf32>')}} %0 = tosa.cast_from_block_scaled %arg0, %arg1 {block_size = #tosa.block_size : i32} : (tensor<4x32xf4E2M1FN>, tensor<4x1xf8E8M0FNU>) -> tensor<5x32xf32> return %0 : tensor<5x32xf32> } // ----- func.func @cast_from_block_scaled_not_scalar(%arg0: tensor, %arg1: tensor) -> tensor { // expected-error@+1 {{'tosa.cast_from_block_scaled' op operand #0 must be tosa-conformant tensor of at least rank 1, but got 'tensor'}} %0 = tosa.cast_from_block_scaled %arg0, %arg1 {block_size = #tosa.block_size : i32} : (tensor, tensor) -> tensor return %0 : tensor } // ----- func.func @cast_from_block_scaled_not_divisible_by_block_size(%arg0: tensor<4x33xf4E2M1FN>, %arg1: tensor<4x1xf8E8M0FNU>) -> tensor<4x33xf32> { // expected-error@+1 {{'tosa.cast_from_block_scaled' op expect last dimension of input_data (33) to be divisible by block_size (32)}} %0 = tosa.cast_from_block_scaled %arg0, %arg1 {block_size = #tosa.block_size : i32} : (tensor<4x33xf4E2M1FN>, tensor<4x1xf8E8M0FNU>) -> tensor<4x33xf32> return %0 : tensor<4x33xf32> } // ----- func.func @cast_from_block_scaled_data_scale_mismatch(%arg0: tensor<4x32xf4E2M1FN>, %arg1: tensor<5x1xf8E8M0FNU>) -> tensor<4x32xf32> { // expected-error@+1 {{'tosa.cast_from_block_scaled' op require compatible shapes for input_data ('tensor<4x32xf4E2M1FN>') and input_scale ('tensor<5x1xf8E8M0FNU>') except for the last dimension}} %0 = tosa.cast_from_block_scaled %arg0, %arg1 {block_size = #tosa.block_size : i32} : (tensor<4x32xf4E2M1FN>, tensor<5x1xf8E8M0FNU>) -> tensor<4x32xf32> return %0 : tensor<4x32xf32> } // ----- func.func @cast_from_block_scaled_data_scale_channel_mismatch(%arg0: tensor<4x32xf4E2M1FN>, %arg1: tensor<4x2xf8E8M0FNU>) -> tensor<4x32xf32> { // expected-error@+1 {{'tosa.cast_from_block_scaled' op expect last dimension of input_scale (2) to be equal to last dimension of input_data / block_size (1)}} %0 = tosa.cast_from_block_scaled %arg0, %arg1 {block_size = #tosa.block_size} : (tensor<4x32xf4E2M1FN>, tensor<4x2xf8E8M0FNU>) -> tensor<4x32xf32> return %0 : tensor<4x32xf32> } // ----- func.func @test_cast_from_block_scaled_block_size_mismatch(%arg0: tensor<4x32xf4E2M1FN>, %arg1: tensor<4x1xf8E8M0FNU>) -> tensor<4x32xf32> { // expected-error@+1 {{'tosa.cast_from_block_scaled' op expect block size to be 32, got 1}} %0 = tosa.cast_from_block_scaled %arg0, %arg1 {block_size = #tosa.block_size : i32} : (tensor<4x32xf4E2M1FN>, tensor<4x1xf8E8M0FNU>) -> tensor<4x32xf32> return %0 : tensor<4x32xf32> } // ----- func.func @test_cast_to_block_scaled_incompatible_input_output_shape(%arg0: tensor<4x32xf32>) -> (tensor<5x32xf4E2M1FN>, tensor<4x1xf8E8M0FNU>) { // expected-error@+1 {{'tosa.cast_to_block_scaled' op require compatible shapes for input_data ('tensor<4x32xf32>') and output_data ('tensor<5x32xf4E2M1FN>')}} %0:2 = tosa.cast_to_block_scaled %arg0 {block_size = #tosa.block_size} : (tensor<4x32xf32>) -> (tensor<5x32xf4E2M1FN>, tensor<4x1xf8E8M0FNU>) return %0#0, %0#1 : tensor<5x32xf4E2M1FN>, tensor<4x1xf8E8M0FNU> } // ----- func.func @test_cast_to_block_scaled_not_scalar(%arg0: tensor) -> (tensor, tensor) { // expected-error@+1 {{'tosa.cast_to_block_scaled' op operand #0 must be tosa-conformant tensor of at least rank 1, but got 'tensor'}} %0:2 = tosa.cast_to_block_scaled %arg0 {block_size = #tosa.block_size} : (tensor) -> (tensor, tensor) return %0#0, %0#1 : tensor, tensor } // ----- func.func @test_cast_to_block_scaled_not_divisible_by_block_size(%arg0: tensor<4x33xf32>) -> (tensor<4x33xf4E2M1FN>, tensor<4x1xf8E8M0FNU>) { // expected-error@+1 {{'tosa.cast_to_block_scaled' op expect last dimension of input_data (33) to be divisible by block_size (32)}} %0:2 = tosa.cast_to_block_scaled %arg0 {block_size = #tosa.block_size} : (tensor<4x33xf32>) -> (tensor<4x33xf4E2M1FN>, tensor<4x1xf8E8M0FNU>) return %0#0, %0#1 : tensor<4x33xf4E2M1FN>, tensor<4x1xf8E8M0FNU> } // ----- func.func @test_cast_to_block_scaled_data_scale_mismatch(%arg0: tensor<4x32xf32>) -> (tensor<4x32xf4E2M1FN>, tensor<5x1xf8E8M0FNU>) { // expected-error@+1 {{'tosa.cast_to_block_scaled' op require compatible shapes for output_data ('tensor<4x32xf4E2M1FN>') and output_scale ('tensor<5x1xf8E8M0FNU>') except for the last dimension}} %0:2 = tosa.cast_to_block_scaled %arg0 {block_size = #tosa.block_size} : (tensor<4x32xf32>) -> (tensor<4x32xf4E2M1FN>, tensor<5x1xf8E8M0FNU>) return %0#0, %0#1 : tensor<4x32xf4E2M1FN>, tensor<5x1xf8E8M0FNU> } // ----- func.func @test_cast_to_block_scaled_data_scale_channel_mismatch(%arg0: tensor<4x32xf32>) -> (tensor<4x32xf4E2M1FN>, tensor<4x2xf8E8M0FNU>) { // expected-error@+1 {{'tosa.cast_to_block_scaled' op expect last dimension of output_scale (2) to be equal to last dimension of output_data / block_size (1)}} %0:2 = tosa.cast_to_block_scaled %arg0 {block_size = #tosa.block_size} : (tensor<4x32xf32>) -> (tensor<4x32xf4E2M1FN>, tensor<4x2xf8E8M0FNU>) return %0#0, %0#1 : tensor<4x32xf4E2M1FN>, tensor<4x2xf8E8M0FNU> } // ----- func.func @test_cast_to_block_scaled_block_size_mismatch(%arg0: tensor<4x32xf32>) -> (tensor<4x32xf4E2M1FN>, tensor<4x1xf8E8M0FNU>) { // expected-error@+1 {{'tosa.cast_to_block_scaled' op expect block size to be 32, got 1}} %0:2 = tosa.cast_to_block_scaled %arg0 {block_size = #tosa.block_size} : (tensor<4x32xf32>) -> (tensor<4x32xf4E2M1FN>, tensor<4x1xf8E8M0FNU>) return %0#0, %0#1 : tensor<4x32xf4E2M1FN>, tensor<4x1xf8E8M0FNU> } // ----- func.func @test_clamp_quantized(%arg0:tensor>) -> (tensor>) { // expected-error@+1 {{'tosa.clamp' op min/max attributes types are incompatible with input/output element types.}} %0 = tosa.clamp %arg0 {max_val = 127 : i8, min_val = -128 : i8} : (tensor>) -> tensor> return %0 : tensor> } // ----- func.func @test_elementwise_shape_op_same_inputs_rank(%arg0: !tosa.shape<4>, %arg1: !tosa.shape<3>) -> !tosa.shape<4> { // expected-error@+1 {{'tosa.add_shape' op operands don't have matching ranks}} %0 = tosa.add_shape %arg0, %arg1 : (!tosa.shape<4>, !tosa.shape<3>) -> !tosa.shape<4> return %0 : !tosa.shape<4> } // ----- func.func @test_elementwise_shape_op_same_input_output_rank(%arg0: !tosa.shape<4>, %arg1: !tosa.shape<4>) -> !tosa.shape<3> { // expected-error@+1 {{'tosa.div_floor_shape' op result shape has different rank than operands}} %0 = tosa.div_floor_shape %arg0, %arg1 : (!tosa.shape<4>, !tosa.shape<4>) -> !tosa.shape<3> return %0 : !tosa.shape<3> } // ----- func.func @test_dim_invalid_output_rank(%arg0: tensor<1x2x3xi32>) -> !tosa.shape<2> { // expected-error@+1 {{'tosa.dim' op expect output shape type to contain one element, got '!tosa.shape<2>'}} %0 = tosa.dim %arg0 {axis = 2 : i32} : (tensor<1x2x3xi32>) -> !tosa.shape<2> return %0 : !tosa.shape<2> } // ----- func.func @test_dim_invalid_axis(%arg0: tensor<1x2x3xi32>) -> !tosa.shape<1> { // expected-error@+1 {{'tosa.dim' op expect axis to be in the range [0, 3), got 4}} %0 = tosa.dim %arg0 {axis = 4 : i32} : (tensor<1x2x3xi32>) -> !tosa.shape<1> return %0 : !tosa.shape<1> } // ----- func.func @test_dim_scalar(%arg0: tensor) -> !tosa.shape<1> { // expected-error@+1 {{'tosa.dim' op operand #0 must be tosa-conformant tensor of at least rank 1, but got 'tensor'}} %0 = tosa.dim %arg0 {axis = 4 : i32} : (tensor) -> !tosa.shape<1> return %0 : !tosa.shape<1> } // ----- func.func @test_concat_shape_rank_mismatch() -> !tosa.shape<4> { %0 = tosa.const_shape {values = dense<[10]> : tensor<1xindex>} : () -> !tosa.shape<1> %1 = tosa.const_shape {values = dense<[10, 15]> : tensor<2xindex>} : () -> !tosa.shape<2> %2 = tosa.const_shape {values = dense<[5, 2]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.concat_shape' op requires output shape rank to be equal to the sum of the input shape ranks (5), got 4}} %3 = tosa.concat_shape %0, %1, %2 : (!tosa.shape<1>, !tosa.shape<2>, !tosa.shape<2>) -> !tosa.shape<4> return %3 : !tosa.shape<4> } // ----- func.func @test_concat_shape_no_inputs() -> !tosa.shape<0> { // expected-error@+1 {{'tosa.concat_shape' op requires at least one input shape}} %0 = tosa.concat_shape {} : () -> !tosa.shape<0> return %0 : !tosa.shape<0> } // ----- func.func @test_concat_shape_rank_0() -> !tosa.shape<0> { %0 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0> %1 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0> %2 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0> // expected-error@+1 {{'tosa.concat_shape' op requires all inputs shapes have a rank greater than 0}} %3 = tosa.concat_shape %0, %1, %2 : (!tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>) -> !tosa.shape<0> return %3 : !tosa.shape<0> } // ----- func.func @test_slice_shape_negative_start() -> !tosa.shape<3> { %0 = tosa.const_shape {values = dense<[4, 5, 6, 7, 8, 9]> : tensor<6xindex>} : () -> !tosa.shape<6> %1 = "tosa.const"() {values = dense<-1> : tensor<1xi32>} : () -> tensor<1xi32> %2 = "tosa.const"() {values = dense<3> : tensor<1xi32>} : () -> tensor<1xi32> // expected-error@+1 {{'tosa.slice_shape' op expected non-negative start index, got -1}} %3 = tosa.slice_shape %0, %1, %2 : (!tosa.shape<6>, tensor<1xi32>, tensor<1xi32>) -> !tosa.shape<3> return %3 : !tosa.shape<3> } // ----- func.func @test_slice_shape_non_positive_size() -> !tosa.shape<3> { %0 = tosa.const_shape {values = dense<[4, 5, 6, 7, 8, 9]> : tensor<6xindex>} : () -> !tosa.shape<6> %1 = "tosa.const"() {values = dense<1> : tensor<1xi32>} : () -> tensor<1xi32> %2 = "tosa.const"() {values = dense<0> : tensor<1xi32>} : () -> tensor<1xi32> // expected-error@+1 {{'tosa.slice_shape' op expected positive size, got 0}} %3 = tosa.slice_shape %0, %1, %2 : (!tosa.shape<6>, tensor<1xi32>, tensor<1xi32>) -> !tosa.shape<3> return %3 : !tosa.shape<3> } // ----- func.func @test_slice_out_of_range() -> !tosa.shape<3> { %0 = tosa.const_shape {values = dense<[4, 5, 6, 7, 8, 9]> : tensor<6xindex>} : () -> !tosa.shape<6> %1 = "tosa.const"() {values = dense<5> : tensor<1xi32>} : () -> tensor<1xi32> %2 = "tosa.const"() {values = dense<3> : tensor<1xi32>} : () -> tensor<1xi32> // expected-error@+1 {{'tosa.slice_shape' op expected start + size to be less than or equal to input shape rank (6), got 8}} %3 = tosa.slice_shape %0, %1, %2 : (!tosa.shape<6>, tensor<1xi32>, tensor<1xi32>) -> !tosa.shape<3> return %3 : !tosa.shape<3> } // ----- func.func @test_slice_shape_incorrect_output_size() -> !tosa.shape<4> { %shape = tosa.const_shape {values = dense<[4, 5, 6, 7, 8, 9]> : tensor<6xindex>} : () -> !tosa.shape<6> %start = "tosa.const"() {values = dense<1> : tensor<1xi32>} : () -> tensor<1xi32> %size = "tosa.const"() {values = dense<3> : tensor<1xi32>} : () -> tensor<1xi32> // expected-error@+1 {{'tosa.slice_shape' op expected output type size to be equal to size attribute, got 4 vs 3}} %slice = tosa.slice_shape %shape, %start, %size : (!tosa.shape<6>, tensor<1xi32>, tensor<1xi32>) -> !tosa.shape<4> return %slice : !tosa.shape<4> } // ----- func.func @test_mod_shape_input1_input2_rank_mismatch() -> !tosa.shape<6> { %a = tosa.const_shape {values = dense<[1, 2, 3, 4, 5, 6]> : tensor<6xindex>} : () -> !tosa.shape<6> %b = tosa.const_shape {values = dense<[1, 2, 3, 4, 5]> : tensor<5xindex>} : () -> !tosa.shape<5> // expected-error@+1 {{'tosa.mod_shape' op operands don't have matching ranks}} %c = tosa.mod_shape %a, %b : (!tosa.shape<6>, !tosa.shape<5>) -> !tosa.shape<6> return %c : !tosa.shape<6> } // ----- func.func @test_conv2d_block_scaled_data_type_mismatch(%arg0: tensor<1x4x4x64xf4E2M1FN>, %arg1: tensor<1x4x4x2xf8E8M0FNU>, %arg2: tensor<8x1x1x64xf8E4M3FN>, %arg3: tensor<8x1x1x2xf8E8M0FNU>, %arg4: tensor<1xf32>) -> tensor<*xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op expect input_data and weight_data to have same element type, got 'f4E2M1FN' and 'f8E4M3FN'}} %3 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = BLOCK_SIZE_32} : (tensor<1x4x4x64xf4E2M1FN>, tensor<1x4x4x2xf8E8M0FNU>, tensor<8x1x1x64xf8E4M3FN>, tensor<8x1x1x2xf8E8M0FNU>, tensor<1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<*xf32> return %3 : tensor<*xf32> } // ----- func.func @test_conv2d_block_scaled_bias_output_type_mismatch(%arg0: tensor<1x4x4x64xf4E2M1FN>, %arg1: tensor<1x4x4x2xf8E8M0FNU>, %arg2: tensor<8x1x1x64xf4E2M1FN>, %arg3: tensor<8x1x1x2xf8E8M0FNU>, %arg4: tensor<1xf16>) -> tensor<*xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op expect bias and output to have same element type, got 'f16' and 'f32'}} %3 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = BLOCK_SIZE_32} : (tensor<1x4x4x64xf4E2M1FN>, tensor<1x4x4x2xf8E8M0FNU>, tensor<8x1x1x64xf4E2M1FN>, tensor<8x1x1x2xf8E8M0FNU>, tensor<1xf16>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<*xf32> return %3 : tensor<*xf32> } // ----- func.func @test_conv2d_block_scaled_invalid_padding(%arg0: tensor<1x4x4x64xf4E2M1FN>, %arg1: tensor<1x4x4x2xf8E8M0FNU>, %arg2: tensor<8x1x1x64xf4E2M1FN>, %arg3: tensor<8x1x1x2xf8E8M0FNU>, %arg4: tensor<1xf32>, %arg5: tensor<4xi32>, %arg6: tensor<2xi32>, %arg7: tensor<2xi32>) -> tensor<*xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, -1]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op expect all padding values to be >= 0, got 0, 0, 0, -1}} %0 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = #tosa.block_size} : (tensor<1x4x4x64xf4E2M1FN>, tensor<1x4x4x2xf8E8M0FNU>, tensor<8x1x1x64xf4E2M1FN>, tensor<8x1x1x2xf8E8M0FNU>, tensor<1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<*xf32> return %0 : tensor<*xf32> } // ----- func.func @test_conv2d_block_scaled_invalid_stride(%arg0: tensor<1x4x4x64xf4E2M1FN>, %arg1: tensor<1x4x4x2xf8E8M0FNU>, %arg2: tensor<8x1x1x64xf4E2M1FN>, %arg3: tensor<8x1x1x2xf8E8M0FNU>, %arg4: tensor<1xf32>, %arg5: tensor<4xi32>, %arg6: tensor<2xi32>, %arg7: tensor<2xi32>) -> tensor<*xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[0, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op expect all stride values to be >= 1, got 0, 1}} %0 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = #tosa.block_size} : (tensor<1x4x4x64xf4E2M1FN>, tensor<1x4x4x2xf8E8M0FNU>, tensor<8x1x1x64xf4E2M1FN>, tensor<8x1x1x2xf8E8M0FNU>, tensor<1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<*xf32> return %0 : tensor<*xf32> } // ----- func.func @test_conv2d_block_scaled_invalid_dilation(%arg0: tensor<1x4x4x64xf4E2M1FN>, %arg1: tensor<1x4x4x2xf8E8M0FNU>, %arg2: tensor<8x1x1x64xf4E2M1FN>, %arg3: tensor<8x1x1x2xf8E8M0FNU>, %arg4: tensor<1xf32>, %arg5: tensor<4xi32>, %arg6: tensor<2xi32>, %arg7: tensor<2xi32>) -> tensor<*xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 0]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op expect all dilation values to be >= 1, got 1, 0}} %0 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = #tosa.block_size} : (tensor<1x4x4x64xf4E2M1FN>, tensor<1x4x4x2xf8E8M0FNU>, tensor<8x1x1x64xf4E2M1FN>, tensor<8x1x1x2xf8E8M0FNU>, tensor<1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<*xf32> return %0 : tensor<*xf32> } // ----- func.func @test_conv2d_block_scaled_input_width_mismatch(%arg0: tensor<1x4x4x64xf4E2M1FN>, %arg1: tensor<1x4x5x2xf8E8M0FNU>, %arg2: tensor<8x1x1x64xf4E2M1FN>, %arg3: tensor<8x1x1x2xf8E8M0FNU>, %arg4: tensor<1xf32>, %arg5: tensor<4xi32>, %arg6: tensor<2xi32>, %arg7: tensor<2xi32>) -> tensor<1x4x4x8xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op expected input width of input_scale to match size 4, got 5}} %0 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = #tosa.block_size} : (tensor<1x4x4x64xf4E2M1FN>, tensor<1x4x5x2xf8E8M0FNU>, tensor<8x1x1x64xf4E2M1FN>, tensor<8x1x1x2xf8E8M0FNU>, tensor<1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x4x4x8xf32> return %0 : tensor<1x4x4x8xf32> } // ----- func.func @test_conv2d_block_scaled_kernel_height_mismatch(%arg0: tensor<1x4x4x64xf4E2M1FN>, %arg1: tensor<1x4x4x2xf8E8M0FNU>, %arg2: tensor<8x2x1x64xf4E2M1FN>, %arg3: tensor<8x1x1x2xf8E8M0FNU>, %arg4: tensor<1xf32>, %arg5: tensor<4xi32>, %arg6: tensor<2xi32>, %arg7: tensor<2xi32>) -> tensor<1x4x4x8xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op expected kernel height of weight_scale to match size 2, got 1}} %0 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = #tosa.block_size} : (tensor<1x4x4x64xf4E2M1FN>, tensor<1x4x4x2xf8E8M0FNU>, tensor<8x2x1x64xf4E2M1FN>, tensor<8x1x1x2xf8E8M0FNU>, tensor<1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x4x4x8xf32> return %0 : tensor<1x4x4x8xf32> } // ----- func.func @test_conv2d_block_scaled_output_shape_indivisible(%arg0: tensor<1x4x4x64xf4E2M1FN>, %arg1: tensor<1x4x4x2xf8E8M0FNU>, %arg2: tensor<8x1x1x64xf4E2M1FN>, %arg3: tensor<8x1x1x2xf8E8M0FNU>, %arg4: tensor<1xf32>, %arg5: tensor<4xi32>, %arg6: tensor<2xi32>, %arg7: tensor<2xi32>) -> tensor<1x4x5x8xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[1, 2]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op expected input_width - 1 + pad_left + pad_right - (kernel_width - 1) * dilation_x to be wholly divisible by stride_x, got (4 - 1 + 0 + 0 - (1 - 1) * 1) / 2}} %0 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = #tosa.block_size} : (tensor<1x4x4x64xf4E2M1FN>, tensor<1x4x4x2xf8E8M0FNU>, tensor<8x1x1x64xf4E2M1FN>, tensor<8x1x1x2xf8E8M0FNU>, tensor<1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x4x5x8xf32> return %0 : tensor<1x4x5x8xf32> } // ----- func.func @test_conv2d_block_scaled_output_shape_mismatch(%arg0: tensor<1x4x4x64xf4E2M1FN>, %arg1: tensor<1x4x4x2xf8E8M0FNU>, %arg2: tensor<8x1x1x64xf4E2M1FN>, %arg3: tensor<8x1x1x2xf8E8M0FNU>, %arg4: tensor<1xf32>, %arg5: tensor<4xi32>, %arg6: tensor<2xi32>, %arg7: tensor<2xi32>) -> tensor<1x4x5x8xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op calculated output width did not match expected: calculated=4, expected=5}} %0 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = #tosa.block_size} : (tensor<1x4x4x64xf4E2M1FN>, tensor<1x4x4x2xf8E8M0FNU>, tensor<8x1x1x64xf4E2M1FN>, tensor<8x1x1x2xf8E8M0FNU>, tensor<1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x4x5x8xf32> return %0 : tensor<1x4x5x8xf32> } // ----- func.func @test_conv2d_block_scaled_invalid_ic(%arg0: tensor<1x4x4x63xf4E2M1FN>, %arg1: tensor<1x4x4x2xf8E8M0FNU>, %arg2: tensor<8x1x1x63xf4E2M1FN>, %arg3: tensor<8x1x1x2xf8E8M0FNU>, %arg4: tensor<1xf32>, %arg5: tensor<4xi32>, %arg6: tensor<2xi32>, %arg7: tensor<2xi32>) -> tensor<1x4x5x8xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op expect IC to be a multiple of block size, got IC=63, block_size=32}} %0 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = #tosa.block_size} : (tensor<1x4x4x63xf4E2M1FN>, tensor<1x4x4x2xf8E8M0FNU>, tensor<8x1x1x63xf4E2M1FN>, tensor<8x1x1x2xf8E8M0FNU>, tensor<1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x4x5x8xf32> return %0 : tensor<1x4x5x8xf32> } // ----- func.func @test_conv2d_block_scaled_invalid_ic_mutiple(%arg0: tensor<1x4x4x64xf4E2M1FN>, %arg1: tensor<1x4x4x3xf8E8M0FNU>, %arg2: tensor<8x1x1x64xf4E2M1FN>, %arg3: tensor<8x1x1x3xf8E8M0FNU>, %arg4: tensor<1xf32>, %arg5: tensor<4xi32>, %arg6: tensor<2xi32>, %arg7: tensor<2xi32>) -> tensor<1x4x5x8xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op expect scale operands dimension 2 to equal IC/block_size (64/32), got 3}} %0 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = #tosa.block_size} : (tensor<1x4x4x64xf4E2M1FN>, tensor<1x4x4x3xf8E8M0FNU>, tensor<8x1x1x64xf4E2M1FN>, tensor<8x1x1x3xf8E8M0FNU>, tensor<1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x4x5x8xf32> return %0 : tensor<1x4x5x8xf32> } // ----- func.func @test_conv2d_block_scaled_invalid_bias_size(%arg0: tensor<1x4x4x64xf4E2M1FN>, %arg1: tensor<1x4x4x2xf8E8M0FNU>, %arg2: tensor<8x1x1x64xf4E2M1FN>, %arg3: tensor<8x1x1x2xf8E8M0FNU>, %arg4: tensor<6xf32>, %arg5: tensor<4xi32>, %arg6: tensor<2xi32>, %arg7: tensor<2xi32>) -> tensor<1x4x4x8xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op bias channels expected to be equal to output channels (8) or 1, got 6}} %0 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = #tosa.block_size} : (tensor<1x4x4x64xf4E2M1FN>, tensor<1x4x4x2xf8E8M0FNU>, tensor<8x1x1x64xf4E2M1FN>, tensor<8x1x1x2xf8E8M0FNU>, tensor<6xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x4x4x8xf32> return %0 : tensor<1x4x4x8xf32> } // ----- func.func @test_conv2d_block_scaled_block_size_mismatch(%arg0: tensor<1x4x4x64xf4E2M1FN>, %arg1: tensor<1x4x4x2xf8E8M0FNU>, %arg2: tensor<8x1x1x64xf4E2M1FN>, %arg3: tensor<8x1x1x2xf8E8M0FNU>, %arg4: tensor<1xf32>) -> tensor<*xf32> { %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %dilation = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.conv2d_block_scaled' op expect block size to be 32, got 1}} %3 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %pad, %stride, %dilation {block_size = #tosa.block_size} : (tensor<1x4x4x64xf4E2M1FN>, tensor<1x4x4x2xf8E8M0FNU>, tensor<8x1x1x64xf4E2M1FN>, tensor<8x1x1x2xf8E8M0FNU>, tensor<1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<*xf32> return %3 : tensor<*xf32> } // ----- func.func @test_missmatched_ranks() { %0 = tosa.const_shape {values = dense<[10]> : tensor<1xindex>} : () -> !tosa.shape<1> %1 = tosa.const_shape {values = dense<[10, 15]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.assert_equal_shape' op operands don't have matching ranks}} tosa.assert_equal_shape %0, %1 {allow_broadcast = true} : (!tosa.shape<1>, !tosa.shape<2>) -> () return } // ----- func.func @test_reshape_block_scaled_static_zero_dim_input(%arg0 : tensor<13x0x3xf32>) -> () { %s = tosa.const_shape {values = dense<[13, 21, 3]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.reshape_block_scaled' op operand #0 must be variadic of tosa-conformant tensor of number values, but got 'tensor<13x0x3xf32>'}} %0 = "tosa.reshape_block_scaled"(%arg0, %s) {block_size = #tosa.block_size : i32} : (tensor<13x0x3xf32>, !tosa.shape<3>) -> tensor<13x0x3xf32> return } // ----- func.func @test_reshape_block_scaled_zero_dim_input(%arg0 : tensor) -> () { %s = tosa.const_shape {values = dense<[13, 21, 3]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.reshape_block_scaled' op operand #0 must be variadic of tosa-conformant tensor of number values, but got 'tensor'}} %0 = "tosa.reshape_block_scaled"(%arg0, %s) {block_size = #tosa.block_size : i32} : (tensor, !tosa.shape<3>) -> tensor<13x0x3xf32> return } // ----- func.func @test_reshape_block_scaled_zero_dim_input(%arg0 : tensor) -> () { %1 = tosa.const_shape {values = dense<[13, 21, 3]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.reshape_block_scaled' op operand #0 must be variadic of tosa-conformant tensor of number values, but got 'tensor'}} %0 = "tosa.reshape_block_scaled"(%arg0, %1) {block_size = #tosa.block_size : i32} : (tensor, !tosa.shape<3>) -> tensor<13x0x3xf32> return } // ----- func.func @test_reshape_block_scaled_invalid_tensor_dim(%arg0 : tensor<4x?xf32>) -> () { %s = tosa.const_shape {values = dense<[1, -1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op result shape is inconsistent with new shape}} %0 = "tosa.reshape_block_scaled" (%arg0, %s) {block_size = #tosa.block_size : i32} : (tensor<4x?xf32>, !tosa.shape<2>) -> tensor return } // ----- func.func @test_reshape_block_scaled_invalid_size(%arg0 : tensor<2x4xf32>) -> () { %s = tosa.const_shape {values = dense<[3, 5]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op cannot reshape 8 elements into 15}} %0 = "tosa.reshape_block_scaled"(%arg0, %s) {block_size = #tosa.block_size : i32} : (tensor<2x4xf32>, !tosa.shape<2>) -> tensor<3x5xf32> return } // ----- func.func @test_reshape_block_scaled_invalid_newshape(%arg0 : tensor<1xf32>) -> () { %s = tosa.const_shape {values = dense<[1, 4]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op cannot reshape 1 elements into 4}} %0 = "tosa.reshape_block_scaled"(%arg0, %s) {block_size = #tosa.block_size : i32} : (tensor<1xf32>, !tosa.shape<2>) -> tensor return } // ----- func.func @test_reshape_block_scaled_inconsistent_dynamic_result(%arg0 : tensor) -> () { %s = tosa.const_shape {values = dense<[2, 4, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.reshape_block_scaled' op result shape is inconsistent with new shape}} %0 = "tosa.reshape_block_scaled"(%arg0, %s) {block_size = #tosa.block_size : i32} : (tensor, !tosa.shape<3>) -> tensor return } // ----- func.func @test_reshape_block_scaled_rank_mismatch(%arg0 : tensor) -> () { %s = tosa.const_shape {values = dense<[2, 4]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op result does not match new shape rank}} %0 = "tosa.reshape_block_scaled"(%arg0, %s) {block_size = #tosa.block_size : i32} : (tensor, !tosa.shape<2>) -> tensor return } // ----- func.func @test_reshape_block_scaled_types_mismatch(%arg0 : tensor<2x4xf32>) -> () { %s = tosa.const_shape {values = dense<[8]> : tensor<1xindex>} : () -> !tosa.shape<1> // expected-error@+1 {{'tosa.reshape_block_scaled' op expect input and output to have same element type, got 'f32' and 'i32'}} %0 = "tosa.reshape_block_scaled"(%arg0, %s) {block_size = #tosa.block_size : i32} : (tensor<2x4xf32>, !tosa.shape<1>) -> tensor<8xi32> return } // ----- func.func @test_reshape_block_scaled_outputs_mismatch_inputs(%arg0 : tensor<64xf8E4M3FN>) -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op requires number of results to match inputs}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %s) {block_size = #tosa.block_size : i32} : (tensor<64xf8E4M3FN>, !tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>, tensor<2x1xf8E8M0FNU>) return } // ----- func.func @test_reshape_block_scaled_inputs_mismatch_outputs(%arg0 : tensor<64xf8E4M3FN>, %arg1 : tensor<2xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op requires number of results to match inputs}} %0 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor<64xf8E4M3FN>, tensor<2xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>) return } // ----- func.func @test_reshape_block_scaled_no_inputs() -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op requires at least one input}} %0 = "tosa.reshape_block_scaled"(%s) {block_size = #tosa.block_size : i32} : (!tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>) return } // ----- func.func @test_reshape_block_scaled_too_many_inputs(%arg0 : tensor<64xf8E4M3FN>, %arg1 : tensor<2xf8E8M0FNU>, %arg2 : tensor<2xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op requires at most two inputs}} %0 = "tosa.reshape_block_scaled"(%arg0, %arg1, %arg2, %s) {block_size = #tosa.block_size : i32} : (tensor<64xf8E4M3FN>, tensor<2xf8E8M0FNU>, tensor<2xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>) return } // ----- func.func @test_reshape_block_scaled_scale_types_mismatch(%arg0 : tensor<64xf8E4M3FN>, %arg1 : tensor<2xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op expect input and output to have same element type, got 'f8E8M0FNU' and 'f8E4M3FN'}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor<64xf8E4M3FN>, tensor<2xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>, tensor<2x1xf8E4M3FN>) return } // ----- func.func @test_reshape_block_scaled_input_ranks_mismatch(%arg0 : tensor<64xf8E4M3FN>, %arg1 : tensor<2x1xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op input shapes do not have same rank}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor<64xf8E4M3FN>, tensor<2x1xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>, tensor<2x1xf8E8M0FNU>) return } // ----- func.func @test_reshape_block_scaled_scale_dims_mismatch(%arg0 : tensor<1x64xf8E4M3FN>, %arg1 : tensor<2x2xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op input shapes for data and scale do not match on dimension 0}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor<1x64xf8E4M3FN>, tensor<2x2xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>, tensor<2x1xf8E8M0FNU>) return } // ----- func.func @test_reshape_block_scaled_block_size_dim_mismatch(%arg0 : tensor<60xf8E4M3FN>, %arg1 : tensor<2xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op expect last dimension of input_data (60) to be divisible by block_size (32)}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor<60xf8E4M3FN>, tensor<2xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>, tensor<2x1xf8E8M0FNU>) return } // ----- func.func @test_reshape_block_scaled_scale_blocks_mismatch(%arg0 : tensor<64xf8E4M3FN>, %arg1 : tensor<3xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op expect last dimension of scale_data (3) to be 64/32}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor<64xf8E4M3FN>, tensor<3xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>, tensor<2x1xf8E8M0FNU>) return } // ----- func.func @test_reshape_block_scaled_new_shape_block_size_dim_mismatch(%arg0 : tensor<64xf8E4M3FN>, %arg1 : tensor<2xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<[2, 30]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op expect last dimension of new shape (30) to be divisible by block_size (32)}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor<64xf8E4M3FN>, tensor<2xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x30xf8E4M3FN>, tensor<2x1xf8E8M0FNU>) return } // ----- func.func @test_reshape_block_scaled_inconsistent_scale_output_rank(%arg0 : tensor<64xf8E4M3FN>, %arg1 : tensor<2xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op result scale does not match new shape rank}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor<64xf8E4M3FN>, tensor<2xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>, tensor<2xf8E8M0FNU>) return } // ----- func.func @test_reshape_block_scaled_inconsistent_scale(%arg0 : tensor<64xf8E4M3FN>, %arg1 : tensor<2xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op result scale shape is inconsistent with new shape}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor<64xf8E4M3FN>, tensor<2xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>, tensor<3x?xf8E8M0FNU>) return } // ----- func.func @test_reshape_block_scaled_rank0_input(%arg0 : tensor, %arg1 : tensor<2xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op requires all input shapes have a rank greater than 0}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor, tensor<2xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>, tensor<2x2xf8E8M0FNU>) return } // ----- func.func @test_reshape_block_scaled_rank0_scale_output(%arg0 : tensor<64xf8E4M3FN>, %arg1 : tensor<2xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<[2, 32]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op requires all result shapes have a rank greater than 0}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor<64xf8E4M3FN>, tensor<2xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x32xf8E4M3FN>, tensor) return } // ----- func.func @test_reshape_block_scaled_rank0_scale_input(%arg0 : tensor<64xf8E4M3FN>, %arg1 : tensor<2xf8E8M0FNU>) -> () { %s = tosa.const_shape {values = dense<> : tensor<0xindex>} : () -> !tosa.shape<0> // expected-error@+1 {{'tosa.reshape_block_scaled' op requires new shape to have a rank greater than 0}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor<64xf8E4M3FN>, tensor<2xf8E8M0FNU>, !tosa.shape<0>) -> (tensor<2x32xf8E4M3FN>, tensor<2x2xf8E8M0FNU>) return } // ----- func.func @test_reshape_non_block_scaled_block_size_mismatch(%arg0: tensor<13x21x3xf32>) -> tensor<1x819xf32> { %s = tosa.const_shape {values = dense<[1, 819]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op expect block size to be 1, got 32}} %0 = "tosa.reshape_block_scaled"(%arg0, %s) {block_size = #tosa.block_size : i32} : (tensor<13x21x3xf32>, !tosa.shape<2>) -> tensor<1x819xf32> return %0 : tensor<1x819xf32> } // ----- func.func @test_reshape_block_scaled_block_size_mismatch(%arg0: tensor<4x32xf4E2M1FN>, %arg1: tensor<4x1xf8E8M0FNU>) -> (tensor<2x64xf4E2M1FN>, tensor<2x2xf8E8M0FNU>) { %s = tosa.const_shape {values = dense<[2, 64]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.reshape_block_scaled' op expect block size to be 32, got 1}} %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size : i32} : (tensor<4x32xf4E2M1FN>, tensor<4x1xf8E8M0FNU>, !tosa.shape<2>) -> (tensor<2x64xf4E2M1FN>, tensor<2x2xf8E8M0FNU>) return %0#0, %0#1 : tensor<2x64xf4E2M1FN>, tensor<2x2xf8E8M0FNU> } // ----- func.func @test_maxpool2d_adaptive_invalid_kernel(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x2x32x8xf32> { %kernel = tosa.const_shape {values = dense<[0, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> // expected-error@+1 {{'tosa.max_pool2d_adaptive' op expect all kernel values to be >= 1, got 0, 1}} %0 = tosa.max_pool2d_adaptive %arg0, %kernel, %stride, %pad : (tensor<1x32x32x8xf32>, !tosa.shape<2>, !tosa.shape<2>, !tosa.shape<4>) -> tensor<1x2x32x8xf32> return %0 : tensor<1x2x32x8xf32> } // ----- func.func @test_maxpool2d_adaptive_unexpected_output_width(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x32x2x8xf32> { %kernel = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %stride = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> %pad = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> // expected-error@+1 {{'tosa.max_pool2d_adaptive' op calculated output width did not match expected: calculated=32, expected=2}} %0 = tosa.max_pool2d_adaptive %arg0, %kernel, %stride, %pad : (tensor<1x32x32x8xf32>, !tosa.shape<2>, !tosa.shape<2>, !tosa.shape<4>) -> tensor<1x32x2x8xf32> return %0 : tensor<1x32x2x8xf32> }