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