blob: 517e9c2b9178a46ed26b69d3dedae8026761d7f9 [file] [log] [blame]
// 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>
}
}
}