brintos

brintos / llvm-project-archived public Read only

0
0
Text · 89.0 KiB · f4020ed Raw
2061 lines · plain
1// RUN: mlir-opt %s -canonicalize="test-convergence" -split-input-file | FileCheck %s2 3// CHECK-LABEL: func @memref_cast(4func.func @memref_cast(%a: index, %b: index) -> memref<?x?xf32> {5  %c0 = arith.constant 0 : index6  %c1 = arith.constant 1 : index7  %c8 = arith.constant 8 : index8  %c16 = arith.constant 16 : index9  %1 = memref.alloc (%b) : memref<?xi8>10  %2 = memref.view %1[%c0][] : memref<?xi8> to memref<16x16xf32>11  %3 = memref.cast %2 : memref<16x16xf32> to memref<?x?xf32>12 13  // CHECK:  linalg.matmul ins({{.*}}memref<16x16xf32>, memref<16x16xf32>) outs({{.*}}memref<16x16xf32>)14  linalg.matmul ins(%3, %3: memref<?x?xf32>, memref<?x?xf32>)15               outs(%3: memref<?x?xf32>)16  return %3: memref<?x?xf32>17}18 19// -----20 21#accesses = [22  affine_map<(i) -> (i)>23]24 25#trait = {26  indexing_maps = #accesses,27  iterator_types = ["parallel"]28}29 30func.func @dce_zero_memref(%arg0 : memref<0xf32>, %arg1: tensor<0xf32>) -> tensor<0xf32> {31  // memref<0x32> is expected to be dce'ed32  memref.copy %arg0, %arg0 : memref<0xf32> to memref<0xf32>33 34  // tensor<0xf32> cannot be dce'ed35  %1 = linalg.generic #trait outs(%arg1 : tensor<0xf32>) {36  ^bb(%0: f32) :37    linalg.yield %0 : f3238  } -> tensor<0xf32>39 40  return %1: tensor<0xf32>41}42// CHECK-LABEL: @dce_zero_memref43//  CHECK-SAME:   %[[ARG0:[a-zA-Z0-9_]+]]: memref<0xf32>44//  CHECK-SAME:   %[[ARG1:[a-zA-Z0-9_]+]]: tensor<0xf32>45//   CHECK-NOT:   memref.copy46//  CHECK-NEXT:   return %[[ARG1]]47 48// -----49 50func.func @dce_self_linalg_copy(%arg0 : memref<?xf32>) {51  linalg.copy ins(%arg0: memref<?xf32>) outs(%arg0: memref<?xf32>)52  return53}54 55// CHECK-LABEL: @dce_self_linalg_copy56//   CHECK-NOT:   copy57 58// -----59 60// CHECK-LABEL: func @tensor.cast(61func.func @tensor.cast(%a : tensor<3x4xf32>, %b : tensor<4x?xf32>, %c : tensor<3x?xf32>)62  -> tensor<3x?xf32>63{64  %ta = tensor.cast %a : tensor<3x4xf32> to tensor<?x?xf32>65  %tb = tensor.cast %b : tensor<4x?xf32> to tensor<?x?xf32>66  %tc = tensor.cast %c : tensor<3x?xf32> to tensor<?x?xf32>67 68  //      CHECK:  linalg.matmul ins({{.*}}tensor<3x4xf32>, tensor<4x?xf32>)69  // CHECK-SAME:    outs({{.*}}tensor<3x?xf32>) -> tensor<3x?xf32>70  %0 = linalg.matmul ins(%ta, %tb: tensor<?x?xf32>, tensor<?x?xf32>)71                    outs(%tc: tensor<?x?xf32>) -> tensor<?x?xf32>72 73  %1 = tensor.cast %0 : tensor<?x?xf32> to tensor<3x?xf32>74 75  return %1: tensor<3x?xf32>76}77 78// -----79 80// CHECK-LABEL: func @tensor.cast.unranked(81func.func @tensor.cast.unranked(%a : tensor<*xf32>, %b : tensor<*xf32>, %c : tensor<*xf32>)82  -> tensor<*xf32>83{84  //      CHECK:  tensor.cast85  //      CHECK:  tensor.cast86  //      CHECK:  tensor.cast87  %ta = tensor.cast %a : tensor<*xf32> to tensor<?x?xf32>88  %tb = tensor.cast %b : tensor<*xf32> to tensor<?x?xf32>89  %tc = tensor.cast %c : tensor<*xf32> to tensor<?x?xf32>90 91  //      CHECK:  linalg.matmul ins({{.*}}tensor<?x?xf32>, tensor<?x?xf32>)92  // CHECK-SAME:    outs({{.*}}tensor<?x?xf32>) -> tensor<?x?xf32>93  %0 = linalg.matmul ins(%ta, %tb: tensor<?x?xf32>, tensor<?x?xf32>)94                    outs(%tc: tensor<?x?xf32>) -> tensor<?x?xf32>95 96  //      CHECK:  tensor.cast97  %1 = tensor.cast %0 : tensor<?x?xf32> to tensor<*xf32>98 99  return %1: tensor<*xf32>100}101 102// -----103 104// CHECK-LABEL: func @linalg_effects(105func.func @linalg_effects(106    %a : tensor<?x?xf32>, %b : tensor<?x?xf32>, %c : tensor<?x?xf32>,107    %d : memref<?x?xf32>, %e : memref<?x?xf32>, %f : memref<?x?xf32>) {108  // CHECK-NOT:   %{{.*}} = linalg.matmul109  %t = linalg.matmul ins(%a, %b : tensor<?x?xf32>, tensor<?x?xf32>)110                    outs(%c : tensor<?x?xf32>) -> tensor<?x?xf32>111 112  // CHECK:   linalg.matmul113  linalg.matmul ins(%d, %e : memref<?x?xf32>, memref<?x?xf32>)114               outs(%f : memref<?x?xf32>)115  return116}117 118// -----119 120#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)>121func.func @remove_no_op(%arg0 : tensor<?x?x?xf32>, %arg1 : tensor<?x?x?xf32>)122  -> (tensor<?x?x?xf32>, tensor<?x?x?xf32>) {123  %c0 = arith.constant 0 : index124  %c1 = arith.constant 1 : index125  %c2 = arith.constant 2 : index126  %0 = tensor.dim %arg0, %c0 : tensor<?x?x?xf32>127  %1 = tensor.dim %arg0, %c1 : tensor<?x?x?xf32>128  %2 = tensor.dim %arg0, %c2 : tensor<?x?x?xf32>129  %3 = tensor.empty(%0, %1, %2) : tensor<?x?x?xf32>130  %4, %5 = linalg.generic {131    indexing_maps = [#map, #map, #map, #map],132    iterator_types = ["parallel", "parallel", "parallel"]133  } ins(%arg0, %arg1 : tensor<?x?x?xf32>, tensor<?x?x?xf32>)134    outs(%3, %3 : tensor<?x?x?xf32>, tensor<?x?x?xf32>) {135  ^bb0(%arg2 : f32, %arg3 : f32, %arg4 : f32, %arg5 : f32):136    linalg.yield %arg3, %arg2 : f32, f32137  } -> (tensor<?x?x?xf32>, tensor<?x?x?xf32>)138  return %4, %5 : tensor<?x?x?xf32>, tensor<?x?x?xf32>139}140// CHECK-LABEL: func @remove_no_op141//  CHECK-SAME:   %[[ARG0:[a-zA-Z0-9_]+]]: tensor<?x?x?xf32>142//  CHECK-SAME:   %[[ARG1:[a-zA-Z0-9_]+]]: tensor<?x?x?xf32>143//       CHECK:     return %[[ARG1]], %[[ARG0]]144 145// -----146 147#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)>148func.func @remove_no_op_mismatched_types(%arg0 : tensor<?x?x?xf32>)149  -> tensor<1x2x3xf32> {150  %out = tensor.empty() : tensor<1x2x3xf32>151  %g = linalg.generic {152    indexing_maps = [#map, #map],153    iterator_types = ["parallel", "parallel", "parallel"]154  } ins(%arg0 : tensor<?x?x?xf32>)155    outs(%out : tensor<1x2x3xf32>) {156  ^bb0(%arg2 : f32, %arg3 : f32):157    linalg.yield %arg2 : f32158  } -> (tensor<1x2x3xf32>)159  return %g : tensor<1x2x3xf32>160}161// CHECK-LABEL: func @remove_no_op_mismatched_types162//  CHECK-SAME:   %[[ARG0:[a-zA-Z0-9_]+]]: tensor<?x?x?xf32>163//       CHECK:     %[[CAST:.*]] = tensor.cast %[[ARG0]] : tensor<?x?x?xf32> to tensor<1x2x3xf32>164//       CHECK:     return %[[CAST]]165 166// -----167 168#map = affine_map<() -> ()>169func.func @cant_fold_to_tensor_cast(%arg0 : f32) -> tensor<f32> {170  %out = tensor.empty() : tensor<f32>171  %g = linalg.generic {172    indexing_maps = [#map, #map],173    iterator_types = []174  } ins(%arg0 : f32)175    outs(%out : tensor<f32>) {176  ^bb0(%arg2 : f32, %arg3 : f32):177    linalg.yield %arg2 : f32178  } -> (tensor<f32>)179  return %g : tensor<f32>180}181// CHECK-LABEL: func @cant_fold_to_tensor_cast182//       CHECK:     linalg.generic183 184// -----185 186#map = affine_map<(d0, d1) -> (d0, d1)>187func.func @keep_not_noop(%arg0 : tensor<?x?xf32>) -> tensor<?x?xf32> {188  %c0 = arith.constant 0 : index189  %c1 = arith.constant 1 : index190  %cst = arith.constant 1.000000e+00 : f32191  %0 = tensor.dim %arg0, %c0 : tensor<?x?xf32>192  %1 = tensor.dim %arg0, %c1 : tensor<?x?xf32>193  %2 = tensor.empty(%0, %1) : tensor<?x?xf32>194  cf.br ^bb1(%cst : f32)195 196^bb1(%arg1 : f32):197  %3 = linalg.generic198    {indexing_maps = [#map, #map], iterator_types = ["parallel", "parallel"]}199    ins(%arg0 : tensor<?x?xf32>) outs(%2 : tensor<?x?xf32>) {200    ^bb0(%arg2: f32, %arg3 : f32):201      linalg.yield %arg1 : f32202    } -> tensor<?x?xf32>203  return %3 : tensor<?x?xf32>204}205// CHECK-LABEL: func @keep_not_noop206//       CHECK:   %[[RESULT:.+]] = linalg.generic207//       CHECK:   return %[[RESULT]]208 209// -----210 211#map = affine_map<(d0, d1) -> (d0, d1)>212func.func @keep_not_noop(%arg0 : tensor<?x?xf32>, %arg1 : tensor<?x?xf32>)213  -> (tensor<?x?xf32>, tensor<?x?xf32>) {214  %c0 = arith.constant 0 : index215  %c1 = arith.constant 1 : index216  %cst = arith.constant 1.000000e+00 : f32217  %0 = tensor.dim %arg0, %c0 : tensor<?x?xf32>218  %1 = tensor.dim %arg0, %c1 : tensor<?x?xf32>219  %2 = tensor.empty(%0, %1) : tensor<?x?xf32>220  cf.br ^bb1(%cst : f32)221 222^bb1(%arg2 : f32):223  %3:2 = linalg.generic224    {indexing_maps = [#map, #map, #map, #map],225     iterator_types = ["parallel", "parallel"]}226    ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)227    outs(%2, %2 : tensor<?x?xf32>, tensor<?x?xf32>) {228    ^bb0(%arg3: f32, %arg4 : f32, %arg5 : f32, %arg6 : f32):229      linalg.yield %arg2, %arg4 : f32, f32230    } -> (tensor<?x?xf32>, tensor<?x?xf32>)231  return %3#0, %3#1 : tensor<?x?xf32>, tensor<?x?xf32>232}233// CHECK-LABEL: func @keep_not_noop234//       CHECK:   %[[RESULT:.+]]:2 = linalg.generic235//       CHECK:   return %[[RESULT]]#0, %[[RESULT]]#1236 237// -----238 239#accesses = [240  affine_map<(i, j) -> (i, j)>241]242 243#trait = {244  indexing_maps = #accesses,245  iterator_types = ["parallel", "parallel"]246}247 248// CHECK-LABEL: func @dead_linalg_tensor249//   CHECK-NOT:   linalg.fill250//   CHECK-NOT:   linalg.matmul251//   CHECK-NOT:   linalg.generic252//   CHECK-NOT:   tensor.pad253//       CHECK:   return254func.func @dead_linalg_tensor(%arg0 : tensor<7x7xi32>, %arg1 : tensor<7x7xf32>,255                         %arg2: tensor<?x?xf32>, %high : index) {256  %c0_i32 = arith.constant 0 : i32257  %c0 = arith.constant 0 : index258  %cst = arith.constant 0.000000e+00 : f32259  %0 = linalg.fill ins(%c0_i32 : i32) outs(%arg0 : tensor<7x7xi32>) -> tensor<7x7xi32>260  %1 = linalg.matmul ins(%arg1, %arg1: tensor<7x7xf32>, tensor<7x7xf32>)261                     outs(%arg1: tensor<7x7xf32>) -> tensor<7x7xf32>262  %2 = linalg.generic #trait outs(%arg0 : tensor<7x7xi32>) {263  ^bb(%3: i32) :264    linalg.yield %3 : i32265  } -> tensor<7x7xi32>266  %3 = tensor.pad %arg2 low[%c0, %c0] high[%high, %high] {267        ^bb0(%arg9: index, %arg10: index):268          tensor.yield %cst : f32269  } : tensor<?x?xf32> to tensor<2x4xf32>270  return271}272 273// -----274 275func.func @propagate_casts(%arg0 : tensor<?x?xf32>, %arg1 : f32, %arg2 : index,276    %arg3 : index) -> tensor<?x?xf32> {277  %c0 = arith.constant 0 : index278  %c1 = arith.constant 1 : index279  %c21 = arith.constant 21 : index280  %c42 = arith.constant 42 : index281  %0 = tensor.empty(%c21, %c42) : tensor<?x?xf32>282  %1 = linalg.fill ins(%arg1 : f32) outs(%0 : tensor<?x?xf32>) -> tensor<?x?xf32>283  %2 = tensor.dim %arg0, %c0 : tensor<?x?xf32>284  %3 = tensor.dim %arg0, %c1 : tensor<?x?xf32>285  %4 = tensor.insert_slice %arg0 into %1[%arg2, %arg3] [%2, %3] [1, 1] : tensor<?x?xf32> into tensor<?x?xf32>286  return %4 : tensor<?x?xf32>287}288// CHECK-LABEL: func @propagate_casts289//       CHECK:   %[[INIT:.+]] = tensor.empty290//       CHECK:   %[[FILL:.+]] = linalg.fill ins(%{{.+}}{{.*}}outs(%[[INIT]]291//       CHECK:   %[[INSERTED:.+]] = tensor.insert_slice %{{.+}} into %[[FILL]]292//       CHECK:   %[[RESULT:.+]] = tensor.cast %[[INSERTED]]293//       CHECK:   return %[[RESULT]]294 295// -----296 297// CHECK-LABEL: @self_copy298func.func @self_copy(%arg0 : memref<2x3x?x4xf32>) {299 300//   CHECK-NOT: memref.copy301  memref.copy %arg0, %arg0 : memref<2x3x?x4xf32> to memref<2x3x?x4xf32>302 303//   CHECK: return304  return305}306 307// -----308 309// CHECK: func @fold_linalg_index_tensor_static310func.func @fold_linalg_index_tensor_static(%0: tensor<4x16xi32>, %1: tensor<1x16xi32>,311                                           %2: tensor<4x1xi32>) -> tensor<4x1xi32> {312// CHECK-NEXT: linalg.generic313// CHECK:        %[[IDX_0:.+]] = linalg.index 0 : index314// CHECK-NOT:    linalg.index 1315// CHECK:        %[[IDX_2:.+]] = linalg.index 2 : index316// CHECK:        %[[ADD:.+]] = arith.addi %[[IDX_0]], %[[IDX_2]]317// CHECK:        %[[CAST:.+]] = arith.index_cast %[[ADD]]318// CHECK:        linalg.yield %[[CAST]]319  %res = linalg.generic {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>,320                                          affine_map<(d0, d1, d2) -> (d1, d2)>,321                                          affine_map<(d0, d1, d2) -> (d0, d1)>],322                         iterator_types = ["parallel", "parallel", "reduction"]}323    ins(%0, %1 : tensor<4x16xi32>, tensor<1x16xi32>)324    outs(%2 : tensor<4x1xi32>) {325      ^bb0(%lhs: i32, %rhs: i32, %out: i32):326        %idx0 = linalg.index 0 : index327        %idx1 = linalg.index 1 : index328        %idx2 = linalg.index 2 : index329        %add0 = arith.addi %idx0, %idx1 : index330        %add1 = arith.addi %add0, %idx2 : index331        %int = arith.index_cast %add1 : index to i32332        linalg.yield %int : i32333    } -> tensor<4x1xi32>334  return %res : tensor<4x1xi32>335}336 337// -----338 339// CHECK: func @fold_linalg_index_tensor_dynamic340func.func @fold_linalg_index_tensor_dynamic(%0: tensor<?x1xi32>,341                                            %1: tensor<?x1xi32>) -> tensor<?x1xi32> {342// CHECK-NEXT: linalg.generic343// CHECK:        %[[IDX_0:.+]] = linalg.index 0 : index344// CHECK-NOT:    linalg.index 1345// CHECK:        %[[CAST:.+]] = arith.index_cast %[[IDX_0]]346// CHECK:        linalg.yield %[[CAST]]347  %res = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,348                                          affine_map<(d0, d1) -> (d1, d1)>],349                         iterator_types = ["parallel", "parallel"]}350    ins(%0 : tensor<?x1xi32>)351    outs(%1 : tensor<?x1xi32>) {352      ^bb0(%lhs: i32, %out: i32):353        %idx0 = linalg.index 0 : index354        %idx1 = linalg.index 1 : index355        %add = arith.addi %idx0, %idx1 : index356        %int = arith.index_cast %add : index to i32357        linalg.yield %int : i32358    } -> tensor<?x1xi32>359  return %res : tensor<?x1xi32>360}361 362// -----363 364// CHECK: func @fold_linalg_index_memref365func.func @fold_linalg_index_memref(%0: memref<1x?xi32>, %1: memref<1x?xi32>) {366// CHECK-NEXT: linalg.generic367// CHECK-NOT:    linalg.index 0368// CHECK:        %[[IDX_1:.+]] = linalg.index 1 : index369// CHECK:        %[[CAST:.+]] = arith.index_cast %[[IDX_1]]370// CHECK:        linalg.yield %[[CAST]]371  linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,372                                   affine_map<(d0, d1) -> (d1, d1)>],373                  iterator_types = ["parallel", "parallel"]}374    ins(%0 : memref<1x?xi32>)375    outs(%1 : memref<1x?xi32>) {376      ^bb0(%lhs: i32, %out: i32):377        %idx0 = linalg.index 0 : index378        %idx1 = linalg.index 1 : index379        %add = arith.addi %idx0, %idx1 : index380        %int = arith.index_cast %add : index to i32381        linalg.yield %int : i32382    }383  return384}385 386// -----387 388// CHECK-LABEL: func @fold_fill_reshape()389func.func @fold_fill_reshape() -> tensor<6x4xf32> {390  %zero = arith.constant 0.0 : f32391  %empty = tensor.empty() : tensor<1x2x3x4xf32>392  // CHECK:      %[[COLLAPSE:.+]] = tensor.collapse_shape393  // CHECK-NEXT: %[[FILL:.+]] = linalg.fill ins(%cst : f32)394  // CHECK-SAME:   outs(%[[COLLAPSE]] : tensor<6x4xf32>)395  %fill = linalg.fill ins(%zero : f32) outs(%empty : tensor<1x2x3x4xf32>) -> tensor<1x2x3x4xf32>396  %reshape = tensor.collapse_shape %fill [[0, 1, 2], [3]]397      : tensor<1x2x3x4xf32> into tensor<6x4xf32>398  // CHECK: return %[[FILL]] : tensor<6x4xf32>399  return %reshape : tensor<6x4xf32>400}401 402// -----403 404//       CHECK: func @fold_fill_reshape_dynamic405//  CHECK-SAME:   %[[ARG0:.+]]: tensor<?x?x?x?x?xf32>406func.func @fold_fill_reshape_dynamic(%arg0 : tensor<?x?x?x?x?xf32>) -> tensor<?x?xf32> {407  %zero = arith.constant 0.0 : f32408  // CHECK: %[[RESHAPE:.+]] = tensor.collapse_shape %[[ARG0]]409  %0 = linalg.fill ins(%zero : f32) outs(%arg0 : tensor<?x?x?x?x?xf32>) -> tensor<?x?x?x?x?xf32>410  // CHECK: %[[RESULT:.+]] = linalg.fill ins(%{{.+}}{{.*}}outs(%[[RESHAPE]]411  %1 = tensor.collapse_shape %0 [[0, 1, 2], [3, 4]]412      : tensor<?x?x?x?x?xf32> into tensor<?x?xf32>413  // CHECK: return %[[RESULT]]414  return %1 : tensor<?x?xf32>415}416 417// -----418//       CHECK: func @fold_fill_extract419//  CHECK-SAME:   %[[ARG0:.+]]: i1420func.func @fold_fill_extract(%arg0 : i1) -> i1 {421  %c0 = arith.constant 0 : index422  %c1 = arith.constant 1 : index423 424  %empty_dynamic = tensor.empty(%c1) : tensor<1x2x3x?xi1>425  %filled = linalg.fill ins(%arg0 : i1) outs(%empty_dynamic : tensor<1x2x3x?xi1>) -> tensor<1x2x3x?xi1>426 427  %extracted = tensor.extract %filled[%c0, %c0, %c0, %c0] : tensor<1x2x3x?xi1>428 429  //  CHECK:   return %[[ARG0]]430  return %extracted : i1431}432 433// -----434 435func.func @fill_pack() -> tensor<24x32x16x16xf32> {436  %dest = tensor.empty() : tensor<384x512xf32>437  %cst = arith.constant 0.000000e+00 : f32438  %0 = tensor.empty() : tensor<24x32x16x16xf32>439  %1 = linalg.fill ins(%cst : f32) outs(%dest : tensor<384x512xf32>) -> tensor<384x512xf32>440  %pack = linalg.pack %1 inner_dims_pos = [0, 1] inner_tiles = [16, 16] into %0 : tensor<384x512xf32> -> tensor<24x32x16x16xf32>441  return %pack : tensor<24x32x16x16xf32>442}443// CHECK-LABEL: func.func @fill_pack444// CHECK:         %[[PACKED_EMPTY:.+]] = tensor.empty() : tensor<24x32x16x16xf32>445// CHECK:         %[[FILL:.+]] = linalg.fill ins(%{{.+}}) outs(%[[PACKED_EMPTY]]446// CHECK:         return %[[FILL]]447 448// -----449 450func.func @fill_pack_general() -> tensor<1x1x8x4x4x8xi32>{451  %c0_i32 = arith.constant 0 : i32452  %alloc = memref.alloc() : memref<1x1x8x4x4x8xi32>453  %9 = tensor.empty() : tensor<1x1x16x64xi32>454  %extracted_slice_15 = tensor.extract_slice %9[0, 0, 0, 0] [1, 1, 16, 64] [1, 1, 1, 1] : tensor<1x1x16x64xi32> to tensor<1x1x16x64xi32>455  %16 = linalg.fill ins(%c0_i32 : i32) outs(%extracted_slice_15 : tensor<1x1x16x64xi32>) -> tensor<1x1x16x64xi32>456  %0 = bufferization.to_tensor %alloc restrict writable : memref<1x1x8x4x4x8xi32> to tensor<1x1x8x4x4x8xi32>457  %pack_18 = linalg.pack %16 outer_dims_perm = [0, 1, 3, 2] inner_dims_pos = [2, 3] inner_tiles = [4, 8] into %0 : tensor<1x1x16x64xi32> -> tensor<1x1x8x4x4x8xi32>458  return %pack_18 : tensor<1x1x8x4x4x8xi32>459}460 461// CHECK-LABEL: func.func @fill_pack_general462// CHECK:         %[[ALLOC:.+]] = memref.alloc() : memref<1x1x8x4x4x8xi32>463// CHECK:         %[[TENSOR:.+]] = bufferization.to_tensor %[[ALLOC]]464// CHECK:         %[[FILL:.+]] = linalg.fill ins(%{{.+}}) outs(%[[TENSOR]]465// CHECK:         return %[[FILL]]466 467// -----468 469#map = affine_map<()[s0] -> (s0 ceildiv 16)>470func.func @dynamic_fill_pack(%arg0: tensor<?x?xf32>) -> tensor<?x?x16x16xf32> {471  %cst = arith.constant 0.000000e+00 : f32472  %c0 = arith.constant 0 : index473  %c1 = arith.constant 1 : index474  %0 = linalg.fill ins(%cst : f32) outs(%arg0 : tensor<?x?xf32>) -> tensor<?x?xf32>475  %dim = tensor.dim %0, %c0 : tensor<?x?xf32>476  %dim_0 = tensor.dim %0, %c1 : tensor<?x?xf32>477  %1 = affine.apply #map()[%dim]478  %2 = affine.apply #map()[%dim_0]479  %3 = tensor.empty(%1, %2) : tensor<?x?x16x16xf32>480  %pack = linalg.pack %0 padding_value(%cst : f32) inner_dims_pos = [0, 1] inner_tiles = [16, 16] into %3 : tensor<?x?xf32> -> tensor<?x?x16x16xf32>481  return %pack : tensor<?x?x16x16xf32>482}483// CHECK-DAG:   #[[MAP:.+]] = affine_map<()[s0] -> (s0 ceildiv 16)>484// CHECK:       func.func @dynamic_fill_pack485// CHECK-SAME:    %[[DEST:[a-zA-Z0-9]+]]486// CHECK-DAG:     %[[C0:.+]] = arith.constant 0 : index487// CHECK-DAG:     %[[C1:.+]] = arith.constant 1 : index488// CHECK:         %[[D0:.+]] = tensor.dim %[[DEST]], %[[C0]]489// CHECK:         %[[D1:.+]] = tensor.dim %[[DEST]], %[[C1]]490// CHECK:         %[[PACKED_D0:.+]] = affine.apply #[[MAP]]()[%[[D0]]]491// CHECK:         %[[PACKED_D1:.+]] = affine.apply #[[MAP]]()[%[[D1]]]492// CHECK:         %[[PACKED_EMPTY:.+]] = tensor.empty(%[[PACKED_D0]], %[[PACKED_D1]]) : tensor<?x?x16x16xf32>493// CHECK:         %[[FILL:.+]] = linalg.fill ins(%{{.+}}) outs(%[[PACKED_EMPTY]]494// CHECK:         return %[[FILL]]495 496// -----497 498// CHECK-LABEL: func @fold_self_copy499func.func @fold_self_copy(%0 : memref<4x16xf32>) {500// CHECK-NEXT: return501  linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,502                                   affine_map<(d0, d1) -> (d0, d1)>],503                  iterator_types = ["parallel", "parallel"]}504    ins(%0 : memref<4x16xf32>)505    outs(%0 : memref<4x16xf32>) {506      ^bb0(%arg4: f32, %arg5: f32):507        linalg.yield %arg4 : f32508    }509  return510}511 512// -----513 514// CHECK-LABEL: func @no_fold_fill_like_memref515//  CHECK-NEXT:   linalg.generic 516func.func @no_fold_fill_like_memref(%in_out : memref<4x16xf32>, %fill_val : f32) {517  linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,518                                   affine_map<(d0, d1) -> (d0, d1)>],519                  iterator_types = ["parallel", "parallel"]}520    ins(%in_out : memref<4x16xf32>)521    outs(%in_out : memref<4x16xf32>) {522      ^bb0(%arg0: f32, %arg1: f32):523        linalg.yield %fill_val : f32524  }525  return526}527 528// -----529 530// CHECK-LABEL: func @no_fold_fill_like_tensor531//  CHECK-NEXT:   linalg.generic 532func.func @no_fold_fill_like_tensor(%in_out : tensor<4x16xf32>, %fill_val : f32) -> tensor<4x16xf32> {533  %result = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,534                                   affine_map<(d0, d1) -> (d0, d1)>],535                  iterator_types = ["parallel", "parallel"]}536    ins(%in_out : tensor<4x16xf32>)537    outs(%in_out : tensor<4x16xf32>) {538      ^bb0(%arg0: f32, %arg1: f32):539        linalg.yield %fill_val : f32540  } -> tensor<4x16xf32>541  return %result : tensor<4x16xf32>542}543 544// CHECK-LABEL: func @fold_static_pad_fill545//       CHECK:   %[[F0:.+]] = arith.constant 0.000000e+00 : f32546//       CHECK:   %[[INIT:.+]] = tensor.empty() : tensor<412x276xf32>547//       CHECK:   %[[FILL:.+]] = linalg.fill ins(%[[F0]]{{.*}}outs(%[[INIT]]548//       CHECK:   return %[[FILL]]549func.func @fold_static_pad_fill() -> tensor<412x276xf32> {550  %f0 = arith.constant 0.0 : f32551  %empty = tensor.empty() : tensor<400x273xf32>552  %fill = linalg.fill ins(%f0 : f32) outs(%empty : tensor<400x273xf32>) -> tensor<400x273xf32>553  %pad = tensor.pad %fill low[4, 1] high[8, 2] {554  ^bb0(%arg1: index, %arg2: index):555    tensor.yield %f0 : f32556  } : tensor<400x273xf32> to tensor<412x276xf32>557  return %pad : tensor<412x276xf32>558}559 560// -----561 562// CHECK: #[[MAP0:.+]] = affine_map<()[s0] -> (s0 + 9)>563// CHECK: #[[MAP1:.+]] = affine_map<()[s0] -> (s0 + 10)>564// CHECK: #[[MAP2:.+]] = affine_map<()[s0] -> (s0 + 23)>565// CHECK: #[[MAP3:.+]] = affine_map<()[s0, s1] -> (s0 + s1 + 32)>566 567//      CHECK: func @fold_dynamic_pad_fill568// CHECK-SAME: %[[SRC:.+]]: tensor<8x?x16x32xf32>, %[[LOW0:.+]]: index, %[[LOW3:.+]]: index, %[[HIGH2:.+]]: index, %[[HIGH3:.+]]: index569 570//  CHECK-DAG:   %[[I1:.+]] = arith.constant 1 : index571//  CHECK-DAG:   %[[F0:.+]] = arith.constant 0.000000e+00 : f32572//      CHECK:   %[[S0:.+]] = affine.apply #[[MAP0]]()[%[[LOW0]]]573//      CHECK:   %[[DIM1:.+]] = tensor.dim %[[SRC]], %[[I1]] : tensor<8x?x16x32xf32>574//      CHECK:   %[[S1:.+]] = affine.apply #[[MAP1]]()[%[[DIM1]]]575//      CHECK:   %[[S2:.+]] = affine.apply #[[MAP2]]()[%[[HIGH2]]]576//      CHECK:   %[[S3:.+]] = affine.apply #[[MAP3]]()[%[[LOW3]], %[[HIGH3]]]577//      CHECK:   %[[INIT:.+]] = tensor.empty(%[[S0]], %[[S1]], %[[S2]], %[[S3]]) : tensor<?x?x?x?xf32>578//      CHECK:   %[[FILL:.+]] = linalg.fill ins(%[[F0]]{{.*}}outs(%[[INIT]]579//      CHECK:   return %[[FILL]]580func.func @fold_dynamic_pad_fill(%empty: tensor<8x?x16x32xf32>, %low0: index, %low3: index, %high2: index, %high3: index) -> tensor<?x?x?x?xf32> {581  %f0 = arith.constant 0.0 : f32582  %fill = linalg.fill ins(%f0 : f32) outs(%empty : tensor<8x?x16x32xf32>) -> tensor<8x?x16x32xf32>583  %pad = tensor.pad %fill low[%low0, 8, 7, %low3] high[1, 2, %high2, %high3] {584  ^bb0(%arg1: index, %arg2: index, %arg3: index, %arg4: index):585    tensor.yield %f0 : f32586  } : tensor<8x?x16x32xf32> to tensor<?x?x?x?xf32>587  return %pad : tensor<?x?x?x?xf32>588}589 590// -----591 592// CHECK-LABEL: func @no_fold_pad_fill_value_mismatch593func.func @no_fold_pad_fill_value_mismatch() -> tensor<412x276xf32> {594  %f0 = arith.constant 0.0 : f32595  %f1 = arith.constant 1.0 : f32596  %empty = tensor.empty() : tensor<400x273xf32>597  %fill = linalg.fill ins(%f0 : f32) outs(%empty : tensor<400x273xf32>) -> tensor<400x273xf32>598  // CHECK: tensor.pad599  %pad = tensor.pad %fill low[4, 1] high[8, 2] {600  ^bb0(%arg1: index, %arg2: index):601    tensor.yield %f1 : f32602  } : tensor<400x273xf32> to tensor<412x276xf32>603  return %pad : tensor<412x276xf32>604}605 606// -----607 608// Tests below verify whether static information is propagated through all the operands of generic op.609// 1. If one of the inputs of generic op has static info and it has no cast source.610// 2. If one of the inputs of generic op has static info and it is coming from tensr.cast operation.611// 3. If one of the outputs of generic op has static info and it is coming from tenso.cast operation.612#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)>613// CHECK-LABEL: func @static_input_without_cast614// CHECK-SAME:  (%[[ARG0:.*]]: tensor<2x3x4xf32>, %[[ARG1:.*]]: tensor<?x?x?xf32>) -> tensor<2x3x4xf32> {615func.func @static_input_without_cast(%arg0 : tensor<2x3x4xf32>, %arg1: tensor<?x?x?xf32>) -> tensor<2x3x4xf32> {616  %c0 = arith.constant 0 : index617  %c1 = arith.constant 1 : index618  %c2 = arith.constant 2 : index619  %0 = tensor.dim %arg0, %c0 : tensor<2x3x4xf32>620  %1 = tensor.dim %arg0, %c1 : tensor<2x3x4xf32>621  %2 = tensor.dim %arg0, %c2 : tensor<2x3x4xf32>622  %3 = tensor.empty(%0, %1, %2) : tensor<?x?x?xf32>623  %4 = linalg.generic {624    indexing_maps = [#map, #map, #map],625    iterator_types = ["parallel", "parallel", "parallel"]626  } ins(%arg0, %arg1 : tensor<2x3x4xf32>, tensor<?x?x?xf32>)627    outs(%3 : tensor<?x?x?xf32>) {628  ^bb0(%arg2 : f32, %arg3 : f32, %arg4 : f32):629    %9 = arith.addf %arg2, %arg3 : f32630    linalg.yield %9 : f32631  } -> (tensor<?x?x?xf32>)632  %5 = tensor.cast %4 : tensor<?x?x?xf32> to tensor<2x3x4xf32>633  return %5 : tensor<2x3x4xf32>634    //  CHECK:      %[[CAST_ARG1:.*]] = tensor.cast %[[ARG1]] : tensor<?x?x?xf32> to tensor<2x3x4xf32>635    //  CHECK-NEXT: %[[GENERIC_OP:.*]] = linalg.generic636    //  CHECK-SAME: ins(%[[ARG0]], %[[CAST_ARG1]] : tensor<2x3x4xf32>, tensor<2x3x4xf32>)637    //  CHECK-SAME: outs({{.*}} : tensor<2x3x4xf32>)638}639 640// -----641 642#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)>643// CHECK-LABEL: func @static_input_with_cast644// CHECK-SAME:  (%[[ARG0:.*]]: tensor<2x3x4xf32>, %[[ARG1:.*]]: tensor<?x?x?xf32>) -> tensor<2x3x4xf32> {645func.func @static_input_with_cast(%arg0 : tensor<2x3x4xf32>, %arg1: tensor<?x?x?xf32>) -> tensor<2x3x4xf32> {646  %c0 = arith.constant 0 : index647  %c1 = arith.constant 1 : index648  %c2 = arith.constant 2 : index649  %0 = tensor.dim %arg0, %c0 : tensor<2x3x4xf32>650  %1 = tensor.dim %arg0, %c1 : tensor<2x3x4xf32>651  %2 = tensor.dim %arg0, %c2 : tensor<2x3x4xf32>652  %3 = tensor.empty(%0, %1, %2) : tensor<?x?x?xf32>653  %4 = tensor.cast %arg1 : tensor<?x?x?xf32> to tensor<2x?x?xf32>654  %5 = linalg.generic {655    indexing_maps = [#map, #map, #map],656    iterator_types = ["parallel", "parallel", "parallel"]657  } ins(%arg0, %4 : tensor<2x3x4xf32>, tensor<2x?x?xf32>)658    outs(%3 : tensor<?x?x?xf32>) {659  ^bb0(%arg2 : f32, %arg3 : f32, %arg4 : f32):660    %9 = arith.addf %arg2, %arg3 : f32661    linalg.yield %9 : f32662  } -> (tensor<?x?x?xf32>)663  %6 = tensor.cast %5 : tensor<?x?x?xf32> to tensor<2x3x4xf32>664  return %6: tensor<2x3x4xf32>665    //  CHECK:      %[[CAST_ARG1:.*]] = tensor.cast %[[ARG1]] : tensor<?x?x?xf32> to tensor<2x3x4xf32>666    //  CHECK-NEXT: %[[GENERIC_OP:.*]] = linalg.generic667    //  CHECK-SAME: ins(%[[ARG0]], %[[CAST_ARG1]] : tensor<2x3x4xf32>, tensor<2x3x4xf32>)668    //  CHECK-SAME: outs({{.*}} : tensor<2x3x4xf32>)669}670 671// -----672 673#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)>674// CHECK-LABEL: func @static_output_with_cast675// CHECK-SAME:  (%[[ARG0:.*]]: tensor<?x?x?xf32>, %[[ARG1:.*]]: tensor<?x?x?xf32>, %[[ARG2:.*]]: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> {676func.func @static_output_with_cast(%arg0 : tensor<?x?x?xf32>, %arg1: tensor<?x?x?xf32>, %arg2: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> {677  %c0 = arith.constant 0 : index678  %c1 = arith.constant 1 : index679  %c2 = arith.constant 2 : index680  %0 = tensor.dim %arg2, %c0 : tensor<2x3x4xf32>681  %1 = tensor.dim %arg2, %c1 : tensor<2x3x4xf32>682  %2 = tensor.dim %arg2, %c2 : tensor<2x3x4xf32>683  %3 = tensor.empty(%0, %1, %2) : tensor<?x?x?xf32>684  %4 = tensor.cast %3 : tensor<?x?x?xf32> to tensor<2x3x4xf32>685  %5 = tensor.cast %arg1 : tensor<?x?x?xf32> to tensor<2x?x?xf32>686  %6 = linalg.generic {687    indexing_maps = [#map, #map, #map],688    iterator_types = ["parallel", "parallel", "parallel"]689  } ins(%arg0, %5 : tensor<?x?x?xf32>, tensor<2x?x?xf32>)690    outs(%4 : tensor<2x3x4xf32>) {691  ^bb0(%arg3 : f32, %arg4 : f32, %arg5 : f32):692    %9 = arith.addf %arg3, %arg4 : f32693    linalg.yield %9 : f32694  } -> (tensor<2x3x4xf32>)695  return %6: tensor<2x3x4xf32>696    //  CHECK:      %[[CAST_ARG0:.*]] = tensor.cast %[[ARG0]] : tensor<?x?x?xf32> to tensor<2x3x4xf32>697    //  CHECK-NEXT: %[[CAST_ARG1:.*]] = tensor.cast %[[ARG1]] : tensor<?x?x?xf32> to tensor<2x3x4xf32>698    //  CHECK-NEXT: %[[GENERIC_OP:.*]] = linalg.generic699    //  CHECK-SAME: ins(%[[CAST_ARG0]], %[[CAST_ARG1]] : tensor<2x3x4xf32>, tensor<2x3x4xf32>)700    //  CHECK-SAME: outs({{.*}} : tensor<2x3x4xf32>)701}702 703// -----704 705// This test checks the folding of tensor.cast operation when the source value of cast706// has more static information than the destination value.707#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)>708// CHECK-LABEL: func @cast_source709// CHECK-SAME:  (%[[ARG0:.*]]: tensor<2x3x4xf32>, %[[ARG1:.*]]: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> {710func.func @cast_source(%arg0 : tensor<2x3x4xf32>, %arg1: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> {711  %c0 = arith.constant 0 : index712  %c1 = arith.constant 1 : index713  %c2 = arith.constant 2 : index714  %0 = tensor.dim %arg0, %c0 : tensor<2x3x4xf32>715  %1 = tensor.dim %arg0, %c1 : tensor<2x3x4xf32>716  %2 = tensor.dim %arg0, %c2 : tensor<2x3x4xf32>717  %3 = tensor.empty(%0, %1, %2) : tensor<?x?x?xf32>718  %4 = tensor.cast %arg0 : tensor<2x3x4xf32> to tensor<2x?x?xf32>719  %5 = tensor.cast %arg1 : tensor<2x3x4xf32> to tensor<2x?x?xf32>720  %6 = linalg.generic {721    indexing_maps = [#map, #map, #map],722    iterator_types = ["parallel", "parallel", "parallel"]723  } ins(%4, %5 : tensor<2x?x?xf32>, tensor<2x?x?xf32>)724    outs(%3 : tensor<?x?x?xf32>) {725  ^bb0(%arg2 : f32, %arg3 : f32, %arg4 : f32):726    %9 = arith.addf %arg2, %arg3 : f32727    linalg.yield %9 : f32728  } -> (tensor<?x?x?xf32>)729  %7 = tensor.cast %6 : tensor<?x?x?xf32> to tensor<2x3x4xf32>730  return %7: tensor<2x3x4xf32>731    //  CHECK:      %[[GENERIC_OP:.*]] = linalg.generic732    //  CHECK-SAME: ins(%[[ARG0]], %[[ARG1]] : tensor<2x3x4xf32>, tensor<2x3x4xf32>)733    //  CHECK-SAME: outs({{.*}} : tensor<2x3x4xf32>)734}735 736// -----737 738#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)>739// CHECK-LABEL: func @cast_dest740// CHECK-SAME:  (%[[ARG0:.*]]: tensor<?x?x?xf32>, %[[ARG1:.*]]: tensor<1x?x?xf32>,741func.func @cast_dest(%arg0: tensor<?x?x?xf32>, %arg1: tensor<1x?x?xf32>, %arg2: index, %arg3: index, %arg4: index) -> tensor<?x?x?xf32> {742  %0 = tensor.empty(%arg2, %arg3, %arg4) : tensor<?x?x?xf32>743  %1 = tensor.cast %arg1 : tensor<1x?x?xf32> to tensor<?x?x?xf32>744  %2 = linalg.generic {745    indexing_maps = [#map, #map, #map],746    iterator_types = ["parallel", "parallel", "parallel"]747  } ins(%arg0, %arg1 : tensor<?x?x?xf32>, tensor<1x?x?xf32>)748    outs(%0 : tensor<?x?x?xf32>) {749  ^bb0(%arg5: f32, %arg6: f32, %arg7: f32):750    %3 = arith.subf %arg5, %arg6 : f32751    linalg.yield %3 : f32752  } -> tensor<?x?x?xf32>753  return %2 : tensor<?x?x?xf32>754// CHECK:      %[[GENERIC_OP:.*]] = linalg.generic755// CHECK-SAME: ins(%{{.*}}, %[[ARG1]] : tensor<1x?x?xf32>, tensor<1x?x?xf32>)756// CHECK-SAME: outs(%{{.*}} : tensor<1x?x?xf32>)757// CHECK: tensor.cast %[[GENERIC_OP]] : tensor<1x?x?xf32> to tensor<?x?x?xf32>758}759 760// -----761 762#map = affine_map<(d0, d1) -> (d0, d1)>763#sparse = #sparse_tensor.encoding<{ map = (d0, d1) -> (d0 : dense, d1 : compressed) }>764// CHECK-DAG:   #[[$SPARSE:.+]] = #sparse_tensor.encoding<{ map = (d0, d1) -> (d0 : dense, d1 : compressed) }>765// CHECK-LABEL: func @static_shape_inference_with_encoding(766// CHECK-SAME:    %[[ARG0:[a-zA-Z0-9]+]]767// CHECK-SAME:    %[[ARG1:[a-zA-Z0-9]+]]768func.func @static_shape_inference_with_encoding(%arg0: tensor<?x?xf32, #sparse>, %arg1: tensor<?x?xf32>) -> tensor<3x4xf32> {769  %0 = tensor.empty() : tensor<3x4xf32>770  %1 = linalg.generic {771    indexing_maps = [#map, #map, #map],772    iterator_types = ["parallel", "parallel"]773  } ins(%arg0, %arg1 : tensor<?x?xf32, #sparse>, tensor<?x?xf32>)774    outs(%0 : tensor<3x4xf32>) {775  ^bb0(%in: f32, %in_0: f32, %out: f32):776    %2 = arith.addf %in, %in_0 : f32777    linalg.yield %2 : f32778  } -> tensor<3x4xf32>779  return %1 : tensor<3x4xf32>780    //  CHECK:      %[[CAST_ARG0:.*]] = tensor.cast %[[ARG0]] : tensor<?x?xf32, #[[$SPARSE]]> to tensor<3x4xf32, #[[$SPARSE]]>781    //  CHECK-NEXT: %[[CAST_ARG1:.*]] = tensor.cast %[[ARG1]] : tensor<?x?xf32> to tensor<3x4xf32>782    //  CHECK-NEXT: %[[GENERIC_OP:.*]] = linalg.generic783    //  CHECK-SAME: ins(%[[CAST_ARG0]], %[[CAST_ARG1]] : tensor<3x4xf32, #[[$SPARSE]]>, tensor<3x4xf32>)784    //  CHECK-SAME: outs({{.*}} : tensor<3x4xf32>)785}786 787// -----788 789//       CHECK: #[[$MAP:.+]] = affine_map<()[s0] -> (s0 + 1)>790// CHECK-LABEL: func @insert_pad_into_fill791//  CHECK-SAME: (%[[INPUT:.+]]: tensor<?x?x?xf32>, %[[LOW0:.+]]: index, %[[LOW1:.+]]: index, %{{.+}}: index, %{{.+}}: index)792//   CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index793//   CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index794//   CHECK-DAG: %[[C2:.+]] = arith.constant 2 : index795//   CHECK-DAG: %[[F0:.+]] = arith.constant 0.000000e+00 : f32796//       CHECK: %[[INIT:.+]] = tensor.empty()797//       CHECK: %[[FILL:.+]] = linalg.fill ins(%[[F0]]{{.*}}outs(%[[INIT]]798//       CHECK: %[[OFFSET1:.+]] = affine.apply #[[$MAP]]()[%[[LOW1]]]799//       CHECK: %[[D0:.+]] = tensor.dim %[[INPUT]], %[[C0]] : tensor<?x?x?xf32>800//       CHECK: %[[D1:.+]] = tensor.dim %[[INPUT]], %[[C1]] : tensor<?x?x?xf32>801//       CHECK: %[[D2:.+]] = tensor.dim %[[INPUT]], %[[C2]] : tensor<?x?x?xf32>802//       CHECK: tensor.insert_slice %[[INPUT]] into %[[FILL]][%[[LOW0]], %[[OFFSET1]], 2] [%[[D0]], %[[D1]], %[[D2]]] [1, 1, 1]803func.func @insert_pad_into_fill(%input: tensor<?x?x?xf32>, %low0: index, %low1: index, %high1: index, %high2: index) -> tensor<8x384x384xf32> {804  %f0 = arith.constant 0.0 : f32805  %c0 = arith.constant 0 : index806  %pad = tensor.pad %input low[%low0, %low1, %c0] high[%c0, %high1, %high2] {807  ^bb0(%arg3: index, %arg4: index, %arg5: index):808    tensor.yield %f0 : f32809  } : tensor<?x?x?xf32> to tensor<8x128x128xf32>810  %empty = tensor.empty() : tensor<8x384x384xf32>811  %fill = linalg.fill ins(%f0 : f32) outs(%empty : tensor<8x384x384xf32>) -> tensor<8x384x384xf32>812  %0 = tensor.insert_slice %pad into %fill[0, 1, 2] [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>813  return %0: tensor<8x384x384xf32>814}815 816// -----817 818// CHECK-LABEL: func @multi_insert_pad_into_fill819//  CHECK-SAME: (%[[INPUT:.+]]: tensor<7x123x124xf32>, %[[A:.+]]: tensor<8x128x128xf32>, %[[OFFSET:.+]]: index)820//       CHECK:   %[[FILL:.+]] = linalg.fill821//       CHECK:   %[[INSERT0:.+]] = tensor.insert_slice %[[A]] into %[[FILL]][%[[OFFSET]], 0, 0] [8, 128, 128] [1, 1, 1]822//       CHECK:   %[[INSERT1:.+]] = tensor.insert_slice %[[A]] into %[[INSERT0]][0, 128, %[[OFFSET]]] [8, 128, 128] [1, 1, 1]823//       CHECK:                  tensor.insert_slice %[[INPUT]] into %[[INSERT1]][1, 2, 256] [7, 123, 124] [1, 1, 1]824func.func @multi_insert_pad_into_fill(%input: tensor<7x123x124xf32>, %a: tensor<8x128x128xf32>, %offset: index) -> tensor<8x384x384xf32> {825  %f0 = arith.constant 0.0 : f32826  %c0 = arith.constant 0 : index827  %pad = tensor.pad %input low[1, 2, 0] high[0, 3, 4] {828  ^bb0(%arg3: index, %arg4: index, %arg5: index):829    tensor.yield %f0 : f32830  } : tensor<7x123x124xf32> to tensor<8x128x128xf32>831  %empty = tensor.empty() : tensor<8x384x384xf32>832  %fill = linalg.fill ins(%f0 : f32) outs(%empty : tensor<8x384x384xf32>) -> tensor<8x384x384xf32>833  %0 = tensor.insert_slice %a   into %fill[%offset, 0, 0]  [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>834  %1 = tensor.insert_slice %a   into %0   [0, 128, %offset][8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>835  %2 = tensor.insert_slice %pad into %1   [0, 0, 256]      [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>836  return %2: tensor<8x384x384xf32>837}838 839// -----840 841// CHECK-LABEL: func @multi_insert_pad_into_fill_overlap842func.func @multi_insert_pad_into_fill_overlap(%input: tensor<7x123x124xf32>, %a: tensor<8x128x128xf32>, %offset: index) -> tensor<8x384x384xf32> {843  %f0 = arith.constant 0.0 : f32844  %c0 = arith.constant 0 : index845  // CHECK: tensor.pad846  %pad = tensor.pad %input low[1, 2, 0] high[0, 3, 4] {847  ^bb0(%arg3: index, %arg4: index, %arg5: index):848    tensor.yield %f0 : f32849  } : tensor<7x123x124xf32> to tensor<8x128x128xf32>850  %empty = tensor.empty() : tensor<8x384x384xf32>851  %fill = linalg.fill ins(%f0 : f32) outs(%empty : tensor<8x384x384xf32>) -> tensor<8x384x384xf32>852  %0 = tensor.insert_slice %a   into %fill[%offset, 0, 0]  [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>853  %1 = tensor.insert_slice %a   into %0   [0, 0, 129]      [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>854  // Range overlap with %1 at dim#3855  %2 = tensor.insert_slice %pad into %1   [0, 0, 256]      [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>856  return %2: tensor<8x384x384xf32>857}858 859// -----860 861// CHECK-LABEL: func @multi_insert_pad_into_fill_overlap862func.func @multi_insert_pad_into_fill_overlap(%input: tensor<7x123x124xf32>, %a: tensor<8x128x128xf32>, %offset: index) -> tensor<8x384x384xf32> {863  %f0 = arith.constant 0.0 : f32864  %c0 = arith.constant 0 : index865  // CHECK: tensor.pad866  %pad = tensor.pad %input low[1, 2, 0] high[0, 3, 4] {867  ^bb0(%arg3: index, %arg4: index, %arg5: index):868    tensor.yield %f0 : f32869  } : tensor<7x123x124xf32> to tensor<8x128x128xf32>870  %empty = tensor.empty() : tensor<8x384x384xf32>871  %fill = linalg.fill ins(%f0 : f32) outs(%empty : tensor<8x384x384xf32>) -> tensor<8x384x384xf32>872  %0 = tensor.insert_slice %a   into %fill[0, 0, %offset]  [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>873  %1 = tensor.insert_slice %a   into %0   [0, 128, 255]    [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>874  // Range overlap with %0 at dim#3875  %2 = tensor.insert_slice %pad into %1   [0, 0, 256]      [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>876  return %2: tensor<8x384x384xf32>877}878 879// -----880 881// CHECK-LABEL: func @multi_insert_pad_into_fill882func.func @multi_insert_pad_into_fill(%input: tensor<7x123x124xf32>, %a: tensor<8x128x128xf32>, %offset: index) -> tensor<8x384x384xf32> {883  %f0 = arith.constant 0.0 : f32884  %c0 = arith.constant 0 : index885  // CHECK-NOT: tensor.pad886  %pad = tensor.pad %input low[1, 2, 0] high[0, 3, 4] {887  ^bb0(%arg3: index, %arg4: index, %arg5: index):888    tensor.yield %f0 : f32889  } : tensor<7x123x124xf32> to tensor<8x128x128xf32>890  %empty = tensor.empty() : tensor<8x384x384xf32>891  %fill = linalg.fill ins(%f0 : f32) outs(%empty : tensor<8x384x384xf32>) -> tensor<8x384x384xf32>892  // Overlap btween %0 and %1 is fine but not with %2 is fine.893  // CHECK-COUNT-3: tensor.insert_slice894  %0 = tensor.insert_slice %a   into %fill[0, 0, %offset]  [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>895  %1 = tensor.insert_slice %a   into %0   [0, 1, %offset]  [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>896  %2 = tensor.insert_slice %pad into %1   [0, 256, 256]    [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>897  return %2: tensor<8x384x384xf32>898}899 900// -----901 902// CHECK-LABEL: func @multi_insert_pad_into_fill_mismatch903func.func @multi_insert_pad_into_fill_mismatch(%input: tensor<7x123x124xf32>, %a: tensor<8x128x128xf32>, %offset: index) -> tensor<8x384x384xf32> {904  %f0 = arith.constant 0.0 : f32905  %f1 = arith.constant 1.0 : f32906  %c0 = arith.constant 0 : index907  // CHECK: tensor.pad908  %pad = tensor.pad %input low[1, 2, 0] high[0, 3, 4] {909  ^bb0(%arg3: index, %arg4: index, %arg5: index):910    tensor.yield %f0 : f32911  } : tensor<7x123x124xf32> to tensor<8x128x128xf32>912  %empty = tensor.empty() : tensor<8x384x384xf32>913  // Different filling value than padding value.914  %fill = linalg.fill ins(%f1 : f32) outs(%empty : tensor<8x384x384xf32>) -> tensor<8x384x384xf32>915  %0 = tensor.insert_slice %a   into %fill[%offset, 0, 0]  [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>916  %1 = tensor.insert_slice %a   into %0   [0, 128, %offset][8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>917  %2 = tensor.insert_slice %pad into %1   [0, 0, 256]      [8, 128, 128] [1, 1, 1] : tensor<8x128x128xf32> into tensor<8x384x384xf32>918  return %2: tensor<8x384x384xf32>919}920 921// -----922 923func.func @fold_linalgop_with_cast_consumer(%arg0 : tensor<?x?xf32>, %arg1 : tensor<?x?xf32>,924    %arg2 : tensor<?x?xf32>) -> (tensor<4x8xf32>, tensor<?x?xf32>) {925  %0 = linalg.matmul ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)926      outs(%arg2 : tensor<?x?xf32>) -> tensor<?x?xf32>927  %1 = tensor.cast %0 : tensor<?x?xf32> to tensor<4x8xf32>928  return %1, %0 : tensor<4x8xf32>, tensor<?x?xf32>929}930//       CHECK: func @fold_linalgop_with_cast_consumer(931//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: tensor<?x?xf32>932//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: tensor<?x?xf32>933//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: tensor<?x?xf32>)934//   CHECK-DAG:  %[[LHS_CAST:.+]] = tensor.cast %[[ARG0]] : tensor<?x?xf32> to tensor<4x?xf32>935//   CHECK-DAG:  %[[RHS_CAST:.+]] = tensor.cast %[[ARG1]] : tensor<?x?xf32> to tensor<?x8xf32>936//   CHECK-DAG:  %[[OUT_CAST:.+]] = tensor.cast %[[ARG2]] : tensor<?x?xf32> to tensor<4x8xf32>937//       CHECK:  %[[MATMUL:.+]] = linalg.matmul938//  CHECK-SAME:      ins(%[[LHS_CAST]], %[[RHS_CAST]] :939//  CHECK-SAME:      outs(%[[OUT_CAST]] :940//       CHECK:  %[[RESULT_CAST:.+]] = tensor.cast %[[MATMUL]]941//       CHECK:  return %[[MATMUL]], %[[RESULT_CAST]]942 943// -----944 945func.func private @some_use(%0 : tensor<4x8xf32>)946 947func.func @linalgop_with_cond_cast_consumer(%arg0 : tensor<?x?xf32>, %arg1 : tensor<?x?xf32>,948    %arg2 : tensor<?x?xf32>, %arg3 : i1) -> tensor<?x?xf32> {949  %0 = linalg.matmul ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)950      outs(%arg2 : tensor<?x?xf32>) -> tensor<?x?xf32>951  scf.if %arg3 {952    %1 = tensor.cast %0 : tensor<?x?xf32> to tensor<4x8xf32>953    func.call @some_use(%1) : (tensor<4x8xf32>) -> ()954  }955  return %0 : tensor<?x?xf32>956}957 958// Check conditionally reachable cast is not folded into producer.959// CHECK-LABEL: func @linalgop_with_cond_cast_consumer960//  CHECK-SAME:     (%[[ARG0:.*]]: tensor<?x?xf32>, %[[ARG1:.*]]: tensor<?x?xf32>, %[[ARG2:.*]]: tensor<?x?xf32>, %[[ARG3:.*]]: i1)961//       CHECK: %[[RES:.*]] = linalg.matmul ins(%[[ARG0]], %[[ARG1]] : tensor<?x?xf32>, tensor<?x?xf32>)962//  CHECK-SAME:      outs(%[[ARG2]] : tensor<?x?xf32>) -> tensor<?x?xf32>963//       CHECK: scf.if %[[ARG3]] {964//       CHECK:   %[[CAST:.*]] = tensor.cast %[[RES]] : tensor<?x?xf32> to tensor<4x8xf32>965//       CHECK:   func.call @some_use(%[[CAST]]) : (tensor<4x8xf32>) -> ()966//       CHECK: }967//       CHECK: return %[[RES]] : tensor<?x?xf32>968 969 970// -----971 972func.func @fold_conv_op_with_cast_consumer(%arg0 : tensor<?x?x?x?xf32>,973    %arg1 : tensor<?x?x?x?xf32>,  %arg2 : tensor<?x?x?x?xf32>) ->974    (tensor<4x8x12x16xf32>, tensor<?x?x?x?xf32>) {975  %0 = linalg.conv_2d_nchw_fchw ins(%arg0, %arg1 : tensor<?x?x?x?xf32>, tensor<?x?x?x?xf32>)976      outs(%arg2 : tensor<?x?x?x?xf32>) -> tensor<?x?x?x?xf32>977  %1 = tensor.cast %0 : tensor<?x?x?x?xf32> to tensor<4x8x12x16xf32>978  return %1, %0 : tensor<4x8x12x16xf32>, tensor<?x?x?x?xf32>979}980//       CHECK: func @fold_conv_op_with_cast_consumer(981//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: tensor<?x?x?x?xf32>982//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: tensor<?x?x?x?xf32>983//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: tensor<?x?x?x?xf32>)984//       CHECK:  %[[OUT_CAST:.+]] = tensor.cast %[[ARG2]] : tensor<?x?x?x?xf32> to tensor<4x8x12x16xf32>985//       CHECK:  %[[CONV:.+]] = linalg.conv_2d_nchw_fchw986//  CHECK-SAME:      ins(%[[ARG0]], %[[ARG1]] :987//  CHECK-SAME:      outs(%[[OUT_CAST]] :988//       CHECK:  %[[RESULT_CAST:.+]] = tensor.cast %[[CONV]]989//       CHECK:  return %[[CONV]], %[[RESULT_CAST]]990 991// -----992 993func.func @fold_multi_use_generic_op_with_consumer(%arg0 : tensor<?x?x?xf32>) -> (tensor<?x?x?xf32>, tensor<2x3x4xf32>) {994  %c0 = arith.constant 0 : index995  %c1 = arith.constant 1 : index996  %c2 = arith.constant 2 : index997  %d0 = tensor.dim %arg0, %c0 : tensor<?x?x?xf32>998  %d1 = tensor.dim %arg0, %c1 : tensor<?x?x?xf32>999  %d2 = tensor.dim %arg0, %c2 : tensor<?x?x?xf32>1000  %empty1 = tensor.empty(%d1, %d2, %d0) : tensor<?x?x?xf32>1001  %empty2 = tensor.empty(%d2, %d1, %d0) : tensor<?x?x?xf32>1002  %0:2 = linalg.generic {1003      iterator_types = ["parallel", "parallel", "parallel"],1004      indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d1, d2)>,1005                       affine_map<(d0, d1, d2) -> (d1, d2, d0)>,1006                       affine_map<(d0, d1, d2) -> (d2, d1, d0)>]}1007      ins(%arg0 : tensor<?x?x?xf32>) outs(%empty1, %empty2 : tensor<?x?x?xf32>, tensor<?x?x?xf32>) {1008    ^bb0(%b0 : f32, %b1 : f32, %b2 : f32) :1009      linalg.yield %b0, %b0 : f32, f321010    } -> (tensor<?x?x?xf32>, tensor<?x?x?xf32>)1011  %1 = tensor.cast %0#1 : tensor<?x?x?xf32> to tensor<2x3x4xf32>1012  return %0#0, %1 : tensor<?x?x?xf32>, tensor<2x3x4xf32>1013}1014//       CHECK: func @fold_multi_use_generic_op_with_consumer1015//  CHECK-SAME:     %[[ARG0:.+]]: tensor<?x?x?xf32>1016//   CHECK-DAG:   %[[INIT1:.+]] = tensor.empty() : tensor<2x3x4xf32>1017//   CHECK-DAG:   %[[CAST:.+]] = tensor.cast %[[ARG0]] : tensor<?x?x?xf32> to tensor<4x3x2xf32>1018//   CHECK-DAG:   %[[INIT2:.+]] = tensor.empty() : tensor<3x2x4xf32>1019//       CHECK:   %[[GENERIC:.+]]:2 = linalg.generic1020//  CHECK-SAME:       ins(%[[CAST]] :1021//  CHECK-SAME:       outs(%[[INIT2]], %[[INIT1]] :1022//       CHECK:   %[[RETURN_CAST:.+]] = tensor.cast %[[GENERIC]]#0 : tensor<3x2x4xf32> to tensor<?x?x?xf32>1023//       CHECK:   return %[[RETURN_CAST]], %[[GENERIC]]#11024 1025// -----1026 1027#map = affine_map<(d0) -> (d0)>1028func.func @identity_buffer(%arg0 : memref<?xf32>, %arg1: memref<?xf32>) {1029  linalg.generic {1030    indexing_maps = [#map, #map],1031    iterator_types = ["parallel"]1032  } ins(%arg0 : memref<?xf32>)1033    outs(%arg1 : memref<?xf32>) {1034  ^bb0(%arg2 : f32, %arg3 : f32):1035    linalg.yield %arg2 : f321036  }1037  return1038}1039 1040// Do not erase ops with buffer semantics.1041// CHECK-LABEL: func @identity_buffer1042//  CHECK-SAME:     (%[[ARG1:.*]]: memref<?xf32>, %[[ARG2:.*]]: memref<?xf32>)1043//       CHECK:     linalg.generic {1044//  CHECK-SAME:    indexing_maps = [#map, #map],1045//  CHECK-SAME:    iterator_types = ["parallel"]1046//  CHECK-SAME:  } ins(%[[ARG1]] : memref<?xf32>)1047//  CHECK-SAME:    outs(%[[ARG2]] : memref<?xf32>) {1048 1049// -----1050 1051#map = affine_map<(d0, d1) -> (d1, d0)>1052func.func @erase_non_identity_noop(%arg0 : tensor<?x?xf32>, %arg1: tensor<?x?xf32>) -> tensor<?x?xf32> {1053  %0 = linalg.generic {1054    indexing_maps = [#map, #map],1055    iterator_types = ["parallel", "parallel"]1056  } ins(%arg0 : tensor<?x?xf32>)1057    outs(%arg1 : tensor<?x?xf32>) {1058  ^bb0(%in: f32, %out: f32):1059    linalg.yield %in: f321060  } -> tensor<?x?xf32>1061  return %0 : tensor<?x?xf32>1062}1063 1064// Do not erase ops with buffer semantics.1065// CHECK-LABEL: func @erase_non_identity_noop1066//  CHECK-SAME:   (%[[ARG0:.*]]: tensor<?x?xf32>, %[[ARG1:.*]]: tensor<?x?xf32>)1067//       CHECK:   return %[[ARG0]] : tensor<?x?xf32>1068 1069// -----1070 1071// Just make sure that we don't crash.1072 1073// CHECK-LABEL: func @dedeplicate_regression_test1074func.func @dedeplicate_regression_test(%0: tensor<4xf32>, %1: tensor<4xf32>) {1075  %36 = linalg.generic1076    {indexing_maps = [affine_map<(d0) -> (d0)>,1077                      affine_map<(d0) -> (d0)>, affine_map<(d0) -> (d0)>],1078     iterator_types = ["parallel"]}1079    ins(%1, %1 : tensor<4xf32>, tensor<4xf32>)1080    outs(%0 : tensor<4xf32>) {1081  ^bb0(%in: f32, %in_24: f32, %out: f32):1082    linalg.yield %in : f321083  } -> tensor<4xf32>1084  %53 = linalg.generic {indexing_maps = [affine_map<(d0) -> (d0)>],1085                        iterator_types = ["parallel"]}1086                        outs(%36 : tensor<4xf32>) {1087  ^bb0(%out: f32):1088    linalg.yield %out : f321089  } -> tensor<4xf32>1090  return1091}1092 1093// -----1094 1095// CHECK-LABEL: dead_softmax1096func.func @dead_softmax(%arg0: tensor<16x64x256xf32>) -> tensor<16x64x256xf32> {1097  %0 = tensor.empty() : tensor<16x64x256xf32>1098  // CHECK-NOT: linalg.softmax1099  %1 = linalg.softmax dimension(1)1100    ins(%arg0 : tensor<16x64x256xf32>) outs(%0 : tensor<16x64x256xf32>) -> tensor<16x64x256xf32>1101  return %arg0 : tensor<16x64x256xf32>1102}1103 1104// -----1105 1106// CHECK-LABEL: func @canonicalize_dim_of_dest_style_op1107//       CHECK: tensor.dim1108//       CHECK: tensor.dim1109//   CHECK-NOT: tensor.dim1110//       CHECK: return1111func.func @canonicalize_dim_of_dest_style_op(%arg0 : tensor<?x?xf32>) -> tensor<?x?xf32> {1112  %c0 = arith.constant 0 : index1113  %c1 = arith.constant 1 : index1114  %dim0_0 = tensor.dim %arg0, %c0 : tensor<?x?xf32>1115  %dim1_0 = tensor.dim %arg0, %c1 : tensor<?x?xf32>1116  %0 = tensor.empty(%dim0_0, %dim1_0) : tensor<?x?xf32>1117  %1 = linalg.copy ins(%arg0 : tensor<?x?xf32>) outs(%0 : tensor<?x?xf32>) -> tensor<?x?xf32>1118  %dim0_1 = tensor.dim %1, %c0 : tensor<?x?xf32>1119  %dim1_1 = tensor.dim %1, %c1 : tensor<?x?xf32>1120  %2 = tensor.empty(%dim0_1, %dim1_1) : tensor<?x?xf32>1121  %3 = linalg.copy ins(%1 : tensor<?x?xf32>) outs(%2 : tensor<?x?xf32>) -> tensor<?x?xf32>1122  return %3: tensor<?x?xf32>1123}1124// -----1125 1126// CHECK-LABEL: func @canonicalize_fill_to_copy_input(1127//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: tensor<?x?xf32>1128//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: tensor<?x?xf32>)1129//       CHECK:   %[[ZERO:.+]] = arith.constant 0.01130//       CHECK:   linalg.fill ins(%[[ZERO]] : f32) outs(%[[ARG1]] : tensor<?x?xf32>)1131func.func @canonicalize_fill_to_copy_input(%arg0 : tensor<?x?xf32>, %arg1 : tensor<?x?xf32>) -> tensor<?x?xf32> {1132  %c0 = arith.constant 0.0 : f321133  %fill = linalg.fill ins(%c0 : f32) outs(%arg0 : tensor<?x?xf32>) -> tensor<?x?xf32>1134  %copy = linalg.copy ins(%fill : tensor<?x?xf32>) outs(%arg1 : tensor<?x?xf32>) -> tensor<?x?xf32>1135  return %copy : tensor<?x?xf32>1136}1137 1138// -----1139 1140// CHECK-LABEL: func @canonicalize_fill_to_copy_dest(1141//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: tensor<?x?xf32>1142//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: tensor<?x?xf32>)1143//       CHECK:   linalg.copy ins(%[[ARG1]] : tensor<?x?xf32>) outs(%[[ARG0]] : tensor<?x?xf32>)1144func.func @canonicalize_fill_to_copy_dest(%arg0 : tensor<?x?xf32>, %arg1 : tensor<?x?xf32>) -> tensor<?x?xf32> {1145  %c0 = arith.constant 0.0 : f321146  %fill = linalg.fill ins(%c0 : f32) outs(%arg0 : tensor<?x?xf32>) -> tensor<?x?xf32>1147  %copy = linalg.copy ins(%arg1 : tensor<?x?xf32>) outs(%fill : tensor<?x?xf32>) -> tensor<?x?xf32>1148  return %copy : tensor<?x?xf32>1149}1150 1151// -----1152 1153// CHECK-LABEL: func @canonicalize_fill_to_transpose_input(1154//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: tensor<?x?xf32>1155//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: tensor<?x?xf32>)1156//       CHECK:   %[[ZERO:.+]] = arith.constant 0.01157//       CHECK:   linalg.fill ins(%[[ZERO]] : f32) outs(%[[ARG1]] : tensor<?x?xf32>)1158func.func @canonicalize_fill_to_transpose_input(%arg0 : tensor<?x?xf32>, %arg1 : tensor<?x?xf32>) -> tensor<?x?xf32> {1159  %c0 = arith.constant 0.0 : f321160  %fill = linalg.fill ins(%c0 : f32) outs(%arg0 : tensor<?x?xf32>) -> tensor<?x?xf32>1161  %transpose = linalg.transpose ins(%fill : tensor<?x?xf32>) outs(%arg1 : tensor<?x?xf32>) permutation = [1, 0]1162  return %transpose : tensor<?x?xf32>1163}1164 1165// -----1166 1167// CHECK-LABEL: func @broadcast_same_shape(1168//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: tensor<2x3xf32>1169//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: tensor<2x3xf32>)1170//       CHECK-NOT:   linalg.broadcast1171//       CHECK:       return %[[ARG0]] : tensor<2x3xf32>1172func.func @broadcast_same_shape(%input: tensor<2x3xf32>, %init: tensor<2x3xf32>) -> tensor<2x3xf32> {1173  %0 = linalg.broadcast ins(%input: tensor<2x3xf32>) outs(%init: tensor<2x3xf32>) dimensions = []1174  return %0 : tensor<2x3xf32>1175}1176 1177// -----1178 1179// CHECK-LABEL: @broadcast_broadcast_fold1180//  CHECK-SAME:     %[[INPUT:[a-zA-Z0-9]+]]: tensor<2xf32>1181//  CHECK-SAME:     %[[INIT1:[a-zA-Z0-9]+]]: tensor<2x3xf32>1182//  CHECK-SAME:     %[[INIT2:[a-zA-Z0-9]+]]: tensor<2x3x4xf32>1183//       CHECK:   %[[BROADCAST:.+]] = linalg.broadcast ins(%[[INPUT]] : tensor<2xf32>) outs(%[[INIT2]] : tensor<2x3x4xf32>) dimensions = [1, 2]1184//   CHECK-NOT:   linalg.broadcast1185//       CHECK:   return %[[BROADCAST]] : tensor<2x3x4xf32>1186func.func @broadcast_broadcast_fold(%input: tensor<2xf32>,1187                                    %init1: tensor<2x3xf32>,1188                                    %init2: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> {1189  %broadcast1 = linalg.broadcast1190      ins(%input: tensor<2xf32>)1191      outs(%init1: tensor<2x3xf32>)1192      dimensions = [1]1193  %broadcast2 = linalg.broadcast1194      ins(%broadcast1: tensor<2x3xf32>)1195      outs(%init2: tensor<2x3x4xf32>)1196      dimensions = [2]1197  func.return %broadcast2 : tensor<2x3x4xf32>1198}1199 1200// -----1201 1202// CHECK-LABEL: @broadcast_broadcast_fold1203//  CHECK-SAME:     %[[INPUT:[a-zA-Z0-9]+]]: tensor<2xf32>1204//  CHECK-SAME:     %[[INIT1:[a-zA-Z0-9]+]]: tensor<2x4xf32>1205//  CHECK-SAME:     %[[INIT2:[a-zA-Z0-9]+]]: tensor<2x3x4xf32>1206//       CHECK:   %[[BROADCAST:.+]] = linalg.broadcast ins(%[[INPUT]] : tensor<2xf32>) outs(%[[INIT2]] : tensor<2x3x4xf32>) dimensions = [1, 2]1207//   CHECK-NOT:   linalg.broadcast1208//       CHECK:   return %[[BROADCAST]] : tensor<2x3x4xf32>1209func.func @broadcast_broadcast_fold(%input: tensor<2xf32>,1210                                    %init1: tensor<2x4xf32>,1211                                    %init2: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> {1212  %broadcast1 = linalg.broadcast1213      ins(%input: tensor<2xf32>)1214      outs(%init1: tensor<2x4xf32>)1215      dimensions = [1]1216  %broadcast2 = linalg.broadcast1217      ins(%broadcast1: tensor<2x4xf32>)1218      outs(%init2: tensor<2x3x4xf32>)1219      dimensions = [1]1220  func.return %broadcast2 : tensor<2x3x4xf32>1221}1222 1223// -----1224 1225func.func @transpose_1d(%input: tensor<16xf32>,1226                        %init: tensor<16xf32>) -> tensor<16xf32> {1227  %transpose = linalg.transpose1228      ins(%input:tensor<16xf32>)1229      outs(%init:tensor<16xf32>)1230      permutation = [0]1231  func.return %transpose : tensor<16xf32>1232}1233 1234// CHECK-LABEL: func @transpose_1d(1235//  CHECK-SAME:     %[[INPUT:[a-zA-Z0-9]+]]: tensor<16xf32>,1236//  CHECK-SAME:     %[[INIT:[a-zA-Z0-9]+]]: tensor<16xf32>)1237//   CHECK-NOT:   linalg.transpose1238//       CHECK:   return %[[INPUT]] : tensor<16xf32>1239 1240// -----1241 1242func.func @transpose_identity_perm(%input: tensor<16x32x64xf32>,1243                                   %init: tensor<16x32x64xf32>) -> tensor<16x32x64xf32> {1244  %transpose = linalg.transpose1245      ins(%input:tensor<16x32x64xf32>)1246      outs(%init:tensor<16x32x64xf32>)1247      permutation = [0, 1, 2]1248  func.return %transpose : tensor<16x32x64xf32>1249}1250 1251// CHECK-LABEL: func @transpose_identity_perm(1252//  CHECK-SAME:     %[[INPUT:[a-zA-Z0-9]+]]: tensor<16x32x64xf32>,1253//  CHECK-SAME:     %[[INIT:[a-zA-Z0-9]+]]: tensor<16x32x64xf32>)1254//   CHECK-NOT:   linalg.transpose1255//       CHECK:   return %[[INPUT]] : tensor<16x32x64xf32>1256 1257// -----1258 1259func.func @transpose_transpose_cancel(%input: tensor<5x4x3xf32>,1260                                      %init1: tensor<4x3x5xf32>,1261                                      %init2: tensor<5x4x3xf32>) -> tensor<5x4x3xf32> {1262  // CHECK-LABEL: @transpose_transpose_cancel1263  //  CHECK-SAME:     %[[INPUT:[a-zA-Z0-9]+]]: tensor<5x4x3xf32>1264  //  CHECK-SAME:     %[[INIT1:[a-zA-Z0-9]+]]: tensor<4x3x5xf32>1265  //  CHECK-SAME:     %[[INIT2:[a-zA-Z0-9]+]]: tensor<5x4x3xf32>1266  //   CHECK-NOT:   linalg.transpose1267  //       CHECK:   return %[[INPUT]] : tensor<5x4x3xf32>1268  %transpose1 = linalg.transpose1269      ins(%input:tensor<5x4x3xf32>)1270      outs(%init1:tensor<4x3x5xf32>)1271      permutation = [1, 2, 0]1272  %transpose2 = linalg.transpose1273      ins(%transpose1:tensor<4x3x5xf32>)1274      outs(%init2:tensor<5x4x3xf32>)1275      permutation = [2, 0, 1]1276  func.return %transpose2 : tensor<5x4x3xf32>1277}1278 1279// -----1280 1281func.func @transpose_transpose_fold(%input: tensor<5x4x3xf32>,1282                                    %init1: tensor<4x3x5xf32>,1283                                    %init2: tensor<3x4x5xf32>) -> tensor<3x4x5xf32> {1284  // CHECK-LABEL: @transpose_transpose_fold1285  //  CHECK-SAME:     %[[INPUT:[a-zA-Z0-9]+]]: tensor<5x4x3xf32>1286  //  CHECK-SAME:     %[[INIT1:[a-zA-Z0-9]+]]: tensor<4x3x5xf32>1287  //  CHECK-SAME:     %[[INIT2:[a-zA-Z0-9]+]]: tensor<3x4x5xf32>1288  //       CHECK:   %[[TRANSPOSE:.+]] = linalg.transpose ins(%[[INPUT]] : tensor<5x4x3xf32>) outs(%[[INIT2]] : tensor<3x4x5xf32>) permutation = [2, 1, 0]1289  //   CHECK-NOT:   linalg.transpose1290  //       CHECK:   return %[[TRANSPOSE]] : tensor<3x4x5xf32>1291  %transpose1 = linalg.transpose1292      ins(%input:tensor<5x4x3xf32>)1293      outs(%init1:tensor<4x3x5xf32>)1294      permutation = [1, 2, 0]1295  %transpose2 = linalg.transpose1296      ins(%transpose1:tensor<4x3x5xf32>)1297      outs(%init2:tensor<3x4x5xf32>)1298      permutation = [1, 0, 2]1299  func.return %transpose2 : tensor<3x4x5xf32>1300}1301 1302// -----1303 1304func.func @broadcast_transpose_fold(%input: tensor<2x4x5xf32>,1305                                    %init1: tensor<1x2x3x4x5x6xf32>,1306                                    %init2: tensor<1x6x2x3x5x4xf32>) -> tensor<1x6x2x3x5x4xf32> {1307  // CHECK-LABEL: @broadcast_transpose_fold1308  //  CHECK-SAME:     %[[INPUT:[a-zA-Z0-9]+]]: tensor<2x4x5xf32>1309  //  CHECK-SAME:     %[[INIT1:[a-zA-Z0-9]+]]: tensor<1x2x3x4x5x6xf32>1310  //  CHECK-SAME:     %[[INIT2:[a-zA-Z0-9]+]]: tensor<1x6x2x3x5x4xf32>1311  //       CHECK:   %[[TMP_INIT:.+]] = tensor.empty() : tensor<2x5x4xf32>1312  //       CHECK:   %[[TRANSPOSE:.+]] = linalg.transpose ins(%[[INPUT]] : tensor<2x4x5xf32>) outs(%[[TMP_INIT]] : tensor<2x5x4xf32>) permutation = [0, 2, 1]1313  //       CHECK:   %[[BROADCAST:.+]] = linalg.broadcast ins(%[[TRANSPOSE]] : tensor<2x5x4xf32>) outs(%[[INIT2]] : tensor<1x6x2x3x5x4xf32>) dimensions = [0, 3, 1]1314  //       CHECK:   return %[[BROADCAST]] : tensor<1x6x2x3x5x4xf32>1315  %broadcast = linalg.broadcast1316      ins(%input : tensor<2x4x5xf32>)1317      outs(%init1 : tensor<1x2x3x4x5x6xf32>)1318      dimensions = [0, 2, 5]1319  %transpose = linalg.transpose1320      ins(%broadcast : tensor<1x2x3x4x5x6xf32>)1321      outs(%init2 : tensor<1x6x2x3x5x4xf32>)1322      permutation = [0, 5, 1, 2, 4, 3]1323  func.return %transpose : tensor<1x6x2x3x5x4xf32>1324}1325 1326// -----1327 1328func.func @broadcast_transpose_fold_dynamic(%input: tensor<?x?x5xf32>,1329                                            %init1: tensor<1x?x3x?x5x6xf32>,1330                                            %init2: tensor<1x3x?x6x5x?xf32>) -> tensor<1x3x?x6x5x?xf32> {1331  // CHECK-LABEL: @broadcast_transpose_fold_dynamic1332  //  CHECK-SAME:     %[[INPUT:[a-zA-Z0-9]+]]: tensor<?x?x5xf32>1333  //  CHECK-SAME:     %[[INIT1:[a-zA-Z0-9]+]]: tensor<1x?x3x?x5x6xf32>1334  //  CHECK-SAME:     %[[INIT2:[a-zA-Z0-9]+]]: tensor<1x3x?x6x5x?xf32>1335  //   CHECK-DAG:   %[[C1:.+]] = arith.constant 1 : index1336  //   CHECK-DAG:   %[[C0:.+]] = arith.constant 0 : index1337  //       CHECK:   %[[DIM0:.+]] = tensor.dim %[[INPUT]], %[[C0]] : tensor<?x?x5xf32>1338  //       CHECK:   %[[DIM1:.+]] = tensor.dim %[[INPUT]], %[[C1]] : tensor<?x?x5xf32>1339  //       CHECK:   %[[TMP_INIT:.+]] = tensor.empty(%[[DIM1]], %[[DIM0]]) : tensor<?x5x?xf32>1340  //       CHECK:   %[[TRANSPOSE:.+]] = linalg.transpose ins(%[[INPUT]] : tensor<?x?x5xf32>) outs(%[[TMP_INIT]] : tensor<?x5x?xf32>) permutation = [1, 2, 0]1341  //       CHECK:   %[[BROADCAST:.+]] = linalg.broadcast ins(%[[TRANSPOSE]] : tensor<?x5x?xf32>) outs(%[[INIT2]] : tensor<1x3x?x6x5x?xf32>) dimensions = [0, 1, 3]1342  //       CHECK:   return %[[BROADCAST]] : tensor<1x3x?x6x5x?xf32>1343  %broadcast = linalg.broadcast1344      ins(%input : tensor<?x?x5xf32>)1345      outs(%init1 : tensor<1x?x3x?x5x6xf32>)1346      dimensions = [0, 2, 5]1347  %transpose = linalg.transpose1348      ins(%broadcast : tensor<1x?x3x?x5x6xf32>)1349      outs(%init2 : tensor<1x3x?x6x5x?xf32>)1350      permutation = [0, 2, 3, 5, 4, 1]1351  func.return %transpose : tensor<1x3x?x6x5x?xf32>1352}1353 1354// -----1355 1356func.func @broadcast_transpose_fold_2dim(%input: tensor<2xf32>,1357                                         %init1: tensor<2x4xf32>,1358                                         %init2: tensor<4x2xf32>) -> tensor<4x2xf32> {1359  // CHECK-LABEL: @broadcast_transpose_fold_2dim1360  //  CHECK-SAME:     %[[INPUT:[a-zA-Z0-9]+]]: tensor<2xf32>1361  //  CHECK-SAME:     %[[INIT1:[a-zA-Z0-9]+]]: tensor<2x4xf32>1362  //  CHECK-SAME:     %[[INIT2:[a-zA-Z0-9]+]]: tensor<4x2xf32>1363  //       CHECK:   %[[BROADCAST:.+]] = linalg.broadcast ins(%[[INPUT]] : tensor<2xf32>) outs(%[[INIT2]] : tensor<4x2xf32>) dimensions = [0]1364  //       CHECK:   return %[[BROADCAST]] : tensor<4x2xf32>1365  %broadcast = linalg.broadcast1366      ins(%input : tensor<2xf32>)1367      outs(%init1 : tensor<2x4xf32>)1368      dimensions = [1]1369  %transpose = linalg.transpose1370      ins(%broadcast : tensor<2x4xf32>)1371      outs(%init2 : tensor<4x2xf32>)1372      permutation = [1, 0]1373  func.return %transpose : tensor<4x2xf32>1374}1375 1376// -----1377 1378func.func @concats_of_fill(1379    %arg0 : index, %arg1 : index, %arg2 : index, %arg3 : index)1380    -> tensor<5x?x?xf32>1381{1382  %cst0 = arith.constant 0.0 : f321383  %cst1 = arith.constant 0.0 : f321384  %0 = tensor.empty(%arg0, %arg1) : tensor<5x?x?xf32>1385  %1 = linalg.fill ins(%cst0 : f32) outs(%0 : tensor<5x?x?xf32>) -> tensor<5x?x?xf32>1386  %2 = tensor.empty(%arg2, %arg3) : tensor<5x?x?xf32>1387  %3 = linalg.fill ins(%cst1 : f32) outs(%2 : tensor<5x?x?xf32>) -> tensor<5x?x?xf32>1388  %4 = tensor.concat dim(1) %1, %3 : (tensor<5x?x?xf32>, tensor<5x?x?xf32>) -> tensor<5x?x?xf32>1389  return %4 : tensor<5x?x?xf32>1390}1391//       CHECK: func @concats_of_fill(1392//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1393//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,1394//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index,1395//  CHECK-SAME:     %[[ARG3:[a-zA-Z0-9]+]]: index)1396//   CHECK-DAG:   %[[CST:.+]] = arith.constant 0.01397//   CHECK-DAG:   %[[EMPTY0:.+]] = tensor.empty(%[[ARG0]], %[[ARG1]])1398//   CHECK-DAG:   %[[EMPTY1:.+]] = tensor.empty(%[[ARG2]], %[[ARG3]])1399//       CHECK:   %[[CONCAT:.+]] = tensor.concat dim(1) %[[EMPTY0]], %[[EMPTY1]]1400//       CHECK:   %[[FILL:.+]] = linalg.fill ins(%[[CST]] : f32) outs(%[[CONCAT]] :1401//       CHECK:   return %[[FILL]]1402 1403// -----1404 1405func.func @transpose_buffer(%input: memref<?xf32>,1406                            %init: memref<?xf32>) {1407  linalg.transpose ins(%input:memref<?xf32>)1408                   outs(%init:memref<?xf32>)1409                   permutation = [0]1410  func.return1411}1412 1413// CHECK-LABEL:   func.func @transpose_buffer(1414//  CHECK-SAME:            %[[VAL_0:.*]]: memref<?xf32>,1415//  CHECK-SAME:            %[[VAL_1:.*]]: memref<?xf32>) {1416//       CHECK:     linalg.transpose ins(%[[VAL_0]] : memref<?xf32>)1417//  CHECK-SAME:       outs(%[[VAL_1]] : memref<?xf32>) permutation = [0]1418 1419// -----1420 1421// This test checks linalg op has a recursive memory effect. Otherwise1422// linalg.map without a user would be DCEd.1423func.func @recursive_effect(%arg : tensor<1xf32>) {1424  %init = arith.constant dense<0.0> : tensor<1xf32>1425  %mapped = linalg.map ins(%arg:tensor<1xf32>) outs(%init :tensor<1xf32>)1426            (%in : f32, %out: f32) {1427              vector.print %in : f321428              linalg.yield %in : f321429            }1430  func.return1431}1432 1433// CHECK-LABEL: @recursive_effect1434//       CHECK: linalg.map1435 1436// -----1437 1438//===----------------------------------------------------------------------===//1439// linalg.pack1440//===----------------------------------------------------------------------===//1441 1442// CHECK-LABEL: func @fold_pack_constant_splat1443//   CHECK-NOT: linalg.pack1444//       CHECK: arith.constant dense<1.000000e-01> : tensor<4x8x8x32xf32>1445func.func @fold_pack_constant_splat(%dest : tensor<4x8x8x32xf32>) -> tensor<4x8x8x32xf32> {1446  %cst = arith.constant dense<1.000000e-01> : tensor<64x128xf32>1447  %0 = linalg.pack %cst outer_dims_perm = [1, 0] inner_dims_pos = [0, 1]1448    inner_tiles = [8, 32] into %dest : tensor<64x128xf32> -> tensor<4x8x8x32xf32>1449  return %0 : tensor<4x8x8x32xf32>1450}1451 1452// -----1453 1454// CHECK-LABEL: func @fold_padding_value_pack_constant_splat1455//   CHECK-NOT: linalg.pack1456//       CHECK: arith.constant dense<1.000000e-01> : tensor<4x8x8x32xf32>1457func.func @fold_padding_value_pack_constant_splat(%dest : tensor<4x8x8x32xf32>) -> tensor<4x8x8x32xf32> {1458  %pad = arith.constant 1.000000e-01 : f321459  %cst = arith.constant dense<1.000000e-01> : tensor<63x127xf32>1460  %0 = linalg.pack %cst1461    padding_value(%pad : f32)1462    outer_dims_perm = [1, 0] inner_dims_pos = [0, 1]1463    inner_tiles = [8, 32] into %dest : tensor<63x127xf32> -> tensor<4x8x8x32xf32>1464  return %0 : tensor<4x8x8x32xf32>1465}1466 1467// -----1468 1469// CHECK-LABEL: func @nofold_padding_value_pack_constant_splat1470//       CHECK: arith.constant dense<1.000000e-01> : tensor<63x127xf32>1471//       CHECK: linalg.pack1472func.func @nofold_padding_value_pack_constant_splat(%dest : tensor<4x8x8x32xf32>) -> tensor<4x8x8x32xf32> {1473  %pad = arith.constant 0.0 : f321474  %cst = arith.constant dense<1.000000e-01> : tensor<63x127xf32>1475  %0 = linalg.pack %cst1476    padding_value(%pad : f32)1477    outer_dims_perm = [1, 0]1478    inner_dims_pos = [0, 1]1479    inner_tiles = [8, 32]1480    into %dest : tensor<63x127xf32> -> tensor<4x8x8x32xf32>1481  return %0 : tensor<4x8x8x32xf32>1482}1483 1484// -----1485 1486func.func @fold_padding_value_pack(%arg0: tensor<1200x500000xf32>) -> tensor<31250x1200x16x1xf32> {1487  %cst = arith.constant 0.000000e+00 : f321488  %0 = tensor.empty() : tensor<31250x1200x16x1xf32>1489  %pack = linalg.pack %arg01490    padding_value(%cst : f32)1491    outer_dims_perm = [1, 0]1492    inner_dims_pos = [1, 0]1493    inner_tiles = [16, 1]1494    into %0 : tensor<1200x500000xf32> -> tensor<31250x1200x16x1xf32>1495  return %pack : tensor<31250x1200x16x1xf32>1496}1497// CHECK-LABEL: func @fold_padding_value_pack1498// CHECK-NOT:     padding_value1499 1500// -----1501 1502func.func @infer_src_shape_pack(%src: tensor<?x?x?x?xf32>, %dest: tensor<10x20x30x40x16xf32>) -> tensor<10x20x30x40x16xf32> {1503  %cst = arith.constant 0.000000e+00 : f321504   %pack = linalg.pack %src1505    padding_value(%cst : f32)1506    outer_dims_perm = [2, 1, 3, 0]1507    inner_dims_pos = [2]1508    inner_tiles = [16]1509    into %dest : tensor<?x?x?x?xf32> -> tensor<10x20x30x40x16xf32>1510  return %pack : tensor<10x20x30x40x16xf32>1511}1512// CHECK-LABEL: func.func @infer_src_shape_pack1513// CHECK-SAME:    %[[SRC:[0-9a-zA-Z]+]]1514// CHECK-SAME:    %[[DEST:[0-9a-zA-Z]+]]1515// CHECK:         %[[CAST_SRC:.+]] = tensor.cast %[[SRC]] : tensor<?x?x?x?xf32> to tensor<40x20x?x30xf32>1516// CHECK:         %[[PACK:.+]] = linalg.pack %[[CAST_SRC]] {{.+}} into %[[DEST]]1517// CHECK:         return %[[PACK]]1518 1519// -----1520 1521func.func @infer_dest_shape_pack(%src: tensor<30x20x?x10xf32>, %dest: tensor<?x?x?x?x16xf32>) -> tensor<?x?x?x?x16xf32> {1522  %cst = arith.constant 0.000000e+00 : f321523   %pack = linalg.pack %src1524    padding_value(%cst : f32)1525    outer_dims_perm = [2, 1, 3, 0]1526    inner_dims_pos = [2]1527    inner_tiles = [16]1528    into %dest : tensor<30x20x?x10xf32> -> tensor<?x?x?x?x16xf32>1529  return %pack : tensor<?x?x?x?x16xf32>1530}1531// CHECK-LABEL: func.func @infer_dest_shape_pack1532// CHECK-SAME:    %[[SRC:[0-9a-zA-Z]+]]1533// CHECK-SAME:    %[[DEST:[0-9a-zA-Z]+]]1534// CHECK:         %[[CAST_DEST:.+]] = tensor.cast %[[DEST]] : tensor<?x?x?x?x16xf32> to tensor<?x20x10x30x16xf32>1535// CHECK:         %[[PACK:.+]] = linalg.pack %[[SRC]] {{.+}} into %[[CAST_DEST]]1536// CHECK:         %[[CAST_PACK:.+]] = tensor.cast %[[PACK]] : tensor<?x20x10x30x16xf32> to tensor<?x?x?x?x16xf32>1537// CHECK:         return %[[CAST_PACK]]1538 1539// -----1540 1541func.func @no_infer_pack_shape(%arg0: tensor<?x32x100xf32>, %arg1: index) -> tensor<32x7x?x16x1xf32> {1542  %cst = arith.constant 0.000000e+00 : f321543  %0 = tensor.empty(%arg1) : tensor<32x7x?x16x1xf32>1544  %pack = linalg.pack %arg0 padding_value(%cst : f32) outer_dims_perm = [1, 2, 0] inner_dims_pos = [2, 0] inner_tiles = [16, 1] into %0 : tensor<?x32x100xf32> -> tensor<32x7x?x16x1xf32>1545  return %pack : tensor<32x7x?x16x1xf32>1546}1547// CHECK-LABEL: func.func @no_infer_pack_shape1548// CHECK-NOT:     tensor.cast1549 1550// -----1551 1552func.func @fold_padding_value_pack_negative1(%arg0: tensor<1200x499999xf32>) -> tensor<31250x1200x16x1xf32> {1553  %cst = arith.constant 0.000000e+00 : f321554  %0 = tensor.empty() : tensor<31250x1200x16x1xf32>1555  %pack = linalg.pack %arg01556    padding_value(%cst : f32)1557    outer_dims_perm = [1, 0]1558    inner_dims_pos = [1, 0]1559    inner_tiles = [16, 1]1560    into %0 : tensor<1200x499999xf32> -> tensor<31250x1200x16x1xf32>1561  return %pack : tensor<31250x1200x16x1xf32>1562}1563// CHECK-LABEL: func @fold_padding_value_pack_negative11564// CHECK:         linalg.pack1565// CHECK-SAME:      padding_value1566 1567// -----1568 1569func.func @fold_padding_value_pack_negative2(%arg0: tensor<1200x?xf32>, %arg1: tensor<?x1200x16x1xf32>) -> tensor<?x1200x16x1xf32> {1570  %cst = arith.constant 0.000000e+00 : f321571  %pack = linalg.pack %arg01572    padding_value(%cst : f32)1573    outer_dims_perm = [1, 0]1574    inner_dims_pos = [1, 0]1575    inner_tiles = [16, 1]1576    into %arg1 : tensor<1200x?xf32> -> tensor<?x1200x16x1xf32>1577  return %pack : tensor<?x1200x16x1xf32>1578}1579// CHECK-LABEL: func @fold_padding_value_pack_negative21580// CHECK:         linalg.pack1581// CHECK-SAME:      padding_value1582 1583// -----1584 1585func.func @fold_padding_value_pack_negative3(%arg0: tensor<1200x500000xf32>, %arg1: tensor<?x1200x?x1xf32>, %tile : index) -> tensor<?x1200x?x1xf32> {1586  %cst = arith.constant 0.000000e+00 : f321587  %pack = linalg.pack %arg01588    padding_value(%cst : f32)1589    outer_dims_perm = [1, 0]1590    inner_dims_pos = [1, 0]1591    inner_tiles = [%tile, 1]1592    into %arg1 : tensor<1200x500000xf32> -> tensor<?x1200x?x1xf32>1593  return %pack : tensor<?x1200x?x1xf32>1594}1595// CHECK-LABEL: func @fold_padding_value_pack_negative31596// CHECK:         linalg.pack1597// CHECK-SAME:      padding_value1598 1599// -----1600 1601//===----------------------------------------------------------------------===//1602// linalg.unpack1603//===----------------------------------------------------------------------===//1604 1605 1606// CHECK-LABEL: func @fold_unpack_constant_splat1607//   CHECK-NOT: linalg.unpack1608//       CHECK: arith.constant dense<1.000000e-01> : tensor<128x256xf32>1609func.func @fold_unpack_constant_splat(%dest : tensor<128x256xf32>) -> tensor<128x256xf32> {1610  %cst = arith.constant dense<1.000000e-01> : tensor<16x8x8x32xf32>1611  %0 = linalg.unpack %cst inner_dims_pos = [0, 1]1612    inner_tiles = [8, 32] into %dest : tensor<16x8x8x32xf32> -> tensor<128x256xf32>1613  return %0 : tensor<128x256xf32>1614}1615 1616// -----1617 1618func.func @infer_dest_shape_unpack(%src: tensor<10x20x30x40x16xf32>, %dest: tensor<?x?x?x?xf32>) -> tensor<?x?x?x?xf32> {1619  %unpack = linalg.unpack %src1620    outer_dims_perm = [2, 1, 3, 0]1621    inner_dims_pos = [2]1622    inner_tiles = [16]1623    into %dest : tensor<10x20x30x40x16xf32> -> tensor<?x?x?x?xf32>1624  return %unpack : tensor<?x?x?x?xf32>1625}1626// CHECK-LABEL: func.func @infer_dest_shape_unpack1627// CHECK-SAME:    %[[SRC:[0-9a-zA-Z]+]]1628// CHECK-SAME:    %[[DEST:[0-9a-zA-Z]+]]1629// CHECK:         %[[CAST_DEST:.+]] = tensor.cast %[[DEST]] : tensor<?x?x?x?xf32> to tensor<40x20x?x30xf32>1630// CHECK:         %[[UNPACK:.+]] = linalg.unpack %[[SRC]] {{.+}} into %[[CAST_DEST]]1631// CHECK:         %[[CAST_UNPACK:.+]] = tensor.cast %[[UNPACK]] : tensor<40x20x?x30xf32> to tensor<?x?x?x?xf32>1632// CHECK:         return %[[CAST_UNPACK]]1633 1634// -----1635 1636func.func @infer_src_shape_unpack(%src: tensor<?x?x?x?x16xf32>, %dest: tensor<30x20x?x10xf32>) -> tensor<30x20x?x10xf32> {1637  %unpack = linalg.unpack %src1638    outer_dims_perm = [2, 1, 3, 0]1639    inner_dims_pos = [2]1640    inner_tiles = [16]1641    into %dest : tensor<?x?x?x?x16xf32> -> tensor<30x20x?x10xf32>1642  return %unpack : tensor<30x20x?x10xf32>1643}1644// CHECK-LABEL: func.func @infer_src_shape_unpack1645// CHECK-SAME:    %[[SRC:[0-9a-zA-Z]+]]1646// CHECK-SAME:    %[[DEST:[0-9a-zA-Z]+]]1647// CHECK:         %[[CAST_SRC:.+]] = tensor.cast %[[SRC]] : tensor<?x?x?x?x16xf32> to tensor<?x20x10x30x16xf32>1648// CHECK:         %[[UNPACK:.+]] = linalg.unpack %[[CAST_SRC]]1649// CHECK:         return %[[UNPACK]]1650 1651// -----1652 1653func.func @no_infer_unpack_shape(%arg1: tensor<32x7x?x16x1xf32>, %arg2: index) -> tensor<?x32x100xf32> {1654  %cst = arith.constant 0.000000e+00 : f321655  %0 = tensor.empty(%arg2) : tensor<?x32x100xf32>1656  %unpack = linalg.unpack %arg1 outer_dims_perm = [1, 2, 0] inner_dims_pos = [2, 0] inner_tiles = [16, 1] into %0 : tensor<32x7x?x16x1xf32> -> tensor<?x32x100xf32>1657  return %unpack : tensor<?x32x100xf32>1658}1659// CHECK-LABEL: func.func @no_infer_unpack_shape1660// CHECK-NOT:     tensor.cast1661 1662// -----1663 1664//===----------------------------------------------------------------------===//1665// linalg.pack + linalg.unpack1666//===----------------------------------------------------------------------===//1667 1668// Chain: NC -> NCnc -> NCnc -> NC1669// CHECK: func.func @unpack_pack(1670// CHECK-SAME: %[[T:.+]]: tensor<128x128xf32>)1671// CHECK: return %[[T]] : tensor<128x128xf32>1672func.func @unpack_pack(%t: tensor<128x128xf32>) -> tensor<128x128xf32> {1673  %tensor_empty = tensor.empty() : tensor<16x16x8x8xf32>1674  %packed = linalg.pack %t inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %tensor_empty : tensor<128x128xf32> -> tensor<16x16x8x8xf32>1675  %tensor_empty1 = tensor.empty() : tensor<128x128xf32>1676  %unpacked = linalg.unpack %packed inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %tensor_empty1 : tensor<16x16x8x8xf32> -> tensor<128x128xf32>1677  return %unpacked : tensor<128x128xf32>1678}1679 1680// -----1681 1682// Chain: NC -> NCcn -> NCnc -> NC1683// CHECK: func.func @unpack_pack(1684// CHECK-SAME: %[[T:.+]]: tensor<128x128xf32>)1685// CHECK-NOT: return %[[T]] : tensor<128x128xf32>1686func.func @unpack_pack(%t: tensor<128x128xf32>) -> tensor<128x128xf32> {1687  %tensor_empty = tensor.empty() : tensor<16x16x8x8xf32>1688  %packed = linalg.pack %t inner_dims_pos = [1, 0] inner_tiles = [8, 8] into %tensor_empty : tensor<128x128xf32> -> tensor<16x16x8x8xf32>1689  %tensor_empty1 = tensor.empty() : tensor<128x128xf32>1690  %unpacked = linalg.unpack %packed inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %tensor_empty1 : tensor<16x16x8x8xf32> -> tensor1691<128x128xf32>1692  return %unpacked : tensor<128x128xf32>1693}1694 1695// -----1696 1697// Chain: NC -> CNcn -> NCnc -> NC1698// CHECK: func.func @unpack_pack(1699// CHECK-SAME: %[[T:.+]]: tensor<128x128xf32>)1700// CHECK-NOT: return %[[T]] : tensor<128x128xf32>1701func.func @unpack_pack(%t: tensor<128x128xf32>) -> tensor<128x128xf32> {1702  %tensor_empty = tensor.empty() : tensor<16x16x8x8xf32>1703  %packed = linalg.pack %t outer_dims_perm = [1, 0] inner_dims_pos = [1, 0] inner_tiles = [8, 8] into %tensor_empty : tensor<128x128xf32> -> tensor<16x16x8x8xf32>1704  %tensor_empty1 = tensor.empty() : tensor<128x128xf32>1705  %unpacked = linalg.unpack %packed inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %tensor_empty1 : tensor<16x16x8x8xf32> -> tensor1706<128x128xf32>1707  return %unpacked : tensor<128x128xf32>1708}1709 1710// -----1711 1712// Chain: NC -> NCnc -> NCnc -> NC1713// CHECK: func.func @unpack_pack(1714// CHECK-SAME: %[[T:.+]]: tensor<128x128xf32>,1715// CHECK: return %[[T]] : tensor<128x128xf32>1716func.func @unpack_pack(%t: tensor<128x128xf32>, %tile1: index, %tile2: index) -> tensor<128x128xf32> {1717  %tensor_empty = tensor.empty(%tile1, %tile2) : tensor<16x16x?x?xf32>1718  %packed = linalg.pack %t inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty : tensor<128x128xf32> -> tensor<16x16x?x?xf32>1719  %tensor_empty1 = tensor.empty() : tensor<128x128xf32>1720  %unpacked = linalg.unpack %packed inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty1 : tensor<16x16x?x?xf32> -> tensor1721<128x128xf32>1722  return %unpacked : tensor<128x128xf32>1723}1724 1725// -----1726 1727// CHECK: func.func @unpack_pack_with_padding_no_canonicalization(1728// CHECK:         linalg.pack1729// CHECK:         linalg.unpack1730func.func @unpack_pack_with_padding_no_canonicalization(%t: tensor<256x512xbf16>) -> tensor<224x512xbf16> {1731  %tensor_empty = tensor.empty() : tensor<4x16x64x32xbf16>1732  %tensor_empty1 = tensor.empty() : tensor<224x512xbf16>1733  %packed = linalg.pack %t outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [64, 32] into %tensor_empty : tensor<256x512xbf16> -> tensor<4x16x64x32xbf16>1734  %unpacked = linalg.unpack %packed inner_dims_pos = [0, 1] inner_tiles = [64, 32] into %tensor_empty1 : tensor<4x16x64x32xbf16> -> tensor<224x512xbf16>1735  return %unpacked : tensor<224x512xbf16>1736}1737 1738// -----1739 1740// Chain NCnc -> NC -> NC -> NCnc1741// CHECK: func.func @pack_unpack(1742// CHECK-SAME: %[[T:.+]]: tensor<16x16x?x?xf32>,1743// CHECK: return %[[T]] : tensor<16x16x?x?xf32>1744func.func @pack_unpack(%t: tensor<16x16x?x?xf32>, %tile1: index, %tile2: index) -> tensor<16x16x?x?xf32> {1745  %tensor_empty = tensor.empty() : tensor<128x128xf32>1746  %unpacked = linalg.unpack %t inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty : tensor<16x16x?x?xf32> -> tensor<128x128xf32>1747  %tensor_empty1 = tensor.empty(%tile1, %tile2) : tensor<16x16x?x?xf32>1748  %packed = linalg.pack %unpacked inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty1 : tensor<128x128xf32> -> tensor<16x16x?x?xf32>1749  return %packed : tensor<16x16x?x?xf32>1750}1751 1752// -----1753 1754// Chain NCnc -> NC -> NC -> NCnc1755// CHECK: func.func @pack_unpack(1756// CHECK-SAME: %[[T:.+]]: tensor<16x16x8x8xf32>1757// CHECK: return %[[T]] : tensor<16x16x8x8xf32>1758func.func @pack_unpack(%t: tensor<16x16x8x8xf32>) -> tensor<16x16x8x8xf32> {1759  %cst = arith.constant 0.000000e+00 : f321760  %tensor_empty = tensor.empty() : tensor<128x128xf32>1761  %unpacked = linalg.unpack %t inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %tensor_empty : tensor<16x16x8x8xf32> -> tensor<128x128xf32>1762  %tensor_empty1 = tensor.empty() : tensor<16x16x8x8xf32>1763  %packed = linalg.pack %unpacked padding_value(%cst : f32) inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %tensor_empty1 : tensor<128x128xf32> -> tensor<16x16x8x8xf32>1764  return %packed : tensor<16x16x8x8xf32>1765}1766 1767// -----1768 1769// CHECK: func.func @pack_unpack_same_tiles(1770// CHECK-SAME:  %[[T:.+]]: tensor<?x?x?x?xf32>,1771// CHECK: return %[[T]] : tensor<?x?x?x?xf32>1772func.func @pack_unpack_same_tiles(%t: tensor<?x?x?x?xf32>, %dim1: index, %dim2: index, %dim3: index, %dim4: index, %dim5: index, %dim6: index,1773                       %tile1: index, %tile2: index) -> tensor<?x?x?x?xf32> {1774  %tensor_empty = tensor.empty(%dim1, %dim2) : tensor<?x?xf32>1775  %unpacked = linalg.unpack %t inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty : tensor<?x?x?x?xf32> -> tensor<?x?xf32>1776  %tensor_empty1 = tensor.empty(%dim3, %dim4, %dim5, %dim6) : tensor<?x?x?x?xf32>1777  %packed = linalg.pack %unpacked inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty1 : tensor<?x?xf32> -> tensor<?x?x?x?xf32>1778  return %packed : tensor<?x?x?x?xf32>1779}1780 1781// -----1782 1783// CHECK: func.func @pack_unpack_different_tiles(1784// CHECK-SAME:  %[[T:.+]]: tensor<?x?x?x?xf32>,1785// CHECK-NOT: return %[[T]] : tensor<?x?x?x?xf32>1786func.func @pack_unpack_different_tiles(%t: tensor<?x?x?x?xf32>, %dim1: index, %dim2: index, %dim3: index, %dim4: index, %dim5: index, %dim6: index,1787                       %tile1: index, %tile2: index) -> tensor<?x?x?x?xf32> {1788  %tensor_empty = tensor.empty(%dim1, %dim2) : tensor<?x?xf32>1789  %unpacked = linalg.unpack %t inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty : tensor<?x?x?x?xf32> -> tensor<?x?xf32>1790  %tensor_empty1 = tensor.empty(%dim3, %dim4, %dim5, %dim6) : tensor<?x?x?x?xf32>1791  %packed = linalg.pack %unpacked inner_dims_pos = [0, 1] inner_tiles = [%tile2, %tile1] into %tensor_empty1 : tensor<?x?xf32> -> tensor<?x?x?x?xf32>1792  return %packed : tensor<?x?x?x?xf32>1793}1794 1795// -----1796 1797// CHECK: func.func @pack_unpack_dynamic_with_padding(1798// CHECK-SAME:  %[[T:.+]]: tensor<?x?x?x?xf32>,1799// CHECK-NOT: return %[[T]] : tensor<?x?x?x?xf32>1800func.func @pack_unpack_dynamic_with_padding(%t: tensor<?x?x?x?xf32>, %dim1: index, %dim2: index, %dim3: index, %dim4: index, %dim5: index, %dim6: index,1801                       %tile1: index, %tile2: index, %pad: f32) -> tensor<?x?x?x?xf32> {1802  %tensor_empty = tensor.empty(%dim1, %dim2) : tensor<?x?xf32>1803  %unpacked = linalg.unpack %t inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty : tensor<?x?x?x?xf32> -> tensor<?x?xf32>1804  %tensor_empty1 = tensor.empty(%dim3, %dim4, %dim5, %dim6) : tensor<?x?x?x?xf32>1805  %packed = linalg.pack %unpacked padding_value(%pad: f32) inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty1 : tensor<?x?xf32> -> tensor<?x?x?x?xf32>1806  return %packed : tensor<?x?x?x?xf32>1807}1808 1809// -----1810 1811// CHECK: func.func @pack_outer_dims_unpack_no_outer_dims(1812// CHECK-SAME: %[[T:.+]]: tensor<16x16x?x?xf32>,1813// CHECK: return %[[T]] : tensor<16x16x?x?xf32>1814func.func @pack_outer_dims_unpack_no_outer_dims(%t: tensor<16x16x?x?xf32>, %tile1: index, %tile2: index) -> tensor<16x16x?x?xf32> {1815  %tensor_empty = tensor.empty() : tensor<128x128xf32>1816  %unpacked = linalg.unpack %t inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty : tensor<16x16x?x?xf32> -> tensor<128x128xf32>1817  %tensor_empty1 = tensor.empty(%tile1, %tile2) : tensor<16x16x?x?xf32>1818  %packed = linalg.pack %unpacked outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty1 : tensor<128x128xf32> -> tensor<16x16x?x?xf32>1819  return %packed : tensor<16x16x?x?xf32>1820}1821 1822// -----1823 1824// CHECK: func.func @pack_no_outer_dims_unpack_outer_dims(1825// CHECK-SAME: %[[T:.+]]: tensor<16x16x?x?xf32>,1826// CHECK: return %[[T]] : tensor<16x16x?x?xf32>1827func.func @pack_no_outer_dims_unpack_outer_dims(%t: tensor<16x16x?x?xf32>, %tile1: index, %tile2: index) -> tensor<16x16x?x?xf32> {1828  %tensor_empty = tensor.empty() : tensor<128x128xf32>1829  %unpacked = linalg.unpack %t outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty : tensor<16x16x?x?xf32> -> tensor<128x128xf32>1830  %tensor_empty1 = tensor.empty(%tile1, %tile2) : tensor<16x16x?x?xf32>1831  %packed = linalg.pack %unpacked inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty1 : tensor<128x128xf32> -> tensor<16x16x?x?xf32>1832  return %packed : tensor<16x16x?x?xf32>1833}1834 1835// -----1836 1837//===----------------------------------------------------------------------===//1838// tensor.cast + linalg.pack1839//===----------------------------------------------------------------------===//1840 1841// CHECK-LABEL:   func.func @fold_cast_pack_dynamic_tile_size1842// CHECK-SAME:      %[[DEST:.*]]: tensor<1x1x8x1xi32>,1843// CHECK-SAME:      %[[SRC:.*]]: tensor<7x?xi32>,1844// CHECK-SAME:      %[[PAD:.*]]: i32) -> tensor<1x1x8x1xi32> {1845// CHECK:           %[[PACK:.*]] = linalg.pack %[[SRC]] padding_value(%[[PAD]] : i32)1846// CHECK-SAME:        inner_dims_pos = [0, 1] inner_tiles = [8, 1] into %[[DEST]]1847// CHECK-SAME:        test_attr1848// CHECK-SAME:        : tensor<7x?xi32> -> tensor<1x1x8x1xi32>1849// CHECK:           return %[[PACK]] : tensor<1x1x8x1xi32>1850func.func @fold_cast_pack_dynamic_tile_size(1851  %dest: tensor<1x1x8x1xi32>,1852  %src: tensor<7x?xi32>,1853  %pad: i32) -> tensor<1x1x8x1xi32> {1854 1855    %cast = tensor.cast %dest : tensor<1x1x8x1xi32> to tensor<1x1x?x1xi32>1856    %c8 = arith.constant 8 : index1857    %pack = linalg.pack %src padding_value(%pad : i32)1858      inner_dims_pos = [0, 1]1859      inner_tiles = [%c8, 1]1860      into %cast {test_attr} : tensor<7x?xi32> -> tensor<1x1x?x1xi32>1861    %res = tensor.cast %pack : tensor<1x1x?x1xi32> to tensor<1x1x8x1xi32>1862    return %res : tensor<1x1x8x1xi32>1863}1864 1865// -----1866 1867func.func @infer_and_fold_pack_unpack_same_tiles(%t: tensor<10x20x4x4xf32>) -> tensor<10x20x4x4xf32> {1868  %dim1 = arith.constant 40 : index1869  %dim2 = arith.constant 80 : index1870  %tensor_empty = tensor.empty(%dim1, %dim2) : tensor<?x?xf32>1871  %unpacked = linalg.unpack %t inner_dims_pos = [0, 1] inner_tiles = [4, 4] into %tensor_empty : tensor<10x20x4x4xf32> -> tensor<?x?xf32>1872  %cast = tensor.cast %unpacked : tensor<?x?xf32> to tensor<40x80xf32>1873  %tensor_empty1 = tensor.empty() : tensor<10x20x4x4xf32>1874  %packed = linalg.pack %cast inner_dims_pos = [0, 1] inner_tiles = [4, 4] into %tensor_empty1 : tensor<40x80xf32> -> tensor<10x20x4x4xf32>1875  return %packed : tensor<10x20x4x4xf32>1876}1877// CHECK-LABEL: func.func @infer_and_fold_pack_unpack_same_tiles1878// CHECK-SAME:    %[[SRC:[0-9a-zA-Z]+]]1879// CHECK:         return %[[SRC]]1880 1881// -----1882 1883// CHECK-LABEL:   func.func @pack_dont_drop_attributes(1884// CHECK: linalg.pack {{.*}}  {test_attr}1885func.func @pack_dont_drop_attributes(%arg0: tensor<?x?x?xf16>, %arg1: tensor<128x?x100x16x1xf16>) -> tensor<128x?x100x16x1xf16> {1886  %c32_i64 = arith.constant 32 : i641887  %cst = arith.constant 0.000000e+00 : f161888  %pack = linalg.pack %arg0 padding_value(%cst : f16) outer_dims_perm = [0, 1, 2] inner_dims_pos = [1, 2] inner_tiles = [16, 1] into %arg1 {test_attr} : tensor<?x?x?xf16> -> tensor<128x?x100x16x1xf16>1889  return %pack : tensor<128x?x100x16x1xf16>1890}1891// -----1892 1893//===----------------------------------------------------------------------===//1894// linalg.fill + linalg.unpack1895//===----------------------------------------------------------------------===//1896// Fold DstStyleOp -> tensor.unpack operations.1897func.func @fold_dst_style_ops_into_unpack(%arg0 : tensor<?x?x16x64xf32>, %init : tensor<?x?xf32>) -> tensor<?x?xf32> {1898  %cst = arith.constant 0.0 : f321899  %fill = linalg.fill ins(%cst : f32) outs(%init : tensor<?x?xf32>) -> tensor<?x?xf32>1900  %unpack = linalg.unpack %arg0 inner_dims_pos = [0, 1] inner_tiles = [16, 64] into %fill : tensor<?x?x16x64xf32> -> tensor<?x?xf32>1901  return %unpack : tensor<?x?xf32>1902}1903// CHECK-LABEL: func @fold_dst_style_ops_into_unpack1904//  CHECK-SAME:     %[[ARG0:.+]]: tensor<?x?x16x64xf32>1905//  CHECK-SAME:     %[[INIT:.+]]: tensor<?x?xf32>1906//       CHECK:   %[[UNPACK:.+]] = linalg.unpack %[[ARG0]]1907//  CHECK-SAME:       into %[[INIT]]1908//       CHECK:   return %[[UNPACK]]1909 1910// -----1911 1912//===----------------------------------------------------------------------===//1913// tensor.cast + linalg.unpack1914//===----------------------------------------------------------------------===//1915 1916// CHECK-LABEL:   func.func @fold_cast_unpack_dynamic_tile_size(1917// CHECK-SAME:      %[[SRC:.*]]: tensor<1x1x8x1xi32>,1918// CHECK-SAME:      %[[DEST:.*]]: tensor<7x?xi32>) -> tensor<7x?xi32> {1919// CHECK:           %[[RES:.*]] = linalg.unpack %[[SRC]] inner_dims_pos = [0, 1] inner_tiles = [8, 1] into %[[DEST]] {test_attr} : tensor<1x1x8x1xi32> -> tensor<7x?xi32>1920// CHECK:           return %[[RES]] : tensor<7x?xi32>1921func.func @fold_cast_unpack_dynamic_tile_size(1922  %src: tensor<1x1x8x1xi32>,1923  %res: tensor<7x?xi32>) -> tensor<7x?xi32> {1924 1925    %cast = tensor.cast %src : tensor<1x1x8x1xi32> to tensor<1x1x?x1xi32>1926    %c8 = arith.constant 8 : index1927    %unpack = linalg.unpack %cast1928      inner_dims_pos = [0, 1]1929      inner_tiles = [%c8, 1]1930      into %res {test_attr} : tensor<1x1x?x1xi32> -> tensor<7x?xi32>1931    return %unpack : tensor<7x?xi32>1932}1933 1934// -----1935 1936//===----------------------------------------------------------------------===//1937// linalg.unpack + tensor.extract_slice1938//===----------------------------------------------------------------------===//1939 1940func.func @fold_extract_slice_into_unpack_slicing_trailing_dim(%src : tensor<28x2x1x16x16xf32>, %dest : tensor<28x28x15xf32>) -> tensor<28x28x10xf32> {1941  %unpack = linalg.unpack %src1942      outer_dims_perm = [0, 1, 2]1943      inner_dims_pos = [1, 2]1944      inner_tiles = [16, 16]1945      into %dest : tensor<28x2x1x16x16xf32> -> tensor<28x28x15xf32>1946  %extracted_slice = tensor.extract_slice %unpack1947      [0, 0, 0] [28, 28, 10] [1, 1, 1] : tensor<28x28x15xf32> to tensor<28x28x10xf32>1948  return %extracted_slice : tensor<28x28x10xf32>1949}1950// CHECK-LABEL: func @fold_extract_slice_into_unpack_slicing_trailing_dim1951//  CHECK-SAME:     %[[SRC:[a-zA-Z0-9]+]]1952//  CHECK-SAME:     %[[DEST:[a-zA-Z0-9]+]]1953//       CHECK:   %[[DEST_SLICE:.+]] = tensor.extract_slice %[[DEST]]1954//  CHECK-SAME:     [0, 0, 0] [28, 28, 10] [1, 1, 1]1955//       CHECK:   %[[UNPACK:.+]] = linalg.unpack %[[SRC]]1956//  CHECK-SAME:       into %[[DEST_SLICE]]1957//       CHECK:   return %[[UNPACK]]1958 1959// -----1960 1961// The available dimension size is [17, 32], because CeilDiv(%d1, 16) == 2.1962 1963func.func @fold_extract_slice_into_unpack_slicing_dim_1(%src : tensor<28x2x1x16x16xf32>, %dest : tensor<28x28x15xf32>) -> tensor<28x17x15xf32> {1964  %unpack = linalg.unpack %src1965      inner_dims_pos = [1, 2]1966      inner_tiles = [16, 16]1967      into %dest : tensor<28x2x1x16x16xf32> -> tensor<28x28x15xf32>1968  %extracted_slice = tensor.extract_slice %unpack1969      [0, 0, 0] [28, 17, 15] [1, 1, 1] : tensor<28x28x15xf32> to tensor<28x17x15xf32>1970  return %extracted_slice : tensor<28x17x15xf32>1971}1972// CHECK-LABEL: func @fold_extract_slice_into_unpack_slicing_dim_1(1973//  CHECK-SAME:     %[[SRC:[a-zA-Z0-9]+]]1974//  CHECK-SAME:     %[[DEST:[a-zA-Z0-9]+]]1975//       CHECK:   %[[DEST_SLICE:.+]] = tensor.extract_slice %[[DEST]]1976//  CHECK-SAME:     [0, 0, 0] [28, 17, 15] [1, 1, 1]1977//       CHECK:   %[[UNPACK:.+]] = linalg.unpack %[[SRC]]1978//  CHECK-SAME:       into %[[DEST_SLICE]]1979//       CHECK:   return %[[UNPACK]]1980 1981// -----1982 1983// The available dimension size is [17, 32], because CeilDiv(%d1, 16) == 2.1984 1985func.func @no_fold_extract_slice_into_unpack_artificial_padding(%src : tensor<28x2x1x16x16xf32>, %dest : tensor<28x28x15xf32>) -> tensor<28x16x15xf32> {1986  %unpack = linalg.unpack %src1987      inner_dims_pos = [1, 2]1988      inner_tiles = [16, 16]1989      into %dest : tensor<28x2x1x16x16xf32> -> tensor<28x28x15xf32>1990  %extracted_slice = tensor.extract_slice %unpack1991      [0, 0, 0] [28, 16, 15] [1, 1, 1] : tensor<28x28x15xf32> to tensor<28x16x15xf32>1992  return %extracted_slice : tensor<28x16x15xf32>1993}1994// CHECK-LABEL: func @no_fold_extract_slice_into_unpack_artificial_padding1995//       CHECK:   linalg.unpack1996//       CHECK:   tensor.extract_slice1997 1998// -----1999 2000func.func @no_fold_extract_slice_into_unpack_dynamic(2001    %src : tensor<28x2x?x16x16xf32>, %dest : tensor<28x32x?xf32>, %size : index2002) -> tensor<28x28x?xf32> {2003  %unpack = linalg.unpack %src2004      outer_dims_perm = [0, 1, 2]2005      inner_dims_pos = [1, 2]2006      inner_tiles = [16, 16]2007      into %dest : tensor<28x2x?x16x16xf32> -> tensor<28x32x?xf32>2008  %extracted_slice = tensor.extract_slice %unpack2009      [0, 0, 0] [28, 28, %size] [1, 1, 1] : tensor<28x32x?xf32> to tensor<28x28x?xf32>2010  return %extracted_slice : tensor<28x28x?xf32>2011}2012// CHECK-LABEL: func @no_fold_extract_slice_into_unpack_dynamic2013//       CHECK:   linalg.unpack2014//       CHECK:   tensor.extract_slice2015 2016// -----2017 2018func.func @no_fold_extract_slice_into_unpack_rank_reducing(2019    %src : tensor<28x2x16xf32>, %dest : tensor<28x32xf32>2020) -> tensor<28xf32> {2021  %unpack = linalg.unpack %src2022      outer_dims_perm = [0, 1]2023      inner_dims_pos = [1]2024      inner_tiles = [16]2025      into %dest : tensor<28x2x16xf32> -> tensor<28x32xf32>2026  %extracted_slice = tensor.extract_slice %unpack2027      [0, 0] [1, 28] [1, 1] : tensor<28x32xf32> to tensor<28xf32>2028  return %extracted_slice : tensor<28xf32>2029}2030 2031// CHECK-LABEL: func @no_fold_extract_slice_into_unpack_rank_reducing2032//  CHECK-SAME:     %[[SRC:.+]]: tensor<28x2x16xf32>2033//  CHECK-SAME:     %[[DEST:.+]]: tensor<28x32xf32>2034//       CHECK:   %[[UNPACK:.+]] = linalg.unpack %[[SRC]]2035//  CHECK-SAME:       into %[[DEST]]2036//       CHECK:   %[[SLICE:.+]] = tensor.extract_slice %[[UNPACK]]2037//       CHECK:   return %[[SLICE]]2038 2039// -----2040 2041func.func @no_fold_extract_slice_into_unpack_non_zero_offset(2042    %src : tensor<28x2x16xf32>, %dest : tensor<28x32xf32>2043) -> tensor<28x28xf32> {2044  %unpack = linalg.unpack %src2045      outer_dims_perm = [0, 1]2046      inner_dims_pos = [1]2047      inner_tiles = [16]2048      into %dest : tensor<28x2x16xf32> -> tensor<28x32xf32>2049  %extracted_slice = tensor.extract_slice %unpack2050      [0, 1] [28, 28] [1, 1] : tensor<28x32xf32> to tensor<28x28xf32>2051  return %extracted_slice : tensor<28x28xf32>2052}2053 2054// CHECK-LABEL: func @no_fold_extract_slice_into_unpack_non_zero_offset2055//  CHECK-SAME:     %[[SRC:.+]]: tensor<28x2x16xf32>2056//  CHECK-SAME:     %[[DEST:.+]]: tensor<28x32xf32>2057//       CHECK:   %[[UNPACK:.+]] = linalg.unpack %[[SRC]]2058//  CHECK-SAME:       into %[[DEST]]2059//       CHECK:   %[[SLICE:.+]] = tensor.extract_slice %[[UNPACK]]2060//       CHECK:   return %[[SLICE]]2061