| // RUN: iree-dialects-opt -split-input-file -verify-diagnostics %s |
| |
| func @sort_invalid_dimension(%arg0: tensor<128xi32>) -> tensor<128xi32> { |
| // expected-error @+1 {{dimension must be within (0, 1]}} |
| %0 = iree_linalg_ext.sort dimension(1) |
| outs(%arg0 : tensor<128xi32>) { |
| ^bb0(%arg1: i32, %arg2: i32): // no predecessors |
| %1 = arith.cmpi sgt, %arg1, %arg2 : i32 |
| iree_linalg_ext.yield %1 : i1 |
| } -> tensor<128xi32> |
| return %0 : tensor<128xi32> |
| } |
| |
| // ----- |
| |
| func @sort_mismatch_rank(%arg0: tensor<?x?xi32>, %arg1: tensor<?xf32>) |
| -> (tensor<?x?xi32>, tensor<?xf32>) { |
| // expected-error @+1 {{expected operand 1 to be rank 2, same as other operands}} |
| %0:2 = iree_linalg_ext.sort dimension(0) |
| outs(%arg0, %arg1 : tensor<?x?xi32>, tensor<?xf32>) { |
| ^bb0(%arg2: i32, %arg3: i32, %arg4 : f32, %arg5 : f32): // no predecessors |
| %1 = arith.cmpf ogt, %arg4, %arg5 : f32 |
| iree_linalg_ext.yield %1 : i1 |
| } -> tensor<?x?xi32>, tensor<?xf32> |
| return %0#0, %0#1 : tensor<?x?xi32>, tensor<?xf32> |
| } |
| |
| // ----- |
| |
| func @sort_mismatch_shape(%arg0: tensor<?xi32>, %arg1: tensor<42xf32>) |
| -> (tensor<?xi32>, tensor<42xf32>) { |
| // expected-error @+1 {{expected operand 1 to have same shape as other operands}} |
| %0:2 = iree_linalg_ext.sort dimension(0) |
| outs(%arg0, %arg1 : tensor<?xi32>, tensor<42xf32>) { |
| ^bb0(%arg2: i32, %arg3: i32, %arg4 : f32, %arg5 : f32): // no predecessors |
| %1 = arith.cmpf ogt, %arg4, %arg5 : f32 |
| iree_linalg_ext.yield %1 : i1 |
| } -> tensor<?xi32>, tensor<42xf32> |
| return %0#0, %0#1 : tensor<?xi32>, tensor<42xf32> |
| } |
| |
| // ----- |
| |
| func @scatter_mixed_tensor_memref( |
| %update : memref<?x?xf32>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xf32>) -> tensor<?x?xf32> { |
| // expected-error @+1 {{expected inputs and outputs to be RankedTensorType or scalar}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : memref<?x?xf32>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xf32>) { |
| ^bb0(%arg1: f32, %arg2: f32): |
| %1 = arith.addf %arg1, %arg2 : f32 |
| iree_linalg_ext.yield %1 : f32 |
| } -> tensor<?x?xf32> |
| return %0 : tensor<?x?xf32> |
| } |
| |
| // ----- |
| |
| func @scatter_mixed_tensor_memref( |
| %update : tensor<?x?xf32>, %indices : memref<?x1xi32>, |
| %original : tensor<?x?xf32>) -> tensor<?x?xf32> { |
| // expected-error @+1 {{expected inputs and outputs to be RankedTensorType or scalar}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xf32>, memref<?x1xi32>) |
| outs(%original : tensor<?x?xf32>) { |
| ^bb0(%arg1: f32, %arg2: f32): |
| %1 = arith.addf %arg1, %arg2 : f32 |
| iree_linalg_ext.yield %1 : f32 |
| } -> tensor<?x?xf32> |
| return %0 : tensor<?x?xf32> |
| } |
| |
| // ----- |
| |
| func @scatter_extra_outputs( |
| %update : tensor<?x?xf32>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xf32>) -> (tensor<?x?xf32>, tensor<?x?xf32>) { |
| // expected-error @+1 {{expected number of outputs to be same as the number of results}} |
| %0, %1 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xf32>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xf32>) { |
| ^bb0(%arg1: f32, %arg2: f32): |
| %1 = arith.addf %arg1, %arg2 : f32 |
| iree_linalg_ext.yield %1 : f32 |
| } -> tensor<?x?xf32>, tensor<?x?xf32> |
| return %0, %1 : tensor<?x?xf32>, tensor<?x?xf32> |
| } |
| |
| // ----- |
| |
| func @scatter_mixed_tensor_memref( |
| %update : tensor<?x?xf32>, %indices : tensor<?x1xi32>, |
| %original : memref<?x?xf32>) -> tensor<?x?xf32> { |
| // expected-error @+1 {{expected inputs and outputs to be RankedTensorType or scalar}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xf32>, tensor<?x1xi32>) |
| outs(%original : memref<?x?xf32>) { |
| ^bb0(%arg1: f32, %arg2: f32): |
| %1 = arith.addf %arg1, %arg2 : f32 |
| iree_linalg_ext.yield %1 : f32 |
| } -> tensor<?x?xf32> |
| return %0 : tensor<?x?xf32> |
| } |
| |
| // ----- |
| |
| func @scatter_output_type_mismatch( |
| %update : tensor<?x?xf32>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xf32>) -> tensor<4x?xf32> { |
| // expected-error @+1 {{expected type of `outs` operand #0 'tensor<?x?xf32>' to be same as result type 'tensor<4x?xf32>'}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xf32>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xf32>) { |
| ^bb0(%arg1: f32, %arg2: f32): |
| %1 = arith.addf %arg1, %arg2 : f32 |
| iree_linalg_ext.yield %1 : f32 |
| } -> tensor<4x?xf32> |
| return %0 : tensor<4x?xf32> |
| } |
| |
| // ----- |
| |
| func @scatter_mixed_tensor_memref( |
| %update : memref<?x?xf32>, %indices : tensor<?x1xi32>, |
| %original : memref<?x?xf32>) { |
| // expected-error @+1 {{expected inputs and outputs to be MemRefType or scalar}} |
| iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : memref<?x?xf32>, tensor<?x1xi32>) |
| outs(%original : memref<?x?xf32>) { |
| ^bb0(%arg1: f32, %arg2: f32): |
| %1 = arith.addf %arg1, %arg2 : f32 |
| iree_linalg_ext.yield %1 : f32 |
| } |
| return |
| } |
| |
| // ----- |
| |
| func @scatter_mixed_tensor_memref( |
| %update : memref<?x?xf32>, %indices : memref<?x1xi32>, |
| %original : tensor<?x?xf32>) { |
| // expected-error @+1 {{expected inputs and outputs to be MemRefType or scalar}} |
| iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : memref<?x?xf32>, memref<?x1xi32>) |
| outs(%original : tensor<?x?xf32>) { |
| ^bb0(%arg1: f32, %arg2: f32): |
| %1 = arith.addf %arg1, %arg2 : f32 |
| iree_linalg_ext.yield %1 : f32 |
| } |
| return |
| } |
| |
| // ----- |
| |
| func @scatter_dim_mismatch( |
| %update : tensor<?x?xf32>, %indices : tensor<48x1xi32>, |
| %original : tensor<?x?xf32>) -> tensor<?x?xf32> { |
| // expected-error @+1 {{mismatch in shape of indices and update value at dim#0}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xf32>, tensor<48x1xi32>) |
| outs(%original : tensor<?x?xf32>) { |
| ^bb0(%arg1: f32, %arg2: f32): |
| %1 = arith.addf %arg1, %arg2 : f32 |
| iree_linalg_ext.yield %1 : f32 |
| } -> tensor<?x?xf32> |
| return %0 : tensor<?x?xf32> |
| } |
| |
| // ----- |
| |
| func @scatter_dim_mismatch( |
| %update : tensor<64x?xf32>, %indices : tensor<48x1xi32>, |
| %original : tensor<?x?xf32>) -> tensor<?x?xf32> { |
| // expected-error @+1 {{mismatch in shape of indices and update value at dim#0}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<64x?xf32>, tensor<48x1xi32>) |
| outs(%original : tensor<?x?xf32>) { |
| ^bb0(%arg1: f32, %arg2: f32): |
| %1 = arith.addf %arg1, %arg2 : f32 |
| iree_linalg_ext.yield %1 : f32 |
| } -> tensor<?x?xf32> |
| return %0 : tensor<?x?xf32> |
| } |
| |
| // ----- |
| |
| func @scatter_dim_mismatch( |
| %update : tensor<?x?x?x?xf32>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xf32>) -> tensor<?x?xf32> { |
| // expected-error @+1 {{op update value rank exceeds the rank of the original value}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?x?x?xf32>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xf32>) { |
| ^bb0(%arg1: f32, %arg2: f32): |
| %1 = arith.addf %arg1, %arg2 : f32 |
| iree_linalg_ext.yield %1 : f32 |
| } -> tensor<?x?xf32> |
| return %0 : tensor<?x?xf32> |
| } |
| |
| // ----- |
| |
| func @scatter_dim_mismatch( |
| %update : tensor<?x4xf32>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xf32>) -> tensor<?x?xf32> { |
| // expected-error @+1 {{mismatch in shape of update value dim#1 and original value at dim#1}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x4xf32>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xf32>) { |
| ^bb0(%arg1: f32, %arg2: f32): |
| %1 = arith.addf %arg1, %arg2 : f32 |
| iree_linalg_ext.yield %1 : f32 |
| } -> tensor<?x?xf32> |
| return %0 : tensor<?x?xf32> |
| } |
| |
| // ----- |
| |
| func @scatter_region_type_mismatch( |
| %update : tensor<?x?xi32>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xi32>) -> tensor<?x?xi32> { |
| // expected-error @+1 {{expected region to have scalar argument of integer or float types}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xi32>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xi32>) { |
| ^bb0(%arg1: index, %arg2: index): |
| %1 = arith.addi %arg1, %arg2 : index |
| %2 = arith.index_cast %1 : index to i32 |
| iree_linalg_ext.yield %2 : i32 |
| } -> tensor<?x?xi32> |
| return %0 : tensor<?x?xi32> |
| } |
| |
| // ----- |
| |
| func @scatter_region_type_mismatch( |
| %update : tensor<?x?xi32>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xi32>) -> tensor<?x?xi32> { |
| // expected-error @+1 {{mismatch in argument 0 of region 'i64' and element type of update value 'i32'}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xi32>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xi32>) { |
| ^bb0(%arg1: i64, %arg2: i32): |
| %1 = arith.trunci %arg1 : i64 to i32 |
| %2 = arith.addi %1, %arg2 : i32 |
| iree_linalg_ext.yield %2 : i32 |
| } -> tensor<?x?xi32> |
| return %0 : tensor<?x?xi32> |
| } |
| |
| // ----- |
| |
| func @scatter_region_type_mismatch( |
| %update : tensor<?x?xi32>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xi32>) -> tensor<?x?xi32> { |
| // expected-error @+1 {{mismatch in argument 1 of region 'i64' and element type of original value 'i32'}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xi32>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xi32>) { |
| ^bb0(%arg1: i32, %arg2: i64): |
| %1 = arith.trunci %arg2 : i64 to i32 |
| %2 = arith.addi %1, %arg1 : i32 |
| iree_linalg_ext.yield %2 : i32 |
| } -> tensor<?x?xi32> |
| return %0 : tensor<?x?xi32> |
| } |
| |
| // ----- |
| |
| func @scatter_region_type_mismatch( |
| %update : tensor<?x?xi32>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xi64>) -> tensor<?x?xi64> { |
| // expected-error @+1 {{mismatch in region argument types 'i32' and 'i64'}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xi32>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xi64>) { |
| ^bb0(%arg1: i32, %arg2: i64): |
| %1 = arith.extsi %arg1 : i32 to i64 |
| %2 = arith.addi %1, %arg2 : i64 |
| iree_linalg_ext.yield %2 : i64 |
| } -> tensor<?x?xi64> |
| return %0 : tensor<?x?xi64> |
| } |
| |
| // ----- |
| |
| func @scatter_region_type_mismatch( |
| %update : tensor<?x?xi64>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xi64>) -> tensor<?x?xi64> { |
| // expected-error @+1 {{expected region to have two arguments}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xi64>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xi64>) { |
| ^bb0(%arg1: i64, %arg2: i64, %arg3 : i64): |
| %1 = arith.addi %arg1, %arg2 : i64 |
| iree_linalg_ext.yield %1 : i64 |
| } -> tensor<?x?xi64> |
| return %0 : tensor<?x?xi64> |
| } |
| |
| |
| // ----- |
| |
| func @scatter_yield_mismatch( |
| %update : tensor<?x?xi64>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xi64>) -> tensor<?x?xi64> { |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xi64>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xi64>) { |
| ^bb0(%arg1: i64, %arg2: i64): |
| %1 = arith.addi %arg1, %arg2 : i64 |
| %2 = arith.trunci %1 : i64 to i32 |
| // expected-error @+1 {{mismatch in type of yielded value 'i32' and argument of the region 'i64'}} |
| iree_linalg_ext.yield %2 : i32 |
| } -> tensor<?x?xi64> |
| return %0 : tensor<?x?xi64> |
| } |
| |
| // ----- |
| |
| func @scatter_yield_mismatch( |
| %update : tensor<?x?xi64>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xi64>) -> tensor<?x?xi64> { |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xi64>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xi64>) { |
| ^bb0(%arg1: i64, %arg2: i64): |
| %1 = arith.addi %arg1, %arg2 : i64 |
| %2 = arith.trunci %1 : i64 to i32 |
| // expected-error @+1 {{expected region to yield a single value}} |
| iree_linalg_ext.yield %1, %2 : i64, i32 |
| } -> tensor<?x?xi64> |
| return %0 : tensor<?x?xi64> |
| } |
| |
| // ----- |
| |
| func @scatter_index_depth_dynamic( |
| %update : tensor<?x?xi64>, %indices : tensor<?x?xi32>, |
| %original : tensor<?x?xi64>) -> tensor<?x?xi64> { |
| // expected-error @+1 {{expected index depth is static}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?x?xi64>, tensor<?x?xi32>) |
| outs(%original : tensor<?x?xi64>) { |
| ^bb0(%arg1: i64, %arg2: i64): |
| %1 = arith.addi %arg1, %arg2 : i64 |
| %2 = arith.trunci %1 : i64 to i32 |
| iree_linalg_ext.yield %1, %2 : i64, i32 |
| } -> tensor<?x?xi64> |
| return %0 : tensor<?x?xi64> |
| } |
| |
| // ----- |
| |
| func @scatter_original_rank_mismatch( |
| %update : tensor<?xi64>, %indices : tensor<?x1xi32>, |
| %original : tensor<?x?xi64>) -> tensor<?x?xi64> { |
| // expected-error @+1 {{op index depth and update value does not cover rank of original value}} |
| %0 = iree_linalg_ext.scatter unique_indices(true) |
| ins(%update, %indices : tensor<?xi64>, tensor<?x1xi32>) |
| outs(%original : tensor<?x?xi64>) { |
| ^bb0(%arg1: i64, %arg2: i64): |
| %1 = arith.addi %arg1, %arg2 : i64 |
| %2 = arith.trunci %1 : i64 to i32 |
| iree_linalg_ext.yield %1, %2 : i64, i32 |
| } -> tensor<?x?xi64> |
| return %0 : tensor<?x?xi64> |
| } |
| |
| // ----- |
| |
| func @reverse_diff_element_type(%arg0: tensor<3x5xi32>) -> tensor<3x5xf32> { |
| %init = linalg.init_tensor [3, 5] : tensor<3x5xf32> |
| // expected-error @+1 {{expected input/output element types to be identical}} |
| %0 = iree_linalg_ext.reverse |
| dimensions(dense<0> : tensor<1xi64>) |
| ins(%arg0 : tensor<3x5xi32>) |
| outs(%init : tensor<3x5xf32>) : tensor<3x5xf32> |
| return %0 : tensor<3x5xf32> |
| } |
| |
| // ----- |
| |
| func @reverse_diff_shape(%arg0: tensor<3x5xi32>) -> tensor<3x6xi32> { |
| %init = linalg.init_tensor [3, 6] : tensor<3x6xi32> |
| // expected-error @+1 {{incompatible input/output shapes}} |
| %0 = iree_linalg_ext.reverse |
| dimensions(dense<0> : tensor<1xi64>) |
| ins(%arg0 : tensor<3x5xi32>) |
| outs(%init : tensor<3x6xi32>) : tensor<3x6xi32> |
| return %0 : tensor<3x6xi32> |
| } |
| |
| // ----- |
| |
| func @reverse_dup_dims(%arg0: tensor<3x5xi32>) -> tensor<3x5xi32> { |
| %init = linalg.init_tensor [3, 5] : tensor<3x5xi32> |
| // expected-error @+1 {{expected dimensions numbers are all unique}} |
| %0 = iree_linalg_ext.reverse |
| dimensions(dense<[0, 0]> : tensor<2xi64>) |
| ins(%arg0 : tensor<3x5xi32>) |
| outs(%init : tensor<3x5xi32>) : tensor<3x5xi32> |
| return %0 : tensor<3x5xi32> |
| } |
| |
| // ----- |
| |
| func @not_enough_results() -> () { |
| %num_threads = arith.constant 100 : index |
| // expected-error@+1 {{'iree_linalg_ext.in_parallel' op produces 1 results, but its terminator yields 0 values}} |
| %result = iree_linalg_ext.in_parallel %num_threads -> tensor<100xf32> { |
| ^bb0(%thread_idx : index): |
| iree_linalg_ext.perform_concurrently {} |
| } |
| } |
| |
| // ----- |
| |
| func @too_many_results(%1 : tensor<1xf32>, %out : tensor<100xf32>) -> () { |
| %num_threads = arith.constant 100 : index |
| // expected-error@+1 {{'iree_linalg_ext.in_parallel' op produces 1 results, but its terminator yields 2 values}} |
| %result = iree_linalg_ext.in_parallel %num_threads -> tensor<100xf32> { |
| ^bb0(%thread_idx : index): |
| %0 = arith.constant 1 : index |
| iree_linalg_ext.perform_concurrently { |
| iree_linalg_ext.parallel_insert_slice %1 into %out[%thread_idx][%0][%0] : |
| tensor<1xf32> into tensor<100xf32> |
| iree_linalg_ext.parallel_insert_slice %1 into %out[%thread_idx][%0][%0] : |
| tensor<1xf32> into tensor<100xf32> |
| } |
| } |
| } |
| |
| // ----- |
| |
| func @type_mismatch(%1 : tensor<1xf32>, %out : tensor<200xf32>) -> () { |
| %num_threads = arith.constant 100 : index |
| // expected-error@+1 {{'iree_linalg_ext.in_parallel' op type mismatch between 0th result of in_parallel ('tensor<200xf32>') and 0th result yielded by its terminator ('tensor<100xf32>')}} |
| %result = iree_linalg_ext.in_parallel %num_threads -> tensor<100xf32> { |
| ^bb0(%thread_idx : index): |
| %0 = arith.constant 1 : index |
| iree_linalg_ext.perform_concurrently { |
| iree_linalg_ext.parallel_insert_slice %1 into %out[%thread_idx][%0][%0] : |
| tensor<1xf32> into tensor<200xf32> |
| } |
| } |
| } |