1 // RUN: mlir-opt --split-input-file -pass-pipeline="builtin.module(func.func(tosa-to-linalg))" %s -o -| FileCheck %s
3 // CHECK-LABEL: @unary_resize_nearest_fp32
4 func.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>
7 return %resize : tensor<3x1x1x7xf32>
12 // CHECK-LABEL: @unary_resize_nearest_fp16
13 func.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>
21 // CHECK-LABEL: @unary_resize_bilinear_fp32
22 func.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>
30 // CHECK-LABEL: @unary_resize_bilinear_fp16
31 func.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>
39 // CHECK-LABEL: @unary_resize_nearest_i8
40 func.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>
48 // CHECK-LABEL: @broadcast_resize_nearest_f32
49 func.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>
60 // CHECK: return %[[GENERIC]]
61 return %resize : tensor<3x1x5x7xf32>
66 // CHECK-LABEL: @broadcast_resize_bilinear_i8
67 func.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>
94 // CHECK: return %[[BROADCAST]]
95 return %resize : tensor<3x4x5x7xi32>
100 // CHECK-LABEL: @unary_resize_bilinear_i32
101 func.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>
121 // CHECK: return %[[EXPAND]]
122 return %resize : tensor<3x1x1x7xi32>
127 // CHECK-LABEL: @resize_nearest_int
128 func.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
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
150 // find the remainder and integer component of the target index.
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]]
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]]
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]]
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]]
183 // CHECK: %[[EXTRACT:.+]] = tensor.extract %arg0[%[[IDX_0]], %[[IDY]], %[[IDX]], %[[IDX_3]]]
184 // CHECK: linalg.yield %[[EXTRACT]]
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>
193 // CHECK-LABEL: @resize_bilinear_int
194 // CHECK-SAME: (%[[ARG0:[0-9a-zA-Z_]*]]:
195 func.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
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]]
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]]
228 // Compute the left, right, and top indices for the bilinear interpolation.
230 // CHECK-DAG: %[[ONE:.*]] = arith.constant 1
231 // CHECK: %[[Y1:.*]] = arith.addi %[[I_Y]], %[[ONE]]
233 // Bound check each dimension.
235 // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[I_Y]]
236 // CHECK: %[[YLO:.*]] = arith.minsi %[[Y_MAX]], %[[BOUND]]
238 // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[Y1]]
239 // CHECK: %[[YHI:.*]] = arith.minsi %[[Y_MAX]], %[[BOUND]]
241 // CHECK: %[[YLOI:.+]] = arith.index_cast %[[YLO]]
242 // CHECK: %[[YHII:.+]] = arith.index_cast %[[YHI]]
244 // CHECK: %[[X1:.*]] = arith.addi %[[I_X]], %[[ONE]]
245 // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[I_X]]
246 // CHECK: %[[XLO:.*]] = arith.minsi %[[X_MAX]], %[[BOUND]]
248 // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[X1]]
249 // CHECK: %[[XHI:.*]] = arith.minsi %[[X_MAX]], %[[BOUND]]
251 // CHECK: %[[XLOI:.+]] = arith.index_cast %[[XLO]]
252 // CHECK: %[[XHII:.+]] = arith.index_cast %[[XHI]]
254 // Extract each corner of the bilinear interpolation.
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]]]
261 // CHECK: %[[XLOLO:.+]] = arith.extsi %[[LOLO]]
262 // CHECK: %[[XLOHI:.+]] = arith.extsi %[[LOHI]]
263 // CHECK: %[[XHILO:.+]] = arith.extsi %[[HILO]]
264 // CHECK: %[[XHIHI:.+]] = arith.extsi %[[HIHI]]
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]]
271 // Compute the bilinear interpolation.
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]]
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>
294 // CHECK-LABEL: @resize_nearest_fp32
295 func.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
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]]
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]]
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]]
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]]
349 // CHECK: %[[EXTRACT:.+]] = tensor.extract %arg0[%[[IDX0]], %[[IDY]], %[[IDX]], %[[IDX3]]]
350 // CHECK: linalg.yield %[[EXTRACT]]
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>
358 // CHECK-LABEL: @resize_bilinear_fp
359 func.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
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]]
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]]
396 // Compute the left, right, and top indices for the bilinear interpolation.
398 // CHECK: %[[ONE:.*]] = arith.constant 1
400 // Bound check each dimension.
402 // CHECK: %[[Y1:.*]] = arith.addi %[[I_Y]], %[[ONE]]
404 // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[I_Y]]
405 // CHECK: %[[YLO:.*]] = arith.minsi %[[Y_MAX]], %[[BOUND]]
407 // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[Y1]]
408 // CHECK: %[[YHI:.*]] = arith.minsi %[[Y_MAX]], %[[BOUND]]
410 // CHECK: %[[YLOI:.+]] = arith.index_cast %[[YLO]]
411 // CHECK: %[[YHII:.+]] = arith.index_cast %[[YHI]]
413 // CHECK: %[[X1:.*]] = arith.addi %[[I_X]], %[[ONE]]
414 // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[I_X]]
415 // CHECK: %[[XLO:.*]] = arith.minsi %[[X_MAX]], %[[BOUND]]
417 // CHECK: %[[BOUND:.*]] = arith.maxsi %[[ZERO]], %[[X1]]
418 // CHECK: %[[XHI:.*]] = arith.minsi %[[X_MAX]], %[[BOUND]]
420 // CHECK: %[[XLOI:.+]] = arith.index_cast %[[XLO]]
421 // CHECK: %[[XHII:.+]] = arith.index_cast %[[XHI]]
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]]]
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]]
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>
451 // CHECK-LABEL: @resize_dyn
452 // CHECK-SAME: (%[[ARG0:[0-9a-zA-Z_]*]]:
453 func.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>)
464 // CHECK-LABEL: @resize_bilinear_int48
465 func.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>
472 // CHECK-LABEL: skip_interpolate_bilinear_i8
473 func.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>
491 // CHECK: return %[[GENERIC]]
492 return %resize : tensor<3x1x5x7xi32>
495 // CHECK-LABEL: skip_interpolate_bilinear_f32
496 func.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>
510 // CHECK: return %[[GENERIC]]
511 return %resize : tensor<3x1x5x7xf32>