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