764 lines · plain
1// RUN: mlir-opt %s --one-shot-bufferize="dialect-filter=tensor,bufferization copy-before-write unknown-type-conversion=identity-layout-map" -cse -split-input-file | FileCheck %s2 3// CHECK-LABEL: func @dim(4// CHECK-SAME: %[[TENSOR:.*]]: tensor<*xf32>,5// CHECK-SAME: %[[INDEX:.*]]: index) -> index {6// CHECK: %[[MEMREF:.*]] = bufferization.to_buffer %[[TENSOR]] : tensor<*xf32> to memref<*xf32>7// CHECK: %[[EXTENT:.*]] = memref.dim %[[MEMREF]], %[[INDEX]] : memref<*xf32>8// CHECK: return %[[EXTENT]] : index9func.func @dim(%arg0: tensor<*xf32>, %arg1: index) -> index {10 %0 = tensor.dim %arg0, %arg1 : tensor<*xf32>11 return %0 : index12}13 14// -----15 16// CHECK-LABEL: func @rank(17// CHECK-SAME: %[[TENSOR:.*]]: tensor<*xf32>) -> index {18// CHECK: %[[MEMREF:.*]] = bufferization.to_buffer %[[TENSOR]]19// CHECK: %[[EXTENT:.*]] = memref.rank %[[MEMREF]] : memref<*xf32>20func.func @rank(%arg0: tensor<*xf32>) -> index {21 %0 = tensor.rank %arg0 : tensor<*xf32>22 return %0 : index23}24 25// -----26 27// CHECK-LABEL: func @tensor.cast(28// CHECK-SAME: %[[TENSOR:.*]]: tensor<?xindex>) -> tensor<2xindex> {29// CHECK: %[[MEMREF:.*]] = bufferization.to_buffer %[[TENSOR]]30// CHECK: %[[CASTED:.*]] = memref.cast %[[MEMREF]] : memref<?xindex> to memref<2xindex>31// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[CASTED]]32// CHECK: return %[[RET]] : tensor<2xindex>33func.func @tensor.cast(%arg0: tensor<?xindex>) -> tensor<2xindex> {34 %0 = tensor.cast %arg0 : tensor<?xindex> to tensor<2xindex>35 return %0 : tensor<2xindex>36}37 38// -----39 40// CHECK-LABEL: func @tensor.cast_from_unranked(41// CHECK-SAME: %[[TENSOR:.*]]: tensor<*xf32>) -> tensor<2xf32> {42// CHECK: %[[MEMREF:.*]] = bufferization.to_buffer %[[TENSOR]] : tensor<*xf32> to memref<*xf32>43// CHECK: %[[CASTED_MEMREF:.*]] = memref.cast %[[MEMREF]] : memref<*xf32> to memref<2xf32, strided<[?], offset: ?>>44// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[CASTED_MEMREF]] : memref<2xf32, strided<[?], offset: ?>>45// CHECK: return %[[RET]] : tensor<2xf32>46func.func @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// -----52 53// CHECK-LABEL: func @tensor.cast_to_unranked(54// CHECK-SAME: %[[TENSOR:.*]]: tensor<2xf32>) -> tensor<*xf32> {55// CHECK: %[[MEMREF:.*]] = bufferization.to_buffer %[[TENSOR]] : tensor<2xf32> to memref<2xf32>56// CHECK: %[[CASTED_MEMREF:.*]] = memref.cast %[[MEMREF]] : memref<2xf32> to memref<*xf32>57// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[CASTED_MEMREF]] : memref<*xf32>58// CHECK: return %[[RET]] : tensor<*xf32>59func.func @tensor.cast_to_unranked(%arg0: tensor<2xf32>) -> tensor<*xf32> {60 %0 = tensor.cast %arg0 : tensor<2xf32> to tensor<*xf32>61 return %0 : tensor<*xf32>62}63 64// -----65 66// CHECK-LABEL: func @tensor.empty(67// CHECK: %[[ALLOC:.*]] = memref.alloc() {{.*}} : memref<5xf32>68// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[ALLOC]] : memref<5xf32>69// CHECK: return %[[RET]] : tensor<5xf32>70func.func @tensor.empty() -> tensor<5xf32> {71 %0 = tensor.empty() : tensor<5xf32>72 return %0 : tensor<5xf32>73}74 75// -----76 77// CHECK-LABEL: func @tensor.extract(78// CHECK-SAME: %[[TENSOR:.*]]: tensor<?xf32>,79// CHECK-SAME: %[[IDX:.*]]: index) -> f32 {80// CHECK: %[[MEMREF:.*]] = bufferization.to_buffer %[[TENSOR]] : tensor<?xf32> to memref<?xf32>81// CHECK: %[[RET:.*]] = memref.load %[[MEMREF]][%[[IDX]]] : memref<?xf32>82// CHECK: return %[[RET]] : f3283// CHECK: }84func.func @tensor.extract(%arg0: tensor<?xf32>, %arg1: index) -> f32 {85 %0 = tensor.extract %arg0[%arg1] : tensor<?xf32>86 return %0 : f3287}88 89// -----90 91// CHECK-LABEL: func @tensor.from_elements_0d(92// CHECK-SAME: %[[ELEM0:.*]]: index) -> tensor<index> {93// CHECK: %[[MEMREF:.*]] = memref.alloc() {{.*}} : memref<index>94// CHECK: store %[[ELEM0]], %[[MEMREF]]95// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[MEMREF]]96// CHECK: return %[[RET]] : tensor<index>97func.func @tensor.from_elements_0d(%arg0: index) -> tensor<index> {98 %0 = tensor.from_elements %arg0 : tensor<index>99 return %0 : tensor<index>100}101 102// -----103 104// CHECK-LABEL: func @tensor.from_elements_1d(105// CHECK-SAME: %[[ELEM0:.*]]: index,106// CHECK-SAME: %[[ELEM1:.*]]: index) -> tensor<2xindex> {107// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index108// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index109// CHECK-DAG: %[[MEMREF:.*]] = memref.alloc() {{.*}} : memref<2xindex>110// CHECK: store %[[ELEM0]], %[[MEMREF]][%[[C0]]]111// CHECK: store %[[ELEM1]], %[[MEMREF]][%[[C1]]]112// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[MEMREF]]113// CHECK: return %[[RET]] : tensor<2xindex>114func.func @tensor.from_elements_1d(%arg0: index, %arg1: index) -> tensor<2xindex> {115 %0 = tensor.from_elements %arg0, %arg1 : tensor<2xindex>116 return %0 : tensor<2xindex>117}118 119// -----120 121// CHECK-LABEL: func @tensor.from_elements_2d(122// CHECK-SAME: %[[ELEM0:.*]]: index, %[[ELEM1:.*]]: index)123// CHECK-SAME: -> tensor<3x2xindex> {124// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index125// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index126// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index127// CHECK-DAG: %[[MEMREF:.*]] = memref.alloc() {{.*}} : memref<3x2xindex>128// CHECK: store %[[ELEM0]], %[[MEMREF]][%[[C0]], %[[C0]]]129// CHECK: store %[[ELEM1]], %[[MEMREF]][%[[C0]], %[[C1]]]130// CHECK: store %[[ELEM0]], %[[MEMREF]][%[[C1]], %[[C0]]]131// CHECK: store %[[ELEM1]], %[[MEMREF]][%[[C1]], %[[C1]]]132// CHECK: store %[[ELEM0]], %[[MEMREF]][%[[C2]], %[[C0]]]133// CHECK: store %[[ELEM1]], %[[MEMREF]][%[[C2]], %[[C1]]]134// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[MEMREF]]135// CHECK: return %[[RET]] : tensor<3x2xindex>136func.func @tensor.from_elements_2d(%arg0: index, %arg1: index) -> tensor<3x2xindex> {137 %0 = tensor.from_elements %arg0, %arg1, %arg0, %arg1, %arg0, %arg1138 : tensor<3x2xindex>139 return %0 : tensor<3x2xindex>140}141 142// -----143 144// CHECK-LABEL: func @tensor.from_elements_3d(145// CHECK-SAME: %[[F0:.*]]: f32146 147// CHECK-DAG: %[[F1:.*]] = arith.constant 1.0{{0+}}e+00148// CHECK-DAG: %[[F2:.*]] = arith.constant 2.0149// CHECK-DAG: %[[F3:.*]] = arith.constant 3.0150// CHECK-DAG: %[[F4:.*]] = arith.constant 4.0151// CHECK-DAG: %[[F5:.*]] = arith.constant 5.0152// CHECK-DAG: %[[F6:.*]] = arith.constant 6.0153// CHECK-DAG: %[[F7:.*]] = arith.constant 7.0154// CHECK-DAG: %[[F8:.*]] = arith.constant 8.0155// CHECK-DAG: %[[F9:.*]] = arith.constant 9.0156// CHECK-DAG: %[[F10:.*]] = arith.constant 1.0{{0+}}e+01157// CHECK-DAG: %[[F11:.*]] = arith.constant 1.1{{0+}}e+01158 159// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index160// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index161// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index162 163// CHECK-DAG: %[[MEMREF:.*]] = memref.alloc() {{.*}} : memref<3x2x2xf32>164 165// CHECK: store %[[F0]], %[[MEMREF]][%[[C0]], %[[C0]], %[[C0]]]166// CHECK: store %[[F1]], %[[MEMREF]][%[[C0]], %[[C0]], %[[C1]]]167// CHECK: store %[[F2]], %[[MEMREF]][%[[C0]], %[[C1]], %[[C0]]]168// CHECK: store %[[F3]], %[[MEMREF]][%[[C0]], %[[C1]], %[[C1]]]169// CHECK: store %[[F4]], %[[MEMREF]][%[[C1]], %[[C0]], %[[C0]]]170// CHECK: store %[[F5]], %[[MEMREF]][%[[C1]], %[[C0]], %[[C1]]]171// CHECK: store %[[F6]], %[[MEMREF]][%[[C1]], %[[C1]], %[[C0]]]172// CHECK: store %[[F7]], %[[MEMREF]][%[[C1]], %[[C1]], %[[C1]]]173// CHECK: store %[[F8]], %[[MEMREF]][%[[C2]], %[[C0]], %[[C0]]]174// CHECK: store %[[F9]], %[[MEMREF]][%[[C2]], %[[C0]], %[[C1]]]175// CHECK: store %[[F10]], %[[MEMREF]][%[[C2]], %[[C1]], %[[C0]]]176// CHECK: store %[[F11]], %[[MEMREF]][%[[C2]], %[[C1]], %[[C1]]]177 178// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[MEMREF]]179// CHECK: return %[[RET]] : tensor<3x2x2xf32>180func.func @tensor.from_elements_3d(%f0 : f32) -> tensor<3x2x2xf32> {181 %f1 = arith.constant 1.0 : f32182 %f2 = arith.constant 2.0 : f32183 %f3 = arith.constant 3.0 : f32184 %f4 = arith.constant 4.0 : f32185 %f5 = arith.constant 5.0 : f32186 %f6 = arith.constant 6.0 : f32187 %f7 = arith.constant 7.0 : f32188 %f8 = arith.constant 8.0 : f32189 %f9 = arith.constant 9.0 : f32190 %f10 = arith.constant 10.0 : f32191 %f11 = arith.constant 11.0 : f32192 %0 = tensor.from_elements %f0,%f1,%f2,%f3,%f4,%f5,%f6,%f7,%f8,%f9,%f10,%f11193 : tensor<3x2x2xf32>194 return %0 : tensor<3x2x2xf32>195}196 197// -----198 199// CHECK-LABEL: func @tensor.generate(200// CHECK-SAME: %[[ARG:.*]]: tensor<*xf32>,201// CHECK-SAME: %[[DYNAMIC_EXTENT:.*]]: index) -> tensor<?xindex> {202// CHECK-DAG: %[[ARG_M:.*]] = bufferization.to_buffer %[[ARG]] : tensor<*xf32> to memref<*xf32>203// CHECK-DAG: %[[ALLOC:.*]] = memref.alloc(%[[DYNAMIC_EXTENT]]) {{.*}} : memref<?xindex>204// CHECK: %[[ALLOC_T:.*]] = bufferization.to_tensor %[[ALLOC]]205// CHECK: %[[MAPPED:.*]] = linalg.map206// CHECK: outs(%[[ALLOC_T]] : tensor<?xindex>)207// CHECK: %[[INDEX:.*]] = linalg.index 0 : index208// CHECK: %[[ELEM:.*]] = memref.dim %[[ARG_M]], %[[INDEX]] : memref<*xf32>209// CHECK: linalg.yield %[[ELEM]]210// CHECK: }211// CHECK: return %[[MAPPED]] : tensor<?xindex>212// CHECK: }213func.func @tensor.generate(%arg: tensor<*xf32>, %dynamic_extent: index) -> tensor<?xindex> {214 %result = tensor.generate %dynamic_extent {215 ^bb0(%i : index):216 %elem = tensor.dim %arg, %i : tensor<*xf32>217 tensor.yield %elem : index218 } : tensor<?xindex>219 return %result : tensor<?xindex>220}221 222// -----223 224// Additional test that checks the logic for intermixed static and dynamic225// extents.226//227// CHECK-LABEL: func @tensor.generate_static_and_dynamic(228// CHECK-SAME: %[[DYNAMIC_EXTENT:.*]]: index) -> tensor<16x?xindex> {229// CHECK: %[[ALLOC:.*]] = memref.alloc(%[[DYNAMIC_EXTENT]]) {{.*}} : memref<16x?xindex>230// CHECK: %[[ALLOC_T:.*]] = bufferization.to_tensor %[[ALLOC]]231// CHECK: %[[MAPPED:.*]] = linalg.map232// CHECK: outs(%[[ALLOC_T]] : tensor<16x?xindex>)233// CHECK: %[[INDEX0:.*]] = linalg.index 0234// CHECK: %[[INDEX1:.*]] = linalg.index 1235// CHECK: %[[ADD:.*]] = arith.addi %[[INDEX0]], %[[INDEX1]]236// CHECK: linalg.yield %[[ADD]]237// CHECK: }238// CHECK: return %[[MAPPED]] : tensor<16x?xindex>239// CHECK: }240func.func @tensor.generate_static_and_dynamic(%arg0: index) -> tensor<16x?xindex> {241 %result = tensor.generate %arg0 {242 ^bb0(%i: index, %j: index):243 %sum = arith.addi %i, %j : index244 tensor.yield %sum : index245 } : tensor<16x?xindex>246 return %result : tensor<16x?xindex>247}248 249// -----250 251// CHECK-LABEL: func @tensor.generate_unknown_ops_in_body252func.func @tensor.generate_unknown_ops_in_body(%arg0: index) -> tensor<?xindex> {253 // CHECK-NOT: tensor.generate254 %tensor = tensor.generate %arg0 {255 ^bb0(%iv: index):256 // CHECK: test.source257 %0 = "test.source"() : () -> index258 tensor.yield %0 : index259 } : tensor<?xindex>260 return %tensor : tensor<?xindex>261}262 263// -----264 265// CHECK-LABEL: func @tensor.extract_slice(266// CHECK-SAME: %[[t1:.*]]: tensor<?x?xf32>, %[[idx1:.*]]: index, %[[idx2:.*]]: index267func.func @tensor.extract_slice(268 %t1: tensor<?x?xf32>, %idx1: index, %idx2: index) -> tensor<?x10xf32> {269 // CHECK: %[[m:.*]] = bufferization.to_buffer %[[t1]] : tensor<?x?xf32> to memref<?x?xf32>270 // CHECK: %[[r:.*]] = memref.subview %[[m]][5, %[[idx2]]] [%[[idx1]], 10] [1, 1] : memref<?x?xf32> to memref<?x10xf32, strided<[?, 1], offset: ?>>271 %0 = tensor.extract_slice %t1[5, %idx2][%idx1, 10][1, 1]272 : tensor<?x?xf32> to tensor<?x10xf32>273 // CHECK: %[[r_tensor:.*]] = bufferization.to_tensor %[[r]]274 // CHECK: return %[[r_tensor]]275 return %0 : tensor<?x10xf32>276}277 278// -----279 280// CHECK-LABEL: func @tensor.extract_slice_rank_reducing(281// CHECK-SAME: %[[t1:.*]]: tensor<?x10x?xf32>, %[[idx1:.*]]: index,282// CHECK-SAME: %[[idx2:.*]]: index283func.func @tensor.extract_slice_rank_reducing(284 %t1: tensor<?x10x?xf32>, %idx1: index, %idx2: index) -> tensor<?x15xf32> {285 // CHECK: %[[m1:.*]] = bufferization.to_buffer %[[t1]] : tensor<?x10x?xf32> to memref<?x10x?xf32>286 // CHECK: %[[r:.*]] = memref.subview %[[m1]][5, %[[idx1]], 10] [%[[idx2]], 1, 15] [1, 1, 1] : memref<?x10x?xf32> to memref<?x15xf32, strided<[?, 1], offset: ?>>287 %0 = tensor.extract_slice %t1[5, %idx1, 10][%idx2, 1, 15][1, 1, 1]288 : tensor<?x10x?xf32> to tensor<?x15xf32>289 // CHECK: %[[r_tensor:.*]] = bufferization.to_tensor %[[r]]290 // CHECK: return %[[r_tensor]]291 return %0 : tensor<?x15xf32>292}293 294// -----295 296// CHECK-LABEL: func @tensor.insert_slice(297// CHECK-SAME: %[[t1:.*]]: tensor<?x?xf32>, %[[t2:.*]]: tensor<?x10xf32>,298// CHECK-SAME: %[[idx1:.*]]: index, %[[idx2:.*]]: index299func.func @tensor.insert_slice(%t1: tensor<?x?xf32>, %t2: tensor<?x10xf32>,300 %idx1: index, %idx2: index) -> tensor<?x?xf32> {301 // CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index302 // CHECK-DAG: %[[c1:.*]] = arith.constant 1 : index303 // CHECK-DAG: %[[m1:.*]] = bufferization.to_buffer %[[t1]] : tensor<?x?xf32> to memref<?x?xf32>304 // CHECK-DAG: %[[m2:.*]] = bufferization.to_buffer %[[t2]] : tensor<?x10xf32> to memref<?x10xf32>305 // CHECK-DAG: %[[dim0:.*]] = memref.dim %[[m1]], %[[c0]]306 // CHECK-DAG: %[[dim1:.*]] = memref.dim %[[m1]], %[[c1]]307 // CHECK: %[[alloc:.*]] = memref.alloc(%[[dim0]], %[[dim1]])308 // CHECK: memref.copy %[[m1]], %[[alloc]]309 // CHECK: %[[subview:.*]] = memref.subview %[[alloc]][%[[idx1]], 5] [%[[idx2]], 10] [1, 1]310 // CHECK: memref.copy %[[m2]], %[[subview]]311 %0 = tensor.insert_slice %t2 into %t1[%idx1, 5][%idx2, 10][1, 1]312 : tensor<?x10xf32> into tensor<?x?xf32>313 314 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[alloc]]315 // CHECK: return %[[r]]316 return %0 : tensor<?x?xf32>317}318 319// -----320 321// CHECK-LABEL: func @tensor.insert_slice_rank_reducing_1(322func.func @tensor.insert_slice_rank_reducing_1(323 %t1: tensor<?x?xf32>, %f: tensor<f32>, %idx1: index, %idx2: index)324 -> tensor<?x?xf32>325{326 // CHECK: %[[alloc:.*]] = memref.alloc{{.*}} : memref<?x?xf32>327 // CHECK: memref.subview %[[alloc]][%{{.*}}, %{{.*}}] [1, 1] [1, 1] : memref<?x?xf32> to memref<f32, strided<[], offset: ?>>328 // CHECK: memref.copy {{.*}} : memref<f32> to memref<f32, strided<[], offset: ?>>329 %0 = tensor.insert_slice %f into %t1[%idx1, %idx2][1, 1][1, 1]330 : tensor<f32> into tensor<?x?xf32>331 return %0 : tensor<?x?xf32>332}333 334// -----335 336// CHECK-LABEL: func @tensor.insert_slice_rank_reducing_2(337func.func @tensor.insert_slice_rank_reducing_2(338 %t1: tensor<?x?x?x?x?x?x?xf32>, %t2: tensor<2x1x4x1x1xf32>, %i: index)339 -> tensor<?x?x?x?x?x?x?xf32>340{341 // CHECK: %[[alloc:.*]] = memref.alloc{{.*}} : memref<?x?x?x?x?x?x?xf32>342 // CHECK: memref.subview %[[alloc]][{{.*}}] [1, 2, 1, 4, 1, 1, 1] [1, 1, 1, 1, 1, 1, 1] : memref<?x?x?x?x?x?x?xf32> to memref<2x1x4x1x1xf32, strided<[?, ?, ?, ?, ?], offset: ?>>343 // CHECK: memref.copy {{.*}} : memref<2x1x4x1x1xf32> to memref<2x1x4x1x1xf32, strided<[?, ?, ?, ?, ?], offset: ?>>344 %0 = tensor.insert_slice %t2 into %t1[%i, %i, %i, %i, %i, %i, %i][1, 2, 1, 4, 1, 1, 1][1, 1, 1, 1, 1, 1, 1]345 : tensor<2x1x4x1x1xf32> into tensor<?x?x?x?x?x?x?xf32>346 return %0 : tensor<?x?x?x?x?x?x?xf32>347}348 349// -----350 351// CHECK-LABEL: func @tensor.insert(352// CHECK-SAME: %[[t1:.*]]: tensor<5xf32>, %[[idx1:.*]]: index,353// CHECK-SAME: %[[f:.*]]: f32354func.func @tensor.insert(%t1: tensor<5xf32>, %idx1: index, %f: f32) -> tensor<5xf32> {355 // CHECK-DAG: %[[alloc:.*]] = memref.alloc() {{.*}} : memref<5xf32>356 // CHECK-DAG: %[[m1:.*]] = bufferization.to_buffer %[[t1]] : tensor<5xf32> to memref<5xf32>357 // CHECK: memref.copy %[[m1]], %[[alloc]]358 // CHECK: memref.store %[[f]], %[[alloc]][%[[idx1]]]359 %0 = tensor.insert %f into %t1[%idx1] : tensor<5xf32>360 361 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[alloc]]362 // CHECK: return %[[r]]363 return %0 : tensor<5xf32>364}365 366// -----367 368// CHECK-LABEL: func @tensor.expand_shape(369// CHECK-SAME: %[[t1:.*]]: tensor<?x10xf32>, %[[sz0:.*]]: index370func.func @tensor.expand_shape(%t1: tensor<?x10xf32>, %sz0: index) -> tensor<2x?x10xf32> {371 // CHECK: %[[m1:.*]] = bufferization.to_buffer %[[t1]]372 // CHECK: %[[expanded:.*]] = memref.expand_shape %[[m1]] {{\[\[}}0, 1], [2]] output_shape [2, %[[sz0]], 10] : memref<?x10xf32> into memref<2x?x10xf32>373 %0 = tensor.expand_shape %t1 [[0, 1], [2]] output_shape [2, %sz0, 10]374 : tensor<?x10xf32> into tensor<2x?x10xf32>375 376 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[expanded]]377 // CHECK: return %[[r]]378 return %0 : tensor<2x?x10xf32>379}380 381// -----382 383// CHECK-LABEL: func @tensor.expand_shape_of_slice(384// CHECK-SAME: %[[t1:.*]]: tensor<?x20xf32>, %{{.*}}: index, %{{.*}}: index, %[[sz0:.*]]: index385func.func @tensor.expand_shape_of_slice(386 %t1: tensor<?x20xf32>, %o1: index, %s1: index, %sz0: index) -> tensor<?x7x2x5xf32> {387 // CHECK: %[[m1:.*]] = bufferization.to_buffer %[[t1]] :388 // CHECK: %[[subview:.*]] = memref.subview %[[m1]][%{{.*}}, 5] [%{{.*}}, 10] [1, 1] : memref<?x20xf32> to memref<?x10xf32, strided<[20, 1], offset: ?>>389 %0 = tensor.extract_slice %t1[%o1, 5][%s1, 10][1, 1] :390 tensor<?x20xf32> to tensor<?x10xf32>391 // CHECK: %[[expanded:.*]] = memref.expand_shape %[[subview]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[sz0]], 7, 2, 5] : memref<?x10xf32, strided<[20, 1], offset: ?>> into memref<?x7x2x5xf32, strided<[140, 20, 5, 1], offset: ?>>392 %1 = tensor.expand_shape %0 [[0, 1], [2, 3]] output_shape [%sz0, 7, 2, 5] :393 tensor<?x10xf32> into tensor<?x7x2x5xf32>394 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[expanded]]395 // CHECK: return %[[r]]396 return %1 : tensor<?x7x2x5xf32>397}398// -----399 400// CHECK-LABEL: func @tensor.expand_shape_of_scalar_slice(401// CHECK-SAME: %[[t1:.*]]: tensor<?xf32>402func.func @tensor.expand_shape_of_scalar_slice(403 %t1: tensor<?xf32>, %o1: index, %s1: index) -> tensor<1xf32> {404 // CHECK: %[[m1:.*]] = bufferization.to_buffer %[[t1]] : tensor<?xf32> to memref<?xf32>405 // CHECK: %[[subview:.*]] = memref.subview %[[m1]][%{{.*}}] [1] [1] : memref<?xf32> to memref<f32, strided<[], offset: ?>>406 %0 = tensor.extract_slice %t1[%o1][1][1] : tensor<?xf32> to tensor<f32>407 // CHECK: %[[expanded:.*]] = memref.expand_shape %[[subview]] [] output_shape [1] : memref<f32, strided{{.*}}> into memref<1xf32, strided<[1], offset: ?>>408 %1 = tensor.expand_shape %0 [] output_shape [1] : tensor<f32> into tensor<1xf32>409 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[expanded]]410 // CHECK: return %[[r]]411 return %1 : tensor<1xf32>412}413// -----414 415// CHECK-LABEL: func @tensor.expand_shape_multiple_dynamic_indices(416// CHECK-SAME: %[[t1:.*]]: tensor<?x256xf32>, %[[sz0:.*]]: index, %[[sz1:.*]]: index, %[[sz2:.*]]: index417func.func @tensor.expand_shape_multiple_dynamic_indices(%t1: tensor<?x256xf32>, %sz0: index, %sz1: index, %sz2: index) -> tensor<?x?x?x256xf32> {418 // CHECK: %[[m1:.*]] = bufferization.to_buffer %[[t1]]419 // CHECK: %[[expanded:.*]] = memref.expand_shape %[[m1]] {{\[\[}}0, 1, 2], [3]] output_shape [%[[sz0]], %[[sz1]], %[[sz2]], 256] : memref<?x256xf32> into memref<?x?x?x256xf32>420 %0 = tensor.expand_shape %t1 [[0, 1, 2], [3]] output_shape [%sz0, %sz1, %sz2, 256]421 : tensor<?x256xf32> into tensor<?x?x?x256xf32>422 423 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[expanded]]424 // CHECK: return %[[r]]425 return %0 : tensor<?x?x?x256xf32>426}427// -----428 429// CHECK-LABEL: func @tensor.collapse_shape(430// CHECK-SAME: %[[t1:.*]]: tensor<2x?x?xf32>431func.func @tensor.collapse_shape(%t1: tensor<2x?x?xf32>) -> tensor<?x?xf32> {432 // CHECK: %[[m1:.*]] = bufferization.to_buffer %[[t1]] : tensor<2x?x?xf32> to memref<2x?x?xf32>433 // CHECK: %[[collapsed:.*]] = memref.collapse_shape %[[m1]] [434 // CHECK-SAME: [0, 1], [2]] : memref<2x?x?xf32> into memref<?x?xf32>435 %0 = tensor.collapse_shape %t1 [[0, 1], [2]]436 : tensor<2x?x?xf32> into tensor<?x?xf32>437 438 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[collapsed]]439 // CHECK: return %[[r]]440 return %0 : tensor<?x?xf32>441}442 443// -----444 445// CHECK-LABEL: func @tensor.collapse_shape_to_scalar(446// CHECK-SAME: %[[t1:.*]]: tensor<1x1x1xf32>447func.func @tensor.collapse_shape_to_scalar(%t1: tensor<1x1x1xf32>) -> tensor<f32> {448 // CHECK: %[[m1:.*]] = bufferization.to_buffer %[[t1]] : tensor<1x1x1xf32> to memref<1x1x1xf32>449 // CHECK: %[[collapsed:.*]] = memref.collapse_shape %[[m1]] [] : memref<1x1x1xf32> into memref<f32>450 %0 = tensor.collapse_shape %t1 []451 : tensor<1x1x1xf32> into tensor<f32>452 453 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[collapsed]]454 // CHECK: return %[[r]]455 return %0 : tensor<f32>456}457 458// -----459 460// CHECK-LABEL: func @tensor.collapse_shape_of_slice(461func.func @tensor.collapse_shape_of_slice(%arg0: tensor<2xi32>) -> tensor<i32> {462 // CHECK: memref.subview %{{.*}}[1] [1] [1] : memref<2xi32> to memref<1xi32, strided<[1], offset: 1>>463 %0 = tensor.extract_slice %arg0[1] [1] [1] : tensor<2xi32> to tensor<1xi32>464 // CHECK: memref.collapse_shape %{{.*}} [] : memref<1xi32, strided<[1], offset: 1>> into memref<i32, strided<[], offset: 1>>465 %1 = tensor.collapse_shape %0 [] : tensor<1xi32> into tensor<i32>466 return %1 : tensor<i32>467}468 469// -----470 471// CHECK-LABEL: func @tensor.collapse_shape_of_slice2(472func.func @tensor.collapse_shape_of_slice2(473 %arg0: tensor<?x?x?x?xi64>, %o1: index, %o2: index, %o3: index, %o4: index)474 -> tensor<87x63648xi64> {475 // CHECK: %[[subview:.*]] = memref.subview %{{.*}} : memref<?x?x?x?xi64> to memref<87x78x68x12xi64, strided{{.*}}>476 %0 = tensor.extract_slice %arg0[%o1, %o2, %o3, %o4] [87, 78, 68, 12] [1, 1, 1, 1] : tensor<?x?x?x?xi64> to tensor<87x78x68x12xi64>477 478 // This memref may not be collapsible, so the buffer must be copied to get rid479 // of the layout map.480 // CHECK: %[[alloc:.*]] = memref.alloc() {{.*}} : memref<87x78x68x12xi64>481 // CHECK: memref.copy %[[subview]], %[[alloc]]482 // CHECK: memref.collapse_shape %[[alloc]] [483 // CHECK-SAME: [0], [1, 2, 3]] : memref<87x78x68x12xi64> into memref<87x63648xi64>484 %1 = tensor.collapse_shape %0 [[0], [1, 2, 3]] : tensor<87x78x68x12xi64> into tensor<87x63648xi64>485 return %1 : tensor<87x63648xi64>486}487 488// -----489 490// CHECK-LABEL: func @tensor.collapse_shape_of_slice3(491// CHECK-SAME: %[[t1:.*]]: tensor<1x2xf32>492func.func @tensor.collapse_shape_of_slice3(%t1: tensor<1x2xf32>) -> tensor<1xf32> {493 // CHECK: memref.subview {{.*}} : memref<1x2xf32> to memref<1x1xf32, strided<[2, 1]>>494 %0 = tensor.extract_slice %t1[0, 0][1, 1][1, 1] : tensor<1x2xf32> to tensor<1x1xf32>495 // CHECK: memref.collapse_shape %{{.*}} [496 // CHECK-SAME: [0, 1]] : memref<1x1xf32, strided<[2, 1]>> into memref<1xf32, strided<[2]>>497 %1 = tensor.collapse_shape %0 [[0, 1]] : tensor<1x1xf32> into tensor<1xf32>498 return %1 : tensor<1xf32>499}500 501// -----502 503// CHECK-LABEL: func @tensor.collapse_shape_of_slice4(504// CHECK-SAME: %[[t1:.*]]: tensor<?x2x4xf32>,505// CHECK-SAME: %[[OFFSET:.*]]: index) -> tensor<8xf32> {506func.func @tensor.collapse_shape_of_slice4(%arg0: tensor<?x2x4xf32>, %offset: index, %size: index) -> tensor<8xf32> {507 // CHECK: memref.subview %{{.*}} : memref<?x2x4xf32> to memref<4x2x1xf32, strided<[8, 4, 1], offset: ?>>508 %0 = tensor.extract_slice %arg0[0, 0, %offset] [4, 2, 1] [1, 1, 1] : tensor<?x2x4xf32> to tensor<4x2x1xf32>509 // CHECK: memref.collapse_shape %{{.*}} [510 // CHECK-SAME: [0, 1, 2]] : memref<4x2x1xf32, strided<[8, 4, 1], offset: ?>> into memref<8xf32, strided<[4], offset: ?>>511 %ret = tensor.collapse_shape %0 [[0, 1, 2]] : tensor<4x2x1xf32> into tensor<8xf32>512 return %ret: tensor<8xf32>513}514 515// -----516 517// CHECK-LABEL: func @tensor.collapse_shape_of_slice5(518func.func @tensor.collapse_shape_of_slice5(%arg0: tensor<2x2x2xi64>) -> tensor<4xi64> {519 // CHECK: %[[subview:.*]] = memref.subview %{{.*}} : memref<2x2x2xi64> to memref<2x1x2xi64, {{.*}}>520 %0 = tensor.extract_slice %arg0[0, 0, 0] [2, 1, 2] [1, 1, 1] : tensor<2x2x2xi64> to tensor<2x1x2xi64>521 522 // This memref is not collapsible, so the buffer must be copied to get rid of523 // the layout map.524 // CHECK: %[[alloc:.*]] = memref.alloc() {{.*}} : memref<2x1x2xi64>525 // CHECK: memref.copy %[[subview]], %[[alloc]]526 // CHECK: memref.collapse_shape %[[alloc]] [527 // CHECK-SAME: [0, 1, 2]] : memref<2x1x2xi64> into memref<4xi64>528 %1 = tensor.collapse_shape %0 [[0, 1, 2]] : tensor<2x1x2xi64> into tensor<4xi64>529 return %1 : tensor<4xi64>530}531 532// -----533 534// CHECK-LABEL: func @tensor.reshape(535// CHECK-SAME: %[[t1:.*]]: tensor<?x10xf32>536func.func @tensor.reshape(%t1: tensor<?x10xf32>) -> tensor<2x2x5xf32> {537 // CHECK: %[[m1:.*]] = bufferization.to_buffer %[[t1]] : tensor<?x10xf32> to memref<?x10xf32>538 539 // CHECK: %[[two:.*]] = arith.constant 2 : i64540 %two = arith.constant 2 : i64541 // CHECK: %[[five:.*]] = arith.constant 5 : i64542 %five = arith.constant 5 : i64543 544 // CHECK: %[[alloc:.*]] = memref.alloc() {alignment = 64 : i64} : memref<3xi64>545 // CHECK: %[[zero_idx:.*]] = arith.constant 0 : index546 // CHECK: %[[one_idx:.*]] = arith.constant 1 : index547 // CHECK: %[[two_idx:.*]] = arith.constant 2 : index548 // CHECK: memref.store %[[two]], %[[alloc]][%[[zero_idx]]] : memref<3xi64>549 // CHECK: memref.store %[[two]], %[[alloc]][%[[one_idx]]] : memref<3xi64>550 // CHECK: memref.store %[[five]], %[[alloc]][%[[two_idx]]] : memref<3xi64>551 %shape = tensor.from_elements %two, %two, %five : tensor<3xi64>552 553 // CHECK: %[[reshaped:.*]] = memref.reshape %[[m1]](%[[alloc]]) : (memref<?x10xf32>, memref<3xi64>) -> memref<2x2x5xf32>554 %reshaped = tensor.reshape %t1(%shape) : (tensor<?x10xf32>, tensor<3xi64>) -> tensor<2x2x5xf32>555 556 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[reshaped]]557 // CHECK: return %[[r]]558 return %reshaped : tensor<2x2x5xf32>559}560 561// -----562 563// CHECK: #[[$sum_map_1:.+]] = affine_map<()[s0, s1] -> (s0 + s1 + 5)>564// CHECK: #[[$sum_map_2:.+]] = affine_map<()[s0, s1] -> (s0 + s1 + 10)>565// CHECK-LABEL: func @tensor.pad(566// CHECK-SAME: %[[t1:.*]]: tensor<?x10xindex>, %[[l2:.*]]: index, %[[h1:.*]]: index, %[[h2:.*]]: index567func.func @tensor.pad(%t1: tensor<?x10xindex>, %l2: index, %h1: index,568 %h2: index) -> tensor<?x?xindex> {569 // CHECK-DAG: %[[m1:.*]] = bufferization.to_buffer %[[t1]] : tensor<?x10xindex> to memref<?x10xindex>570 // CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index571 // CHECK-DAG: %[[c1:.*]] = arith.constant 1 : index572 // CHECK-DAG: %[[dim0:.*]] = memref.dim %[[m1]], %[[c0]]573 // CHECK-DAG: %[[dim1:.*]] = memref.dim %[[m1]], %[[c1]]574 // CHECK-DAG: %[[size0:.*]] = affine.apply #[[$sum_map_1]]()[%[[dim0]], %[[h1]]]575 // CHECK-DAG: %[[size1:.*]] = affine.apply #[[$sum_map_2]]()[%[[l2]], %[[h2]]]576 // CHECK: %[[alloc:.*]] = memref.alloc(%[[size0]], %[[size1]]) {{.*}} : memref<?x?xindex>577 // CHECK: %[[alloc_t:.*]] = bufferization.to_tensor %[[alloc]]578 // CHECK: %[[mapped:.*]] = linalg.map579 // CHECK: outs(%[[alloc_t]] : tensor<?x?xindex>)580 // CHECK: %[[index0:.*]] = linalg.index 0581 // CHECK: %[[index1:.*]] = linalg.index 1582 // CHECK: %[[mul:.*]] = arith.muli %[[index0]], %[[index1]]583 // CHECK: linalg.yield %[[mul]]584 // CHECK: }585 // CHECK: %[[mapped_m:.*]] = bufferization.to_buffer %[[mapped]]586 // CHECK: %[[subview:.*]] = memref.subview %[[mapped_m]][5, %[[l2]]] [%[[dim0]], 10] [1, 1]587 // CHECK: memref.copy %[[m1]], %[[subview]]588 %0 = tensor.pad %t1 low[5, %l2] high[%h1, %h2] {589 ^bb0(%arg0: index, %arg1: index):590 %m = arith.muli %arg0, %arg1 : index591 tensor.yield %m : index592 } : tensor<?x10xindex> to tensor<?x?xindex>593 594 // CHECK: %[[r:.*]] = bufferization.to_tensor %[[mapped_m]]595 // CHECK: return %[[r]] : tensor<?x?xindex>596 return %0 : tensor<?x?xindex>597}598 599// -----600 601// CHECK-LABEL: func @tensor.splat(602// CHECK-SAME: %[[F:.*]]: f32)603// CHECK-DAG: %[[ALLOC:.*]] = memref.alloc() {{.*}} : memref<10x2x4xf32>604// CHECK: %[[ALLOC_T:.*]] = bufferization.to_tensor %[[ALLOC]]605// CHECK: %[[MAPPED:.*]] = linalg.map606// CHECK: outs(%[[ALLOC_T]] : tensor<10x2x4xf32>)607// CHECK: linalg.yield %[[F]]608// CHECK: }609// CHECK: return %[[MAPPED]] : tensor<10x2x4xf32>610// CHECK: }611func.func @tensor.splat(%f: f32) -> tensor<10x2x4xf32> {612 %t = tensor.splat %f : tensor<10x2x4xf32>613 return %t : tensor<10x2x4xf32>614}615 616// -----617 618// CHECK-LABEL: func @tensor.splat_other(619// CHECK-SAME: %[[F:.*]]: !test.memref_element)620// CHECK-DAG: %[[ALLOC:.*]] = memref.alloc() {{.*}} : memref<10x2x4x!test.memref_element>621// CHECK: %[[ALLOC_T:.*]] = bufferization.to_tensor %[[ALLOC]]622// CHECK: %[[MAPPED:.*]] = linalg.map623// CHECK: outs(%[[ALLOC_T]] : tensor<10x2x4x!test.memref_element>)624// CHECK: linalg.yield %[[F]]625// CHECK: return %[[MAPPED]] : tensor<10x2x4x!test.memref_element>626func.func @tensor.splat_other(%f: !test.memref_element) -> tensor<10x2x4x!test.memref_element> {627 %t = tensor.splat %f : tensor<10x2x4x!test.memref_element>628 return %t : tensor<10x2x4x!test.memref_element>629}630 631// -----632 633// CHECK-LABEL: func @tensor.concat(634// CHECK-SAME: %[[F:.*]]: tensor<8xf32>)635// CHECK: %[[F_MEMREF:.*]] = bufferization.to_buffer %[[F]]636// CHECK: %[[ALLOC:.*]] = memref.alloc() {{.*}} : memref<16xf32>637// CHECK: %[[SUBVIEW1:.*]] = memref.subview %[[ALLOC]][0] [8] [1]638// CHECK: memref.copy %[[F_MEMREF]], %[[SUBVIEW1]]639// CHECK: %[[SUBVIEW2:.*]] = memref.subview %[[ALLOC]][8] [8] [1]640// CHECK: memref.copy %[[F_MEMREF]], %[[SUBVIEW2]]641// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[ALLOC]]642// CHECK: return %[[RET]]643// CHECK: }644func.func @tensor.concat(%f: tensor<8xf32>) -> tensor<16xf32> {645 %t = tensor.concat dim(0) %f, %f : (tensor<8xf32>, tensor<8xf32>) -> tensor<16xf32>646 return %t : tensor<16xf32>647}648 649// -----650 651// CHECK-LABEL: func @tensor.concat_different_shapes(652// CHECK-SAME: %[[F:.*]]: tensor<8x4xf32>653// CHECK-SAME: %[[G:.*]]: tensor<8x5xf32>654// CHECK-DAG: %[[F_MEMREF:.*]] = bufferization.to_buffer %[[F]]655// CHECK-DAG: %[[G_MEMREF:.*]] = bufferization.to_buffer %[[G]]656// CHECK: %[[ALLOC:.*]] = memref.alloc() {{.*}} : memref<8x9xf32>657// CHECK: %[[SUBVIEW1:.*]] = memref.subview %[[ALLOC]][0, 0] [8, 4] [1, 1]658// CHECK: memref.copy %[[F_MEMREF]], %[[SUBVIEW1]]659// CHECK: %[[SUBVIEW2:.*]] = memref.subview %[[ALLOC]][0, 4] [8, 5] [1, 1]660// CHECK: memref.copy %[[G_MEMREF]], %[[SUBVIEW2]]661// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[ALLOC]]662// CHECK: return %[[RET]]663// CHECK: }664func.func @tensor.concat_different_shapes(%f: tensor<8x4xf32>, %g: tensor<8x5xf32>) -> tensor<8x9xf32> {665 %t = tensor.concat dim(1) %f, %g : (tensor<8x4xf32>, tensor<8x5xf32>) -> tensor<8x9xf32>666 return %t : tensor<8x9xf32>667}668 669// -----670 671// CHECK-LABEL: func @tensor.concat_dynamic(672// CHECK-SAME: %[[F:.*]]: tensor<8x?xf32>,673// CHECK-SAME: %[[G:.*]]: tensor<8x?xf32>674// CHECK-DAG: %[[F_MEMREF:.*]] = bufferization.to_buffer %[[F]]675// CHECK-DAG: %[[G_MEMREF:.*]] = bufferization.to_buffer %[[G]]676// CHECK-DAG: %[[c1:.*]] = arith.constant 1 : index677// CHECK-DAG: %[[F_DIM:.*]] = memref.dim %[[F_MEMREF]], %[[c1]]678// CHECK-DAG: %[[G_DIM:.*]] = memref.dim %[[G_MEMREF]], %[[c1]]679// CHECK: %[[ALLOC:.*]] = memref.alloc680// CHECK-SAME: memref<8x?xf32>681// CHECK-DAG: %[[OFFSET:.*]] = arith.constant 0 : index682// CHECK: %[[SUBVIEW1:.*]] = memref.subview %[[ALLOC]][0, %[[OFFSET]]] [8, %[[F_DIM]]] [1, 1]683// CHECK: memref.copy %[[F_MEMREF]], %[[SUBVIEW1]]684// CHECK: %[[OFFSET_2:.*]] = arith.addi %[[OFFSET]], %[[F_DIM]] : index685// CHECK: %[[SUBVIEW2:.*]] = memref.subview %[[ALLOC]][0, %[[OFFSET_2]]] [8, %[[G_DIM]]] [1, 1]686// CHECK: memref.copy %[[G_MEMREF]], %[[SUBVIEW2]]687// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[ALLOC]]688// CHECK: return %[[RET]]689// CHECK: }690func.func @tensor.concat_dynamic(%f: tensor<8x?xf32>, %g: tensor<8x?xf32>) -> tensor<8x?xf32> {691 %t = tensor.concat dim(1) %f, %g : (tensor<8x?xf32>, tensor<8x?xf32>) -> tensor<8x?xf32>692 return %t : tensor<8x?xf32>693}694 695// -----696 697// CHECK-LABEL: func @tensor.concat_dynamic_nonconcat_dim(698// CHECK-SAME: %[[F:.*]]: tensor<?x?xf32>,699// CHECK-SAME: %[[G:.*]]: tensor<?x?xf32>700// CHECK-DAG: %[[F_MEMREF:.*]] = bufferization.to_buffer %[[F]]701// CHECK-DAG: %[[G_MEMREF:.*]] = bufferization.to_buffer %[[G]]702// CHECK-DAG: %[[c1:.*]] = arith.constant 1 : index703// CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index704// CHECK-DAG: %[[F_DIM:.*]] = memref.dim %[[F_MEMREF]], %[[c1]]705// CHECK-DAG: %[[G_DIM:.*]] = memref.dim %[[G_MEMREF]], %[[c1]]706// CHECK: %[[ALLOC:.*]] = memref.alloc707// CHECK-SAME: memref<?x?xf32>708// CHECK-DAG: %[[NON_CONCAT_DIM:.*]] = memref.dim %[[ALLOC]], %[[c0]]709// CHECK: %[[SUBVIEW1:.*]] = memref.subview %[[ALLOC]][0, %[[c0]]] [%[[NON_CONCAT_DIM]], %[[F_DIM]]] [1, 1]710// CHECK: memref.copy %[[F_MEMREF]], %[[SUBVIEW1]]711// CHECK: %[[OFFSET_2:.*]] = arith.addi %[[c0]], %[[F_DIM]] : index712// CHECK: %[[SUBVIEW2:.*]] = memref.subview %[[ALLOC]][0, %[[OFFSET_2]]] [%[[NON_CONCAT_DIM]], %[[G_DIM]]] [1, 1]713// CHECK: memref.copy %[[G_MEMREF]], %[[SUBVIEW2]]714// CHECK: %[[RET:.*]] = bufferization.to_tensor %[[ALLOC]]715// CHECK: return %[[RET]]716// CHECK: }717func.func @tensor.concat_dynamic_nonconcat_dim(%f: tensor<?x?xf32>, %g: tensor<?x?xf32>) -> tensor<?x?xf32> {718 %t = tensor.concat dim(1) %f, %g : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>719 return %t : tensor<?x?xf32>720}721 722// -----723 724// CHECK-LABEL: func @tensor.splat_dynamic(725// CHECK-SAME: %[[F:[a-zA-Z0-9_]+]]: f32726// CHECK-SAME: %[[M:[a-zA-Z0-9_]+]]: index727// CHECK-SAME: %[[N:[a-zA-Z0-9_]+]]: index728// CHECK-DAG: %[[ALLOC:.*]] = memref.alloc(%[[M]], %[[N]]) {{.*}} : memref<?x3x?xf32>729// CHECK: %[[ALLOC_T:.*]] = bufferization.to_tensor %[[ALLOC]]730// CHECK: %[[MAPPED:.*]] = linalg.map outs(%[[ALLOC_T]] : tensor<?x3x?xf32>)731// CHECK: (%[[INIT:.*]]: f32) {732// CHECK: linalg.yield %[[F]] : f32733// CHECK: }734// CHECK: return %[[MAPPED]] : tensor<?x3x?xf32>735// CHECK: }736func.func @tensor.splat_dynamic(%f: f32, %m: index, %n: index) -> tensor<?x3x?xf32> {737 %0 = tensor.splat %f[%m, %n] : tensor<?x3x?xf32>738 return %0 : tensor<?x3x?xf32>739}740 741// -----742 743// CHECK-LABEL: func.func @parallel_insert_slice_copy_before_write744func.func @parallel_insert_slice_copy_before_write(%in: tensor<4xf32>, %out: tensor<4xf32>) {745 %c1 = arith.constant 1 : index746 %num_threads = arith.constant 4 : index747 748 // CHECK: scf.forall {{.*}} {749 %result = scf.forall (%thread_idx) in (%num_threads) shared_outs (%o = %out) -> tensor<4xf32> {750 %1 = tensor.extract_slice %in[%thread_idx][1][1] : tensor<4xf32> to tensor<1xf32>751 scf.forall.in_parallel {752 // CHECK: memref.subview %{{.*}}[%{{.*}}] [1] [1] : memref<4xf32> to memref<1xf32, strided<[1], offset: ?>>753 // CHECK: memref.subview %{{.*}}[%{{.*}}] [1] [1] : memref<4xf32> to memref<1xf32, strided<[1], offset: ?>>754 tensor.parallel_insert_slice %1 into %o[%thread_idx][1][1] :755 tensor<1xf32> into tensor<4xf32>756 }757 }758 // CHECK: }759 return760}761 762// -----763 764