xref: /llvm-project/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-resize.mlir (revision 4edeaffbf255137861f5153eb1a6183d956efede)
1// RUN: mlir-opt --split-input-file -pass-pipeline="builtin.module(func.func(tosa-to-linalg))" %s -o -| FileCheck %s
2
3// CHECK-LABEL: @unary_resize_nearest_fp32
4func.func @unary_resize_nearest_fp32(%arg0 : tensor<3x1x1x7xf32>) -> tensor<3x1x1x7xf32> {
5  %resize = "tosa.resize"(%arg0) {mode = "NEAREST_NEIGHBOR", scale = array<i64: 2, 2, 1, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xf32>) -> tensor<3x1x1x7xf32>
6  // CHECK: return %arg0
7  return %resize : tensor<3x1x1x7xf32>
8}
9
10// -----
11
12// CHECK-LABEL: @unary_resize_nearest_fp16
13func.func @unary_resize_nearest_fp16(%arg0 : tensor<3x1x1x7xf16>) -> tensor<3x1x1x7xf16> {
14  %resize = "tosa.resize"(%arg0) {mode = "NEAREST_NEIGHBOR", scale = array<i64: 2, 2, 1, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xf16>) -> tensor<3x1x1x7xf16>
15  // CHECK: return %arg0
16  return %resize : tensor<3x1x1x7xf16>
17}
18
19// -----
20
21// CHECK-LABEL: @unary_resize_bilinear_fp32
22func.func @unary_resize_bilinear_fp32(%arg0 : tensor<3x1x1x7xf32>) -> tensor<3x1x1x7xf32> {
23  %resize = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 2, 2, 1, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xf32>) -> tensor<3x1x1x7xf32>
24  // CHECK: return %arg0
25  return %resize : tensor<3x1x1x7xf32>
26}
27
28// -----
29
30// CHECK-LABEL: @unary_resize_bilinear_fp16
31func.func @unary_resize_bilinear_fp16(%arg0 : tensor<3x1x1x7xf16>) -> tensor<3x1x1x7xf16> {
32  %resize = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 2, 2, 1, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xf16>) -> tensor<3x1x1x7xf16>
33  // CHECK: return %arg0
34  return %resize : tensor<3x1x1x7xf16>
35}
36
37// -----
38
39// CHECK-LABEL: @unary_resize_nearest_i8
40func.func @unary_resize_nearest_i8(%arg0 : tensor<3x1x1x7xi8>) -> tensor<3x1x1x7xi8> {
41  %resize = "tosa.resize"(%arg0) {mode = "NEAREST_NEIGHBOR", scale = array<i64: 2, 1, 3, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xi8>) -> tensor<3x1x1x7xi8>
42  // CHECK: return %arg0
43  return %resize : tensor<3x1x1x7xi8>
44}
45
46// -----
47
48// CHECK-LABEL: @broadcast_resize_nearest_f32
49func.func @broadcast_resize_nearest_f32(%arg0 : tensor<3x1x1x7xf32>) -> tensor<3x1x5x7xf32> {
50  // CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape %arg0
51  // CHECK-NEXT{literal}: [[0], [1, 2, 3]] : tensor<3x1x1x7xf32> into tensor<3x7xf32>
52  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<3x1x5x7xf32>
53  // CHECK: %[[GENERIC:.+]] = linalg.generic
54  // CHECK-SAME: indexing_maps = [#map, #map1], iterator_types = ["parallel", "parallel", "parallel", "parallel"]}
55  // CHECK-SAME: ins(%[[COLLAPSE]] : tensor<3x7xf32>) outs(%[[EMPTY]] : tensor<3x1x5x7xf32>)
56  // CHECK: ^bb0(%[[IN:.+]]: f32, %[[OUT:.+]]: f32):
57  // CHECK:   linalg.yield %[[IN]] : f32
58  %resize = "tosa.resize"(%arg0) {mode = "NEAREST_NEIGHBOR", scale = array<i64: 2, 1, 3, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xf32>) -> tensor<3x1x5x7xf32>
59
60 // CHECK: return %[[GENERIC]]
61  return %resize : tensor<3x1x5x7xf32>
62}
63
64// -----
65
66// CHECK-LABEL: @broadcast_resize_bilinear_i8
67func.func @broadcast_resize_bilinear_i8(%arg0 : tensor<3x1x1x7xi8>) -> tensor<3x4x5x7xi32> {
68  // CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape %arg0
69  // CHECK-SAME{literal}: [[0], [1, 2, 3]] : tensor<3x1x1x7xi8> into tensor<3x7xi8>
70  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<3x7xi32>
71  // CHECK: %[[RESIZE:.+]] = linalg.generic
72  // CHECK-SAME: {indexing_maps = [#map, #map], iterator_types = ["parallel", "parallel"]}
73  // CHECK-SAME: ins(%[[COLLAPSE]] : tensor<3x7xi8>) outs(%[[EMPTY]] : tensor<3x7xi32>)
74  // CHECK: ^bb0(%[[IN:.+]]: i8, %[[OUT:.+]]: i32):
75  // CHECK:   %[[EXT:.+]] = arith.extsi %[[IN]] : i8 to i32
76  // CHECK-DAG:   %[[C2:.+]] = arith.constant 2 : i32
77  // CHECK:   %[[MUL:.+]] = arith.muli %[[EXT]], %[[C2]] : i32
78  // CHECK-DAG:   %[[C3:.+]] = arith.constant 3 : i32
79  // CHECK:   %[[OUT:.+]] = arith.muli %[[MUL]], %[[C3]] : i32
80  // CHECK:   linalg.yield %[[OUT]] : i32
81  // CHECK: } -> tensor<3x7xi32>
82  // CHECK: %[[EXPAND:.+]] = tensor.expand_shape %1
83  // CHECK-SAME{literal}: [[0], [1, 2, 3]] : tensor<3x7xi32> into tensor<3x1x1x7xi32>
84  // CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape %expanded
85  // CHECK-SAME{literal}:[[0], [1, 2, 3]] : tensor<3x1x1x7xi32> into tensor<3x7xi32>
86  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<3x4x5x7xi32>
87  // CHECK: %[[BROADCAST:.+]] = linalg.generic
88  // CHECK-SAME: indexing_maps = [#map1, #map2], iterator_types = ["parallel", "parallel", "parallel", "parallel"]}
89  // CHECK-SAME: ins(%[[COLLAPSE]] : tensor<3x7xi32>) outs(%[[EMPTY]] : tensor<3x4x5x7xi32>) {
90  // CHECK: ^bb0(%[[IN:.+]]: i32, %[[OUT:.+]]: i32):
91  // CHECK:   linalg.yield %[[IN]] : i32
92  %resize = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 2, 1, 3, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xi8>) -> tensor<3x4x5x7xi32>
93
94  // CHECK: return %[[BROADCAST]]
95  return %resize : tensor<3x4x5x7xi32>
96}
97
98// -----
99
100// CHECK-LABEL: @unary_resize_bilinear_i32
101func.func @unary_resize_bilinear_i32(%arg0 : tensor<3x1x1x7xi8>) -> tensor<3x1x1x7xi32> {
102  // CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape %arg0
103  // CHECK-SAME{literal}: [[0], [1, 2, 3]] : tensor<3x1x1x7xi8> into tensor<3x7xi8>
104  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<3x7xi32>
105  // CHECK: %[[GENERIC:.+]] = linalg.generic
106  // CHECK-SAME: indexing_maps = [#map, #map]
107  // CHECK-SAME: iterator_types = ["parallel", "parallel"]}
108  // CHECK-SAME: ins(%[[COLLAPSE]] : tensor<3x7xi8>) outs(%[[EMPTY]] : tensor<3x7xi32>) {
109  // CHECK: ^bb0(%[[IN:.+]]: i8, %[[OUT:.+]]: i32):
110  // CHECK:   %[[EXT:.+]] = arith.extsi %[[IN]] : i8 to i32
111  // CHECK-DAG:   %[[C2:.+]] = arith.constant 2 : i32
112  // CHECK:   %[[MUL0:.+]] = arith.muli %[[EXT]], %[[C2]] : i32
113  // CHECK-DAG:   %[[C1:.+]] = arith.constant 2 : i32
114  // CHECK:   %4 = arith.muli %3, %[[C1]] : i32
115  // CHECK:   linalg.yield %4 : i32
116  // CHECK: } -> tensor<3x7xi32>
117  // CHECK: %[[EXPAND:.+]] = tensor.expand_shape %[[GENERIC:.+]]
118  // CHECK-SAME{literal} [[0], [1, 2, 3]] : tensor<3x7xi32> into tensor<3x1x1x7xi32>
119  %resize = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 2, 1, 2, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xi8>) -> tensor<3x1x1x7xi32>
120
121  // CHECK: return %[[EXPAND]]
122  return %resize : tensor<3x1x1x7xi32>
123}
124
125// -----
126
127// CHECK-LABEL:  @resize_nearest_int
128func.func @resize_nearest_int(%arg0: tensor<1x15x13x1xi8>) -> () {
129  // CHECK: %[[INIT:.+]] = tensor.empty() : tensor<1x23x179x1xi8>
130  // CHECK: %[[GENERIC:.+]] = linalg.generic
131  // CHECK: %[[IDX_0:.+]] = linalg.index 0
132  // CHECK: %[[IDX_1:.+]] = linalg.index 1
133  // CHECK: %[[IDX_2:.+]] = linalg.index 2
134  // CHECK: %[[IDX_3:.+]] = linalg.index 3
135  // CHECK-DAG: %[[ZERO:.+]] = arith.constant 0
136  // CHECK-DAG: %[[Y_MAX:.+]] = arith.constant 14
137  // CHECK-DAG: %[[X_MAX:.+]] = arith.constant 12
138
139  // CHECK: %[[Y:.+]] = arith.index_cast %[[IDX_1]]
140  // CHECK: %[[X:.+]] = arith.index_cast %[[IDX_2]]
141  // CHECK-DAG: %[[SCALE_Y_N:.*]] = arith.constant 11
142  // CHECK-DAG: %[[SCALE_Y_D:.*]] = arith.constant 7
143  // CHECK-DAG: %[[SCALE_X_N:.*]] = arith.constant 89
144  // CHECK-DAG: %[[SCALE_X_D:.*]] = arith.constant 6
145  // CHECK-DAG: %[[OFFSET_Y:.*]] = arith.constant 0
146  // CHECK-DAG: %[[OFFSET_X:.*]] = arith.constant 0
147  // CHECK-DAG: %[[BORDER_Y:.*]] = arith.constant 0
148  // CHECK-DAG: %[[BORDER_X:.*]] = arith.constant 0
149
150  // find the remainder and integer component of the target index.
151
152  // CHECK: %[[TEMP_Y:.*]] = arith.muli %[[Y]], %[[SCALE_Y_D]]
153  // CHECK: %[[Y:.*]] = arith.addi %[[TEMP_Y]], %[[OFFSET_Y]]
154  // CHECK: %[[I_Y:.*]] = arith.divsi %[[Y]], %[[SCALE_Y_N]]
155  // CHECK: %[[TEMP_Y:.*]] = arith.muli %[[I_Y]], %[[SCALE_Y_N]]
156  // CHECK: %[[D_Y:.*]] = arith.subi %[[Y]], %[[TEMP_Y]]
157
158  // CHECK: %[[TEMP_X:.*]] = arith.muli %[[X]], %[[SCALE_X_D]]
159  // CHECK: %[[X:.*]] = arith.addi %[[TEMP_X]], %[[OFFSET_X]]
160  // CHECK: %[[I_X:.*]] = arith.divsi %[[X]], %[[SCALE_X_N]]
161  // CHECK: %[[TEMP_X:.*]] = arith.muli %[[I_X]], %[[SCALE_X_N]]
162  // CHECK: %[[D_X:.*]] = arith.subi %[[X]], %[[TEMP_X]]
163
164  // Compute the offset and bound for the Y position.
165  // CHECK-DAG: %[[ONE:.*]] = arith.constant 1
166  // CHECK: %[[D_Y_DOUBLE:.*]] = arith.shli %[[D_Y]], %[[ONE]]
167  // CHECK: %[[PRED_Y:.*]] = arith.cmpi sge, %[[D_Y_DOUBLE]], %[[SCALE_Y_N]]
168  // CHECK: %[[VAL_37:.*]] = arith.select %[[PRED_Y]], %[[ONE]], %[[ZERO]]
169  // CHECK: %[[VAL_39:.*]] = arith.addi %[[I_Y]], %[[VAL_37]]
170  // CHECK: %[[LOWER:.*]] = arith.maxsi %[[ZERO]], %[[VAL_39]]
171  // CHECK: %[[CLAMPED:.*]] = arith.minsi %[[Y_MAX]], %[[LOWER]]
172  // CHECK: %[[IDY:.+]] = arith.index_cast %[[CLAMPED]]
173
174  // Compute the offset and bound for the X position.
175  // CHECK: %[[D_X_DOUBLE:.*]] = arith.shli %[[D_X]], %[[ONE]]
176  // CHECK: %[[PRED_X:.*]] = arith.cmpi sge, %[[D_X_DOUBLE]], %[[SCALE_X_N]]
177  // CHECK: %[[VAL_38:.*]] = arith.select %[[PRED_X]], %[[ONE]], %[[ZERO]]
178  // CHECK: %[[VAL_40:.*]] = arith.addi %[[I_X]], %[[VAL_38]]
179  // CHECK: %[[LOWER:.*]] = arith.maxsi %[[ZERO]], %[[VAL_40]]
180  // CHECK: %[[CLAMPED:.*]] = arith.minsi %[[X_MAX]], %[[LOWER]]
181  // CHECK: %[[IDX:.+]] = arith.index_cast %[[CLAMPED]]
182
183  // CHECK: %[[EXTRACT:.+]] = tensor.extract %arg0[%[[IDX_0]], %[[IDY]], %[[IDX]], %[[IDX_3]]]
184  // CHECK: linalg.yield %[[EXTRACT]]
185
186  // Round to the nearest index.
187  %0 = "tosa.resize"(%arg0) {mode = "NEAREST_NEIGHBOR", scale = array<i64: 11, 7, 89, 6>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x15x13x1xi8>) -> tensor<1x23x179x1xi8>
188  return
189}
190
191// -----
192
193// CHECK-LABEL:  @resize_bilinear_int
194// CHECK-SAME: (%[[ARG0:[0-9a-zA-Z_]*]]:
195func.func @resize_bilinear_int(%arg0: tensor<1x19x20x1xi8>) {
196  // CHECK: %[[INIT:.+]] = tensor.empty() : tensor<1x304x320x1xi48>
197  // CHECK: %[[GENERIC:.+]] = linalg.generic
198  // CHECK: %[[IDX_0:.+]] = linalg.index 0
199  // CHECK: %[[IDX_1:.+]] = linalg.index 1
200  // CHECK: %[[IDX_2:.+]] = linalg.index 2
201  // CHECK: %[[IDX_3:.+]] = linalg.index 3
202  // CHECK-DAG: %[[ZERO:.+]] = arith.constant 0
203  // CHECK-DAG: %[[Y_MAX:.+]] = arith.constant 18
204  // CHECK-DAG: %[[X_MAX:.+]] = arith.constant 19
205  // CHECK: %[[Y:.+]] = arith.index_cast %[[IDX_1]]
206  // CHECK: %[[X:.+]] = arith.index_cast %[[IDX_2]]
207  // CHECK-DAG: %[[SCALE_Y_N:.*]] = arith.constant 16
208  // CHECK-DAG: %[[SCALE_Y_D:.*]] = arith.constant 1
209  // CHECK-DAG: %[[SCALE_X_N:.*]] = arith.constant 16
210  // CHECK-DAG: %[[SCALE_X_D:.*]] = arith.constant 1
211  // CHECK-DAG: %[[OFFSET_Y:.*]] = arith.constant 0
212  // CHECK-DAG: %[[OFFSET_X:.*]] = arith.constant 0
213  // CHECK-DAG: %[[BORDER_Y:.*]] = arith.constant 0
214  // CHECK-DAG: %[[BORDER_X:.*]] = arith.constant 0
215
216  // CHECK: %[[TEMP_Y:.*]] = arith.muli %[[Y]], %[[SCALE_Y_D]]
217  // CHECK: %[[Y:.*]] = arith.addi %[[TEMP_Y]], %[[OFFSET_Y]]
218  // CHECK: %[[I_Y:.*]] = arith.divsi %[[Y]], %[[SCALE_Y_N]]
219  // CHECK: %[[TEMP_Y:.*]] = arith.muli %[[I_Y]], %[[SCALE_Y_N]]
220  // CHECK: %[[D_Y:.*]] = arith.subi %[[Y]], %[[TEMP_Y]]
221
222  // CHECK: %[[TEMP_X:.*]] = arith.muli %[[X]], %[[SCALE_X_D]]
223  // CHECK: %[[X:.*]] = arith.addi %[[TEMP_X]], %[[OFFSET_X]]
224  // CHECK: %[[I_X:.*]] = arith.divsi %[[X]], %[[SCALE_X_N]]
225  // CHECK: %[[TEMP_X:.*]] = arith.muli %[[I_X]], %[[SCALE_X_N]]
226  // CHECK: %[[D_X:.*]] = arith.subi %[[X]], %[[TEMP_X]]
227
228  // Compute the left, right, and top indices for the bilinear interpolation.
229
230  // CHECK-DAG: %[[ONE:.*]] = arith.constant 1
231  // CHECK: %[[Y1:.*]] = arith.addi %[[I_Y]], %[[ONE]]
232
233  // Bound check each dimension.
234
235  // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[I_Y]]
236  // CHECK: %[[YLO:.*]] = arith.minsi %[[Y_MAX]], %[[BOUND]]
237
238  // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[Y1]]
239  // CHECK: %[[YHI:.*]] = arith.minsi %[[Y_MAX]], %[[BOUND]]
240
241  // CHECK: %[[YLOI:.+]] = arith.index_cast %[[YLO]]
242  // CHECK: %[[YHII:.+]] = arith.index_cast %[[YHI]]
243
244  // CHECK: %[[X1:.*]] = arith.addi %[[I_X]], %[[ONE]]
245  // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[I_X]]
246  // CHECK: %[[XLO:.*]] = arith.minsi %[[X_MAX]], %[[BOUND]]
247
248  // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[X1]]
249  // CHECK: %[[XHI:.*]] = arith.minsi %[[X_MAX]], %[[BOUND]]
250
251  // CHECK: %[[XLOI:.+]] = arith.index_cast %[[XLO]]
252  // CHECK: %[[XHII:.+]] = arith.index_cast %[[XHI]]
253
254  // Extract each corner of the bilinear interpolation.
255
256  // CHECK: %[[LOLO:.+]] = tensor.extract %[[ARG0]][%[[IDX_0]], %[[YLOI]], %[[XLOI]], %[[IDX_3]]]
257  // CHECK: %[[LOHI:.+]] = tensor.extract %[[ARG0]][%[[IDX_0]], %[[YLOI]], %[[XHII]], %[[IDX_3]]]
258  // CHECK: %[[HILO:.+]] = tensor.extract %[[ARG0]][%[[IDX_0]], %[[YHII]], %[[XLOI]], %[[IDX_3]]]
259  // CHECK: %[[HIHI:.+]] = tensor.extract %[[ARG0]][%[[IDX_0]], %[[YHII]], %[[XHII]], %[[IDX_3]]]
260
261  // CHECK: %[[XLOLO:.+]] = arith.extsi %[[LOLO]]
262  // CHECK: %[[XLOHI:.+]] = arith.extsi %[[LOHI]]
263  // CHECK: %[[XHILO:.+]] = arith.extsi %[[HILO]]
264  // CHECK: %[[XHIHI:.+]] = arith.extsi %[[HIHI]]
265
266  // CHECK-NEXT: %[[D_X_EXT:.+]] = arith.extsi %[[D_X]]
267  // CHECK-NEXT: %[[D_Y_EXT:.+]] = arith.extsi %[[D_Y]]
268  // CHECK-NEXT: %[[Y_N_EXT:.+]] = arith.extsi %[[SCALE_Y_N]]
269  // CHECK-NEXT: %[[X_N_EXT:.+]] = arith.extsi %[[SCALE_X_N]]
270
271  // Compute the bilinear interpolation.
272
273  // CHECK: %[[NDX:.+]] = arith.subi %[[X_N_EXT]], %[[D_X_EXT]]
274  // CHECK: %[[WLOLO:.+]] = arith.muli %[[XLOLO]], %[[NDX]]
275  // CHECK: %[[WLOHI:.+]] = arith.muli %[[XLOHI]], %[[D_X_EXT]]
276  // CHECK: %[[LO:.+]] = arith.addi %[[WLOLO]], %[[WLOHI]]
277  // CHECK: %[[NDX:.+]] = arith.subi %[[X_N_EXT]], %[[D_X_EXT]]
278  // CHECK: %[[WHILO:.+]] = arith.muli %[[XHILO]], %[[NDX]]
279  // CHECK: %[[WHIHI:.+]] = arith.muli %[[XHIHI]], %[[D_X_EXT]]
280  // CHECK: %[[HI:.+]] = arith.addi %[[WHILO]], %[[WHIHI]]
281  // CHECK: %[[NDY:.+]] = arith.subi %[[Y_N_EXT]], %[[D_Y_EXT]]
282  // CHECK: %[[WLO:.+]] = arith.muli %[[LO]], %[[NDY]]
283  // CHECK: %[[WHI:.+]] = arith.muli %[[HI]], %[[D_Y_EXT]]
284  // CHECK: %[[RESULT:.+]] = arith.addi %[[WLO]], %[[WHI]]
285  // CHECK: linalg.yield %[[RESULT]]
286
287  // Round to the nearest index.
288  %0 = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 16, 1, 16, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x19x20x1xi8>) -> tensor<1x304x320x1xi48>
289  return
290}
291
292// -----
293
294// CHECK-LABEL: @resize_nearest_fp32
295func.func @resize_nearest_fp32(%input: tensor<1x50x48x1xf32>) -> () {
296  // CHECK: %[[INIT:.+]] = tensor.empty() : tensor<1x1600x1536x1xf32>
297  // CHECK: %[[GENERIC:.+]] = linalg.generic
298  // CHECK: %[[IDX0:.+]] = linalg.index 0
299  // CHECK: %[[IDX1:.+]] = linalg.index 1
300  // CHECK: %[[IDX2:.+]] = linalg.index 2
301  // CHECK: %[[IDX3:.+]] = linalg.index 3
302  // CHECK-DAG: %[[ZERO:.*]] = arith.constant 0
303  // CHECK-DAG: %[[YMAX:.*]] = arith.constant 49
304  // CHECK-DAG: %[[XMAX:.*]] = arith.constant 47
305  // CHECK: %[[Y:.+]] = arith.index_cast %[[IDX1]]
306  // CHECK: %[[X:.+]] = arith.index_cast %[[IDX2]]
307  // CHECK-DAG: %[[SCALE_Y_N:.*]] = arith.constant 64
308  // CHECK-DAG: %[[SCALE_Y_D:.*]] = arith.constant 2
309  // CHECK-DAG: %[[SCALE_X_N:.*]] = arith.constant 64
310  // CHECK-DAG: %[[SCALE_X_D:.*]] = arith.constant 2
311  // CHECK-DAG: %[[OFFSET_Y:.*]] = arith.constant -31
312  // CHECK-DAG: %[[OFFSET_X:.*]] = arith.constant -31
313  // CHECK-DAG: %[[BORDER_Y:.*]] = arith.constant 31
314  // CHECK-DAG: %[[BORDER_X:.*]] = arith.constant 31
315
316  // CHECK: %[[VAL_29:.*]] = arith.muli %[[Y]], %[[SCALE_Y_D]]
317  // CHECK: %[[Y_TEMP:.*]] = arith.addi %[[VAL_29]], %[[OFFSET_Y]]
318  // CHECK: %[[IY_TEMP:.*]] = arith.floordivsi %[[Y_TEMP]], %[[SCALE_Y_N]]
319  // CHECK: %[[RY:.*]] = arith.remsi %[[Y_TEMP]], %[[SCALE_Y_N]]
320  // CHECK: %[[RY_FP:.*]] = arith.sitofp %[[RY]]
321  // CHECK: %[[SCALE_Y_N_FP:.*]] = arith.uitofp %[[SCALE_Y_N]]
322  // CHECK: %[[D_Y:.*]] = arith.divf %[[RY_FP]], %[[SCALE_Y_N_FP]]
323
324  // CHECK: %[[VAL_30:.*]] = arith.muli %[[X]], %[[SCALE_X_D]]
325  // CHECK: %[[X_TEMP:.*]] = arith.addi %[[VAL_30]], %[[OFFSET_X]]
326  // CHECK: %[[IX_TEMP:.*]] = arith.floordivsi %[[X_TEMP]], %[[SCALE_X_N]]
327  // CHECK: %[[RX:.*]] = arith.remsi %[[X_TEMP]], %[[SCALE_X_N]]
328  // CHECK: %[[RX_FP:.*]] = arith.sitofp %[[RX]]
329  // CHECK: %[[SCALE_X_N_FP:.*]] = arith.uitofp %[[SCALE_X_N]]
330  // CHECK: %[[D_X:.*]] = arith.divf %[[RX_FP]], %[[SCALE_X_N_FP]]
331
332  // CHECK-DAG: %[[ONE:.*]] = arith.constant 1
333  // CHECK-DAG: %[[HALF:.*]] = arith.constant 5.000000e-01
334  // CHECK: %[[PRED_Y:.*]] = arith.cmpf oge, %[[D_Y]], %[[HALF]]
335  // CHECK: %[[ROUND_Y:.*]] = arith.select %[[PRED_Y]], %[[ONE]], %[[ZERO]]
336  // CHECK: %[[VAL_48:.*]] = arith.addi %[[IY_TEMP]], %[[ROUND_Y]]
337  // CHECK: %[[LOWER:.*]] = arith.maxsi %[[ZERO]], %[[VAL_48]]
338  // CHECK: %[[CLAMPED:.*]] = arith.minsi %[[YMAX]], %[[LOWER]]
339  // CHECK: %[[IDY:.*]] = arith.index_cast %[[CLAMPED]]
340
341  // CHECK-DAG: %[[HALF:.*]] = arith.constant 5.000000e-01
342  // CHECK: %[[PRED_X:.*]] = arith.cmpf oge, %[[D_X]], %[[HALF]]
343  // CHECK: %[[ROUND_X:.*]] = arith.select %[[PRED_X]], %[[ONE]], %[[ZERO]]
344  // CHECK: %[[VAL_49:.*]] = arith.addi %[[IX_TEMP]], %[[ROUND_X]]
345  // CHECK: %[[LOWER:.*]] = arith.maxsi %[[ZERO]], %[[VAL_49]]
346  // CHECK: %[[CLAMPED:.*]] = arith.minsi %[[XMAX]], %[[LOWER]]
347  // CHECK: %[[IDX:.*]] = arith.index_cast %[[CLAMPED]]
348
349  // CHECK: %[[EXTRACT:.+]] = tensor.extract %arg0[%[[IDX0]], %[[IDY]], %[[IDX]], %[[IDX3]]]
350  // CHECK: linalg.yield %[[EXTRACT]]
351
352  %output = "tosa.resize"(%input) {mode = "NEAREST_NEIGHBOR", scale = array<i64: 64, 2, 64, 2>, offset = array<i64: -31, -31>, border = array<i64: 31, 31>} : (tensor<1x50x48x1xf32>) -> tensor<1x1600x1536x1xf32>
353  return
354}
355
356// -----
357
358// CHECK-LABEL: @resize_bilinear_fp
359func.func @resize_bilinear_fp(%input: tensor<1x23x24x1xf32>) -> () {
360  // CHECK: %[[INIT:.+]] = tensor.empty() : tensor<1x92x96x1xf32>
361  // CHECK: %[[GENERIC:.+]] = linalg.generic
362  // CHECK: %[[IDX_0:.+]] = linalg.index 0
363  // CHECK: %[[IDX_1:.+]] = linalg.index 1
364  // CHECK: %[[IDX_2:.+]] = linalg.index 2
365  // CHECK: %[[IDX_3:.+]] = linalg.index 3
366  // CHECK-DAG: %[[ZERO:.*]] = arith.constant 0
367  // CHECK-DAG: %[[Y_MAX:.*]] = arith.constant 22
368  // CHECK-DAG: %[[X_MAX:.*]] = arith.constant 23
369  // CHECK: %[[Y:.+]] = arith.index_cast %[[IDX_1]]
370  // CHECK: %[[X:.+]] = arith.index_cast %[[IDX_2]]
371  // CHECK-DAG: %[[SCALE_Y_N:.*]] = arith.constant 4
372  // CHECK-DAG: %[[SCALE_Y_D:.*]] = arith.constant 1
373  // CHECK-DAG: %[[SCALE_X_N:.*]] = arith.constant 4
374  // CHECK-DAG: %[[SCALE_X_D:.*]] = arith.constant 1
375  // CHECK-DAG: %[[OFFSET_Y:.*]] = arith.constant 0
376  // CHECK-DAG: %[[OFFSET_X:.*]] = arith.constant 0
377  // CHECK-DAG: %[[BORDER_Y:.*]] = arith.constant 0
378  // CHECK-DAG: %[[BORDER_X:.*]] = arith.constant 0
379
380  // CHECK: %[[VAL_29:.*]] = arith.muli %[[Y]], %[[SCALE_Y_D]]
381  // CHECK: %[[Y_TEMP:.*]] = arith.addi %[[VAL_29]], %[[OFFSET_Y]]
382  // CHECK: %[[I_Y:.*]] = arith.floordivsi %[[Y_TEMP]], %[[SCALE_Y_N]]
383  // CHECK: %[[RY:.*]] = arith.remsi %[[Y_TEMP]], %[[SCALE_Y_N]]
384  // CHECK: %[[RY_FP:.*]] = arith.sitofp %[[RY]]
385  // CHECK: %[[SCALE_Y_N_FP:.*]] = arith.uitofp %[[SCALE_Y_N]]
386  // CHECK: %[[D_Y:.*]] = arith.divf %[[RY_FP]], %[[SCALE_Y_N_FP]]
387
388  // CHECK: %[[VAL_30:.*]] = arith.muli %[[X]], %[[SCALE_X_D]]
389  // CHECK: %[[X_TEMP:.*]] = arith.addi %[[VAL_30]], %[[OFFSET_X]]
390  // CHECK: %[[I_X:.*]] = arith.floordivsi %[[X_TEMP]], %[[SCALE_X_N]]
391  // CHECK: %[[RX:.*]] = arith.remsi %[[X_TEMP]], %[[SCALE_X_N]]
392  // CHECK: %[[RX_FP:.*]] = arith.sitofp %[[RX]]
393  // CHECK: %[[SCALE_X_N_FP:.*]] = arith.uitofp %[[SCALE_X_N]]
394  // CHECK: %[[D_X:.*]] = arith.divf %[[RX_FP]], %[[SCALE_X_N_FP]]
395
396  // Compute the left, right, and top indices for the bilinear interpolation.
397
398  // CHECK: %[[ONE:.*]] = arith.constant 1
399
400  // Bound check each dimension.
401
402  // CHECK: %[[Y1:.*]] = arith.addi %[[I_Y]], %[[ONE]]
403
404  // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[I_Y]]
405  // CHECK: %[[YLO:.*]] = arith.minsi %[[Y_MAX]], %[[BOUND]]
406
407  // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[Y1]]
408  // CHECK: %[[YHI:.*]] = arith.minsi %[[Y_MAX]], %[[BOUND]]
409
410  // CHECK: %[[YLOI:.+]] = arith.index_cast %[[YLO]]
411  // CHECK: %[[YHII:.+]] = arith.index_cast %[[YHI]]
412
413  // CHECK: %[[X1:.*]] = arith.addi %[[I_X]], %[[ONE]]
414  // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[I_X]]
415  // CHECK: %[[XLO:.*]] = arith.minsi %[[X_MAX]], %[[BOUND]]
416
417  // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[X1]]
418  // CHECK: %[[XHI:.*]] = arith.minsi %[[X_MAX]], %[[BOUND]]
419
420  // CHECK: %[[XLOI:.+]] = arith.index_cast %[[XLO]]
421  // CHECK: %[[XHII:.+]] = arith.index_cast %[[XHI]]
422
423  // CHECK: %[[LOLO:.+]] = tensor.extract %arg0[%[[IDX_0]], %[[YLOI]], %[[XLOI]], %[[IDX_3]]]
424  // CHECK: %[[LOHI:.+]] = tensor.extract %arg0[%[[IDX_0]], %[[YLOI]], %[[XHII]], %[[IDX_3]]]
425  // CHECK: %[[HILO:.+]] = tensor.extract %arg0[%[[IDX_0]], %[[YHII]], %[[XLOI]], %[[IDX_3]]]
426  // CHECK: %[[HIHI:.+]] = tensor.extract %arg0[%[[IDX_0]], %[[YHII]], %[[XHII]], %[[IDX_3]]]
427
428  // CHECK-DAG: %[[ONE:.+]] = arith.constant 1.000000e+00 : f32
429  // CHECK: %[[NDX:.+]] = arith.subf %[[ONE]], %[[D_X]]
430  // CHECK: %[[WLOLO:.+]] = arith.mulf %[[LOLO]], %[[NDX]]
431  // CHECK: %[[WLOHI:.+]] = arith.mulf %[[LOHI]], %[[D_X]]
432  // CHECK: %[[LO:.+]] = arith.addf %[[WLOLO]], %[[WLOHI]]
433  // CHECK: %[[NDX:.+]] = arith.subf %[[ONE]], %[[D_X]]
434  // CHECK: %[[WHILO:.+]] = arith.mulf %[[HILO]], %[[NDX]]
435  // CHECK: %[[WHIHI:.+]] = arith.mulf %[[HIHI]], %[[D_X]]
436  // CHECK: %[[HI:.+]] = arith.addf %[[WHILO]], %[[WHIHI]]
437  // CHECK: %[[NDY:.+]] = arith.subf %[[ONE]], %[[D_Y]]
438  // CHECK: %[[WLO:.+]] = arith.mulf %[[LO]], %[[NDY]]
439  // CHECK: %[[WHI:.+]] = arith.mulf %[[HI]], %[[D_Y]]
440  // CHECK: %[[RESULT:.+]] = arith.addf %[[WLO]], %[[WHI]]
441  // CHECK: linalg.yield %[[RESULT]]
442
443  // Round by bilinear interpolation
444  %output = "tosa.resize"(%input) {mode = "BILINEAR", scale = array<i64: 4, 1, 4, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x23x24x1xf32>) -> tensor<1x92x96x1xf32>
445
446  return
447}
448
449// -----
450
451// CHECK-LABEL: @resize_dyn
452// CHECK-SAME: (%[[ARG0:[0-9a-zA-Z_]*]]:
453func.func @resize_dyn(%input: tensor<?x2x2x1xi8>) -> () {
454  // CHECK-DAG: %[[C0:.+]] = arith.constant 0
455  // CHECK: %[[BATCH:.+]] = tensor.dim %arg0, %[[C0]]
456  // CHECK: %[[INIT:.+]] = tensor.empty(%[[BATCH]]) : tensor<?x4x4x1xi32>
457  // CHECK: %[[GENERIC:.+]] = linalg.generic
458  %output = "tosa.resize"(%input) { scale = array<i64: 4, 2, 4, 2>, offset = array<i64: -1, -1>, border = array<i64: 1, 1>, mode = "BILINEAR" } : (tensor<?x2x2x1xi8>)  -> (tensor<?x4x4x1xi32>)
459  return
460}
461
462// -----
463
464// CHECK-LABEL: @resize_bilinear_int48
465func.func @resize_bilinear_int48(%arg0: tensor<1x19x19x1xi16>) {
466  %0 = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 16, 1, 16, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x19x19x1xi16>) -> tensor<1x289x289x1xi48>
467           return
468}
469
470// -----
471
472// CHECK-LABEL: skip_interpolate_bilinear_i8
473func.func @skip_interpolate_bilinear_i8(%arg0 : tensor<3x1x2x7xi8>) -> tensor<3x1x5x7xi32> {
474  // CHECK:  %[[GENERIC:.+]] = linalg.generic
475  // CHECK:    %[[BATCH:.+]] = linalg.index 0
476  // CHECK:    %[[CHANNEL:.+]] = linalg.index 3
477  // CHECK-DAG:    %[[C3:.+]] = arith.constant 3
478  // CHECK-DAG:    %[[C2:.+]] = arith.constant 2
479  // CHECK:    %[[EXTRACT0:.+]] = tensor.extract %arg0[%[[BATCH]], %{{.+}}, %{{.+}}, %[[CHANNEL]]] : tensor<3x1x2x7xi8>
480  // CHECK:    %[[EXTRACT1:.+]] = tensor.extract %arg0[%[[BATCH]], %{{.+}}, %{{.+}}, %[[CHANNEL]]] : tensor<3x1x2x7xi8>
481  // CHECK:    %[[EXT0:.+]] = arith.extsi %[[EXTRACT0]] : i8 to i32
482  // CHECK:    %[[EXT1:.+]] = arith.extsi %[[EXTRACT1]] : i8 to i32
483  // CHECK:    %[[SUB:.+]] = arith.subi %[[C3]], %[[DX:.+]]
484  // CHECK:    %[[MUL0:.+]] = arith.muli %[[EXT0]], %[[SUB]]
485  // CHECK:    %[[MUL1:.+]] = arith.muli %[[EXT1]], %[[DX]]
486  // CHECK:    %[[ADD:.+]] = arith.addi %[[MUL0]], %[[MUL1]]
487  // CHECK:    %[[RES:.+]] = arith.muli %[[ADD]], %[[C2]]
488  // CHECK:    linalg.yield %[[RES]]
489  %resize = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 2, 1, 3, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x2x7xi8>) -> tensor<3x1x5x7xi32>
490
491  // CHECK:  return %[[GENERIC]]
492  return %resize : tensor<3x1x5x7xi32>
493}
494
495// CHECK-LABEL: skip_interpolate_bilinear_f32
496func.func @skip_interpolate_bilinear_f32(%arg0 : tensor<3x1x2x7xf32>) -> tensor<3x1x5x7xf32> {
497  // CHECK:  %[[GENERIC:.+]] = linalg.generic
498  // CHECK:    %[[BATCH:.+]] = linalg.index 0 : index
499  // CHECK:    %[[CHANNEL:.+]] = linalg.index 3 : index
500  // CHECK:    %[[EXTRACT0:.+]] = tensor.extract %arg0[%[[BATCH]], %{{.+}}, %{{.+}}, %[[CHANNEL]]] : tensor<3x1x2x7xf32>
501  // CHECK:    %[[EXTRACT1:.+]] = tensor.extract %arg0[%[[BATCH]], %{{.+}}, %{{.+}}, %[[CHANNEL]]] : tensor<3x1x2x7xf32>
502  // CHECK:    %[[C1:.+]] = arith.constant 1.000000e+00
503  // CHECK:    %[[SUB:.+]] = arith.subf %[[C1]], %[[DX:.+]]
504  // CHECK:    %[[MUL0:.+]] = arith.mulf %[[EXTRACT0]], %[[SUB]]
505  // CHECK:    %[[MUL1:.+]] = arith.mulf %[[EXTRACT1]], %[[DX]]
506  // CHECK:    %[[ADD:.+]] = arith.addf %[[MUL0]], %[[MUL1]]
507  // CHECK:    linalg.yield %[[ADD]]
508  %resize = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 2, 1, 3, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x2x7xf32>) -> tensor<3x1x5x7xf32>
509
510  // CHECK:  return %[[GENERIC]]
511  return %resize : tensor<3x1x5x7xf32>
512}
513