1// RUN: mlir-opt %s -tensor-bufferize | FileCheck %s 2 3// CHECK-DAG: #[[$MAP0:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)> 4// CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0, d1)[s0] -> (d0 * 20 + s0 + d1)> 5// CHECK-DAG: #[[$MAP2:.*]] = affine_map<(d0, d1, d2, d3)[s0] -> (d0 * 140 + d1 * 20 + d2 * 5 + d3 + s0)> 6// CHECK-DAG: #[[$MAP3:.*]] = affine_map<(d0) -> (d0 + 1)> 7// CHECK-DAG: #[[$MAP4:.*]] = affine_map<() -> (1)> 8 9// CHECK-LABEL: func @dim( 10// CHECK-SAME: %[[TENSOR:.*]]: tensor<f32>, 11// CHECK-SAME: %[[INDEX:.*]]: index) -> index { 12// CHECK: %[[MEMREF:.*]] = bufferization.to_memref %[[TENSOR]] : memref<f32> 13// CHECK: %[[EXTENT:.*]] = memref.dim %[[MEMREF]], %[[INDEX]] : memref<f32> 14// CHECK: return %[[EXTENT]] : index 15func @dim(%arg0: tensor<f32>, %arg1: index) -> index { 16 %0 = tensor.dim %arg0, %arg1 : tensor<f32> 17 return %0 : index 18} 19 20// CHECK-LABEL: func @rank( 21// CHECK-SAME: %[[TENSOR:.*]]: tensor<*xf32>) -> index { 22// CHECK: %[[MEMREF:.*]] = bufferization.to_memref %[[TENSOR]] 23// CHECK: %[[EXTENT:.*]] = memref.rank %[[MEMREF]] : memref<*xf32> 24func @rank(%arg0: tensor<*xf32>) -> index { 25 %0 = tensor.rank %arg0 : tensor<*xf32> 26 return %0 : index 27} 28 29// CHECK-LABEL: func @tensor.cast( 30// CHECK-SAME: %[[TENSOR:.*]]: tensor<?xindex>) -> tensor<2xindex> { 31// CHECK: %[[MEMREF:.*]] = bufferization.to_memref %[[TENSOR]] 32// CHECK: %[[CASTED:.*]] = memref.cast %[[MEMREF]] : memref<?xindex> to memref<2xindex> 33// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[CASTED]] 34// CHECK: return %[[RET]] : tensor<2xindex> 35func @tensor.cast(%arg0: tensor<?xindex>) -> tensor<2xindex> { 36 %0 = tensor.cast %arg0 : tensor<?xindex> to tensor<2xindex> 37 return %0 : tensor<2xindex> 38} 39 40// CHECK-LABEL: func @tensor.cast_from_unranked( 41// CHECK-SAME: %[[TENSOR:.*]]: tensor<*xf32>) -> tensor<2xf32> { 42// CHECK: %[[MEMREF:.*]] = bufferization.to_memref %[[TENSOR]] : memref<*xf32> 43// CHECK: %[[CASTED_MEMREF:.*]] = memref.cast %[[MEMREF]] : memref<*xf32> to memref<2xf32> 44// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[CASTED_MEMREF]] : memref<2xf32> 45// CHECK: return %[[RET]] : tensor<2xf32> 46func @tensor.cast_from_unranked(%arg0: tensor<*xf32>) -> tensor<2xf32> { 47 %0 = tensor.cast %arg0 : tensor<*xf32> to tensor<2xf32> 48 return %0 : tensor<2xf32> 49} 50 51// CHECK-LABEL: func @tensor.cast_to_unranked( 52// CHECK-SAME: %[[TENSOR:.*]]: tensor<2xf32>) -> tensor<*xf32> { 53// CHECK: %[[MEMREF:.*]] = bufferization.to_memref %[[TENSOR]] : memref<2xf32> 54// CHECK: %[[CASTED_MEMREF:.*]] = memref.cast %[[MEMREF]] : memref<2xf32> to memref<*xf32> 55// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[CASTED_MEMREF]] : memref<*xf32> 56// CHECK: return %[[RET]] : tensor<*xf32> 57func @tensor.cast_to_unranked(%arg0: tensor<2xf32>) -> tensor<*xf32> { 58 %0 = tensor.cast %arg0 : tensor<2xf32> to tensor<*xf32> 59 return %0 : tensor<*xf32> 60} 61 62// CHECK-LABEL: func @tensor.extract( 63// CHECK-SAME: %[[TENSOR:.*]]: tensor<?xf32>, 64// CHECK-SAME: %[[IDX:.*]]: index) -> f32 { 65// CHECK: %[[MEMREF:.*]] = bufferization.to_memref %[[TENSOR]] : memref<?xf32> 66// CHECK: %[[RET:.*]] = memref.load %[[MEMREF]][%[[IDX]]] : memref<?xf32> 67// CHECK: return %[[RET]] : f32 68// CHECK: } 69func @tensor.extract(%arg0: tensor<?xf32>, %arg1: index) -> f32 { 70 %0 = tensor.extract %arg0[%arg1] : tensor<?xf32> 71 return %0 : f32 72} 73 74// CHECK-LABEL: func @tensor.from_elements_no_elements() -> tensor<0xindex> { 75// CHECK: %[[RET:.*]] = arith.constant dense<> : tensor<0xindex> 76// CHECK: return %[[RET]] : tensor<0xindex> 77func @tensor.from_elements_no_elements() -> tensor<0xindex> { 78 %0 = tensor.from_elements : tensor<0xindex> 79 return %0 : tensor<0xindex> 80} 81 82// CHECK-LABEL: func @tensor.from_elements_0d( 83// CHECK-SAME: %[[ELEM0:.*]]: index) -> tensor<index> { 84// CHECK: %[[MEMREF:.*]] = memref.alloc() {{.*}} : memref<index> 85// CHECK: store %[[ELEM0]], %[[MEMREF]] 86// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[MEMREF]] 87// CHECK: return %[[RET]] : tensor<index> 88func @tensor.from_elements_0d(%arg0: index) -> tensor<index> { 89 %0 = tensor.from_elements %arg0 : tensor<index> 90 return %0 : tensor<index> 91} 92 93// CHECK-LABEL: func @tensor.from_elements_1d( 94// CHECK-SAME: %[[ELEM0:.*]]: index, 95// CHECK-SAME: %[[ELEM1:.*]]: index) -> tensor<2xindex> { 96// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 97// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 98// CHECK-DAG: %[[MEMREF:.*]] = memref.alloc() {{.*}} : memref<2xindex> 99// CHECK: store %[[ELEM0]], %[[MEMREF]][%[[C0]]] 100// CHECK: store %[[ELEM1]], %[[MEMREF]][%[[C1]]] 101// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[MEMREF]] 102// CHECK: return %[[RET]] : tensor<2xindex> 103func @tensor.from_elements_1d(%arg0: index, %arg1: index) -> tensor<2xindex> { 104 %0 = tensor.from_elements %arg0, %arg1 : tensor<2xindex> 105 return %0 : tensor<2xindex> 106} 107 108// CHECK-LABEL: func @tensor.from_elements_2d( 109// CHECK-SAME: %[[ELEM0:.*]]: index, %[[ELEM1:.*]]: index) 110// CHECK-SAME: -> tensor<3x2xindex> { 111// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 112// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 113// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index 114// CHECK-DAG: %[[MEMREF:.*]] = memref.alloc() {{.*}} : memref<3x2xindex> 115// CHECK: store %[[ELEM0]], %[[MEMREF]][%[[C0]], %[[C0]]] 116// CHECK: store %[[ELEM1]], %[[MEMREF]][%[[C0]], %[[C1]]] 117// CHECK: store %[[ELEM0]], %[[MEMREF]][%[[C1]], %[[C0]]] 118// CHECK: store %[[ELEM1]], %[[MEMREF]][%[[C1]], %[[C1]]] 119// CHECK: store %[[ELEM0]], %[[MEMREF]][%[[C2]], %[[C0]]] 120// CHECK: store %[[ELEM1]], %[[MEMREF]][%[[C2]], %[[C1]]] 121// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[MEMREF]] 122// CHECK: return %[[RET]] : tensor<3x2xindex> 123func @tensor.from_elements_2d(%arg0: index, %arg1: index) -> tensor<3x2xindex> { 124 %0 = tensor.from_elements %arg0, %arg1, %arg0, %arg1, %arg0, %arg1 125 : tensor<3x2xindex> 126 return %0 : tensor<3x2xindex> 127} 128 129// CHECK-LABEL: func @tensor.from_elements_3d( 130// CHECK-SAME: %[[F0:.*]]: f32 131 132// CHECK-DAG: %[[F1:.*]] = arith.constant 1.0{{0+}}e+00 133// CHECK-DAG: %[[F2:.*]] = arith.constant 2.0 134// CHECK-DAG: %[[F3:.*]] = arith.constant 3.0 135// CHECK-DAG: %[[F4:.*]] = arith.constant 4.0 136// CHECK-DAG: %[[F5:.*]] = arith.constant 5.0 137// CHECK-DAG: %[[F6:.*]] = arith.constant 6.0 138// CHECK-DAG: %[[F7:.*]] = arith.constant 7.0 139// CHECK-DAG: %[[F8:.*]] = arith.constant 8.0 140// CHECK-DAG: %[[F9:.*]] = arith.constant 9.0 141// CHECK-DAG: %[[F10:.*]] = arith.constant 1.0{{0+}}e+01 142// CHECK-DAG: %[[F11:.*]] = arith.constant 1.1{{0+}}e+01 143 144// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 145// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 146// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index 147 148// CHECK-DAG: %[[MEMREF:.*]] = memref.alloc() {{.*}} : memref<3x2x2xf32> 149 150// CHECK: store %[[F0]], %[[MEMREF]][%[[C0]], %[[C0]], %[[C0]]] 151// CHECK: store %[[F1]], %[[MEMREF]][%[[C0]], %[[C0]], %[[C1]]] 152// CHECK: store %[[F2]], %[[MEMREF]][%[[C0]], %[[C1]], %[[C0]]] 153// CHECK: store %[[F3]], %[[MEMREF]][%[[C0]], %[[C1]], %[[C1]]] 154// CHECK: store %[[F4]], %[[MEMREF]][%[[C1]], %[[C0]], %[[C0]]] 155// CHECK: store %[[F5]], %[[MEMREF]][%[[C1]], %[[C0]], %[[C1]]] 156// CHECK: store %[[F6]], %[[MEMREF]][%[[C1]], %[[C1]], %[[C0]]] 157// CHECK: store %[[F7]], %[[MEMREF]][%[[C1]], %[[C1]], %[[C1]]] 158// CHECK: store %[[F8]], %[[MEMREF]][%[[C2]], %[[C0]], %[[C0]]] 159// CHECK: store %[[F9]], %[[MEMREF]][%[[C2]], %[[C0]], %[[C1]]] 160// CHECK: store %[[F10]], %[[MEMREF]][%[[C2]], %[[C1]], %[[C0]]] 161// CHECK: store %[[F11]], %[[MEMREF]][%[[C2]], %[[C1]], %[[C1]]] 162 163// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[MEMREF]] 164// CHECK: return %[[RET]] : tensor<3x2x2xf32> 165func @tensor.from_elements_3d(%f0 : f32) -> tensor<3x2x2xf32> { 166 %f1 = arith.constant 1.0 : f32 167 %f2 = arith.constant 2.0 : f32 168 %f3 = arith.constant 3.0 : f32 169 %f4 = arith.constant 4.0 : f32 170 %f5 = arith.constant 5.0 : f32 171 %f6 = arith.constant 6.0 : f32 172 %f7 = arith.constant 7.0 : f32 173 %f8 = arith.constant 8.0 : f32 174 %f9 = arith.constant 9.0 : f32 175 %f10 = arith.constant 10.0 : f32 176 %f11 = arith.constant 11.0 : f32 177 %0 = tensor.from_elements %f0,%f1,%f2,%f3,%f4,%f5,%f6,%f7,%f8,%f9,%f10,%f11 178 : tensor<3x2x2xf32> 179 return %0 : tensor<3x2x2xf32> 180} 181 182// CHECK-LABEL: func @tensor.generate( 183// CHECK-SAME: %[[ARG:.*]]: tensor<*xf32>, 184// CHECK-SAME: %[[DYNAMIC_EXTENT:.*]]: index) -> tensor<?xindex> { 185// CHECK: %[[CASTED:.*]] = bufferization.to_memref %[[ARG]] : memref<*xf32> 186// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 187// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 188// CHECK: %[[MEMREF:.*]] = memref.alloc(%[[DYNAMIC_EXTENT]]) {{.*}} : memref<?xindex> 189// CHECK: scf.parallel (%[[I:.*]]) = (%[[C0]]) to (%[[DYNAMIC_EXTENT]]) step (%[[C1]]) { 190// CHECK: %[[ELEM:.*]] = memref.dim %[[CASTED]], %[[I]] : memref<*xf32> 191// CHECK: store %[[ELEM]], %[[MEMREF]][%[[I]]] : memref<?xindex> 192// CHECK: scf.yield 193// CHECK: } 194// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[MEMREF]] : memref<?xindex> 195// CHECK: return %[[RET]] : tensor<?xindex> 196// CHECK: } 197func @tensor.generate(%arg: tensor<*xf32>, %dynamic_extent: index) -> tensor<?xindex> { 198 %result = tensor.generate %dynamic_extent { 199 ^bb0(%i : index): 200 %elem = tensor.dim %arg, %i : tensor<*xf32> 201 tensor.yield %elem : index 202 } : tensor<?xindex> 203 return %result : tensor<?xindex> 204} 205 206// Additional test that checks the logic for intermixed static and dynamic 207// extents. 208// 209// CHECK-LABEL: func @tensor.generate_static_and_dynamic( 210// CHECK-SAME: %[[DYNAMIC_EXTENT:.*]]: index) -> tensor<16x?xindex> { 211// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 212// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 213// CHECK-DAG: %[[C16:.*]] = arith.constant 16 : index 214// CHECK: %[[MEMREF:.*]] = memref.alloc(%[[DYNAMIC_EXTENT]]) {{.*}} : memref<16x?xindex> 215// CHECK: scf.parallel (%[[I:.*]], %[[J:.*]]) = (%[[C0]], %[[C0]]) to (%[[C16]], %[[DYNAMIC_EXTENT]]) step (%[[C1]], %[[C1]]) { 216// CHECK: %[[VAL_7:.*]] = arith.addi %[[I]], %[[J]] : index 217// CHECK: store %[[VAL_7]], %[[MEMREF]][%[[I]], %[[J]]] : memref<16x?xindex> 218// CHECK: scf.yield 219// CHECK: } 220// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[MEMREF]] : memref<16x?xindex> 221// CHECK: return %[[RET]] : tensor<16x?xindex> 222// CHECK: } 223func @tensor.generate_static_and_dynamic(%arg0: index) -> tensor<16x?xindex> { 224 %result = tensor.generate %arg0 { 225 ^bb0(%i: index, %j: index): 226 %sum = arith.addi %i, %j : index 227 tensor.yield %sum : index 228 } : tensor<16x?xindex> 229 return %result : tensor<16x?xindex> 230} 231 232// CHECK-LABEL: func @tensor.generate_unknown_ops_in_body 233func @tensor.generate_unknown_ops_in_body(%arg0: index) -> tensor<?xindex> { 234 // CHECK-NOT: tensor.generate 235 %tensor = tensor.generate %arg0 { 236 ^bb0(%iv: index): 237 // CHECK: test.source 238 %0 = "test.source"() : () -> index 239 tensor.yield %0 : index 240 } : tensor<?xindex> 241 return %tensor : tensor<?xindex> 242} 243 244// CHECK-LABEL: func @tensor.extract_slice( 245// CHECK-SAME: %[[t1:.*]]: tensor<?x?xf32>, %[[idx1:.*]]: index, %[[idx2:.*]]: index 246func @tensor.extract_slice( 247 %t1: tensor<?x?xf32>, %idx1: index, %idx2: index) -> tensor<?x10xf32> { 248 // CHECK: %[[m:.*]] = bufferization.to_memref %[[t1]] : memref<?x?xf32> 249 // CHECK: %[[r:.*]] = memref.subview %[[m]][5, %[[idx2]]] [%[[idx1]], 10] [1, 1] : memref<?x?xf32> to memref<?x10xf32, #[[$MAP0]]> 250 %0 = tensor.extract_slice %t1[5, %idx2][%idx1, 10][1, 1] 251 : tensor<?x?xf32> to tensor<?x10xf32> 252 // CHECK: %[[r_tensor:.*]] = bufferization.to_tensor %[[r]] 253 // CHECK: return %[[r_tensor]] 254 return %0 : tensor<?x10xf32> 255} 256 257// CHECK-LABEL: func @tensor.extract_slice_rank_reducing( 258// CHECK-SAME: %[[t1:.*]]: tensor<?x10x?xf32>, %[[idx1:.*]]: index, 259// CHECK-SAME: %[[idx2:.*]]: index 260func @tensor.extract_slice_rank_reducing( 261 %t1: tensor<?x10x?xf32>, %idx1: index, %idx2: index) -> tensor<?x15xf32> { 262 // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref<?x10x?xf32> 263 // CHECK: %[[r:.*]] = memref.subview %[[m1]][5, %[[idx1]], 10] [%[[idx2]], 1, 15] [1, 1, 1] : memref<?x10x?xf32> to memref<?x15xf32, #[[$MAP0]]> 264 %0 = tensor.extract_slice %t1[5, %idx1, 10][%idx2, 1, 15][1, 1, 1] 265 : tensor<?x10x?xf32> to tensor<?x15xf32> 266 // CHECK: %[[r_tensor:.*]] = bufferization.to_tensor %[[r]] 267 // CHECK: return %[[r_tensor]] 268 return %0 : tensor<?x15xf32> 269} 270 271// CHECK-LABEL: func @tensor.insert_slice( 272// CHECK-SAME: %[[t1:.*]]: tensor<?x?xf32>, %[[t2:.*]]: tensor<?x10xf32>, 273// CHECK-SAME: %[[idx1:.*]]: index, %[[idx2:.*]]: index 274func @tensor.insert_slice(%t1: tensor<?x?xf32>, %t2: tensor<?x10xf32>, 275 %idx1: index, %idx2: index) -> tensor<?x?xf32> { 276 // CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index 277 // CHECK-DAG: %[[c1:.*]] = arith.constant 1 : index 278 // CHECK-DAG: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref<?x?xf32> 279 // CHECK-DAG: %[[m2:.*]] = bufferization.to_memref %[[t2]] : memref<?x10xf32> 280 // CHECK: %[[dim0:.*]] = memref.dim %[[m1]], %[[c0]] 281 // CHECK: %[[dim1:.*]] = memref.dim %[[m1]], %[[c1]] 282 // CHECK: %[[alloc:.*]] = memref.alloc(%[[dim0]], %[[dim1]]) 283 // CHECK: memref.copy %[[m1]], %[[alloc]] 284 // CHECK: %[[subview:.*]] = memref.subview %[[alloc]][%[[idx1]], 5] [%[[idx2]], 10] [1, 1] 285 // CHECK: memref.copy %[[m2]], %[[subview]] 286 %0 = tensor.insert_slice %t2 into %t1[%idx1, 5][%idx2, 10][1, 1] 287 : tensor<?x10xf32> into tensor<?x?xf32> 288 289 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[alloc]] 290 // CHECK: return %[[r]] 291 return %0 : tensor<?x?xf32> 292} 293 294// CHECK-LABEL: func @tensor.insert( 295// CHECK-SAME: %[[t1:.*]]: tensor<5xf32>, %[[idx1:.*]]: index, 296// CHECK-SAME: %[[f:.*]]: f32 297func @tensor.insert(%t1: tensor<5xf32>, %idx1: index, %f: f32) -> tensor<5xf32> { 298 // CHECK-DAG: %[[alloc:.*]] = memref.alloc() {{.*}} : memref<5xf32> 299 // CHECK-DAG: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref<5xf32> 300 // CHECK: memref.copy %[[m1]], %[[alloc]] 301 // CHECK: memref.store %[[f]], %[[alloc]][%[[idx1]]] 302 %0 = tensor.insert %f into %t1[%idx1] : tensor<5xf32> 303 304 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[alloc]] 305 // CHECK: return %[[r]] 306 return %0 : tensor<5xf32> 307} 308 309// CHECK-LABEL: func @tensor.expand_shape( 310// CHECK-SAME: %[[t1:.*]]: tensor<?x10xf32> 311func @tensor.expand_shape(%t1: tensor<?x10xf32>) -> tensor<2x?x10xf32> { 312 // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref<?x10xf32> 313 // CHECK: %[[expanded:.*]] = memref.expand_shape %[[m1]] [ 314 // CHECK-SAME: [0, 1], [2]] : memref<?x10xf32> into memref<2x?x10xf32> 315 %0 = tensor.expand_shape %t1 [[0, 1], [2]] 316 : tensor<?x10xf32> into tensor<2x?x10xf32> 317 318 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[expanded]] 319 // CHECK: return %[[r]] 320 return %0 : tensor<2x?x10xf32> 321} 322 323// CHECK-LABEL: func @tensor.expand_shape_of_slice( 324// CHECK-SAME: %[[t1:.*]]: tensor<?x20xf32> 325func @tensor.expand_shape_of_slice( 326 %t1: tensor<?x20xf32>, %o1: index, %s1: index) -> tensor<?x7x2x5xf32> { 327 // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref<?x20xf32> 328 // CHECK: %[[subview:.*]] = memref.subview %[[m1]][%{{.*}}, 5] [%{{.*}}, 10] [1, 1] : memref<?x20xf32> to memref<?x10xf32, #[[$MAP1]]> 329 %0 = tensor.extract_slice %t1[%o1, 5][%s1, 10][1, 1] : 330 tensor<?x20xf32> to tensor<?x10xf32> 331 // CHECK: %[[expanded:.*]] = memref.expand_shape %[[subview]] [ 332 // CHECK-SAME: [0, 1], [2, 3]] : memref<?x10xf32, #[[$MAP1]]> into memref<?x7x2x5xf32, #[[$MAP2]]> 333 %1 = tensor.expand_shape %0 [[0, 1], [2, 3]] : 334 tensor<?x10xf32> into tensor<?x7x2x5xf32> 335 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[expanded]] 336 // CHECK: return %[[r]] 337 return %1 : tensor<?x7x2x5xf32> 338} 339 340// CHECK-LABEL: func @tensor.collapse_shape( 341// CHECK-SAME: %[[t1:.*]]: tensor<2x?x?xf32> 342func @tensor.collapse_shape(%t1: tensor<2x?x?xf32>) -> tensor<?x?xf32> { 343 // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref<2x?x?xf32> 344 // CHECK: %[[collapsed:.*]] = memref.collapse_shape %[[m1]] [ 345 // CHECK-SAME: [0, 1], [2]] : memref<2x?x?xf32> into memref<?x?xf32> 346 %0 = tensor.collapse_shape %t1 [[0, 1], [2]] 347 : tensor<2x?x?xf32> into tensor<?x?xf32> 348 349 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[collapsed]] 350 // CHECK: return %[[r]] 351 return %0 : tensor<?x?xf32> 352} 353 354// CHECK-LABEL: func @tensor.collapse_shape_to_scalar( 355// CHECK-SAME: %[[t1:.*]]: tensor<1x1x1xf32> 356func @tensor.collapse_shape_to_scalar(%t1: tensor<1x1x1xf32>) -> tensor<f32> { 357 // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref<1x1x1xf32> 358 // CHECK: %[[collapsed:.*]] = memref.collapse_shape %[[m1]] [] : memref<1x1x1xf32> into memref<f32> 359 %0 = tensor.collapse_shape %t1 [] 360 : tensor<1x1x1xf32> into tensor<f32> 361 362 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[collapsed]] 363 // CHECK: return %[[r]] 364 return %0 : tensor<f32> 365} 366 367// CHECK-LABEL: func @tensor.collapse_shape_of_slice( 368func @tensor.collapse_shape_of_slice(%arg0: tensor<2xi32>) -> tensor<i32> { 369 // CHECK: memref.subview %{{.*}}[1] [1] [1] : memref<2xi32> to memref<1xi32, #[[$MAP3]]> 370 %0 = tensor.extract_slice %arg0[1] [1] [1] : tensor<2xi32> to tensor<1xi32> 371 // CHECK: memref.collapse_shape %{{.*}} [] : memref<1xi32, #[[$MAP3]]> into memref<i32, #[[$MAP4]]> 372 %1 = tensor.collapse_shape %0 [] : tensor<1xi32> into tensor<i32> 373 return %1 : tensor<i32> 374} 375