1// RUN: mlir-opt %s -split-input-file -verify-diagnostics
2
3func.func @invalid_new_dense(%arg0: !llvm.ptr<i8>) -> tensor<32xf32> {
4  // expected-error@+1 {{'sparse_tensor.new' op result #0 must be sparse tensor of any type values, but got 'tensor<32xf32>'}}
5  %0 = sparse_tensor.new %arg0 : !llvm.ptr<i8> to tensor<32xf32>
6  return %0 : tensor<32xf32>
7}
8
9// -----
10
11func.func @invalid_pointers_dense(%arg0: tensor<128xf64>) -> memref<?xindex> {
12  %c = arith.constant 0 : index
13  // expected-error@+1 {{'sparse_tensor.pointers' op operand #0 must be sparse tensor of any type values, but got 'tensor<128xf64>'}}
14  %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf64> to memref<?xindex>
15  return %0 : memref<?xindex>
16}
17
18// -----
19
20func.func @invalid_pointers_unranked(%arg0: tensor<*xf64>) -> memref<?xindex> {
21  %c = arith.constant 0 : index
22  // expected-error@+1 {{'sparse_tensor.pointers' op operand #0 must be sparse tensor of any type values, but got 'tensor<*xf64>'}}
23  %0 = sparse_tensor.pointers %arg0, %c : tensor<*xf64> to memref<?xindex>
24  return %0 : memref<?xindex>
25}
26
27// -----
28
29#SparseVector = #sparse_tensor.encoding<{dimLevelType = ["compressed"], pointerBitWidth=32}>
30
31func.func @mismatch_pointers_types(%arg0: tensor<128xf64, #SparseVector>) -> memref<?xindex> {
32  %c = arith.constant 0 : index
33  // expected-error@+1 {{unexpected type for pointers}}
34  %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf64, #SparseVector> to memref<?xindex>
35  return %0 : memref<?xindex>
36}
37
38// -----
39
40#SparseVector = #sparse_tensor.encoding<{dimLevelType = ["compressed"]}>
41
42func.func @pointers_oob(%arg0: tensor<128xf64, #SparseVector>) -> memref<?xindex> {
43  %c = arith.constant 1 : index
44  // expected-error@+1 {{requested pointers dimension out of bounds}}
45  %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf64, #SparseVector> to memref<?xindex>
46  return %0 : memref<?xindex>
47}
48
49// -----
50
51func.func @invalid_indices_dense(%arg0: tensor<10x10xi32>) -> memref<?xindex> {
52  %c = arith.constant 1 : index
53  // expected-error@+1 {{'sparse_tensor.indices' op operand #0 must be sparse tensor of any type values, but got 'tensor<10x10xi32>'}}
54  %0 = sparse_tensor.indices %arg0, %c : tensor<10x10xi32> to memref<?xindex>
55  return %0 : memref<?xindex>
56}
57
58// -----
59
60func.func @invalid_indices_unranked(%arg0: tensor<*xf64>) -> memref<?xindex> {
61  %c = arith.constant 0 : index
62  // expected-error@+1 {{'sparse_tensor.indices' op operand #0 must be sparse tensor of any type values, but got 'tensor<*xf64>'}}
63  %0 = sparse_tensor.indices %arg0, %c : tensor<*xf64> to memref<?xindex>
64  return %0 : memref<?xindex>
65}
66
67// -----
68
69#SparseVector = #sparse_tensor.encoding<{dimLevelType = ["compressed"]}>
70
71func.func @mismatch_indices_types(%arg0: tensor<?xf64, #SparseVector>) -> memref<?xi32> {
72  %c = arith.constant 0 : index
73  // expected-error@+1 {{unexpected type for indices}}
74  %0 = sparse_tensor.indices %arg0, %c : tensor<?xf64, #SparseVector> to memref<?xi32>
75  return %0 : memref<?xi32>
76}
77
78// -----
79
80#SparseVector = #sparse_tensor.encoding<{dimLevelType = ["compressed"]}>
81
82func.func @indices_oob(%arg0: tensor<128xf64, #SparseVector>) -> memref<?xindex> {
83  %c = arith.constant 1 : index
84  // expected-error@+1 {{requested indices dimension out of bounds}}
85  %0 = sparse_tensor.indices %arg0, %c : tensor<128xf64, #SparseVector> to memref<?xindex>
86  return %0 : memref<?xindex>
87}
88
89// -----
90
91func.func @invalid_values_dense(%arg0: tensor<1024xf32>) -> memref<?xf32> {
92  // expected-error@+1 {{'sparse_tensor.values' op operand #0 must be sparse tensor of any type values, but got 'tensor<1024xf32>'}}
93  %0 = sparse_tensor.values %arg0 : tensor<1024xf32> to memref<?xf32>
94  return %0 : memref<?xf32>
95}
96
97// -----
98
99#SparseVector = #sparse_tensor.encoding<{dimLevelType = ["compressed"]}>
100
101func.func @mismatch_values_types(%arg0: tensor<?xf64, #SparseVector>) -> memref<?xf32> {
102  // expected-error@+1 {{unexpected mismatch in element types}}
103  %0 = sparse_tensor.values %arg0 : tensor<?xf64, #SparseVector> to memref<?xf32>
104  return %0 : memref<?xf32>
105}
106
107// -----
108
109func.func @sparse_unannotated_load(%arg0: tensor<16x32xf64>) -> tensor<16x32xf64> {
110  // expected-error@+1 {{'sparse_tensor.load' op operand #0 must be sparse tensor of any type values, but got 'tensor<16x32xf64>'}}
111  %0 = sparse_tensor.load %arg0 : tensor<16x32xf64>
112  return %0 : tensor<16x32xf64>
113}
114
115// -----
116
117func.func @sparse_unannotated_insert(%arg0: tensor<128xf64>, %arg1: memref<?xindex>, %arg2: f64) {
118  // expected-error@+1 {{'sparse_tensor.lex_insert' op operand #0 must be sparse tensor of any type values, but got 'tensor<128xf64>'}}
119  sparse_tensor.lex_insert %arg0, %arg1, %arg2 : tensor<128xf64>, memref<?xindex>, f64
120  return
121}
122
123// -----
124
125func.func @sparse_unannotated_expansion(%arg0: tensor<128xf64>) {
126  // expected-error@+1 {{'sparse_tensor.expand' op operand #0 must be sparse tensor of any type values, but got 'tensor<128xf64>'}}
127  %values, %filled, %added, %count = sparse_tensor.expand %arg0
128    : tensor<128xf64> to memref<?xf64>, memref<?xi1>, memref<?xindex>, index
129  return
130}
131
132// -----
133
134func.func @sparse_unannotated_compression(%arg0: tensor<128xf64>, %arg1: memref<?xindex>,
135                                     %arg2: memref<?xf64>, %arg3: memref<?xi1>,
136				     %arg4: memref<?xindex>, %arg5: index) {
137  // expected-error@+1 {{'sparse_tensor.compress' op operand #0 must be sparse tensor of any type values, but got 'tensor<128xf64>'}}
138  sparse_tensor.compress %arg0, %arg1, %arg2, %arg3, %arg4, %arg5
139    : tensor<128xf64>, memref<?xindex>, memref<?xf64>, memref<?xi1>, memref<?xindex>, index
140}
141
142// -----
143
144func.func @sparse_convert_unranked(%arg0: tensor<*xf32>) -> tensor<10xf32> {
145  // expected-error@+1 {{unexpected type in convert}}
146  %0 = sparse_tensor.convert %arg0 : tensor<*xf32> to tensor<10xf32>
147  return %0 : tensor<10xf32>
148}
149
150// -----
151
152#DCSR = #sparse_tensor.encoding<{dimLevelType = ["compressed", "compressed"]}>
153
154func.func @sparse_convert_rank_mismatch(%arg0: tensor<10x10xf64, #DCSR>) -> tensor<?xf64> {
155  // expected-error@+1 {{unexpected conversion mismatch in rank}}
156  %0 = sparse_tensor.convert %arg0 : tensor<10x10xf64, #DCSR> to tensor<?xf64>
157  return %0 : tensor<?xf64>
158}
159
160// -----
161
162#CSR = #sparse_tensor.encoding<{dimLevelType = ["dense", "compressed"]}>
163
164func.func @sparse_convert_dim_mismatch(%arg0: tensor<10x?xf32>) -> tensor<10x10xf32, #CSR> {
165  // expected-error@+1 {{unexpected conversion mismatch in dimension 1}}
166  %0 = sparse_tensor.convert %arg0 : tensor<10x?xf32> to tensor<10x10xf32, #CSR>
167  return %0 : tensor<10x10xf32, #CSR>
168}
169
170// -----
171
172func.func @invalid_out_dense(%arg0: tensor<10xf64>, %arg1: !llvm.ptr<i8>) {
173  // expected-error@+1 {{'sparse_tensor.out' op operand #0 must be sparse tensor of any type values, but got 'tensor<10xf64>'}}
174  sparse_tensor.out %arg0, %arg1 : tensor<10xf64>, !llvm.ptr<i8>
175  return
176}
177
178// -----
179
180func.func @invalid_binary_num_args_mismatch_overlap(%arg0: f64, %arg1: f64) -> f64 {
181  // expected-error@+1 {{overlap region must have exactly 2 arguments}}
182  %r = sparse_tensor.binary %arg0, %arg1 : f64, f64 to f64
183    overlap={
184      ^bb0(%x: f64):
185        sparse_tensor.yield %x : f64
186    }
187    left={}
188    right={}
189  return %r : f64
190}
191
192// -----
193
194func.func @invalid_binary_num_args_mismatch_right(%arg0: f64, %arg1: f64) -> f64 {
195  // expected-error@+1 {{right region must have exactly 1 arguments}}
196  %r = sparse_tensor.binary %arg0, %arg1 : f64, f64 to f64
197    overlap={}
198    left={}
199    right={
200      ^bb0(%x: f64, %y: f64):
201        sparse_tensor.yield %y : f64
202    }
203  return %r : f64
204}
205
206// -----
207
208func.func @invalid_binary_argtype_mismatch(%arg0: f64, %arg1: f64) -> f64 {
209  // expected-error@+1 {{overlap region argument 2 type mismatch}}
210  %r = sparse_tensor.binary %arg0, %arg1 : f64, f64 to f64
211    overlap={
212      ^bb0(%x: f64, %y: f32):
213        sparse_tensor.yield %x : f64
214    }
215    left=identity
216    right=identity
217  return %r : f64
218}
219
220// -----
221
222func.func @invalid_binary_wrong_return_type(%arg0: f64, %arg1: f64) -> f64 {
223  // expected-error@+1 {{left region yield type mismatch}}
224  %0 = sparse_tensor.binary %arg0, %arg1 : f64, f64 to f64
225    overlap={}
226    left={
227      ^bb0(%x: f64):
228        %1 = arith.constant 0.0 : f32
229        sparse_tensor.yield %1 : f32
230    }
231    right=identity
232  return %0 : f64
233}
234
235// -----
236
237func.func @invalid_binary_wrong_identity_type(%arg0: i64, %arg1: f64) -> f64 {
238  // expected-error@+1 {{left=identity requires first argument to have the same type as the output}}
239  %0 = sparse_tensor.binary %arg0, %arg1 : i64, f64 to f64
240    overlap={}
241    left=identity
242    right=identity
243  return %0 : f64
244}
245
246// -----
247
248func.func @invalid_binary_wrong_yield(%arg0: f64, %arg1: f64) -> f64 {
249  // expected-error@+1 {{left region must end with sparse_tensor.yield}}
250  %0 = sparse_tensor.binary %arg0, %arg1 : f64, f64 to f64
251    overlap={}
252    left={
253      ^bb0(%x: f64):
254        tensor.yield %x : f64
255    }
256    right=identity
257  return %0 : f64
258}
259
260// -----
261
262func.func @invalid_unary_argtype_mismatch(%arg0: f64) -> f64 {
263  // expected-error@+1 {{present region argument 1 type mismatch}}
264  %r = sparse_tensor.unary %arg0 : f64 to f64
265    present={
266      ^bb0(%x: index):
267        sparse_tensor.yield %x : index
268    }
269    absent={}
270  return %r : f64
271}
272
273// -----
274
275func.func @invalid_unary_num_args_mismatch(%arg0: f64) -> f64 {
276  // expected-error@+1 {{absent region must have exactly 0 arguments}}
277  %r = sparse_tensor.unary %arg0 : f64 to f64
278    present={}
279    absent={
280      ^bb0(%x: f64):
281        sparse_tensor.yield %x : f64
282    }
283  return %r : f64
284}
285
286// -----
287
288func.func @invalid_unary_wrong_return_type(%arg0: f64) -> f64 {
289  // expected-error@+1 {{present region yield type mismatch}}
290  %0 = sparse_tensor.unary %arg0 : f64 to f64
291    present={
292      ^bb0(%x: f64):
293        %1 = arith.constant 0.0 : f32
294        sparse_tensor.yield %1 : f32
295    }
296    absent={}
297  return %0 : f64
298}
299
300// -----
301
302func.func @invalid_unary_wrong_yield(%arg0: f64) -> f64 {
303  // expected-error@+1 {{present region must end with sparse_tensor.yield}}
304  %0 = sparse_tensor.unary %arg0 : f64 to f64
305    present={
306      ^bb0(%x: f64):
307        tensor.yield %x : f64
308    }
309    absent={}
310  return %0 : f64
311}
312
313// -----
314
315func.func @invalid_reduce_num_args_mismatch(%arg0: f64, %arg1: f64) -> f64 {
316  %cf1 = arith.constant 1.0 : f64
317  // expected-error@+1 {{reduce region must have exactly 2 arguments}}
318  %r = sparse_tensor.reduce %arg0, %arg1, %cf1 : f64 {
319      ^bb0(%x: f64):
320        sparse_tensor.yield %x : f64
321    }
322  return %r : f64
323}
324
325// -----
326
327func.func @invalid_reduce_block_arg_type_mismatch(%arg0: i64, %arg1: i64) -> i64 {
328  %ci1 = arith.constant 1 : i64
329  // expected-error@+1 {{reduce region argument 1 type mismatch}}
330  %r = sparse_tensor.reduce %arg0, %arg1, %ci1 : i64 {
331      ^bb0(%x: f64, %y: f64):
332        %cst = arith.constant 2 : i64
333        sparse_tensor.yield %cst : i64
334    }
335  return %r : i64
336}
337
338// -----
339
340func.func @invalid_reduce_return_type_mismatch(%arg0: f64, %arg1: f64) -> f64 {
341  %cf1 = arith.constant 1.0 : f64
342  // expected-error@+1 {{reduce region yield type mismatch}}
343  %r = sparse_tensor.reduce %arg0, %arg1, %cf1 : f64 {
344      ^bb0(%x: f64, %y: f64):
345        %cst = arith.constant 2 : i64
346        sparse_tensor.yield %cst : i64
347    }
348  return %r : f64
349}
350
351// -----
352
353func.func @invalid_reduce_wrong_yield(%arg0: f64, %arg1: f64) -> f64 {
354  %cf1 = arith.constant 1.0 : f64
355  // expected-error@+1 {{reduce region must end with sparse_tensor.yield}}
356  %r = sparse_tensor.reduce %arg0, %arg1, %cf1 : f64 {
357      ^bb0(%x: f64, %y: f64):
358        %cst = arith.constant 2 : i64
359        tensor.yield %cst : i64
360    }
361  return %r : f64
362}
363