3964 lines · plain
1// RUN: mlir-opt %s -canonicalize="test-convergence" -split-input-file -allow-unregistered-dialect | FileCheck %s2 3// CHECK-LABEL: create_vector_mask_to_constant_mask4func.func @create_vector_mask_to_constant_mask() -> (vector<4x3xi1>) {5 %c2 = arith.constant 2 : index6 %c3 = arith.constant 3 : index7 // CHECK: vector.constant_mask [3, 2] : vector<4x3xi1>8 %0 = vector.create_mask %c3, %c2 : vector<4x3xi1>9 return %0 : vector<4x3xi1>10}11 12// -----13 14// CHECK-LABEL: create_scalable_vector_mask_to_constant_mask15func.func @create_scalable_vector_mask_to_constant_mask() -> (vector<[8]xi1>) {16 %c-1 = arith.constant -1 : index17 // CHECK: arith.constant dense<false> : vector<[8]xi1>18 %0 = vector.create_mask %c-1 : vector<[8]xi1>19 return %0 : vector<[8]xi1>20}21 22// -----23 24// CHECK-LABEL: create_vector_mask_to_constant_mask_truncation25func.func @create_vector_mask_to_constant_mask_truncation() -> (vector<4x3xi1>) {26 %c2 = arith.constant 2 : index27 %c5 = arith.constant 5 : index28 // CHECK: vector.constant_mask [4, 2] : vector<4x3xi1>29 %0 = vector.create_mask %c5, %c2 : vector<4x3xi1>30 return %0 : vector<4x3xi1>31}32 33// -----34 35// CHECK-LABEL: create_vector_mask_to_constant_mask_truncation_neg36func.func @create_vector_mask_to_constant_mask_truncation_neg() -> (vector<4x3xi1>) {37 %cneg2 = arith.constant -2 : index38 %c5 = arith.constant 5 : index39 // CHECK: arith.constant dense<false> : vector<4x3xi1>40 %0 = vector.create_mask %c5, %cneg2 : vector<4x3xi1>41 return %0 : vector<4x3xi1>42}43 44// -----45 46// CHECK-LABEL: create_vector_mask_to_constant_mask_truncation_zero47func.func @create_vector_mask_to_constant_mask_truncation_zero() -> (vector<4x3xi1>) {48 %c2 = arith.constant 2 : index49 %c0 = arith.constant 0 : index50 // CHECK: arith.constant dense<false> : vector<4x3xi1>51 %0 = vector.create_mask %c0, %c2 : vector<4x3xi1>52 return %0 : vector<4x3xi1>53}54 55// -----56 57// CHECK-LABEL: create_vector_mask_to_constant_mask_scalable_all_true58func.func @create_vector_mask_to_constant_mask_scalable_all_true() -> (vector<8x[16]xi1>) {59 %c8 = arith.constant 8 : index60 %c16 = arith.constant 16 : index61 %0 = vector.vscale62 %1 = arith.muli %0, %c16 : index63 // CHECK: arith.constant dense<true> : vector<8x[16]xi1>64 %10 = vector.create_mask %c8, %1 : vector<8x[16]xi1>65 return %10 : vector<8x[16]xi1>66}67 68// -----69 70// CHECK-LABEL: create_mask_transpose_to_transposed_create_mask71// CHECK-SAME: %[[DIM0:.*]]: index, %[[DIM1:.*]]: index, %[[DIM2:.*]]: index72func.func @create_mask_transpose_to_transposed_create_mask(73 %dim0: index, %dim1: index, %dim2: index) -> (vector<2x3x4xi1>, vector<4x2x3xi1>) {74 // CHECK: vector.create_mask %[[DIM0]], %[[DIM1]], %[[DIM2]] : vector<2x3x4xi1>75 // CHECK: vector.create_mask %[[DIM2]], %[[DIM0]], %[[DIM1]] : vector<4x2x3xi1>76 // CHECK-NOT: vector.transpose77 %0 = vector.create_mask %dim0, %dim1, %dim2 : vector<2x3x4xi1>78 %1 = vector.transpose %0, [2, 0, 1] : vector<2x3x4xi1> to vector<4x2x3xi1>79 return %0, %1 : vector<2x3x4xi1>, vector<4x2x3xi1>80}81 82// -----83 84// CHECK-LABEL: extract_from_create_mask85// CHECK-SAME: %[[DIM0:.*]]: index, %[[DIM1:.*]]: index86func.func @extract_from_create_mask(%dim0: index, %dim1: index) -> vector<[4]x[4]xi1> {87 %c2 = arith.constant 2 : index88 %mask = vector.create_mask %c2, %dim0, %dim1 : vector<4x[4]x[4]xi1>89 // CHECK: vector.create_mask %[[DIM0]], %[[DIM1]] : vector<[4]x[4]xi1>90 // CHECK-NOT: vector.extract91 %extract = vector.extract %mask[1] : vector<[4]x[4]xi1> from vector<4x[4]x[4]xi1>92 return %extract : vector<[4]x[4]xi1>93}94 95// -----96 97// CHECK-LABEL: extract_from_create_mask_all_false98func.func @extract_from_create_mask_all_false(%dim0: index, %dim1: index) -> vector<[4]x[4]xi1> {99 %c2 = arith.constant 2 : index100 %mask = vector.create_mask %c2, %dim0, %dim1 : vector<4x[4]x[4]xi1>101 // CHECK: arith.constant dense<false> : vector<[4]x[4]xi1>102 // CHECK-NOT: vector.extract103 %extract = vector.extract %mask[2] : vector<[4]x[4]xi1> from vector<4x[4]x[4]xi1>104 return %extract : vector<[4]x[4]xi1>105}106 107// -----108 109// CHECK-LABEL: extract_from_create_mask_leading_scalable110// CHECK-SAME: %[[DIM0:.*]]: index111func.func @extract_from_create_mask_leading_scalable(%dim0: index) -> vector<8xi1> {112 %c3 = arith.constant 3 : index113 %mask = vector.create_mask %c3, %dim0 : vector<[4]x8xi1>114 // CHECK: vector.create_mask %[[DIM0]] : vector<8xi1>115 // CHECK-NOT: vector.extract116 %extract = vector.extract %mask[1] : vector<8xi1> from vector<[4]x8xi1>117 return %extract : vector<8xi1>118}119 120// -----121 122// CHECK-LABEL: extract_from_create_mask_dynamic_position123// CHECK-SAME: %[[DIM0:.*]]: index, %[[INDEX:.*]]: index124func.func @extract_from_create_mask_dynamic_position(%dim0: index, %index: index) -> vector<6xi1> {125 %c4 = arith.constant 4 : index126 %c3 = arith.constant 3 : index127 %mask = vector.create_mask %c3, %c4, %dim0 : vector<4x4x6xi1>128 // CHECK: vector.create_mask %[[DIM0]] : vector<6xi1>129 // CHECK-NOT: vector.extract130 %extract = vector.extract %mask[2, %index] : vector<6xi1> from vector<4x4x6xi1>131 return %extract : vector<6xi1>132}133 134// -----135 136// CHECK-LABEL: @extract_scalar_poison137func.func @extract_scalar_poison() -> f32 {138 // CHECK-NEXT: %[[UB:.*]] = ub.poison : f32139 // CHECK-NOT: vector.extract140 // CHECK-NEXT: return %[[UB]] : f32141 %0 = ub.poison : vector<4x8xf32>142 %1 = vector.extract %0[2, 4] : f32 from vector<4x8xf32>143 return %1 : f32144}145 146// -----147 148// CHECK-LABEL: @extract_vector_poison149func.func @extract_vector_poison() -> vector<8xf32> {150 // CHECK-NEXT: %[[UB:.*]] = ub.poison : vector<8xf32>151 // CHECK-NOT: vector.extract152 // CHECK-NEXT: return %[[UB]] : vector<8xf32>153 %0 = ub.poison : vector<4x8xf32>154 %1 = vector.extract %0[2] : vector<8xf32> from vector<4x8xf32>155 return %1 : vector<8xf32>156}157 158// -----159 160// CHECK-LABEL: @extract_scalar_poison_idx161func.func @extract_scalar_poison_idx(%a: vector<4x5xf32>) -> f32 {162 // CHECK-NEXT: %[[UB:.*]] = ub.poison : f32163 // CHECK-NOT: vector.extract164 // CHECK-NEXT: return %[[UB]] : f32165 %0 = vector.extract %a[-1, 0] : f32 from vector<4x5xf32>166 return %0 : f32167}168 169// -----170 171// Similar to the test above, but the index is not a static constant.172 173// CHECK-LABEL: @extract_scalar_poison_idx_non_cst174func.func @extract_scalar_poison_idx_non_cst(%a: vector<4x5xf32>) -> f32 {175 // CHECK-NEXT: %[[UB:.*]] = ub.poison : f32176 // CHECK-NOT: vector.extract177 // CHECK-NEXT: return %[[UB]] : f32178 %c_neg_1 = arith.constant -1 : index179 %0 = vector.extract %a[%c_neg_1, 0] : f32 from vector<4x5xf32>180 return %0 : f32181}182 183// -----184 185// Similar to test above, but now the index is out-of-bounds.186 187// CHECK-LABEL: @no_fold_extract_scalar_oob_idx188func.func @no_fold_extract_scalar_oob_idx(%a: vector<4x5xf32>) -> f32 {189 // CHECK: vector.extract190 %c_neg_2 = arith.constant -2 : index191 %0 = vector.extract %a[%c_neg_2, 0] : f32 from vector<4x5xf32>192 return %0 : f32193}194 195 196// -----197 198// CHECK-LABEL: @extract_vector_poison_idx199func.func @extract_vector_poison_idx(%a: vector<4x5xf32>) -> vector<5xf32> {200 // CHECK-NEXT: %[[UB:.*]] = ub.poison : vector<5xf32>201 // CHECK-NOT: vector.extract202 // CHECK-NEXT: return %[[UB]] : vector<5xf32>203 %0 = vector.extract %a[-1] : vector<5xf32> from vector<4x5xf32>204 return %0 : vector<5xf32>205}206 207// -----208 209// CHECK-LABEL: @extract_multiple_poison_idx210func.func @extract_multiple_poison_idx(%a: vector<4x5x8xf32>)211 -> vector<8xf32> {212 // CHECK-NEXT: %[[UB:.*]] = ub.poison : vector<8xf32>213 // CHECK-NOT: vector.extract214 // CHECK-NEXT: return %[[UB]] : vector<8xf32>215 %0 = vector.extract %a[-1, -1] : vector<8xf32> from vector<4x5x8xf32>216 return %0 : vector<8xf32>217}218 219// -----220 221// CHECK-LABEL: extract_from_create_mask_dynamic_position_all_false222// CHECK-SAME: %[[DIM0:.*]]: index, %[[INDEX:.*]]: index223func.func @extract_from_create_mask_dynamic_position_all_false(%dim0: index, %index: index) -> vector<6xi1> {224 %c0 = arith.constant 0 : index225 %c1 = arith.constant 1 : index226 %mask = vector.create_mask %c1, %c0, %dim0 : vector<1x4x6xi1>227 // CHECK: arith.constant dense<false> : vector<6xi1>228 // CHECK-NOT: vector.extract229 %extract = vector.extract %mask[0, %index] : vector<6xi1> from vector<1x4x6xi1>230 return %extract : vector<6xi1>231}232 233// -----234 235// CHECK-LABEL: extract_from_create_mask_dynamic_position_unknown236// CHECK-SAME: %[[DIM0:.*]]: index, %[[INDEX:.*]]: index237func.func @extract_from_create_mask_dynamic_position_unknown(%dim0: index, %index: index) -> vector<6xi1> {238 %c2 = arith.constant 2 : index239 %mask = vector.create_mask %c2, %dim0 : vector<4x6xi1>240 // CHECK: %[[C2:.*]] = arith.constant 2 : index241 // CHECK-NEXT: %[[MASK:.*]] = vector.create_mask %[[C2]], %[[DIM0]] : vector<4x6xi1>242 // CHECK-NEXT: vector.extract %[[MASK]][%[[INDEX]]] : vector<6xi1> from vector<4x6xi1>243 %extract = vector.extract %mask[%index] : vector<6xi1> from vector<4x6xi1>244 return %extract : vector<6xi1>245}246 247// -----248 249// CHECK-LABEL: extract_from_create_mask_mixed_position_unknown250// CHECK-SAME: %[[DIM0:.*]]: index, %[[INDEX:.*]]: index251func.func @extract_from_create_mask_mixed_position_unknown(%dim0: index, %index0: index) -> vector<4xi1> {252 %c2 = arith.constant 2 : index253 %mask = vector.create_mask %c2, %c2, %dim0 : vector<2x4x4xi1>254 // CHECK: %[[C2:.*]] = arith.constant 2 : index255 // CHECK-NEXT: %[[MASK:.*]] = vector.create_mask %[[C2]], %[[C2]], %[[DIM0]] : vector<2x4x4xi1>256 // CHECK-NEXT: vector.extract %[[MASK]][1, %[[INDEX]]] : vector<4xi1> from vector<2x4x4xi1>257 %extract = vector.extract %mask[1, %index0] : vector<4xi1> from vector<2x4x4xi1>258 return %extract : vector<4xi1>259}260 261// -----262 263// CHECK-LABEL: extract_from_non_constant_create_mask264// CHECK-SAME: %[[DIM0:.*]]: index265func.func @extract_from_non_constant_create_mask(%dim0: index) -> vector<[2]xi1> {266 %mask = vector.create_mask %dim0, %dim0 : vector<[2]x[2]xi1>267 // CHECK: %[[MASK:.*]] = vector.create_mask %[[DIM0]], %[[DIM0]] : vector<[2]x[2]xi1>268 // CHECK-NEXT: vector.extract %[[MASK]][0] : vector<[2]xi1> from vector<[2]x[2]xi1>269 %extract = vector.extract %mask[0] : vector<[2]xi1> from vector<[2]x[2]xi1>270 return %extract : vector<[2]xi1>271}272 273// -----274 275// CHECK-LABEL: constant_mask_to_true_splat276func.func @constant_mask_to_true_splat() -> vector<2x4xi1> {277 // CHECK: arith.constant dense<true>278 // CHECK-NOT: vector.constant_mask279 %0 = vector.constant_mask [2, 4] : vector<2x4xi1>280 return %0 : vector<2x4xi1>281}282 283// CHECK-LABEL: constant_mask_to_false_splat284func.func @constant_mask_to_false_splat() -> vector<2x4xi1> {285 // CHECK: arith.constant dense<false>286 // CHECK-NOT: vector.constant_mask287 %0 = vector.constant_mask [0, 0] : vector<2x4xi1>288 return %0 : vector<2x4xi1>289}290 291// CHECK-LABEL: constant_mask_to_true_splat_0d292func.func @constant_mask_to_true_splat_0d() -> vector<i1> {293 // CHECK: arith.constant dense<true>294 // CHECK-NOT: vector.constant_mask295 %0 = vector.constant_mask [1] : vector<i1>296 return %0 : vector<i1>297}298 299// CHECK-LABEL: constant_mask_transpose_to_transposed_constant_mask300func.func @constant_mask_transpose_to_transposed_constant_mask() -> (vector<2x3x4xi1>, vector<4x2x3xi1>) {301 // CHECK: vector.constant_mask [1, 2, 3] : vector<2x3x4xi1>302 // CHECK: vector.constant_mask [3, 1, 2] : vector<4x2x3xi1>303 // CHECK-NOT: vector.transpose304 %0 = vector.constant_mask [1, 2, 3] : vector<2x3x4xi1>305 %1 = vector.transpose %0, [2, 0, 1] : vector<2x3x4xi1> to vector<4x2x3xi1>306 return %0, %1 : vector<2x3x4xi1>, vector<4x2x3xi1>307}308 309// -----310 311func.func @extract_strided_slice_of_constant_mask() -> (vector<2x2xi1>) {312 %0 = vector.constant_mask [2, 2] : vector<4x3xi1>313 %1 = vector.extract_strided_slice %0314 {offsets = [0, 0], sizes = [2, 2], strides = [1, 1]}315 : vector<4x3xi1> to vector<2x2xi1>316 // CHECK: arith.constant dense<true> : vector<2x2xi1>317 return %1 : vector<2x2xi1>318}319 320// -----321 322func.func @extract_strided_slice_of_constant_mask() -> (vector<2x2xi1>) {323 %0 = vector.constant_mask [2, 2] : vector<4x3xi1>324 %1 = vector.extract_strided_slice %0325 {offsets = [1, 0], sizes = [2, 2], strides = [1, 1]}326 : vector<4x3xi1> to vector<2x2xi1>327 // CHECK: vector.constant_mask [1, 2] : vector<2x2xi1>328 return %1 : vector<2x2xi1>329}330 331// -----332 333func.func @extract_strided_slice_of_constant_mask() -> (vector<2x2xi1>) {334 %0 = vector.constant_mask [2, 2] : vector<4x3xi1>335 %1 = vector.extract_strided_slice %0336 {offsets = [0, 1], sizes = [2, 2], strides = [1, 1]}337 : vector<4x3xi1> to vector<2x2xi1>338 // CHECK: vector.constant_mask [2, 1] : vector<2x2xi1>339 return %1 : vector<2x2xi1>340}341 342// -----343 344func.func @extract_strided_slice_of_constant_mask() -> (vector<2x2xi1>) {345 %0 = vector.constant_mask [2, 2] : vector<4x3xi1>346 %1 = vector.extract_strided_slice %0347 {offsets = [2, 0], sizes = [2, 2], strides = [1, 1]}348 : vector<4x3xi1> to vector<2x2xi1>349 // CHECK: arith.constant dense<false> : vector<2x2xi1>350 return %1 : vector<2x2xi1>351}352 353// -----354 355func.func @extract_strided_slice_of_constant_mask() -> (vector<2x1xi1>) {356 %0 = vector.constant_mask [2, 2] : vector<4x3xi1>357 %1 = vector.extract_strided_slice %0358 {offsets = [0, 2], sizes = [2, 1], strides = [1, 1]}359 : vector<4x3xi1> to vector<2x1xi1>360 // CHECK: arith.constant dense<false> : vector<2x1xi1>361 return %1 : vector<2x1xi1>362}363 364// -----365 366func.func @extract_strided_slice_of_constant_mask() -> (vector<2x1xi1>) {367 %0 = vector.constant_mask [2, 2] : vector<4x3xi1>368 %1 = vector.extract_strided_slice %0369 {offsets = [0, 1], sizes = [2, 1], strides = [1, 1]}370 : vector<4x3xi1> to vector<2x1xi1>371 // CHECK: arith.constant dense<true> : vector<2x1xi1>372 return %1 : vector<2x1xi1>373}374 375// -----376 377func.func @extract_strided_slice_of_constant_mask() -> (vector<2x1xi1>) {378 %0 = vector.constant_mask [2, 2] : vector<4x3xi1>379 %1 = vector.extract_strided_slice %0380 {offsets = [1, 1], sizes = [2, 1], strides = [1, 1]}381 : vector<4x3xi1> to vector<2x1xi1>382 // CHECK: vector.constant_mask [1, 1] : vector<2x1xi1>383 return %1 : vector<2x1xi1>384}385 386// -----387 388// CHECK-LABEL: func.func @extract_strided_slice_of_create_mask389// CHECK-SAME: (%[[DIM0:.+]]: index, %[[DIM1:.+]]: index)390func.func @extract_strided_slice_of_create_mask(%dim0: index, %dim1: index) -> (vector<2x2xi1>) {391 %0 = vector.create_mask %dim0, %dim1 : vector<4x3xi1>392 %1 = vector.extract_strided_slice %0393 {offsets = [2, 1], sizes = [2, 2], strides = [1, 1]}394 : vector<4x3xi1> to vector<2x2xi1>395 // CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index396 // CHECK-DAG: %[[C2:.+]] = arith.constant 2 : index397 // CHECK-DAG: %[[A:.+]] = arith.subi %[[DIM0]], %[[C2]]398 // CHECK-DAG: %[[B:.+]] = arith.subi %[[DIM1]], %[[C1]]399 // CHECK: vector.create_mask %[[A]], %[[B]] : vector<2x2xi1>400 return %1 : vector<2x2xi1>401}402 403// -----404 405// CHECK-LABEL: func.func @extract_strided_slice_partial_of_create_mask406// CHECK-SAME: (%[[DIM0:.+]]: index, %[[DIM1:.+]]: index, %[[DIM2:.+]]: index)407func.func @extract_strided_slice_partial_of_create_mask(408 %dim0: index, %dim1: index, %dim2 : index) -> (vector<2x2x8xi1>) {409 %0 = vector.create_mask %dim0, %dim1, %dim2 : vector<4x3x8xi1>410 %1 = vector.extract_strided_slice %0411 {offsets = [2, 1], sizes = [2, 2], strides = [1, 1]}412 : vector<4x3x8xi1> to vector<2x2x8xi1>413 // CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index414 // CHECK-DAG: %[[C2:.+]] = arith.constant 2 : index415 // CHECK-DAG: %[[A:.+]] = arith.subi %[[DIM0]], %[[C2]]416 // CHECK-DAG: %[[B:.+]] = arith.subi %[[DIM1]], %[[C1]]417 // CHECK: vector.create_mask %[[A]], %[[B]], %[[DIM2]] : vector<2x2x8xi1>418 return %1 : vector<2x2x8xi1>419}420 421// -----422 423// CHECK-LABEL: extract_strided_fold424// CHECK-SAME: (%[[ARG:.*]]: vector<4x3xi1>)425// CHECK-NEXT: return %[[ARG]] : vector<4x3xi1>426func.func @extract_strided_fold(%arg : vector<4x3xi1>) -> (vector<4x3xi1>) {427 %0 = vector.extract_strided_slice %arg428 {offsets = [0, 0], sizes = [4, 3], strides = [1, 1]}429 : vector<4x3xi1> to vector<4x3xi1>430 return %0 : vector<4x3xi1>431}432 433// -----434 435// CHECK-LABEL: extract_strided_fold_insert436// CHECK-SAME: (%[[ARG:.*]]: vector<4x4xf32>437// CHECK-NEXT: return %[[ARG]] : vector<4x4xf32>438func.func @extract_strided_fold_insert(%a: vector<4x4xf32>, %b: vector<8x16xf32>)439 -> (vector<4x4xf32>) {440 %0 = vector.insert_strided_slice %a, %b {offsets = [2, 2], strides = [1, 1]}441 : vector<4x4xf32> into vector<8x16xf32>442 %1 = vector.extract_strided_slice %0443 {offsets = [2, 2], sizes = [4, 4], strides = [1, 1]}444 : vector<8x16xf32> to vector<4x4xf32>445 return %1 : vector<4x4xf32>446}447 448// -----449 450// Case where the vector inserted is a subset of the vector extracted.451// CHECK-LABEL: extract_strided_fold_insert452// CHECK-SAME: (%[[ARG0:.*]]: vector<6x4xf32>453// CHECK-NEXT: %[[EXT:.*]] = vector.extract_strided_slice %[[ARG0]]454// CHECK-SAME: {offsets = [0, 0], sizes = [4, 4], strides = [1, 1]}455// CHECK-SAME: : vector<6x4xf32> to vector<4x4xf32>456// CHECK-NEXT: return %[[EXT]] : vector<4x4xf32>457func.func @extract_strided_fold_insert(%a: vector<6x4xf32>, %b: vector<8x16xf32>)458 -> (vector<4x4xf32>) {459 %0 = vector.insert_strided_slice %a, %b {offsets = [2, 2], strides = [1, 1]}460 : vector<6x4xf32> into vector<8x16xf32>461 %1 = vector.extract_strided_slice %0462 {offsets = [2, 2], sizes = [4, 4], strides = [1, 1]}463 : vector<8x16xf32> to vector<4x4xf32>464 return %1 : vector<4x4xf32>465}466 467// -----468 469// Negative test where the extract is not a subset of the element inserted.470// CHECK-LABEL: negative_extract_strided_fold471// CHECK-SAME: (%[[ARG0:.*]]: vector<4x4xf32>, %[[ARG1:.*]]: vector<8x16xf32>472// CHECK: %[[INS:.*]] = vector.insert_strided_slice %[[ARG0]], %[[ARG1]]473// CHECK-SAME: {offsets = [2, 2], strides = [1, 1]}474// CHECK-SAME: : vector<4x4xf32> into vector<8x16xf32>475// CHECK: %[[EXT:.*]] = vector.extract_strided_slice %[[INS]]476// CHECK-SAME: {offsets = [2, 2], sizes = [6, 4], strides = [1, 1]}477// CHECK-SAME: : vector<8x16xf32> to vector<6x4xf32>478// CHECK-NEXT: return %[[EXT]] : vector<6x4xf32>479func.func @negative_extract_strided_fold(%a: vector<4x4xf32>, %b: vector<8x16xf32>)480 -> (vector<6x4xf32>) {481 %0 = vector.insert_strided_slice %a, %b {offsets = [2, 2], strides = [1, 1]}482 : vector<4x4xf32> into vector<8x16xf32>483 %1 = vector.extract_strided_slice %0484 {offsets = [2, 2], sizes = [6, 4], strides = [1, 1]}485 : vector<8x16xf32> to vector<6x4xf32>486 return %1 : vector<6x4xf32>487}488 489// -----490 491// Case where we need to go through 2 level of insert element.492// CHECK-LABEL: extract_strided_fold_insert493// CHECK-SAME: (%[[ARG0:.*]]: vector<2x8xf32>, %[[ARG1:.*]]: vector<1x4xf32>,494// CHECK-NEXT: %[[EXT:.*]] = vector.extract_strided_slice %[[ARG1]]495// CHECK-SAME: {offsets = [0, 0], sizes = [1, 1], strides = [1, 1]}496// CHECK-SAME: : vector<1x4xf32> to vector<1x1xf32>497// CHECK-NEXT: return %[[EXT]] : vector<1x1xf32>498func.func @extract_strided_fold_insert(%a: vector<2x8xf32>, %b: vector<1x4xf32>,499 %c : vector<1x4xf32>) -> (vector<1x1xf32>) {500 %0 = vector.insert_strided_slice %b, %a {offsets = [0, 1], strides = [1, 1]}501 : vector<1x4xf32> into vector<2x8xf32>502 %1 = vector.insert_strided_slice %c, %0 {offsets = [1, 0], strides = [1, 1]}503 : vector<1x4xf32> into vector<2x8xf32>504 %2 = vector.extract_strided_slice %1505 {offsets = [0, 1], sizes = [1, 1], strides = [1, 1]}506 : vector<2x8xf32> to vector<1x1xf32>507 return %2 : vector<1x1xf32>508}509 510// -----511 512// CHECK-LABEL: transpose_3D_identity513// CHECK-SAME: ([[ARG:%.*]]: vector<4x3x2xf32>)514func.func @transpose_3D_identity(%arg : vector<4x3x2xf32>) -> vector<4x3x2xf32> {515 // CHECK-NOT: transpose516 %0 = vector.transpose %arg, [0, 1, 2] : vector<4x3x2xf32> to vector<4x3x2xf32>517 // CHECK-NEXT: return [[ARG]]518 return %0 : vector<4x3x2xf32>519}520 521// -----522 523// CHECK-LABEL: transpose_2D_sequence524// CHECK-SAME: ([[ARG:%.*]]: vector<4x3xf32>)525func.func @transpose_2D_sequence(%arg : vector<4x3xf32>) -> vector<4x3xf32> {526 // CHECK-NOT: transpose527 %0 = vector.transpose %arg, [1, 0] : vector<4x3xf32> to vector<3x4xf32>528 %1 = vector.transpose %0, [0, 1] : vector<3x4xf32> to vector<3x4xf32>529 %2 = vector.transpose %1, [1, 0] : vector<3x4xf32> to vector<4x3xf32>530 %3 = vector.transpose %2, [0, 1] : vector<4x3xf32> to vector<4x3xf32>531 // CHECK: [[ADD:%.*]] = arith.addf [[ARG]], [[ARG]]532 %4 = arith.addf %2, %3 : vector<4x3xf32>533 // CHECK-NEXT: return [[ADD]]534 return %4 : vector<4x3xf32>535}536 537// -----538 539// CHECK-LABEL: transpose_3D_sequence540// CHECK-SAME: ([[ARG:%.*]]: vector<4x3x2xf32>)541func.func @transpose_3D_sequence(%arg : vector<4x3x2xf32>) -> vector<4x3x2xf32> {542 // CHECK: [[T0:%.*]] = vector.transpose [[ARG]], [2, 1, 0]543 %0 = vector.transpose %arg, [1, 2, 0] : vector<4x3x2xf32> to vector<3x2x4xf32>544 %1 = vector.transpose %0, [1, 0, 2] : vector<3x2x4xf32> to vector<2x3x4xf32>545 // CHECK: [[T1:%.*]] = vector.transpose %arg0, [2, 1, 0]546 %2 = vector.transpose %1, [2, 1, 0] : vector<2x3x4xf32> to vector<4x3x2xf32>547 %3 = vector.transpose %2, [2, 1, 0] : vector<4x3x2xf32> to vector<2x3x4xf32>548 // CHECK: [[MUL:%.*]] = arith.mulf [[T0]], [[T1]]549 %4 = arith.mulf %1, %3 : vector<2x3x4xf32>550 // CHECK: [[T5:%.*]] = vector.transpose [[MUL]], [2, 1, 0]551 %5 = vector.transpose %4, [2, 1, 0] : vector<2x3x4xf32> to vector<4x3x2xf32>552 // CHECK-NOT: transpose553 %6 = vector.transpose %3, [2, 1, 0] : vector<2x3x4xf32> to vector<4x3x2xf32>554 // CHECK: [[ADD:%.*]] = arith.addf [[T5]], [[ARG]]555 %7 = arith.addf %5, %6 : vector<4x3x2xf32>556 // CHECK-NEXT: return [[ADD]]557 return %7 : vector<4x3x2xf32>558}559 560// -----561 562// CHECK-LABEL: cast_transfers563func.func @cast_transfers(%A: memref<4x8xf32>) -> (vector<4x8xf32>) {564 %c0 = arith.constant 0 : index565 %f0 = arith.constant 0.0 : f32566 %0 = memref.cast %A : memref<4x8xf32> to memref<?x?xf32>567 568 // CHECK: vector.transfer_read %{{.*}} {in_bounds = [true, true]} : memref<4x8xf32>, vector<4x8xf32>569 %1 = vector.transfer_read %0[%c0, %c0], %f0 : memref<?x?xf32>, vector<4x8xf32>570 571 // CHECK: vector.transfer_write %{{.*}} {in_bounds = [true, true]} : vector<4x8xf32>, memref<4x8xf32>572 vector.transfer_write %1, %0[%c0, %c0] : vector<4x8xf32>, memref<?x?xf32>573 return %1 : vector<4x8xf32>574}575 576// -----577 578// CHECK-LABEL: cast_transfers579func.func @cast_transfers(%A: tensor<4x8xf32>) -> (vector<4x8xf32>) {580 %c0 = arith.constant 0 : index581 %f0 = arith.constant 0.0 : f32582 %0 = tensor.cast %A : tensor<4x8xf32> to tensor<?x?xf32>583 584 // CHECK: vector.transfer_read %{{.*}} {in_bounds = [true, true]} : tensor<4x8xf32>, vector<4x8xf32>585 %1 = vector.transfer_read %0[%c0, %c0], %f0 : tensor<?x?xf32>, vector<4x8xf32>586 587 return %1 : vector<4x8xf32>588}589 590// -----591 592// CHECK-LABEL: func @insert_extract_transpose_2d(593// CHECK-SAME: %[[V:[a-zA-Z0-9]*]]: vector<2x3xf32>,594// CHECK-SAME: %[[F0:[a-zA-Z0-9]*]]: f32,595// CHECK-SAME: %[[F1:[a-zA-Z0-9]*]]: f32,596// CHECK-SAME: %[[F2:[a-zA-Z0-9]*]]: f32,597// CHECK-SAME: %[[F3:[a-zA-Z0-9]*]]: f32598func.func @insert_extract_transpose_2d(599 %v: vector<2x3xf32>, %f0: f32, %f1: f32, %f2: f32, %f3: f32)600-> (f32, f32, f32)601{602 %0 = vector.insert %f0, %v[0, 0] : f32 into vector<2x3xf32>603 %1 = vector.insert %f1, %0[0, 1] : f32 into vector<2x3xf32>604 %2 = vector.insert %f2, %1[1, 0] : f32 into vector<2x3xf32>605 %3 = vector.insert %f3, %2[1, 1] : f32 into vector<2x3xf32>606 %4 = vector.transpose %3, [1, 0] : vector<2x3xf32> to vector<3x2xf32>607 %5 = vector.insert %f3, %4[1, 0] : f32 into vector<3x2xf32>608 %6 = vector.transpose %5, [1, 0] : vector<3x2xf32> to vector<2x3xf32>609 610 // Expected %f2 from %2 = vector.insert %f2, %1[1, 0].611 %r1 = vector.extract %3[1, 0] : f32 from vector<2x3xf32>612 613 // Expected %f1 from %1 = vector.insert %f1, %0[0, 1] followed by614 // transpose [1, 0].615 %r2 = vector.extract %4[1, 0] : f32 from vector<3x2xf32>616 617 // Expected %f2 from %2 = vector.insert %f2, %1[1, 0] followed by double618 // transpose [1, 0].619 %r3 = vector.extract %6[1, 0] : f32 from vector<2x3xf32>620 621 // CHECK-NEXT: return %[[F2]], %[[F1]], %[[F2]] : f32, f32, f32622 return %r1, %r2, %r3 : f32, f32, f32623}624 625// -----626 627// CHECK-LABEL: insert_extract_chain628// CHECK-SAME: %[[V334:[a-zA-Z0-9]*]]: vector<3x3x4xf32>629// CHECK-SAME: %[[V34:[a-zA-Z0-9]*]]: vector<3x4xf32>630// CHECK-SAME: %[[V4:[a-zA-Z0-9]*]]: vector<4xf32>631func.func @insert_extract_chain(%v334: vector<3x3x4xf32>, %v34: vector<3x4xf32>, %v4: vector<4xf32>)632 -> (vector<4xf32>, vector<4xf32>, vector<3x4xf32>, vector<3x4xf32>) {633 // CHECK-NEXT: %[[A34:.*]] = vector.insert634 %A34 = vector.insert %v34, %v334[0]: vector<3x4xf32> into vector<3x3x4xf32>635 // CHECK-NEXT: %[[B34:.*]] = vector.insert636 %B34 = vector.insert %v34, %A34[1]: vector<3x4xf32> into vector<3x3x4xf32>637 // CHECK-NEXT: %[[A4:.*]] = vector.insert638 %A4 = vector.insert %v4, %B34[1, 0]: vector<4xf32> into vector<3x3x4xf32>639 // CHECK-NEXT: %[[B4:.*]] = vector.insert640 %B4 = vector.insert %v4, %A4[1, 1]: vector<4xf32> into vector<3x3x4xf32>641 642 // Case 2.a. [1, 1] == insertpos ([1, 1])643 // Match %A4 insertionpos and fold to its source(i.e. %V4).644 %r0 = vector.extract %B4[1, 1]: vector<4xf32> from vector<3x3x4xf32>645 646 // Case 3.a. insertpos ([1]) is a prefix of [1, 0].647 // Traverse %B34 to its source(i.e. %V34@[*0*]).648 // CHECK-NEXT: %[[R1:.*]] = vector.extract %[[V34]][0]649 %r1 = vector.extract %B34[1, 0]: vector<4xf32> from vector<3x3x4xf32>650 651 // Case 4. [1] is a prefix of insertpos ([1, 1]).652 // Cannot traverse %B4.653 // CHECK-NEXT: %[[R2:.*]] = vector.extract %[[B4]][1]654 %r2 = vector.extract %B4[1]: vector<3x4xf32> from vector<3x3x4xf32>655 656 // Case 5. [0] is disjoint from insertpos ([1, 1]).657 // Traverse %B4 to its dest(i.e. %A4@[0]).658 // Traverse %A4 to its dest(i.e. %B34@[0]).659 // Traverse %B34 to its dest(i.e. %A34@[0]).660 // Match %A34 insertionpos and fold to its source(i.e. %V34).661 %r3 = vector.extract %B4[0]: vector<3x4xf32> from vector<3x3x4xf32>662 663 // CHECK: return %[[V4]], %[[R1]], %[[R2]], %[[V34]]664 return %r0, %r1, %r2, %r3:665 vector<4xf32>, vector<4xf32>, vector<3x4xf32>, vector<3x4xf32>666}667 668// -----669 670// CHECK-LABEL: func @insert_extract_transpose_3d(671// CHECK-SAME: %[[V234:[a-zA-Z0-9]*]]: vector<2x3x4xf32>672func.func @insert_extract_transpose_3d(673 %v234: vector<2x3x4xf32>, %v43: vector<4x3xf32>, %f0: f32)674 -> (vector<4xf32>, vector<4xf32>, vector<4xf32>, vector<3x4xf32>) {675 676 %a432 = vector.transpose %v234, [2, 1, 0] : vector<2x3x4xf32> to vector<4x3x2xf32>677 %b432 = vector.insert %f0, %a432[0, 0, 1] : f32 into vector<4x3x2xf32>678 %c234 = vector.transpose %b432, [2, 1, 0] : vector<4x3x2xf32> to vector<2x3x4xf32>679 // Case 1. %c234 = transpose [2,1,0] posWithSentinels [1,2,-1] -> [-1,2,1]680 // Case 5. %b432 = insert [0,0,1] (inter([.,2,1], [.,0,1]) == 0) prop to %v432681 // Case 1. %a432 = transpose [2,1,0] posWithSentinels [-1,2,1] -> [1,2,-1]682 // can extract directly from %v234, the rest folds.683 // CHECK: %[[R0:.*]] = vector.extract %[[V234]][1, 2]684 %r0 = vector.extract %c234[1, 2] : vector<4xf32> from vector<2x3x4xf32>685 686 // CHECK-NEXT: vector.transpose687 // CHECK-NEXT: vector.insert688 // CHECK-NEXT: %[[F234:.*]] = vector.transpose689 %d432 = vector.transpose %v234, [2, 1, 0] : vector<2x3x4xf32> to vector<4x3x2xf32>690 %e432 = vector.insert %f0, %d432[0, 2, 1] : f32 into vector<4x3x2xf32>691 %f234 = vector.transpose %e432, [2, 1, 0] : vector<4x3x2xf32> to vector<2x3x4xf32>692 // Case 1. %c234 = transpose [2,1,0] posWithSentinels [1,2,-1] -> [-1,2,1]693 // Case 4. %b432 = insert [0,0,1] (inter([.,2,1], [.,2,1]) != 0)694 // Bail, cannot do better than the current.695 // CHECK: %[[R1:.*]] = vector.extract %[[F234]]696 %r1 = vector.extract %f234[1, 2] : vector<4xf32> from vector<2x3x4xf32>697 698 // CHECK-NEXT: vector.transpose699 // CHECK-NEXT: vector.insert700 // CHECK-NEXT: %[[H234:.*]] = vector.transpose701 %g243 = vector.transpose %v234, [0, 2, 1] : vector<2x3x4xf32> to vector<2x4x3xf32>702 %h243 = vector.insert %v43, %g243[0] : vector<4x3xf32> into vector<2x4x3xf32>703 %i234 = vector.transpose %h243, [0, 2, 1] : vector<2x4x3xf32> to vector<2x3x4xf32>704 // Case 1. %i234 = transpose [0,2,1] posWithSentinels [0,-1,-2] -> [0,-2,-1]705 // Case 3.b. %b432 = insert [0] is prefix of [0,.,.] but internal transpose.706 // Bail, cannot do better than the current.707 // CHECK: %[[R2:.*]] = vector.extract %[[H234]][0, 1]708 %r2 = vector.extract %i234[0, 1] : vector<4xf32> from vector<2x3x4xf32>709 710 // CHECK-NEXT: vector.transpose711 // CHECK-NEXT: vector.insert712 // CHECK-NEXT: %[[K234:.*]] = vector.transpose713 %j243 = vector.transpose %v234, [0, 2, 1] : vector<2x3x4xf32> to vector<2x4x3xf32>714 %k243 = vector.insert %v43, %j243[0] : vector<4x3xf32> into vector<2x4x3xf32>715 %l234 = vector.transpose %k243, [0, 2, 1] : vector<2x4x3xf32> to vector<2x3x4xf32>716 // Case 1. %i234 = transpose [0,2,1] posWithSentinels [0,-1,-2] -> [0,-2,-1]717 // Case 2.b. %b432 = insert [0] == [0,.,.] but internal transpose.718 // Bail, cannot do better than the current.719 // CHECK: %[[R3:.*]] = vector.extract %[[K234]][0]720 %r3 = vector.extract %l234[0] : vector<3x4xf32> from vector<2x3x4xf32>721 722 // CHECK-NEXT: return %[[R0]], %[[R1]], %[[R2]], %[[R3]]723 return %r0, %r1, %r2, %r3: vector<4xf32>, vector<4xf32>, vector<4xf32>, vector<3x4xf32>724}725 726// -----727 728// CHECK-LABEL: fold_extracts729// CHECK-SAME: %[[A:[a-zA-Z0-9]*]]: vector<3x4x5x6xf32>730func.func @fold_extracts(%a : vector<3x4x5x6xf32>) -> (f32, vector<4x5x6xf32>) {731 %b = vector.extract %a[0] : vector<4x5x6xf32> from vector<3x4x5x6xf32>732 %c = vector.extract %b[1, 2] : vector<6xf32> from vector<4x5x6xf32>733 // CHECK-NEXT: vector.extract %[[A]][0, 1, 2, 3] : f32 from vector<3x4x5x6xf32>734 %d = vector.extract %c[3] : f32 from vector<6xf32>735 736 // CHECK-NEXT: vector.extract %[[A]][0] : vector<4x5x6xf32> from vector<3x4x5x6xf32>737 %e = vector.extract %a[0] : vector<4x5x6xf32> from vector<3x4x5x6xf32>738 739 // CHECK-NEXT: return740 return %d, %e : f32, vector<4x5x6xf32>741}742 743// -----744 745// CHECK-LABEL: fold_extract_transpose746// CHECK-SAME: %[[A:[a-zA-Z0-9]*]]: vector<3x4x5x6xf32>747// CHECK-SAME: %[[B:[a-zA-Z0-9]*]]: vector<3x6x5x6xf32>748func.func @fold_extract_transpose(749 %a : vector<3x4x5x6xf32>, %b : vector<3x6x5x6xf32>) -> (750 vector<6xf32>, vector<6xf32>, vector<6xf32>) {751 // [3] is a proper most minor identity map in transpose.752 // Permutation is a self inverse and we have.753 // [0, 2, 1] ^ -1 o [0, 1, 2] = [0, 2, 1] o [0, 1, 2]754 // = [0, 2, 1]755 // CHECK-NEXT: vector.extract %[[A]][0, 2, 1] : vector<6xf32> from vector<3x4x5x6xf32>756 %0 = vector.transpose %a, [0, 2, 1, 3] : vector<3x4x5x6xf32> to vector<3x5x4x6xf32>757 %1 = vector.extract %0[0, 1, 2] : vector<6xf32> from vector<3x5x4x6xf32>758 759 // [3] is a proper most minor identity map in transpose.760 // Permutation is a not self inverse and we have.761 // [1, 2, 0] ^ -1 o [0, 1, 2] = [2, 0, 1] o [0, 1, 2]762 // = [2, 0, 1]763 // CHECK-NEXT: vector.extract %[[A]][2, 0, 1] : vector<6xf32> from vector<3x4x5x6xf32>764 %2 = vector.transpose %a, [1, 2, 0, 3] : vector<3x4x5x6xf32> to vector<4x5x3x6xf32>765 %3 = vector.extract %2[0, 1, 2] : vector<6xf32> from vector<4x5x3x6xf32>766 767 // Not a minor identity map so intra-vector level has been permuted768 // CHECK-NEXT: vector.transpose %[[B]], [0, 2, 3, 1]769 // CHECK-NEXT: vector.extract %{{.*}}[0, 1, 2]770 %4 = vector.transpose %b, [0, 2, 3, 1] : vector<3x6x5x6xf32> to vector<3x5x6x6xf32>771 %5 = vector.extract %4[0, 1, 2] : vector<6xf32> from vector<3x5x6x6xf32>772 773 return %1, %3, %5 : vector<6xf32>, vector<6xf32>, vector<6xf32>774}775 776// -----777 778// CHECK-LABEL: fold_extract_broadcast_same_input_output_scalar779// CHECK-SAME: %[[A:.*]]: f32780// CHECK: return %[[A]] : f32781func.func @fold_extract_broadcast_same_input_output_scalar(%a : f32,782 %idx0 : index, %idx1 : index, %idx2 : index) -> f32 {783 %b = vector.broadcast %a : f32 to vector<1x2x4xf32>784 %r = vector.extract %b[%idx0, %idx1, %idx2] : f32 from vector<1x2x4xf32>785 return %r : f32786}787 788// -----789 790// CHECK-LABEL: fold_extract_broadcast_same_input_output_vec791// CHECK-SAME: %[[A:.*]]: vector<4xf32>792// CHECK: return %[[A]] : vector<4xf32>793func.func @fold_extract_broadcast_same_input_output_vec(%a : vector<4xf32>,794 %idx0 : index, %idx1 : index) -> vector<4xf32> {795 %b = vector.broadcast %a : vector<4xf32> to vector<1x2x4xf32>796 %r = vector.extract %b[%idx0, %idx1] : vector<4xf32> from vector<1x2x4xf32>797 return %r : vector<4xf32>798}799 800// -----801 802// CHECK-LABEL: fold_extract_broadcast_0dvec_input_scalar_output803// CHECK-SAME: %[[A:.*]]: vector<f32>804// CHECK: %[[B:.+]] = vector.extract %[[A]][] : f32 from vector<f32>805// CHECK: return %[[B]] : f32806func.func @fold_extract_broadcast_0dvec_input_scalar_output(%a : vector<f32>,807 %idx0 : index, %idx1 : index, %idx2: index) -> f32 {808 %b = vector.broadcast %a : vector<f32> to vector<1x2x4xf32>809 %r = vector.extract %b[%idx0, %idx1, %idx2] : f32 from vector<1x2x4xf32>810 return %r : f32811}812 813// -----814 815// CHECK-LABEL: negative_fold_extract_broadcast816// CHECK: vector.broadcast %{{.*}} : vector<1x1xf32> to vector<1x1x4xf32>817// CHECK: vector.extract %{{.*}}[0, 0] : vector<4xf32> from vector<1x1x4xf32>818func.func @negative_fold_extract_broadcast(%a : vector<1x1xf32>) -> vector<4xf32> {819 %b = vector.broadcast %a : vector<1x1xf32> to vector<1x1x4xf32>820 %r = vector.extract %b[0, 0] : vector<4xf32> from vector<1x1x4xf32>821 return %r : vector<4xf32>822}823 824// -----825 826// CHECK-LABEL: fold_extract_splatlike827// CHECK-SAME: %[[A:.*]]: f32828// CHECK: return %[[A]] : f32829func.func @fold_extract_splatlike(%a : f32, %idx0 : index, %idx1 : index, %idx2 : index) -> f32 {830 %b = vector.broadcast %a : f32 to vector<1x2x4xf32>831 %r = vector.extract %b[%idx0, %idx1, %idx2] : f32 from vector<1x2x4xf32>832 return %r : f32833}834 835// -----836 837// CHECK-LABEL: fold_extract_vector_from_splat838// CHECK: vector.broadcast {{.*}} f32 to vector<4xf32>839func.func @fold_extract_vector_from_splat(%a : f32, %idx0 : index, %idx1 : index) -> vector<4xf32> {840 %b = vector.broadcast %a : f32 to vector<1x2x4xf32>841 %r = vector.extract %b[%idx0, %idx1] : vector<4xf32> from vector<1x2x4xf32>842 return %r : vector<4xf32>843}844 845// -----846 847// CHECK-LABEL: fold_extract_broadcast_dim1_broadcasting848// CHECK-SAME: %[[A:.*]]: vector<2x1xf32>849// CHECK-SAME: %[[IDX:.*]]: index, %[[IDX1:.*]]: index, %[[IDX2:.*]]: index850// CHECK: %[[R:.*]] = vector.extract %[[A]][%[[IDX1]], 0] : f32 from vector<2x1xf32>851// CHECK: return %[[R]] : f32852func.func @fold_extract_broadcast_dim1_broadcasting(%a : vector<2x1xf32>,853 %idx : index, %idx1 : index, %idx2 : index) -> f32 {854 %b = vector.broadcast %a : vector<2x1xf32> to vector<1x2x4xf32>855 %r = vector.extract %b[%idx, %idx1, %idx2] : f32 from vector<1x2x4xf32>856 return %r : f32857}858 859// -----860 861// CHECK-LABEL: fold_extract_broadcast_to_lower_rank862// CHECK-SAME: %[[A:.*]]: vector<2x4xf32>863// CHECK-SAME: %[[IDX0:.*]]: index, %[[IDX1:.*]]: index864// CHECK: %[[B:.+]] = vector.extract %[[A]][%[[IDX1]]] : vector<4xf32> from vector<2x4xf32>865// CHECK: return %[[B]] : vector<4xf32>866// rank(extract_output) < rank(broadcast_input)867func.func @fold_extract_broadcast_to_lower_rank(%a : vector<2x4xf32>,868 %idx0 : index, %idx1 : index) -> vector<4xf32> {869 %b = vector.broadcast %a : vector<2x4xf32> to vector<1x2x4xf32>870 %r = vector.extract %b[%idx0, %idx1] : vector<4xf32> from vector<1x2x4xf32>871 return %r : vector<4xf32>872}873 874// -----875 876// Test where the shape_cast is broadcast-like.877// CHECK-LABEL: fold_extract_shape_cast_to_lower_rank878// CHECK-SAME: %[[A:.*]]: vector<2x4xf32>879// CHECK-SAME: %[[IDX0:.*]]: index, %[[IDX1:.*]]: index880// CHECK: %[[B:.+]] = vector.extract %[[A]][%[[IDX1]]] : vector<4xf32> from vector<2x4xf32>881// CHECK: return %[[B]] : vector<4xf32>882func.func @fold_extract_shape_cast_to_lower_rank(%a : vector<2x4xf32>,883 %idx0 : index, %idx1 : index) -> vector<4xf32> {884 %b = vector.shape_cast %a : vector<2x4xf32> to vector<1x2x4xf32>885 %r = vector.extract %b[%idx0, %idx1] : vector<4xf32> from vector<1x2x4xf32>886 return %r : vector<4xf32>887}888 889// -----890 891// Test where the shape_cast is not broadcast-like, even though it prepends 1s.892// CHECK-LABEL: negative_fold_extract_shape_cast_to_lower_rank893// CHECK-NEXT: vector.shape_cast894// CHECK-NEXT: vector.extract895// CHECK-NEXT: return896func.func @negative_fold_extract_shape_cast_to_lower_rank(%a : vector<2x4xf32>,897 %idx0 : index, %idx1 : index) -> vector<2xf32> {898 %b = vector.shape_cast %a : vector<2x4xf32> to vector<1x4x2xf32>899 %r = vector.extract %b[%idx0, %idx1] : vector<2xf32> from vector<1x4x2xf32>900 return %r : vector<2xf32>901}902 903// -----904 905// CHECK-LABEL: fold_extract_broadcast_to_higher_rank906// CHECK: %[[B:.*]] = vector.broadcast %{{.*}} : f32 to vector<4xf32>907// CHECK: return %[[B]] : vector<4xf32>908// rank(extract_output) > rank(broadcast_input)909func.func @fold_extract_broadcast_to_higher_rank(%a : f32, %idx0 : index, %idx1 : index)910 -> vector<4xf32> {911 %b = vector.broadcast %a : f32 to vector<1x2x4xf32>912 %r = vector.extract %b[%idx0, %idx1] : vector<4xf32> from vector<1x2x4xf32>913 return %r : vector<4xf32>914}915 916// -----917 918// CHECK-LABEL: fold_extract_broadcast_to_equal_rank919// CHECK-SAME: %[[A:.*]]: vector<1xf32>920// CHECK: %[[R:.*]] = vector.broadcast %[[A]] : vector<1xf32> to vector<8xf32>921// CHECK: return %[[R]] : vector<8xf32>922// rank(extract_output) == rank(broadcast_input)923func.func @fold_extract_broadcast_to_equal_rank(%a : vector<1xf32>, %idx0 : index)924 -> vector<8xf32> {925 %b = vector.broadcast %a : vector<1xf32> to vector<1x8xf32>926 %r = vector.extract %b[%idx0] : vector<8xf32> from vector<1x8xf32>927 return %r : vector<8xf32>928}929 930// -----931 932// CHECK-LABEL: fold_extract_broadcastlike_shape_cast933// CHECK-SAME: %[[A:.*]]: vector<1xf32>934// CHECK: %[[R:.*]] = vector.broadcast %[[A]] : vector<1xf32> to vector<1x1xf32>935// CHECK: return %[[R]] : vector<1x1xf32>936func.func @fold_extract_broadcastlike_shape_cast(%a : vector<1xf32>, %idx0 : index)937 -> vector<1x1xf32> {938 %s = vector.shape_cast %a : vector<1xf32> to vector<1x1x1xf32>939 %r = vector.extract %s[%idx0] : vector<1x1xf32> from vector<1x1x1xf32>940 return %r : vector<1x1xf32>941}942 943// -----944 945// CHECK-LABEL: @fold_extract_shuffle946// CHECK-SAME: %[[A:.*]]: vector<8xf32>, %[[B:.*]]: vector<8xf32>947// CHECK-NOT: vector.shuffle948// CHECK: vector.extract %[[A]][0] : f32 from vector<8xf32>949// CHECK: vector.extract %[[B]][0] : f32 from vector<8xf32>950// CHECK: vector.extract %[[A]][7] : f32 from vector<8xf32>951// CHECK: vector.extract %[[B]][7] : f32 from vector<8xf32>952func.func @fold_extract_shuffle(%a : vector<8xf32>, %b : vector<8xf32>)953 -> (f32, f32, f32, f32) {954 %shuffle = vector.shuffle %a, %b [0, 8, 7, 15] : vector<8xf32>, vector<8xf32>955 %e0 = vector.extract %shuffle[0] : f32 from vector<4xf32>956 %e1 = vector.extract %shuffle[1] : f32 from vector<4xf32>957 %e2 = vector.extract %shuffle[2] : f32 from vector<4xf32>958 %e3 = vector.extract %shuffle[3] : f32 from vector<4xf32>959 return %e0, %e1, %e2, %e3 : f32, f32, f32, f32960}961 962// -----963 964// CHECK-LABEL: func @fold_extract_shapecast965// CHECK-SAME: (%[[A0:.*]]: vector<5x1x3x2xf32>, %[[A1:.*]]: vector<8x4x2xf32>966// CHECK: %[[R0:.*]] = vector.extract %[[A0]][1, 0, 1, 1] : f32 from vector<5x1x3x2xf32>967// CHECK: %[[R1:.*]] = vector.extract %[[A0]][1, 0, 2] : vector<2xf32> from vector<5x1x3x2xf32>968// CHECK: %[[R2:.*]] = vector.extract %[[A1]][7] : vector<4x2xf32> from vector<8x4x2xf32>969// CHECK: return %[[R0]], %[[R1]], %[[R2]], %[[A1]] : f32, vector<2xf32>, vector<4x2xf32>, vector<8x4x2xf32>970func.func @fold_extract_shapecast(%arg0 : vector<5x1x3x2xf32>,971 %arg1 : vector<8x4x2xf32>)972 -> (f32, vector<2xf32>, vector<4x2xf32>, vector<8x4x2xf32>) {973 %0 = vector.shape_cast %arg0 : vector<5x1x3x2xf32> to vector<15x2xf32>974 %1 = vector.shape_cast %arg1 : vector<8x4x2xf32> to vector<4x2x4x2xf32>975 %2 = vector.shape_cast %arg1 : vector<8x4x2xf32> to vector<1x8x4x2xf32>976 %r1 = vector.extract %0[4, 1] : f32 from vector<15x2xf32>977 %r2 = vector.extract %0[5] : vector<2xf32> from vector<15x2xf32>978 %r3 = vector.extract %1[3, 1] : vector<4x2xf32> from vector<4x2x4x2xf32>979 %r4 = vector.extract %2[0] : vector<8x4x2xf32> from vector<1x8x4x2xf32>980 return %r1, %r2, %r3, %r4 : f32, vector<2xf32>, vector<4x2xf32>, vector<8x4x2xf32>981}982 983// -----984 985// CHECK-LABEL: fold_extract_shapecast_0d_result986// CHECK-SAME: %[[IN:.*]]: vector<1x1x1xf32>987// CHECK: %[[R:.*]] = vector.extract %[[IN]][0, 0, 0] : f32 from vector<1x1x1xf32>988// CHECK: return %[[R]] : f32989func.func @fold_extract_shapecast_0d_result(%arg0 : vector<1x1x1xf32>) -> f32 {990 %0 = vector.shape_cast %arg0 : vector<1x1x1xf32> to vector<f32>991 %r = vector.extract %0[] : f32 from vector<f32>992 return %r : f32993}994 995// -----996 997// CHECK-LABEL: fold_extract_shapecast_0d_source998// CHECK-SAME: %[[IN:.*]]: vector<f32>999// CHECK: %[[R:.*]] = vector.extract %[[IN]][] : f32 from vector<f32>1000// CHECK: return %[[R]] : f321001func.func @fold_extract_shapecast_0d_source(%arg0 : vector<f32>) -> f32 {1002 %0 = vector.shape_cast %arg0 : vector<f32> to vector<1xf32>1003 %r = vector.extract %0[0] : f32 from vector<1xf32>1004 return %r : f321005}1006 1007// -----1008 1009// CHECK-LABEL: negative_fold_extract_shapecast1010// CHECK: %[[V:.*]] = vector.shape_cast %{{.*}} : vector<16xf32> to vector<2x4x2xf32>1011// CHECK: %[[R:.*]] = vector.extract %[[V]][1] : vector<4x2xf32> from vector<2x4x2xf32>1012// CHECK: return %[[R]] : vector<4x2xf32>1013func.func @negative_fold_extract_shapecast(%arg0 : vector<16xf32>) -> vector<4x2xf32> {1014 %0 = vector.shape_cast %arg0 : vector<16xf32> to vector<2x4x2xf32>1015 %r = vector.extract %0[1] : vector<4x2xf32> from vector<2x4x2xf32>1016 return %r : vector<4x2xf32>1017}1018 1019// -----1020 1021// CHECK-LABEL: fold_extract_shapecast_to_shapecast1022// CHECK-SAME: (%[[ARG:.+]]: vector<3x4xf32>)1023// CHECK: %[[R:.+]] = vector.shape_cast %[[ARG]] : vector<3x4xf32> to vector<12xf32>1024// CHECK: return %[[R]]1025func.func @fold_extract_shapecast_to_shapecast(%arg0 : vector<3x4xf32>) -> vector<12xf32> {1026 %0 = vector.shape_cast %arg0 : vector<3x4xf32> to vector<1x12xf32>1027 %r = vector.extract %0[0] : vector<12xf32> from vector<1x12xf32>1028 return %r : vector<12xf32>1029}1030 1031// -----1032 1033// CHECK-LABEL: func @extract_no_fold_scalar_to_0d(1034// CHECK-SAME: %[[v:.*]]: vector<f32>)1035// CHECK: %[[extract:.*]] = vector.extract %[[v]][] : f32 from vector<f32>1036// CHECK: return %[[extract]]1037func.func @extract_no_fold_scalar_to_0d(%v: vector<f32>) -> f32 {1038 %0 = vector.extract %v[] : f32 from vector<f32>1039 return %0 : f321040}1041 1042// -----1043 1044// CHECK-LABEL: func @insert_fold_same_rank(1045// CHECK-SAME: %[[v:.*]]: vector<2x2xf32>)1046// CHECK: %[[CST:.+]] = arith.constant1047// CHECK-SAME: : vector<2x2xf32>1048// CHECK-NOT: vector.insert1049// CHECK: return %[[CST]]1050func.func @insert_fold_same_rank(%v: vector<2x2xf32>) -> vector<2x2xf32> {1051 %cst = arith.constant dense<0.000000e+00> : vector<2x2xf32>1052 %0 = vector.insert %cst, %v [] : vector<2x2xf32> into vector<2x2xf32>1053 return %0 : vector<2x2xf32>1054}1055 1056// -----1057 1058// CHECK-LABEL: func @insert_no_fold_scalar_to_0d(1059// CHECK-SAME: %[[v:.*]]: vector<f32>)1060// CHECK: %[[cst:.*]] = arith.constant dense<0.000000e+00> : vector<f32>1061// CHECK: return %[[cst]]1062func.func @insert_no_fold_scalar_to_0d(%v: vector<f32>) -> vector<f32> {1063 %cst = arith.constant 0.000000e+00 : f321064 %0 = vector.insert %cst, %v [] : f32 into vector<f32>1065 return %0 : vector<f32>1066}1067 1068// -----1069 1070// CHECK-LABEL: fold_expand_collapse1071// CHECK: %[[A:.*]] = vector.shape_cast %{{.*}} : vector<1x1x64xf32> to vector<8x8xf32>1072// CHECK: return %[[A]] : vector<8x8xf32>1073func.func @dont_fold_expand_collapse(%arg0: vector<1x1x64xf32>) -> vector<8x8xf32> {1074 %0 = vector.shape_cast %arg0 : vector<1x1x64xf32> to vector<1x1x8x8xf32>1075 %1 = vector.shape_cast %0 : vector<1x1x8x8xf32> to vector<8x8xf32>1076 return %1 : vector<8x8xf32>1077}1078 1079// -----1080 1081// CHECK-LABEL: func @fold_broadcast_shapecast1082// CHECK-SAME: (%[[V:.+]]: vector<4xf32>)1083// CHECK: return %[[V]]1084func.func @fold_broadcast_shapecast(%arg0: vector<4xf32>) -> vector<4xf32> {1085 %0 = vector.broadcast %arg0 : vector<4xf32> to vector<1x1x4xf32>1086 %1 = vector.shape_cast %0 : vector<1x1x4xf32> to vector<4xf32>1087 return %1 : vector<4xf32>1088}1089 1090// -----1091 1092// CHECK-LABEL: func @canonicalize_broadcast_shapecast_scalar1093// CHECK: vector.broadcast1094// CHECK-NOT: vector.shape_cast1095func.func @canonicalize_broadcast_shapecast_scalar(%arg0: f32) -> vector<1xf32> {1096 %0 = vector.broadcast %arg0 : f32 to vector<1x1x1xf32>1097 %1 = vector.shape_cast %0 : vector<1x1x1xf32> to vector<1xf32>1098 return %1 : vector<1xf32>1099}1100 1101// -----1102 1103// CHECK-LABEL: func @dont_fold_broadcast_shapecast_diff_shape1104// CHECK: vector.broadcast1105// CHECK: vector.shape_cast1106func.func @dont_fold_broadcast_shapecast_diff_shape(%arg0: vector<4xf32>) -> vector<8xf32> {1107 %0 = vector.broadcast %arg0 : vector<4xf32> to vector<1x2x4xf32>1108 %1 = vector.shape_cast %0 : vector<1x2x4xf32> to vector<8xf32>1109 return %1 : vector<8xf32>1110}1111 1112// -----1113 1114// CHECK-LABEL: func @canonicalize_broadcast_shapecast_to_broadcast1115// CHECK: vector.broadcast1116// CHECK-NOT: vector.shape_cast1117func.func @canonicalize_broadcast_shapecast_to_broadcast(%arg0: vector<3xf32>) -> vector<8x3xf32> {1118 %0 = vector.broadcast %arg0 : vector<3xf32> to vector<2x4x3xf32>1119 %1 = vector.shape_cast %0 : vector<2x4x3xf32> to vector<8x3xf32>1120 return %1 : vector<8x3xf32>1121}1122 1123// -----1124 1125// CHECK-LABEL: func @canonicalize_broadcast_shapecast_to_broadcast_ones1126// CHECK: vector.broadcast {{.*}} vector<1x1xi8> to vector<1x1x6x1x4xi8>1127// CHECK-NOT: vector.shape_cast1128func.func @canonicalize_broadcast_shapecast_to_broadcast_ones(%arg0: vector<1x1xi8>) -> vector<1x1x6x1x4xi8> {1129 %0 = vector.broadcast %arg0 : vector<1x1xi8> to vector<6x4xi8>1130 %1 = vector.shape_cast %0 : vector<6x4xi8> to vector<1x1x6x1x4xi8>1131 return %1 : vector<1x1x6x1x4xi8>1132}1133 1134// -----1135 1136// CHECK-LABEL: func @canonicalize_broadcast_shapecast_to_broadcast_scalar1137// CHECK: vector.broadcast {{.*}} f32 to vector<3x4x1xf32>1138// CHECK-NOT: vector.shape_cast1139func.func @canonicalize_broadcast_shapecast_to_broadcast_scalar(%arg0: f32) -> vector<3x4x1xf32> {1140 %0 = vector.broadcast %arg0 : f32 to vector<12xf32>1141 %1 = vector.shape_cast %0 : vector<12xf32> to vector<3x4x1xf32>1142 return %1 : vector<3x4x1xf32>1143}1144 1145// -----1146 1147// In this test, broadcast (2)->(1,2,1) is not legal, but shape_cast (2)->(1,2,1) is.1148// CHECK-LABEL: func @canonicalize_broadcast_shapecast_to_shapcast1149// CHECK-NOT: vector.broadcast1150// CHECK: vector.shape_cast {{.+}} : vector<2xf32> to vector<1x2x1xf32>1151func.func @canonicalize_broadcast_shapecast_to_shapcast(%arg0 : vector<2xf32>) -> vector<1x2x1xf32> {1152 %0 = vector.broadcast %arg0 : vector<2xf32> to vector<1x2xf32>1153 %1 = vector.shape_cast %0 : vector<1x2xf32> to vector<1x2x1xf32>1154 return %1 : vector<1x2x1xf32>1155}1156 1157// -----1158 1159// In this test, broadcast (1)->(1,1) and shape_cast (1)->(1,1) are both legal. shape_cast is chosen.1160// CHECK-LABEL: func @canonicalize_broadcast_shapecast_both_possible1161// CHECK-NOT: vector.broadcast1162// CHECK: vector.shape_cast {{.+}} : vector<1xf32> to vector<1x1xf32>1163func.func @canonicalize_broadcast_shapecast_both_possible(%arg0: vector<1xf32>) -> vector<1x1xf32> {1164 %0 = vector.broadcast %arg0 : vector<1xf32> to vector<1x1x1xf32>1165 %1 = vector.shape_cast %0 : vector<1x1x1xf32> to vector<1x1xf32>1166 return %1 : vector<1x1xf32>1167}1168 1169// -----1170 1171// CHECK-LABEL: func @canonicalize_shapecast_broadcast_to_broadcast_prepend_dim1172// CHECK-NOT: vector.shape_cast1173// CHECK: vector.broadcast {{.+}} : vector<2xf32> to vector<32x2xf32>1174func.func @canonicalize_shapecast_broadcast_to_broadcast_prepend_dim(%arg0 : vector<2xf32>) -> vector<32x2xf32> {1175 %0 = vector.shape_cast %arg0 : vector<2xf32> to vector<1x2xf32>1176 %1 = vector.broadcast %0 : vector<1x2xf32> to vector<32x2xf32>1177 return %1 : vector<32x2xf32>1178}1179 1180// -----1181 1182// CHECK-LABEL: func.func @canonicalize_shapecast_broadcast_to_broadcast_prepend_dim2(1183// CHECK-SAME: %[[ARG0:.*]]: vector<2x1xf32>) -> vector<32x2x1xf32> {1184// CHECK: %[[VAL_0:.*]] = vector.broadcast %[[ARG0]] : vector<2x1xf32> to vector<32x2x1xf32>1185// CHECK: return %[[VAL_0]] : vector<32x2x1xf32>1186// CHECK: }1187func.func @canonicalize_shapecast_broadcast_to_broadcast_prepend_dim2(%arg0 : vector<2x1xf32>) -> vector<32x2x1xf32> {1188 %0 = vector.shape_cast %arg0 : vector<2x1xf32> to vector<1x2x1xf32>1189 %1 = vector.broadcast %0 : vector<1x2x1xf32> to vector<32x2x1xf32>1190 return %1 : vector<32x2x1xf32>1191}1192 1193// -----1194 1195// CHECK-LABEL: func.func @canonicalize_shapecast_broadcast_to_broadcast_prepend_dim3(1196// CHECK-SAME: %[[ARG0:.*]]: vector<2x1xf32>) -> vector<32x2x4xf32> {1197// CHECK: %[[VAL_0:.*]] = vector.broadcast %[[ARG0]] : vector<2x1xf32> to vector<32x2x4xf32>1198// CHECK: return %[[VAL_0]] : vector<32x2x4xf32>1199// CHECK: }1200func.func @canonicalize_shapecast_broadcast_to_broadcast_prepend_dim3(%arg0 : vector<2x1xf32>) -> vector<32x2x4xf32> {1201 %0 = vector.shape_cast %arg0 : vector<2x1xf32> to vector<1x2x1xf32>1202 %1 = vector.broadcast %0 : vector<1x2x1xf32> to vector<32x2x4xf32>1203 return %1 : vector<32x2x4xf32>1204}1205 1206// -----1207 1208// CHECK-LABEL: func.func @canonicalize_shapecast_broadcast_to_broadcast_remove_leading_dim(1209// CHECK-SAME: %[[ARG0:.*]]: vector<1x2xf32>) -> vector<32x2xf32> {1210// CHECK: %[[VAL_0:.*]] = vector.broadcast %[[ARG0]] : vector<1x2xf32> to vector<32x2xf32>1211// CHECK: return %[[VAL_0]] : vector<32x2xf32>1212// CHECK: }1213func.func @canonicalize_shapecast_broadcast_to_broadcast_remove_leading_dim(%arg0 : vector<1x2xf32>) -> vector<32x2xf32> {1214 %0 = vector.shape_cast %arg0 : vector<1x2xf32> to vector<2xf32>1215 %1 = vector.broadcast %0 : vector<2xf32> to vector<32x2xf32>1216 return %1 : vector<32x2xf32>1217}1218 1219// -----1220 1221// CHECK-LABEL: func @negative_canonicalize_shapecast_broadcast_invalid_shape1222// CHECK: vector.shape_cast {{.+}} : vector<64xf32> to vector<4x16xf32>1223// CHECK: vector.broadcast {{.+}} : vector<4x16xf32> to vector<2x4x16xf32>1224func.func @negative_canonicalize_shapecast_broadcast_invalid_shape(%arg0 : vector<64xf32>) -> vector<2x4x16xf32> {1225 %0 = vector.shape_cast %arg0 : vector<64xf32> to vector<4x16xf32>1226 %1 = vector.broadcast %0 : vector<4x16xf32> to vector<2x4x16xf32>1227 return %1 : vector<2x4x16xf32>1228}1229 1230// -----1231 1232// CHECK-LABEL: func @negative_canonicalize_shapecast_broadcast_invalid_broadcasted_dims1233// CHECK: vector.shape_cast {{.+}} : vector<2x1xf32> to vector<1x2xf32>1234// CHECK: vector.broadcast {{.+}} : vector<1x2xf32> to vector<2x2xf32>1235func.func @negative_canonicalize_shapecast_broadcast_invalid_broadcasted_dims(%arg0 : vector<2x1xf32>) -> vector<2x2xf32> {1236 %0 = vector.shape_cast %arg0 : vector<2x1xf32> to vector<1x2xf32>1237 %1 = vector.broadcast %0 : vector<1x2xf32> to vector<2x2xf32>1238 return %1 : vector<2x2xf32>1239}1240 1241// -----1242 1243// CHECK-LABEL: func.func @negative_canonicalize_shapecast_broadcast_to_broadcast_append_dim(1244// CHECK-SAME: %[[ARG0:.*]]: vector<2xf32>) -> vector<2x4xf32> {1245// CHECK: %[[VAL_0:.*]] = vector.shape_cast %[[ARG0]] : vector<2xf32> to vector<2x1xf32>1246// CHECK: %[[VAL_1:.*]] = vector.broadcast %[[VAL_0]] : vector<2x1xf32> to vector<2x4xf32>1247// CHECK: return %[[VAL_1]] : vector<2x4xf32>1248// CHECK: }1249func.func @negative_canonicalize_shapecast_broadcast_to_broadcast_append_dim(%arg0 : vector<2xf32>) -> vector<2x4xf32> {1250 %0 = vector.shape_cast %arg0 : vector<2xf32> to vector<2x1xf32>1251 %1 = vector.broadcast %0 : vector<2x1xf32> to vector<2x4xf32>1252 return %1 : vector<2x4xf32>1253}1254 1255// -----1256 1257// CHECK-LABEL: func.func @negative_canonicalize_shapecast_broadcast_to_broadcast_remove_trailing_dim(1258// CHECK-SAME: %[[ARG0:.*]]: vector<2x1xf32>) -> vector<32x2xf32> {1259// CHECK: %[[VAL_0:.*]] = vector.shape_cast %[[ARG0]] : vector<2x1xf32> to vector<2xf32>1260// CHECK: %[[VAL_1:.*]] = vector.broadcast %[[VAL_0]] : vector<2xf32> to vector<32x2xf32>1261// CHECK: return %[[VAL_1]] : vector<32x2xf32>1262// CHECK: }1263func.func @negative_canonicalize_shapecast_broadcast_to_broadcast_remove_trailing_dim(%arg0 : vector<2x1xf32>) -> vector<32x2xf32> {1264 %0 = vector.shape_cast %arg0 : vector<2x1xf32> to vector<2xf32>1265 %1 = vector.broadcast %0 : vector<2xf32> to vector<32x2xf32>1266 return %1 : vector<32x2xf32>1267}1268 1269// -----1270 1271// CHECK-LABEL: fold_vector_transfer_masks1272func.func @fold_vector_transfer_masks(%A: memref<?x?xf32>) -> (vector<4x8xf32>, vector<4x[4]xf32>) {1273 // CHECK: %[[C0:.+]] = arith.constant 0 : index1274 %c0 = arith.constant 0 : index1275 // CHECK: %[[F0:.+]] = arith.constant 0.000000e+00 : f321276 %f0 = arith.constant 0.0 : f321277 1278 %mask = vector.constant_mask [8, 4] : vector<8x4xi1>1279 1280 %arith_all_true_mask = arith.constant dense<true> : vector<4x[4]xi1>1281 1282 // CHECK: vector.transfer_read %{{.*}}, %[[F0]] {permutation_map1283 %1 = vector.transfer_read %A[%c0, %c0], %f0, %mask1284 {permutation_map = affine_map<(d0, d1) -> (d1, d0)>} : memref<?x?xf32>, vector<4x8xf32>1285 1286 // CHECK: vector.transfer_write {{.*}}[%[[C0]], %[[C0]]] {permutation_map1287 vector.transfer_write %1, %A[%c0, %c0], %mask1288 {permutation_map = affine_map<(d0, d1) -> (d1, d0)>} : vector<4x8xf32>, memref<?x?xf32>1289 1290 // CHECK: vector.transfer_read %{{.*}}, %[[F0]] :1291 %2 = vector.transfer_read %A[%c0, %c0], %f0, %arith_all_true_mask : memref<?x?xf32>, vector<4x[4]xf32>1292 1293 // CHECK: vector.transfer_write {{.*}}[%[[C0]], %[[C0]]] :1294 vector.transfer_write %2, %A[%c0, %c0], %arith_all_true_mask : vector<4x[4]xf32>, memref<?x?xf32>1295 1296 // CHECK: return1297 return %1, %2 : vector<4x8xf32>, vector<4x[4]xf32>1298}1299 1300// -----1301 1302// CHECK-LABEL: fold_vector_transfers1303func.func @fold_vector_transfers(%A: memref<?x8xf32>) -> (vector<4x8xf32>, vector<4x9xf32>) {1304 %c0 = arith.constant 0 : index1305 %f0 = arith.constant 0.0 : f321306 1307 // CHECK: vector.transfer_read %{{.*}} {in_bounds = [false, true]}1308 %1 = vector.transfer_read %A[%c0, %c0], %f0 : memref<?x8xf32>, vector<4x8xf32>1309 1310 // CHECK: vector.transfer_write %{{.*}} {in_bounds = [false, true]}1311 vector.transfer_write %1, %A[%c0, %c0] : vector<4x8xf32>, memref<?x8xf32>1312 1313 // Both dims may be out-of-bounds, attribute is elided.1314 // CHECK: vector.transfer_read %{{.*}}1315 // CHECK-NOT: in_bounds1316 %2 = vector.transfer_read %A[%c0, %c0], %f0 : memref<?x8xf32>, vector<4x9xf32>1317 1318 // Both dims may be out-of-bounds, attribute is elided.1319 // CHECK: vector.transfer_write %{{.*}}1320 // CHECK-NOT: in_bounds1321 vector.transfer_write %2, %A[%c0, %c0] : vector<4x9xf32>, memref<?x8xf32>1322 1323 // CHECK: return1324 return %1, %2 : vector<4x8xf32>, vector<4x9xf32>1325}1326 1327// -----1328 1329// CHECK-LABEL: bitcast_folding1330// CHECK-SAME: %[[A:.*]]: vector<4x8xf32>1331// CHECK-SAME: %[[B:.*]]: vector<2xi32>1332// CHECK: return %[[A]], %[[B]] : vector<4x8xf32>, vector<2xi32>1333func.func @bitcast_folding(%I1: vector<4x8xf32>, %I2: vector<2xi32>) -> (vector<4x8xf32>, vector<2xi32>) {1334 %0 = vector.bitcast %I1 : vector<4x8xf32> to vector<4x8xf32>1335 %1 = vector.bitcast %I2 : vector<2xi32> to vector<4xi16>1336 %2 = vector.bitcast %1 : vector<4xi16> to vector<2xi32>1337 return %0, %2 : vector<4x8xf32>, vector<2xi32>1338}1339 1340// -----1341 1342// CHECK-LABEL: func @bitcast_f16_to_f321343// bit pattern: 0x400040001344// CHECK-DAG: %[[CST1:.+]] = arith.constant dense<2.00390625> : vector<4xf32>1345// bit pattern: 0x000000001346// CHECK-DAG: %[[CST0:.+]] = arith.constant dense<0.000000e+00> : vector<4xf32>1347// CHECK: return %[[CST0]], %[[CST1]]1348func.func @bitcast_f16_to_f32() -> (vector<4xf32>, vector<4xf32>) {1349 %cst0 = arith.constant dense<0.0> : vector<8xf16> // bit pattern: 0x00001350 %cst1 = arith.constant dense<2.0> : vector<8xf16> // bit pattern: 0x40001351 %cast0 = vector.bitcast %cst0: vector<8xf16> to vector<4xf32>1352 %cast1 = vector.bitcast %cst1: vector<8xf16> to vector<4xf32>1353 return %cast0, %cast1: vector<4xf32>, vector<4xf32>1354}1355 1356// -----1357 1358// CHECK-LABEL: func @bitcast_i8_to_i321359// bit pattern: 0xA0A0A0A01360// CHECK-DAG: %[[CST1:.+]] = arith.constant dense<-1600085856> : vector<4xi32>1361// bit pattern: 0x000000001362// CHECK-DAG: %[[CST0:.+]] = arith.constant dense<0> : vector<4xi32>1363// CHECK: return %[[CST0]], %[[CST1]]1364func.func @bitcast_i8_to_i32() -> (vector<4xi32>, vector<4xi32>) {1365 %cst0 = arith.constant dense<0> : vector<16xi8> // bit pattern: 0x001366 %cst1 = arith.constant dense<160> : vector<16xi8> // bit pattern: 0xA01367 %cast0 = vector.bitcast %cst0: vector<16xi8> to vector<4xi32>1368 %cast1 = vector.bitcast %cst1: vector<16xi8> to vector<4xi32>1369 return %cast0, %cast1: vector<4xi32>, vector<4xi32>1370}1371 1372// -----1373 1374// CHECK-LABEL: broadcast_poison1375// CHECK: %[[POISON:.*]] = ub.poison : vector<4x6xi8>1376// CHECK: return %[[POISON]] : vector<4x6xi8>1377func.func @broadcast_poison() -> vector<4x6xi8> {1378 %poison = ub.poison : vector<6xi8>1379 %broadcast = vector.broadcast %poison : vector<6xi8> to vector<4x6xi8>1380 return %broadcast : vector<4x6xi8>1381}1382 1383// -----1384 1385// CHECK-LABEL: broadcast_splat_constant1386// CHECK: %[[CONST:.*]] = arith.constant dense<1> : vector<4x6xi8>1387// CHECK: return %[[CONST]] : vector<4x6xi8>1388func.func @broadcast_splat_constant() -> vector<4x6xi8> {1389 %cst = arith.constant dense<1> : vector<6xi8>1390 %broadcast = vector.broadcast %cst : vector<6xi8> to vector<4x6xi8>1391 return %broadcast : vector<4x6xi8>1392}1393 1394// -----1395 1396// CHECK-LABEL: broadcast_folding11397// CHECK: %[[CST:.*]] = arith.constant dense<42> : vector<4xi32>1398// CHECK-NOT: vector.broadcast1399// CHECK: return %[[CST]]1400func.func @broadcast_folding1() -> vector<4xi32> {1401 %0 = arith.constant 42 : i321402 %1 = vector.broadcast %0 : i32 to vector<4xi32>1403 return %1 : vector<4xi32>1404}1405 1406// -----1407 1408// CHECK-LABEL: @broadcast_folding21409// CHECK: %[[CST:.*]] = arith.constant dense<42> : vector<4x16xi32>1410// CHECK-NOT: vector.broadcast1411// CHECK: return %[[CST]]1412func.func @broadcast_folding2() -> vector<4x16xi32> {1413 %0 = arith.constant 42 : i321414 %1 = vector.broadcast %0 : i32 to vector<16xi32>1415 %2 = vector.broadcast %1 : vector<16xi32> to vector<4x16xi32>1416 return %2 : vector<4x16xi32>1417}1418 1419// -----1420 1421// CHECK-LABEL: @fold_consecutive_broadcasts(1422// CHECK-SAME: %[[ARG0:.*]]: i321423// CHECK: %[[RESULT:.*]] = vector.broadcast %[[ARG0]] : i32 to vector<4x16xi32>1424// CHECK: return %[[RESULT]]1425func.func @fold_consecutive_broadcasts(%a : i32) -> vector<4x16xi32> {1426 %1 = vector.broadcast %a : i32 to vector<16xi32>1427 %2 = vector.broadcast %1 : vector<16xi32> to vector<4x16xi32>1428 return %2 : vector<4x16xi32>1429}1430 1431// -----1432 1433// CHECK-LABEL: shape_cast_splat_constant1434// CHECK-DAG: %[[CST1:.*]] = arith.constant dense<1> : vector<3x4x2xi32>1435// CHECK-DAG: %[[CST0:.*]] = arith.constant dense<2.000000e+00> : vector<20x2xf32>1436// CHECK: return %[[CST0]], %[[CST1]] : vector<20x2xf32>, vector<3x4x2xi32>1437func.func @shape_cast_splat_constant() -> (vector<20x2xf32>, vector<3x4x2xi32>) {1438 %cst = arith.constant dense<2.000000e+00> : vector<5x4x2xf32>1439 %cst_1 = arith.constant dense<1> : vector<12x2xi32>1440 %0 = vector.shape_cast %cst : vector<5x4x2xf32> to vector<20x2xf32>1441 %1 = vector.shape_cast %cst_1 : vector<12x2xi32> to vector<3x4x2xi32>1442 return %0, %1 : vector<20x2xf32>, vector<3x4x2xi32>1443}1444 1445// -----1446 1447// Test of shape_cast's fold method:1448// shape_cast(constant) -> constant.1449//1450// CHECK-LABEL: @shape_cast_dense_int_constant1451// CHECK: %[[CST:.*]] = arith.constant1452// CHECK-SAME{LITERAL}: dense<[[2, 3, 5], [7, 11, 13]]>1453// CHECK: return %[[CST]] : vector<2x3xi8>1454func.func @shape_cast_dense_int_constant() -> vector<2x3xi8> {1455 %cst = arith.constant dense<[2, 3, 5, 7, 11, 13]> : vector<6xi8>1456 %0 = vector.shape_cast %cst : vector<6xi8> to vector<2x3xi8>1457 return %0 : vector<2x3xi8>1458}1459 1460// -----1461 1462// Test of shape_cast fold's method:1463// (shape_cast(const_x), const_x) -> (const_x_folded, const_x)1464//1465// CHECK-LABEL: @shape_cast_dense_float_constant1466// CHECK-DAG: %[[CST0:.*]] = {{.*}}1.000000e+00, 2.000000e+00{{.*}} vector<1x2xf32>1467// CHECK-DAG: %[[CST1:.*]] = {{.*}}1.000000e+00, 2.000000e+00{{.*}} vector<2xf32>1468// CHECK: return %[[CST1]], %[[CST0]] : vector<2xf32>, vector<1x2xf32>1469func.func @shape_cast_dense_float_constant() -> (vector<2xf32>, vector<1x2xf32>){1470 %cst = arith.constant dense<[[1.0, 2.0]]> : vector<1x2xf32>1471 %0 = vector.shape_cast %cst : vector<1x2xf32> to vector<2xf32>1472 return %0, %cst : vector<2xf32>, vector<1x2xf32>1473}1474 1475// -----1476 1477// CHECK-LABEL: shape_cast_poison1478// CHECK-DAG: %[[CST1:.*]] = ub.poison : vector<3x4x2xi32>1479// CHECK-DAG: %[[CST0:.*]] = ub.poison : vector<20x2xf32>1480// CHECK: return %[[CST0]], %[[CST1]] : vector<20x2xf32>, vector<3x4x2xi32>1481func.func @shape_cast_poison() -> (vector<20x2xf32>, vector<3x4x2xi32>) {1482 %poison = ub.poison : vector<5x4x2xf32>1483 %poison_1 = ub.poison : vector<12x2xi32>1484 %0 = vector.shape_cast %poison : vector<5x4x2xf32> to vector<20x2xf32>1485 %1 = vector.shape_cast %poison_1 : vector<12x2xi32> to vector<3x4x2xi32>1486 return %0, %1 : vector<20x2xf32>, vector<3x4x2xi32>1487}1488 1489// -----1490 1491// CHECK-LABEL: extract_strided_constant1492// CHECK-DAG: %[[CST1:.*]] = arith.constant dense<1> : vector<2x13x3xi32>1493// CHECK-DAG: %[[CST0:.*]] = arith.constant dense<2.000000e+00> : vector<12x2xf32>1494// CHECK: return %[[CST0]], %[[CST1]] : vector<12x2xf32>, vector<2x13x3xi32>1495func.func @extract_strided_constant() -> (vector<12x2xf32>, vector<2x13x3xi32>) {1496 %cst = arith.constant dense<2.000000e+00> : vector<29x7xf32>1497 %cst_1 = arith.constant dense<1> : vector<4x37x9xi32>1498 %0 = vector.extract_strided_slice %cst1499 {offsets = [2, 3], sizes = [12, 2], strides = [1, 1]}1500 : vector<29x7xf32> to vector<12x2xf32>1501 %1 = vector.extract_strided_slice %cst_11502 {offsets = [1, 2, 5], sizes = [2, 13, 3], strides = [1, 1, 1]}1503 : vector<4x37x9xi32> to vector<2x13x3xi32>1504 return %0, %1 : vector<12x2xf32>, vector<2x13x3xi32>1505}1506 1507// -----1508 1509// CHECK-LABEL: extract_strided_broadcast1510// CHECK: %[[B:.*]] = vector.broadcast %{{.*}} : vector<4xf16> to vector<2x4xf16>1511// CHECK-NEXT: return %[[B]] : vector<2x4xf16>1512func.func @extract_strided_broadcast(%arg0: vector<4xf16>) -> vector<2x4xf16> {1513 %0 = vector.broadcast %arg0 : vector<4xf16> to vector<16x4xf16>1514 %1 = vector.extract_strided_slice %01515 {offsets = [0, 0], sizes = [2, 4], strides = [1, 1]} :1516 vector<16x4xf16> to vector<2x4xf16>1517 return %1 : vector<2x4xf16>1518}1519 1520// -----1521 1522// CHECK-LABEL: extract_strided_broadcast21523// CHECK: %[[E:.*]] = vector.extract_strided_slice %{{.*}} {offsets = [0], sizes = [2], strides = [1]} : vector<4xf16> to vector<2xf16>1524// CHECK-NEXT: %[[B:.*]] = vector.broadcast %[[E]] : vector<2xf16> to vector<2x2xf16>1525// CHECK-NEXT: return %[[B]] : vector<2x2xf16>1526func.func @extract_strided_broadcast2(%arg0: vector<4xf16>) -> vector<2x2xf16> {1527 %0 = vector.broadcast %arg0 : vector<4xf16> to vector<16x4xf16>1528 %1 = vector.extract_strided_slice %01529 {offsets = [0, 0], sizes = [2, 2], strides = [1, 1]} :1530 vector<16x4xf16> to vector<2x2xf16>1531 return %1 : vector<2x2xf16>1532}1533 1534// -----1535 1536// CHECK-LABEL: func @extract_strided_broadcast31537// CHECK-SAME: (%[[ARG:.+]]: vector<1xf32>)1538// CHECK: %[[V:.+]] = vector.broadcast %[[ARG]] : vector<1xf32> to vector<1x4xf32>1539// CHECK: return %[[V]]1540func.func @extract_strided_broadcast3(%arg0: vector<1xf32>) -> vector<1x4xf32> {1541 %0 = vector.broadcast %arg0 : vector<1xf32> to vector<1x8xf32>1542 %1 = vector.extract_strided_slice %01543 {offsets = [0, 4], sizes = [1, 4], strides = [1, 1]}1544 : vector<1x8xf32> to vector<1x4xf32>1545 return %1 : vector<1x4xf32>1546}1547 1548// -----1549 1550// CHECK-LABEL: func @extract_strided_broadcast41551// CHECK-SAME: (%[[ARG:.+]]: f32)1552// CHECK: %[[V:.+]] = vector.broadcast %[[ARG]] : f32 to vector<1x4xf32>1553// CHECK: return %[[V]]1554func.func @extract_strided_broadcast4(%arg0: f32) -> vector<1x4xf32> {1555 %0 = vector.broadcast %arg0 : f32 to vector<1x8xf32>1556 %1 = vector.extract_strided_slice %01557 {offsets = [0, 4], sizes = [1, 4], strides = [1, 1]}1558 : vector<1x8xf32> to vector<1x4xf32>1559 return %1 : vector<1x4xf32>1560}1561 1562// -----1563 1564// Check the case where the same dimension is both broadcasted and sliced 1565// CHECK-LABEL: func @extract_strided_broadcast51566// CHECK-SAME: (%[[ARG:.+]]: vector<2x1xf32>)1567// CHECK: %[[V:.+]] = vector.broadcast %[[ARG]] : vector<2x1xf32> to vector<2x4xf32>1568// CHECK: return %[[V]]1569func.func @extract_strided_broadcast5(%arg0: vector<2x1xf32>) -> vector<2x4xf32> {1570 %0 = vector.broadcast %arg0 : vector<2x1xf32> to vector<2x8xf32>1571 %1 = vector.extract_strided_slice %01572 {offsets = [0, 4], sizes = [2, 4], strides = [1, 1]}1573 : vector<2x8xf32> to vector<2x4xf32>1574 return %1 : vector<2x4xf32>1575}1576 1577// -----1578 1579// CHECK-LABEL: consecutive_shape_cast1580// CHECK: %[[C:.*]] = vector.shape_cast %{{.*}} : vector<16xf16> to vector<4x4xf16>1581// CHECK-NEXT: return %[[C]] : vector<4x4xf16>1582func.func @consecutive_shape_cast(%arg0: vector<16xf16>) -> vector<4x4xf16> {1583 %0 = vector.shape_cast %arg0 : vector<16xf16> to vector<2x8xf16>1584 %1 = vector.shape_cast %0 : vector<2x8xf16> to vector<4x4xf16>1585 return %1 : vector<4x4xf16>1586}1587 1588// -----1589 1590// CHECK-LABEL: func @dead_transfer_op1591// CHECK-NOT: vector.transfer_read1592// CHECK-NOT: vector.transfer_write1593// CHECK: return1594func.func @dead_transfer_op(%arg0 : tensor<4x4xf32>, %arg1 : memref<4x4xf32>,1595 %v0 : vector<1x4xf32>) {1596 %c0 = arith.constant 0 : index1597 %cf0 = arith.constant 0.0 : f321598 %r = vector.transfer_read %arg1[%c0, %c0], %cf0 :1599 memref<4x4xf32>, vector<1x4xf32>1600 %w = vector.transfer_write %v0, %arg0[%c0, %c0] :1601 vector<1x4xf32>, tensor<4x4xf32>1602 return1603}1604 1605// -----1606 1607// CHECK-LABEL: func @dead_load1608// CHECK-NOT: vector.maskedload1609// CHECK-NOT: vector.gather1610// CHECK-NOT: vector.expandload1611// CHECK: return1612func.func @dead_load(%base: memref<?xf32>, %indices: vector<16xi32>,1613 %mask: vector<16xi1>, %passthru: vector<16xf32>) {1614 %c0 = arith.constant 0 : index1615 %0 = vector.maskedload %base[%c0], %mask, %passthru :1616 memref<?xf32>, vector<16xi1>, vector<16xf32> into vector<16xf32>1617 %1 = vector.gather %base[%c0][%indices], %mask, %passthru :1618 memref<?xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32> into vector<16xf32>1619 %2 = vector.expandload %base[%c0], %mask, %passthru :1620 memref<?xf32>, vector<16xi1>, vector<16xf32> into vector<16xf32>1621 return1622}1623 1624// -----1625 1626#contraction_accesses0 = [1627 affine_map<(i, j, k) -> (i, k)>,1628 affine_map<(i, j, k) -> (k, j)>,1629 affine_map<(i, j, k) -> (i, j)>1630]1631#contraction_trait0 = {1632 indexing_maps = #contraction_accesses0,1633 iterator_types = ["parallel", "parallel", "reduction"]1634}1635 1636// CHECK-LABEL: func @contractions1637// CHECK-SAME: %[[A:[0-9a-zA-Z]+]]: vector<2x3xf32>1638// CHECK-SAME: %[[B:[0-9a-zA-Z]+]]: vector<3x4xf32>1639// CHECK-SAME: %[[C:[0-9a-zA-Z]+]]: vector<2x4xf32>1640// CHECK-SAME: %[[A_I8:[0-9a-zA-Z]+]]: vector<2x3xi8>1641// CHECK-SAME: %[[B_I8:[0-9a-zA-Z]+]]: vector<3x4xi8>1642// CHECK-SAME: %[[C_I8:[0-9a-zA-Z]+]]: vector<2x4xi8>1643func.func @contractions(%a: vector<2x3xf32>, %b: vector<3x4xf32>, %c: vector<2x4xf32>,1644 %a_i8: vector<2x3xi8>, %b_i8: vector<3x4xi8>, %c_i8: vector<2x4xi8>)1645 -> (vector<2x4xf32>, vector<2x4xi8>)1646{1647 // CHECK-NOT: arith.constant1648 %vf_0 = arith.constant dense <0.0>: vector<2x4xf32>1649 // CHECK-NOT: arith.addf1650 // CHECK: %[[D:.*]] = vector.contract {{.*}} %[[A]], %[[B]], %[[C]]1651 %0 = vector.contract #contraction_trait0 %a, %b, %vf_0:1652 vector<2x3xf32>, vector<3x4xf32> into vector<2x4xf32>1653 // CHECK-NOT: arith.addf1654 %1 = arith.addf %0, %c: vector<2x4xf32>1655 1656 // CHECK-NOT: arith.constant1657 %vi8_0 = arith.constant dense <0>: vector<2x4xi8>1658 // CHECK-NOT: arith.addi1659 // CHECK: %[[D_I8:.*]] = vector.contract {{.*}} %[[A_I8]], %[[B_I8]], %[[C_I8]]1660 %i8_0 = vector.contract #contraction_trait0 %a_i8, %b_i8, %vi8_0:1661 vector<2x3xi8>, vector<3x4xi8> into vector<2x4xi8>1662 // CHECK-NOT: arith.addi1663 %i8_1 = arith.addi %i8_0, %c_i8: vector<2x4xi8>1664 1665 // CHECK: return %[[D]], %[[D_I8]]1666 return %1, %i8_1: vector<2x4xf32>, vector<2x4xi8>1667}1668 1669// -----1670 1671// CHECK-LABEL: func @transfer_folding_11672// CHECK-SAME: %[[T0:[0-9a-zA-Z]+]]: tensor<2x3x4xf32>1673// CHECK-SAME: %[[T1:[0-9a-zA-Z]+]]: tensor<2x3x4xf32>1674func.func @transfer_folding_1(%t0: tensor<2x3x4xf32>, %t1: tensor<2x3x4xf32>)1675 -> (tensor<2x3x4xf32>, tensor<2x3x4xf32>, tensor<2x3x4xf32>)1676{1677 %c0 = arith.constant 0 : index1678 %pad = arith.constant 0.0 : f321679 %v = vector.transfer_read %t0[%c0, %c0, %c0], %pad {in_bounds = [true, true, true]} :1680 tensor<2x3x4xf32>, vector<2x3x4xf32>1681 1682 %r0 = vector.transfer_write %v, %t1[%c0, %c0, %c0] {in_bounds = [true, true, true]} :1683 vector<2x3x4xf32>, tensor<2x3x4xf32>1684 1685 %t2 = "test.constant"() { value = dense<6.0> : tensor<2x3x4xf32>} : () -> (tensor<2x3x4xf32>)1686 %r1 = vector.transfer_write %v, %t2[%c0, %c0, %c0] {in_bounds = [true, true, true]} :1687 vector<2x3x4xf32>, tensor<2x3x4xf32>1688 1689 1690 // CHECK-NEXT: some_op_that_may_have_side_effects1691 %t3 = "some_op_that_may_have_side_effects"() : () -> (tensor<2x3x4xf32>)1692 %r2 = vector.transfer_write %v, %t0[%c0, %c0, %c0] {in_bounds = [true, true, true]} :1693 vector<2x3x4xf32>, tensor<2x3x4xf32>1694 1695 // CHECK-NEXT: return %[[T0]], %[[T0]], %[[T0]]1696 return %r0, %r1, %r2: tensor<2x3x4xf32>, tensor<2x3x4xf32>, tensor<2x3x4xf32>1697}1698 1699// -----1700 1701// CHECK-LABEL: func @store_after_load_tensor1702// CHECK-SAME: (%[[ARG:.*]]: tensor<4x4xf32>)1703// CHECK-NOT: vector.transfer_read1704// CHECK-NOT: vector.transfer_write1705// CHECK: return %[[ARG]] : tensor<4x4xf32>1706func.func @store_after_load_tensor(%arg0 : tensor<4x4xf32>) -> tensor<4x4xf32> {1707 %c1 = arith.constant 1 : index1708 %c0 = arith.constant 0 : index1709 %cf0 = arith.constant 0.0 : f321710 %0 = vector.transfer_read %arg0[%c1, %c0], %cf0 :1711 tensor<4x4xf32>, vector<1x4xf32>1712 %w0 = vector.transfer_write %0, %arg0[%c1, %c0] :1713 vector<1x4xf32>, tensor<4x4xf32>1714 return %w0 : tensor<4x4xf32>1715}1716 1717// -----1718 1719// CHECK-LABEL: func @negative_store_after_load_tensor1720// CHECK: vector.transfer_read1721// CHECK: vector.transfer_write1722// CHECK: return1723func.func @negative_store_after_load_tensor(%arg0 : tensor<4x4xf32>) -> tensor<4x4xf32> {1724 %c1 = arith.constant 1 : index1725 %c0 = arith.constant 0 : index1726 %cf0 = arith.constant 0.0 : f321727 %0 = vector.transfer_read %arg0[%c1, %c0], %cf0 :1728 tensor<4x4xf32>, vector<1x4xf32>1729 %w0 = vector.transfer_write %0, %arg0[%c0, %c0] :1730 vector<1x4xf32>, tensor<4x4xf32>1731 return %w0 : tensor<4x4xf32>1732}1733 1734// -----1735 1736// CHECK-LABEL: func @store_to_load_tensor1737// CHECK-SAME: (%[[ARG:.*]]: tensor<4x4xf32>, %[[V0:.*]]: vector<1x4xf32>, %[[V1:.*]]: vector<1x4xf32>)1738// CHECK-NOT: vector.transfer_write1739// CHECK-NOT: vector.transfer_read1740// CHECK: return %[[V0]] : vector<1x4xf32>1741func.func @store_to_load_tensor(%arg0 : tensor<4x4xf32>,1742 %v0 : vector<1x4xf32>, %v1 : vector<1x4xf32>) -> vector<1x4xf32> {1743 %c1 = arith.constant 1 : index1744 %c2 = arith.constant 2 : index1745 %c0 = arith.constant 0 : index1746 %cf0 = arith.constant 0.0 : f321747 %w0 = vector.transfer_write %v0, %arg0[%c1, %c0] {in_bounds = [true, true]} :1748 vector<1x4xf32>, tensor<4x4xf32>1749 %w1 = vector.transfer_write %v1, %w0[%c2, %c0] {in_bounds = [true, true]} :1750 vector<1x4xf32>, tensor<4x4xf32>1751 %0 = vector.transfer_read %w1[%c1, %c0], %cf0 {in_bounds = [true, true]} :1752 tensor<4x4xf32>, vector<1x4xf32>1753 return %0 : vector<1x4xf32>1754}1755 1756// -----1757 1758// CHECK-LABEL: func @negative_store_to_load_tensor1759// CHECK: vector.transfer_write1760// CHECK: vector.transfer_write1761// CHECK: %[[V:.*]] = vector.transfer_read1762// CHECK: return %[[V]] : vector<1x4xf32>1763func.func @negative_store_to_load_tensor(%arg0 : tensor<4x4xf32>,1764 %v0 : vector<1x4xf32>, %v1 : vector<1x4xf32>, %i : index) -> vector<1x4xf32> {1765 %c1 = arith.constant 1 : index1766 %c2 = arith.constant 2 : index1767 %c0 = arith.constant 0 : index1768 %cf0 = arith.constant 0.0 : f321769 %w0 = vector.transfer_write %v0, %arg0[%c1, %c0] {in_bounds = [true, true]} :1770 vector<1x4xf32>, tensor<4x4xf32>1771 %w1 = vector.transfer_write %v0, %w0[%i, %i] {in_bounds = [true, true]} :1772 vector<1x4xf32>, tensor<4x4xf32>1773 %0 = vector.transfer_read %w1[%c1, %c0], %cf0 {in_bounds = [true, true]} :1774 tensor<4x4xf32>, vector<1x4xf32>1775 return %0 : vector<1x4xf32>1776}1777 1778// -----1779 1780// CHECK-LABEL: func @store_to_load_tensor_broadcast1781// CHECK-SAME: (%[[ARG:.*]]: tensor<4x4xf32>, %[[V0:.*]]: vector<4x2xf32>)1782// CHECK: %[[B:.*]] = vector.broadcast %[[V0]] : vector<4x2xf32> to vector<6x4x2xf32>1783// CHECK: %[[T:.*]] = vector.transpose %[[B]], [1, 2, 0] : vector<6x4x2xf32> to vector<4x2x6xf32>1784// CHECK: return %[[T]] : vector<4x2x6xf32>1785func.func @store_to_load_tensor_broadcast(%arg0 : tensor<4x4xf32>,1786 %v0 : vector<4x2xf32>) -> vector<4x2x6xf32> {1787 %c0 = arith.constant 0 : index1788 %cf0 = arith.constant 0.0 : f321789 %w0 = vector.transfer_write %v0, %arg0[%c0, %c0] {in_bounds = [true, true]} :1790 vector<4x2xf32>, tensor<4x4xf32>1791 %0 = vector.transfer_read %w0[%c0, %c0], %cf0 {in_bounds = [true, true, true],1792 permutation_map = affine_map<(d0, d1) -> (d0, d1, 0)>} :1793 tensor<4x4xf32>, vector<4x2x6xf32>1794 return %0 : vector<4x2x6xf32>1795}1796 1797// -----1798 1799// CHECK-LABEL: func @negative_store_to_load_tensor_memref1800// CHECK-NOT: vector.broadcast1801// CHECK-NOT: vector.transpose1802// CHECK: vector.transfer_write1803// CHECK: vector.transfer_read1804func.func @negative_store_to_load_tensor_memref(1805 %arg0 : tensor<?x?xf32>,1806 %arg1 : memref<?x?xf32>,1807 %v0 : vector<4x2xf32>1808 ) -> vector<4x2xf32>1809{1810 %c0 = arith.constant 0 : index1811 %cf0 = arith.constant 0.0 : f321812 vector.transfer_write %v0, %arg1[%c0, %c0] {in_bounds = [true, true]} :1813 vector<4x2xf32>, memref<?x?xf32>1814 %0 = vector.transfer_read %arg0[%c0, %c0], %cf0 {in_bounds = [true, true]} :1815 tensor<?x?xf32>, vector<4x2xf32>1816 return %0 : vector<4x2xf32>1817}1818 1819// -----1820 1821// CHECK-LABEL: func @negative_store_to_load_tensor_no_actual_broadcast1822// CHECK-NOT: vector.broadcast1823// CHECK-NOT: vector.transpose1824// CHECK: vector.transfer_write1825// CHECK: vector.transfer_read1826func.func @negative_store_to_load_tensor_no_actual_broadcast(%arg0 : tensor<?x?xf32>,1827 %v0 : vector<4x2xf32>) -> vector<4x2xf32> {1828 %c0 = arith.constant 0 : index1829 %cf0 = arith.constant 0.0 : f321830 %w0 = vector.transfer_write %v0, %arg0[%c0, %c0] :1831 vector<4x2xf32>, tensor<?x?xf32>1832 %0 = vector.transfer_read %w0[%c0, %c0], %cf0 {in_bounds = [true, true]} :1833 tensor<?x?xf32>, vector<4x2xf32>1834 return %0 : vector<4x2xf32>1835}1836 1837// -----1838 1839// CHECK-LABEL: func @negative_store_to_load_tensor_broadcast_out_of_bounds1840// CHECK-NOT: vector.broadcast1841// CHECK-NOT: vector.transpose1842// CHECK: vector.transfer_write1843// CHECK: vector.transfer_read1844func.func @negative_store_to_load_tensor_broadcast_out_of_bounds(%arg0 : tensor<?x?xf32>,1845 %v0 : vector<4x2xf32>) -> vector<4x2x6xf32> {1846 %c0 = arith.constant 0 : index1847 %cf0 = arith.constant 0.0 : f321848 %w0 = vector.transfer_write %v0, %arg0[%c0, %c0] :1849 vector<4x2xf32>, tensor<?x?xf32>1850 %0 = vector.transfer_read %w0[%c0, %c0], %cf0 {in_bounds = [true, true, true],1851 permutation_map = affine_map<(d0, d1) -> (d0, d1, 0)>} :1852 tensor<?x?xf32>, vector<4x2x6xf32>1853 return %0 : vector<4x2x6xf32>1854}1855 1856// -----1857 1858// CHECK-LABEL: func @negative_store_to_load_tensor_broadcast_masked1859// CHECK-NOT: vector.broadcast1860// CHECK-NOT: vector.transpose1861// CHECK: vector.transfer_write1862// CHECK: vector.transfer_read1863func.func @negative_store_to_load_tensor_broadcast_masked(1864 %arg0 : tensor<?x?xf32>, %v0 : vector<4x2xf32>, %mask : vector<4x2xi1>)1865 -> vector<4x2x6xf32>1866{1867 %c0 = arith.constant 0 : index1868 %cf0 = arith.constant 0.0 : f321869 %w0 = vector.transfer_write %v0, %arg0[%c0, %c0], %mask {in_bounds = [true, true]} :1870 vector<4x2xf32>, tensor<?x?xf32>1871 %0 = vector.transfer_read %w0[%c0, %c0], %cf0 {in_bounds = [true, true, true],1872 permutation_map = affine_map<(d0, d1) -> (d0, d1, 0)>} :1873 tensor<?x?xf32>, vector<4x2x6xf32>1874 return %0 : vector<4x2x6xf32>1875}1876 1877// -----1878 1879// CHECK-LABEL: func @store_to_load_tensor_broadcast_scalable1880// CHECK-SAME: (%[[ARG:.*]]: tensor<?xf32>, %[[V0:.*]]: vector<[4]xf32>)1881// CHECK: %[[B:.*]] = vector.broadcast %[[V0]] : vector<[4]xf32> to vector<6x[4]xf32>1882// CHECK: return %[[B]] : vector<6x[4]xf32>1883func.func @store_to_load_tensor_broadcast_scalable(%arg0 : tensor<?xf32>,1884 %v0 : vector<[4]xf32>) -> vector<6x[4]xf32> {1885 %c0 = arith.constant 0 : index1886 %cf0 = arith.constant 0.0 : f321887 %w0 = vector.transfer_write %v0, %arg0[%c0] {in_bounds = [true]} :1888 vector<[4]xf32>, tensor<?xf32>1889 %0 = vector.transfer_read %w0[%c0], %cf0 {in_bounds = [true, true],1890 permutation_map = affine_map<(d0) -> (0, d0)>} :1891 tensor<?xf32>, vector<6x[4]xf32>1892 return %0 : vector<6x[4]xf32>1893}1894 1895// -----1896 1897// CHECK-LABEL: func @store_to_load_tensor_perm_broadcast1898// CHECK-SAME: (%[[ARG:.*]]: tensor<4x4x4xf32>, %[[V0:.*]]: vector<4x1xf32>)1899// CHECK: %[[B:.*]] = vector.broadcast %[[V0]] : vector<4x1xf32> to vector<100x5x4x1xf32>1900// CHECK: %[[T:.*]] = vector.transpose %[[B]], [3, 0, 2, 1] : vector<100x5x4x1xf32> to vector<1x100x4x5xf32>1901// CHECK: return %[[T]] : vector<1x100x4x5xf32>1902func.func @store_to_load_tensor_perm_broadcast(%arg0 : tensor<4x4x4xf32>,1903 %v0 : vector<4x1xf32>) -> vector<1x100x4x5xf32> {1904 %c0 = arith.constant 0 : index1905 %cf0 = arith.constant 0.0 : f321906 %w0 = vector.transfer_write %v0, %arg0[%c0, %c0, %c0] {in_bounds = [true, true],1907 permutation_map = affine_map<(d0, d1, d2) -> (d2, d1)>} :1908 vector<4x1xf32>, tensor<4x4x4xf32>1909 %0 = vector.transfer_read %w0[%c0, %c0, %c0], %cf0 {in_bounds = [true, true, true, true],1910 permutation_map = affine_map<(d0, d1, d2) -> (d1, 0, d2, 0)>} :1911 tensor<4x4x4xf32>, vector<1x100x4x5xf32>1912 return %0 : vector<1x100x4x5xf32>1913}1914 1915// -----1916 1917 1918// CHECK-LABEL: func @dead_store_tensor1919// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index1920// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index1921// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index1922// CHECK-NOT: vector.transfer_write {{.*}}, {{.*}}[%[[C1]], %[[C0]]1923// CHECK: vector.transfer_write {{.*}}, {{.*}}[%[[C2]], %[[C0]]1924// CHECK: %[[VTW:.*]] = vector.transfer_write {{.*}}, {{.*}}[%[[C1]], %[[C0]]1925// CHECK: return %[[VTW]] : tensor<4x4xf32>1926func.func @dead_store_tensor(%arg0 : tensor<4x4xf32>,1927 %v0 : vector<1x4xf32>, %v1 : vector<1x4xf32>, %i : index) -> tensor<4x4xf32> {1928 %c1 = arith.constant 1 : index1929 %c2 = arith.constant 2 : index1930 %c0 = arith.constant 0 : index1931 %cf0 = arith.constant 0.0 : f321932 %w0 = vector.transfer_write %v0, %arg0[%c1, %c0] {in_bounds = [true, true]} :1933 vector<1x4xf32>, tensor<4x4xf32>1934 %w1 = vector.transfer_write %v0, %w0[%c2, %c0] {in_bounds = [true, true]} :1935 vector<1x4xf32>, tensor<4x4xf32>1936 %w2 = vector.transfer_write %v1, %w1[%c1, %c0] {in_bounds = [true, true]} :1937 vector<1x4xf32>, tensor<4x4xf32>1938 return %w2 : tensor<4x4xf32>1939}1940 1941// -----1942 1943// CHECK-LABEL: func @negative_dead_store_tensor1944// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index1945// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index1946// CHECK: vector.transfer_write1947// CHECK: vector.transfer_write1948// CHECK: vector.transfer_read1949// CHECK: %[[VTW:.*]] = vector.transfer_write {{.*}}, {{.*}}[%[[C1]], %[[C0]]]1950// CHECK: return %[[VTW]] : tensor<4x4xf32>1951func.func @negative_dead_store_tensor(%arg0 : tensor<4x4xf32>,1952 %v0 : vector<1x4xf32>, %v1 : vector<1x4xf32>, %i : index) -> tensor<4x4xf32> {1953 %c1 = arith.constant 1 : index1954 %c2 = arith.constant 2 : index1955 %c0 = arith.constant 0 : index1956 %cf0 = arith.constant 0.0 : f321957 %w0 = vector.transfer_write %v0, %arg0[%c1, %c0] {in_bounds = [true, true]} :1958 vector<1x4xf32>, tensor<4x4xf32>1959 %w1 = vector.transfer_write %v0, %w0[%c2, %c0] {in_bounds = [true, true]} :1960 vector<1x4xf32>, tensor<4x4xf32>1961 %0 = vector.transfer_read %w1[%i, %i], %cf0 {in_bounds = [true, true]} :1962 tensor<4x4xf32>, vector<1x4xf32>1963 %x = arith.addf %0, %0 : vector<1x4xf32>1964 %w2 = vector.transfer_write %x, %w0[%c1, %c0] {in_bounds = [true, true]} :1965 vector<1x4xf32>, tensor<4x4xf32>1966 return %w2 : tensor<4x4xf32>1967}1968 1969// -----1970 1971// CHECK: #[[$MAP:[0-9a-z]+]] = affine_map<(d0, d1) -> (d1, d0)>1972 1973// CHECK-LABEL: func @swap_extract_slice_transfer_write1974// CHECK-SAME: %[[VEC:.*]]: vector<8x4xf32>1975// CHECK-SAME: %[[INIT_TENSOR:.*]]: tensor<4x8xf32>,1976// CHECK-SAME: %[[ITER_ARG:.*]]: tensor<64x64xf32>,1977// CHECK-SAME: %[[IV:.*]]: index, %[[SZ:.*]]: index)1978func.func @swap_extract_slice_transfer_write(%arg0 : vector<8x4xf32>,1979 %arg1 : tensor<4x8xf32>,1980 %arg2 : tensor<64x64xf32>,1981 %iv : index, %sz : index) -> tensor<64x64xf32> {1982 // CHECK: %[[C0:.*]] = arith.constant 0 : index1983 %c0 = arith.constant 0 : index1984 1985 // CHECK: %[[T0:.*]] = tensor.extract_slice %[[ITER_ARG]]1986 // CHECK-SAME: [%[[IV]], 16] [%[[SZ]], 8]1987 // CHECK: %[[T1:.*]] = vector.transfer_write %[[VEC]]1988 // CHECK-SAME: %[[T0]][%[[C0]], %[[C0]]]1989 // CHECK-SAME: in_bounds = [true, false]1990 // CHECK-SAME: permutation_map = #[[$MAP]]1991 // CHECK: %[[T2:.*]] = tensor.insert_slice %[[T1]] into %[[ITER_ARG]]1992 // CHECK-SAME: [%[[IV]], 16] [%[[SZ]], 8]1993 %0 = vector.transfer_write %arg0, %arg1[%c0, %c0] {in_bounds = [true, true], permutation_map = affine_map<(d0, d1) -> (d1, d0)>} : vector<8x4xf32>, tensor<4x8xf32>1994 %1 = tensor.extract_slice %0[0, 0] [%sz, 8] [1, 1] : tensor<4x8xf32> to tensor<?x8xf32>1995 %2 = tensor.insert_slice %1 into %arg2[%iv, 16] [%sz, 8] [1, 1] : tensor<?x8xf32> into tensor<64x64xf32>1996 1997 // CHECK: return %[[T2]]1998 func.return %2 : tensor<64x64xf32>1999}2000 2001// -----2002 2003// CHECK-LABEL: func @do_not_swap_extract_slice_transfer_write2004// CHECK-SAME: %[[VEC:.*]]: vector<8xf32>,2005// CHECK-SAME: %[[VEC_SMALL:.*]]: vector<4xf32>,2006// CHECK-SAME: %[[INIT_TENSOR:.*]]: tensor<8xf32>,2007// CHECK-SAME: %[[ITER_ARG:.*]]: tensor<64xf32>,2008// CHECK-SAME: %[[IV:.*]]: index, %[[SZ:.*]]: index)2009func.func @do_not_swap_extract_slice_transfer_write(%arg0 : vector<8xf32>,2010 %arg1 : vector<4xf32>,2011 %arg2 : tensor<8xf32>,2012 %arg3 : tensor<64xf32>,2013 %iv : index, %sz : index) -> (tensor<64xf32>, tensor<64xf32>, tensor<64xf32>) {2014 // CHECK: %[[C0:.*]] = arith.constant 0 : index2015 %c0 = arith.constant 0 : index2016 2017 // Don't swap if the extracted and inserted slices do not match.2018 // CHECK: %[[T0:.*]] = vector.transfer_write %[[VEC]]2019 // CHECK: %[[T1:.*]] = tensor.extract_slice %[[T0]]2020 // CHECK: %[[T2:.*]] = tensor.insert_slice %[[T1]]2021 %0 = vector.transfer_write %arg0, %arg2[%c0] {in_bounds = [true]} : vector<8xf32>, tensor<8xf32>2022 %1 = tensor.extract_slice %0[0] [%iv] [1] : tensor<8xf32> to tensor<?xf32>2023 %2 = tensor.insert_slice %1 into %arg3[%iv] [%sz] [1] : tensor<?xf32> into tensor<64xf32>2024 2025 // Don't swap if the TransferWriteOp takes a small vector.2026 // CHECK: %[[T3:.*]] = vector.transfer_write %[[VEC_SMALL]]2027 // CHECK: %[[T4:.*]] = tensor.extract_slice %[[T3]]2028 // CHECK: %[[T5:.*]] = tensor.insert_slice %[[T4]]2029 %3 = vector.transfer_write %arg1, %arg2[%c0] {in_bounds = [true]} : vector<4xf32>, tensor<8xf32>2030 %4 = tensor.extract_slice %3[0] [%sz] [1] : tensor<8xf32> to tensor<?xf32>2031 %5 = tensor.insert_slice %4 into %arg3[%iv] [%sz] [1] : tensor<?xf32> into tensor<64xf32>2032 2033 // Don't swap if the one of the operations is rank-reducing.2034 // CHECK: %[[T6:.*]] = vector.transfer_write %[[VEC]]2035 // CHECK: %[[T7:.*]] = tensor.extract_slice %[[T6]]2036 // CHECK: %[[T8:.*]] = tensor.insert_slice %[[T7]]2037 %6 = vector.transfer_write %arg0, %arg2[%c0] {in_bounds = [true]} : vector<8xf32>, tensor<8xf32>2038 %7 = tensor.extract_slice %6[0] [1] [1] : tensor<8xf32> to tensor<f32>2039 %8 = tensor.insert_slice %7 into %arg3[%iv] [1] [1] : tensor<f32> into tensor<64xf32>2040 2041 // CHECK: return %[[T2]], %[[T5]], %[[T8]]2042 func.return %2, %5, %8 : tensor<64xf32>, tensor<64xf32>, tensor<64xf32>2043}2044 2045// -----2046 2047// CHECK-LABEL: func @vector_multi_reduction_single_parallel(2048// CHECK-SAME: %[[v:.*]]: vector<2xf32>,2049func.func @vector_multi_reduction_single_parallel(%arg0: vector<2xf32>, %acc: vector<2xf32>) -> vector<2xf32> {2050 %0 = vector.multi_reduction <mul>, %arg0, %acc [] : vector<2xf32> to vector<2xf32>2051 2052// CHECK: return %[[v]] : vector<2xf32>2053 return %0 : vector<2xf32>2054}2055 2056// -----2057 2058// CHECK-LABEL: func @masked_vector_multi_reduction_single_parallel(2059// CHECK-SAME: %[[VAL_0:.*]]: vector<2xf32>, %{{.*}}: vector<2xf32>,2060func.func @masked_vector_multi_reduction_single_parallel(%arg0: vector<2xf32>, %acc: vector<2xf32>, %mask: vector<2xi1>) -> vector<2xf32> {2061 %0 = vector.mask %mask { vector.multi_reduction <mul>, %arg0, %acc [] : vector<2xf32> to vector<2xf32> } : vector<2xi1> -> vector<2xf32>2062// CHECK: return %[[VAL_0]] : vector<2xf32>2063 return %0 : vector<2xf32>2064}2065 2066// -----2067 2068// CHECK-LABEL: func @vector_multi_reduction_unit_dimensions(2069// CHECK-SAME: %[[SOURCE:.+]]: vector<5x1x4x1x20xf32>, %[[ACC:.+]]: vector<5x4x20xf32>2070func.func @vector_multi_reduction_unit_dimensions(%source: vector<5x1x4x1x20xf32>, %acc: vector<5x4x20xf32>) -> vector<5x4x20xf32> {2071// CHECK: %[[CAST:.+]] = vector.shape_cast %[[SOURCE]] : vector<5x1x4x1x20xf32> to vector<5x4x20xf32>2072// CHECK: %[[RESULT:.+]] = arith.mulf %[[ACC]], %[[CAST]] : vector<5x4x20xf32>2073 %0 = vector.multi_reduction <mul>, %source, %acc [1, 3] : vector<5x1x4x1x20xf32> to vector<5x4x20xf32>2074 2075// CHECK: return %[[RESULT]] : vector<5x4x20xf32>2076 return %0 : vector<5x4x20xf32>2077}2078 2079// -----2080 2081// CHECK-LABEL: func.func @vector_multi_reduction_scalable(2082// CHECK-SAME: %[[VAL_0:.*]]: vector<1x[4]x1xf32>,2083// CHECK-SAME: %[[VAL_1:.*]]: vector<1x[4]xf32>,2084// CHECK-SAME: %[[VAL_2:.*]]: vector<1x[4]x1xi1>)2085func.func @vector_multi_reduction_scalable(%source: vector<1x[4]x1xf32>,2086 %acc: vector<1x[4]xf32>,2087 %mask: vector<1x[4]x1xi1>) -> vector<1x[4]xf32> {2088// CHECK: %[[VAL_3:.*]] = vector.shape_cast %[[VAL_2]] : vector<1x[4]x1xi1> to vector<1x[4]xi1>2089// CHECK: %[[VAL_4:.*]] = vector.shape_cast %[[VAL_0]] : vector<1x[4]x1xf32> to vector<1x[4]xf32>2090// CHECK: %[[VAL_5:.*]] = arith.addf %[[VAL_1]], %[[VAL_4]] : vector<1x[4]xf32>2091// CHECK: %[[VAL_6:.*]] = arith.select %[[VAL_3]], %[[VAL_5]], %[[VAL_4]] : vector<1x[4]xi1>, vector<1x[4]xf32>2092 %0 = vector.mask %mask { vector.multi_reduction <add>, %source, %acc [2] : vector<1x[4]x1xf32> to vector<1x[4]xf32> } :2093 vector<1x[4]x1xi1> -> vector<1x[4]xf32>2094 2095 return %0 : vector<1x[4]xf32>2096}2097 2098// -----2099 2100// CHECK-LABEL: func @masked_vector_multi_reduction_unit_dimensions2101// CHECK-SAME: %[[VAL_0:.*]]: vector<5x1x4x1x20xf32>, %[[VAL_1:.*]]: vector<5x4x20xf32>,2102// CHECK-SAME: %[[VAL_2:.*]]: vector<5x1x4x1x20xi1>)2103func.func @masked_vector_multi_reduction_unit_dimensions(%source: vector<5x1x4x1x20xf32>,2104 %acc: vector<5x4x20xf32>,2105 %mask: vector<5x1x4x1x20xi1>) -> vector<5x4x20xf32> {2106// CHECK: %[[VAL_3:.*]] = vector.shape_cast %[[VAL_2]] : vector<5x1x4x1x20xi1> to vector<5x4x20xi1>2107// CHECK: %[[VAL_4:.*]] = vector.shape_cast %[[VAL_0]] : vector<5x1x4x1x20xf32> to vector<5x4x20xf32>2108// CHECK: %[[VAL_5:.*]] = arith.mulf %[[VAL_1]], %[[VAL_4]] : vector<5x4x20xf32>2109// CHECK: %[[VAL_6:.*]] = arith.select %[[VAL_3]], %[[VAL_5]], %[[VAL_4]] : vector<5x4x20xi1>, vector<5x4x20xf32>2110%0 = vector.mask %mask { vector.multi_reduction <mul>, %source, %acc [1, 3] : vector<5x1x4x1x20xf32> to vector<5x4x20xf32> } :2111 vector<5x1x4x1x20xi1> -> vector<5x4x20xf32>2112 return %0 : vector<5x4x20xf32>2113}2114 2115// -----2116 2117// CHECK-LABEL: func @vector_multi_reduction_unit_dimensions_fail(2118// CHECK-SAME: %[[SRC:.+]]: vector<5x1x4x1x20xf32>, %[[ACCUM:.+]]: vector<5x1x20xf32>2119func.func @vector_multi_reduction_unit_dimensions_fail(%source: vector<5x1x4x1x20xf32>, %acc: vector<5x1x20xf32>) -> vector<5x1x20xf32> {2120// CHECK: %[[RES:.+]] = vector.multi_reduction <mul>, %[[SRC]], %[[ACCUM]] [1, 2] : vector<5x1x4x1x20xf32> to vector<5x1x20xf32>2121 %0 = vector.multi_reduction <mul>, %source, %acc [1, 2] : vector<5x1x4x1x20xf32> to vector<5x1x20xf32>2122 2123// CHECK: return %[[RES]] : vector<5x1x20xf32>2124 return %0 : vector<5x1x20xf32>2125}2126 2127// -----2128 2129// CHECK-LABEL: func @vector_multi_reduction_unit_dimensions_single_elem(2130// CHECK-SAME: %[[SOURCE:.+]]: vector<1x1x1xf32>, %[[ACC:.+]]: f322131func.func @vector_multi_reduction_unit_dimensions_single_elem(%source: vector<1x1x1xf32>, %acc: f32) -> f32 {2132// CHECK: %[[CAST:.+]] = vector.extract %[[SOURCE]][0, 0, 0] : f32 from vector<1x1x1xf32>2133// CHECK: %[[RESULT:.+]] = arith.mulf %[[ACC]], %[[CAST]] : f322134 %0 = vector.multi_reduction <mul>, %source, %acc [0,1,2] : vector<1x1x1xf32> to f322135 2136// CHECK: return %[[RESULT]] : f322137 return %0 : f322138}2139 2140// -----2141 2142// CHECK-LABEL: func @masked_vector_multi_reduction_unit_dimensions_single_elem(2143// CHECK-SAME: %[[VAL_0:.*]]: vector<1x1x1xf32>, %[[VAL_1:.*]]: f32,2144// CHECK-SAME: %[[VAL_2:.*]]: vector<1x1x1xi1>)2145func.func @masked_vector_multi_reduction_unit_dimensions_single_elem(%source: vector<1x1x1xf32>, %acc: f32, %mask: vector<1x1x1xi1>) -> f32 {2146 // CHECK: %[[VAL_3:.*]] = vector.extract %[[VAL_2]][0, 0, 0] : i1 from vector<1x1x1xi1>2147 // CHECK: %[[VAL_4:.*]] = vector.extract %[[VAL_0]][0, 0, 0] : f32 from vector<1x1x1xf32>2148 // CHECK: %[[VAL_5:.*]] = arith.mulf %[[VAL_1]], %[[VAL_4]] : f322149 // CHECK: %[[VAL_6:.*]] = arith.select %[[VAL_3]], %[[VAL_5]], %[[VAL_4]] : f322150 %0 = vector.mask %mask { vector.multi_reduction <mul>, %source, %acc [0,1,2] : vector<1x1x1xf32> to f32 } : vector<1x1x1xi1> -> f322151 return %0 : f322152}2153 2154// -----2155 2156// CHECK-LABEL: func @insert_strided_slice_full_range2157// CHECK-SAME: %[[SOURCE:.+]]: vector<16x16xf16>, %{{.+}}: vector<16x16xf16>2158func.func @insert_strided_slice_full_range(%source: vector<16x16xf16>, %dest: vector<16x16xf16>) -> vector<16x16xf16> {2159 %0 = vector.insert_strided_slice %source, %dest {offsets = [0, 0], strides = [1, 1]} : vector<16x16xf16> into vector<16x16xf16>2160 // CHECK: return %[[SOURCE]]2161 return %0: vector<16x16xf16>2162}2163 2164// -----2165 2166// CHECK-LABEL: extract_strided_splatlike2167// CHECK: %[[B:.*]] = vector.broadcast %{{.*}} f16 to vector<2x4xf16>2168// CHECK-NEXT: return %[[B]] : vector<2x4xf16>2169func.func @extract_strided_splatlike(%arg0: f16) -> vector<2x4xf16> {2170 %0 = vector.broadcast %arg0 : f16 to vector<16x4xf16>2171 %1 = vector.extract_strided_slice %02172 {offsets = [1, 0], sizes = [2, 4], strides = [1, 1]} :2173 vector<16x4xf16> to vector<2x4xf16>2174 return %1 : vector<2x4xf16>2175}2176 2177// -----2178 2179// CHECK-LABEL: func @insert_extract_to_broadcast2180// CHECK-SAME: (%[[ARG0:.*]]: vector<1x1x4xf32>, %[[ARG1:.*]]: vector<4xf32>)2181// CHECK: %[[V0:.*]] = vector.extract %[[ARG0]][0, 0] : vector<4xf32> from vector<1x1x4xf32>2182// CHECK: %[[V1:.*]] = vector.broadcast %[[ARG1]] : vector<4xf32> to vector<1x1x4xf32>2183// CHECK: return %[[V0]], %[[V1]] : vector<4xf32>, vector<1x1x4xf32>2184func.func @insert_extract_to_broadcast(%arg0 : vector<1x1x4xf32>,2185 %arg1 : vector<4xf32>) -> (vector<4xf32>, vector<1x1x4xf32>) {2186 %0 = vector.extract %arg0[0, 0] : vector<4xf32> from vector<1x1x4xf32>2187 %1 = vector.insert %arg1, %arg0 [0, 0] : vector<4xf32> into vector<1x1x4xf32>2188 return %0, %1 : vector<4xf32>, vector<1x1x4xf32>2189}2190 2191// -----2192 2193// CHECK-LABEL: func.func @extract_splat_constant2194// CHECK-DAG: %[[CST1:.*]] = arith.constant 1 : i322195// CHECK-DAG: %[[CST0:.*]] = arith.constant dense<2.000000e+00> : vector<7xf32>2196// CHECK-NEXT: return %[[CST0]], %[[CST1]] : vector<7xf32>, i322197func.func @extract_splat_constant() -> (vector<7xf32>, i32) {2198 %cst = arith.constant dense<2.000000e+00> : vector<29x7xf32>2199 %cst_1 = arith.constant dense<1> : vector<4x37x9xi32>2200 %0 = vector.extract %cst[2] : vector<7xf32> from vector<29x7xf32>2201 %1 = vector.extract %cst_1[1, 4, 5] : i32 from vector<4x37x9xi32>2202 return %0, %1 : vector<7xf32>, i322203}2204 2205// -----2206 2207// CHECK-LABEL: func.func @extract_1d_constant2208// CHECK-DAG: %[[I32CST:.*]] = arith.constant 3 : i322209// CHECK-DAG: %[[IDXCST:.*]] = arith.constant 1 : index2210// CHECK-DAG: %[[F32CST:.*]] = arith.constant 2.000000e+00 : f322211// CHECK-NEXT: return %[[I32CST]], %[[IDXCST]], %[[F32CST]] : i32, index, f322212func.func @extract_1d_constant() -> (i32, index, f32) {2213 %icst = arith.constant dense<[1, 2, 3, 4]> : vector<4xi32>2214 %e = vector.extract %icst[2] : i32 from vector<4xi32>2215 %idx_cst = arith.constant dense<[0, 1, 2]> : vector<3xindex>2216 %f = vector.extract %idx_cst[1] : index from vector<3xindex>2217 %fcst = arith.constant dense<[2.000000e+00, 3.000000e+00, 4.000000e+00]> : vector<3xf32>2218 %g = vector.extract %fcst[0] : f32 from vector<3xf32>2219 return %e, %f, %g : i32, index, f322220}2221 2222// -----2223 2224// CHECK-LABEL: func.func @extract_2d_constant2225// CHECK-DAG: %[[ACST:.*]] = arith.constant 0 : i322226// CHECK-DAG: %[[BCST:.*]] = arith.constant 2 : i322227// CHECK-DAG: %[[CCST:.*]] = arith.constant 3 : i322228// CHECK-DAG: %[[DCST:.*]] = arith.constant 5 : i322229// CHECK-NEXT: return %[[ACST]], %[[BCST]], %[[CCST]], %[[DCST]] : i32, i32, i32, i322230func.func @extract_2d_constant() -> (i32, i32, i32, i32) {2231 %cst = arith.constant dense<[[0, 1, 2], [3, 4, 5]]> : vector<2x3xi32>2232 %a = vector.extract %cst[0, 0] : i32 from vector<2x3xi32>2233 %b = vector.extract %cst[0, 2] : i32 from vector<2x3xi32>2234 %c = vector.extract %cst[1, 0] : i32 from vector<2x3xi32>2235 %d = vector.extract %cst[1, 2] : i32 from vector<2x3xi32>2236 return %a, %b, %c, %d : i32, i32, i32, i322237}2238 2239// -----2240 2241// CHECK-LABEL: func.func @extract_vector_2d_constant2242// CHECK-DAG: %[[ACST:.*]] = arith.constant dense<[0, 1, 2]> : vector<3xi32>2243// CHECK-DAG: %[[BCST:.*]] = arith.constant dense<[3, 4, 5]> : vector<3xi32>2244// CHECK-NEXT: return %[[ACST]], %[[BCST]] : vector<3xi32>, vector<3xi32>2245func.func @extract_vector_2d_constant() -> (vector<3xi32>, vector<3xi32>) {2246 %cst = arith.constant dense<[[0, 1, 2], [3, 4, 5]]> : vector<2x3xi32>2247 %a = vector.extract %cst[0] : vector<3xi32> from vector<2x3xi32>2248 %b = vector.extract %cst[1] : vector<3xi32> from vector<2x3xi32>2249 return %a, %b : vector<3xi32>, vector<3xi32>2250}2251 2252// -----2253 2254// CHECK-LABEL: func.func @extract_3d_constant2255// CHECK-DAG: %[[ACST:.*]] = arith.constant 0 : i322256// CHECK-DAG: %[[BCST:.*]] = arith.constant 1 : i322257// CHECK-DAG: %[[CCST:.*]] = arith.constant 9 : i322258// CHECK-DAG: %[[DCST:.*]] = arith.constant 10 : i322259// CHECK-NEXT: return %[[ACST]], %[[BCST]], %[[CCST]], %[[DCST]] : i32, i32, i32, i322260func.func @extract_3d_constant() -> (i32, i32, i32, i32) {2261 %cst = arith.constant dense<[[[0, 1], [2, 3], [4, 5]], [[6, 7], [8, 9], [10, 11]]]> : vector<2x3x2xi32>2262 %a = vector.extract %cst[0, 0, 0] : i32 from vector<2x3x2xi32>2263 %b = vector.extract %cst[0, 0, 1] : i32 from vector<2x3x2xi32>2264 %c = vector.extract %cst[1, 1, 1] : i32 from vector<2x3x2xi32>2265 %d = vector.extract %cst[1, 2, 0] : i32 from vector<2x3x2xi32>2266 return %a, %b, %c, %d : i32, i32, i32, i322267}2268 2269// -----2270 2271// CHECK-LABEL: func.func @extract_vector_3d_constant2272// CHECK-DAG: %[[ACST:.*]] = arith.constant dense<{{\[\[0, 1\], \[2, 3\], \[4, 5\]\]}}> : vector<3x2xi32>2273// CHECK-DAG: %[[BCST:.*]] = arith.constant dense<{{\[\[6, 7\], \[8, 9\], \[10, 11\]\]}}> : vector<3x2xi32>2274// CHECK-DAG: %[[CCST:.*]] = arith.constant dense<[8, 9]> : vector<2xi32>2275// CHECK-DAG: %[[DCST:.*]] = arith.constant dense<[10, 11]> : vector<2xi32>2276// CHECK-NEXT: return %[[ACST]], %[[BCST]], %[[CCST]], %[[DCST]] : vector<3x2xi32>, vector<3x2xi32>, vector<2xi32>, vector<2xi32>2277func.func @extract_vector_3d_constant() -> (vector<3x2xi32>, vector<3x2xi32>, vector<2xi32>, vector<2xi32>) {2278 %cst = arith.constant dense<[[[0, 1], [2, 3], [4, 5]], [[6, 7], [8, 9], [10, 11]]]> : vector<2x3x2xi32>2279 %a = vector.extract %cst[0] : vector<3x2xi32> from vector<2x3x2xi32>2280 %b = vector.extract %cst[1] : vector<3x2xi32> from vector<2x3x2xi32>2281 %c = vector.extract %cst[1, 1] : vector<2xi32> from vector<2x3x2xi32>2282 %d = vector.extract %cst[1, 2] : vector<2xi32> from vector<2x3x2xi32>2283 return %a, %b, %c, %d : vector<3x2xi32>, vector<3x2xi32>, vector<2xi32>, vector<2xi32>2284}2285 2286// -----2287 2288// CHECK-LABEL: func.func @extract_splat_vector_3d_constant2289// CHECK-DAG: %[[ACST:.*]] = arith.constant dense<0> : vector<2xi32>2290// CHECK-DAG: %[[BCST:.*]] = arith.constant dense<4> : vector<2xi32>2291// CHECK-DAG: %[[CCST:.*]] = arith.constant dense<5> : vector<2xi32>2292// CHECK-NEXT: return %[[ACST]], %[[BCST]], %[[CCST]] : vector<2xi32>, vector<2xi32>, vector<2xi32>2293func.func @extract_splat_vector_3d_constant() -> (vector<2xi32>, vector<2xi32>, vector<2xi32>) {2294 %cst = arith.constant dense<[[[0, 0], [1, 1], [2, 2]], [[3, 3], [4, 4], [5, 5]]]> : vector<2x3x2xi32>2295 %a = vector.extract %cst[0, 0] : vector<2xi32> from vector<2x3x2xi32>2296 %b = vector.extract %cst[1, 1] : vector<2xi32> from vector<2x3x2xi32>2297 %c = vector.extract %cst[1, 2] : vector<2xi32> from vector<2x3x2xi32>2298 return %a, %b, %c : vector<2xi32>, vector<2xi32>, vector<2xi32>2299}2300 2301// -----2302 2303// CHECK-LABEL: func.func @extract_strided_slice_1d_constant2304// CHECK-DAG: %[[ACST:.*]] = arith.constant dense<[0, 1, 2]> : vector<3xi32>2305// CHECK-DAG: %[[BCST:.*]] = arith.constant dense<[1, 2]> : vector<2xi32>2306// CHECK-DAG: %[[CCST:.*]] = arith.constant dense<2> : vector<1xi32>2307// CHECK-NEXT: return %[[ACST]], %[[BCST]], %[[CCST]] : vector<3xi32>, vector<2xi32>, vector<1xi32>2308func.func @extract_strided_slice_1d_constant() -> (vector<3xi32>, vector<2xi32>, vector<1xi32>) {2309 %cst = arith.constant dense<[0, 1, 2]> : vector<3xi32>2310 %a = vector.extract_strided_slice %cst2311 {offsets = [0], sizes = [3], strides = [1]} : vector<3xi32> to vector<3xi32>2312 %b = vector.extract_strided_slice %cst2313 {offsets = [1], sizes = [2], strides = [1]} : vector<3xi32> to vector<2xi32>2314 %c = vector.extract_strided_slice %cst2315 {offsets = [2], sizes = [1], strides = [1]} : vector<3xi32> to vector<1xi32>2316 return %a, %b, %c : vector<3xi32>, vector<2xi32>, vector<1xi32>2317}2318 2319// -----2320 2321// CHECK-LABEL: func.func @extract_strided_slice_2d_constant2322// CHECK-DAG: %[[ACST:.*]] = arith.constant dense<0> : vector<1x1xi32>2323// CHECK-DAG: %[[BCST:.*]] = arith.constant dense<{{\[\[4, 5\]\]}}> : vector<1x2xi32>2324// CHECK-DAG: %[[CCST:.*]] = arith.constant dense<{{\[\[1, 2\], \[4, 5\]\]}}> : vector<2x2xi32>2325// CHECK-NEXT: return %[[ACST]], %[[BCST]], %[[CCST]] : vector<1x1xi32>, vector<1x2xi32>, vector<2x2xi32>2326func.func @extract_strided_slice_2d_constant() -> (vector<1x1xi32>, vector<1x2xi32>, vector<2x2xi32>) {2327 %cst = arith.constant dense<[[0, 1, 2], [3, 4, 5]]> : vector<2x3xi32>2328 %a = vector.extract_strided_slice %cst2329 {offsets = [0, 0], sizes = [1, 1], strides = [1, 1]} : vector<2x3xi32> to vector<1x1xi32>2330 %b = vector.extract_strided_slice %cst2331 {offsets = [1, 1], sizes = [1, 2], strides = [1, 1]} : vector<2x3xi32> to vector<1x2xi32>2332 %c = vector.extract_strided_slice %cst2333 {offsets = [0, 1], sizes = [2, 2], strides = [1, 1]} : vector<2x3xi32> to vector<2x2xi32>2334 return %a, %b, %c : vector<1x1xi32>, vector<1x2xi32>, vector<2x2xi32>2335}2336 2337// -----2338 2339// CHECK-LABEL: func.func @extract_strided_slice_3d_constant2340// CHECK-DAG: %[[ACST:.*]] = arith.constant dense<{{\[\[\[8, 9\], \[10, 11\]\]\]}}> : vector<1x2x2xi32>2341// CHECK-DAG: %[[BCST:.*]] = arith.constant dense<{{\[\[\[2, 3\]\]\]}}> : vector<1x1x2xi32>2342// CHECK-DAG: %[[CCST:.*]] = arith.constant dense<{{\[\[\[6, 7\]\], \[\[10, 11\]\]\]}}> : vector<2x1x2xi32>2343// CHECK-DAG: %[[DCST:.*]] = arith.constant dense<11> : vector<1x1x1xi32>2344// CHECK-NEXT: return %[[ACST]], %[[BCST]], %[[CCST]], %[[DCST]]2345func.func @extract_strided_slice_3d_constant() -> (vector<1x2x2xi32>, vector<1x1x2xi32>, vector<2x1x2xi32>, vector<1x1x1xi32>) {2346 %cst = arith.constant dense<[[[0, 1], [2, 3]], [[4, 5], [6, 7]], [[8, 9], [10, 11]]]> : vector<3x2x2xi32>2347 %a = vector.extract_strided_slice %cst2348 {offsets = [2], sizes = [1], strides = [1]} : vector<3x2x2xi32> to vector<1x2x2xi32>2349 %b = vector.extract_strided_slice %cst2350 {offsets = [0, 1], sizes = [1, 1], strides = [1, 1]} : vector<3x2x2xi32> to vector<1x1x2xi32>2351 %c = vector.extract_strided_slice %cst2352 {offsets = [1, 1, 0], sizes = [2, 1, 2], strides = [1, 1, 1]} : vector<3x2x2xi32> to vector<2x1x2xi32>2353 %d = vector.extract_strided_slice %cst2354 {offsets = [2, 1, 1], sizes = [1, 1, 1], strides = [1, 1, 1]} : vector<3x2x2xi32> to vector<1x1x1xi32>2355 return %a, %b, %c, %d : vector<1x2x2xi32>, vector<1x1x2xi32>, vector<2x1x2xi32>, vector<1x1x1xi32>2356}2357 2358// -----2359 2360// CHECK-LABEL: extract_extract_strided2361// CHECK-SAME: %[[A:.*]]: vector<32x16x4xf16>2362// CHECK: %[[V:.*]] = vector.extract %[[A]][9, 7] : vector<4xf16> from vector<32x16x4xf16>2363// CHECK: return %[[V]] : vector<4xf16>2364func.func @extract_extract_strided(%arg0: vector<32x16x4xf16>) -> vector<4xf16> {2365 %1 = vector.extract_strided_slice %arg02366 {offsets = [7, 3], sizes = [10, 8], strides = [1, 1]} :2367 vector<32x16x4xf16> to vector<10x8x4xf16>2368 %2 = vector.extract %1[2, 4] : vector<4xf16> from vector<10x8x4xf16>2369 return %2 : vector<4xf16>2370}2371 2372// -----2373 2374// CHECK-LABEL: extract_insert_strided2375// CHECK-SAME: %[[A:.*]]: vector<6x4xf32>2376// CHECK: %[[V:.*]] = vector.extract %[[A]][0, 2] : f32 from vector<6x4xf32>2377// CHECK: return %[[V]] : f322378func.func @extract_insert_strided(%a: vector<6x4xf32>, %b: vector<8x16xf32>)2379 -> f32 {2380 %0 = vector.insert_strided_slice %a, %b {offsets = [2, 2], strides = [1, 1]}2381 : vector<6x4xf32> into vector<8x16xf32>2382 %2 = vector.extract %0[2, 4] : f32 from vector<8x16xf32>2383 return %2 : f322384}2385 2386// -----2387 2388// CHECK-LABEL: extract_insert_rank_reduce2389// CHECK-SAME: %[[A:.*]]: vector<4xf32>2390// CHECK: %[[V:.*]] = vector.extract %[[A]][2] : f32 from vector<4xf32>2391// CHECK: return %[[V]] : f322392func.func @extract_insert_rank_reduce(%a: vector<4xf32>, %b: vector<8x16xf32>)2393 -> f32 {2394 %0 = vector.insert_strided_slice %a, %b {offsets = [2, 2], strides = [1]}2395 : vector<4xf32> into vector<8x16xf32>2396 %2 = vector.extract %0[2, 4] : f32 from vector<8x16xf32>2397 return %2 : f322398}2399 2400// -----2401 2402// CHECK-LABEL: negative_extract_insert2403// CHECK: vector.insert_strided_slice2404// CHECK: vector.extract2405func.func @negative_extract_insert(%a: vector<2x15xf32>, %b: vector<12x8x16xf32>)2406 -> vector<16xf32> {2407 %0 = vector.insert_strided_slice %a, %b {offsets = [4, 2, 0], strides = [1, 1]}2408 : vector<2x15xf32> into vector<12x8x16xf32>2409 %2 = vector.extract %0[4, 2] : vector<16xf32> from vector<12x8x16xf32>2410 return %2 : vector<16xf32>2411}2412 2413// -----2414 2415// CHECK-LABEL: extract_insert_chain2416// CHECK-SAME: (%[[A:.*]]: vector<2x16xf32>, %[[B:.*]]: vector<12x8x16xf32>, %[[C:.*]]: vector<2x16xf32>)2417// CHECK: %[[V:.*]] = vector.extract %[[C]][0] : vector<16xf32> from vector<2x16xf32>2418// CHECK: return %[[V]] : vector<16xf32>2419func.func @extract_insert_chain(%a: vector<2x16xf32>, %b: vector<12x8x16xf32>, %c: vector<2x16xf32>)2420 -> vector<16xf32> {2421 %0 = vector.insert_strided_slice %c, %b {offsets = [4, 2, 0], strides = [1, 1]}2422 : vector<2x16xf32> into vector<12x8x16xf32>2423 %1 = vector.insert_strided_slice %a, %0 {offsets = [0, 2, 0], strides = [1, 1]}2424 : vector<2x16xf32> into vector<12x8x16xf32>2425 %2 = vector.extract %1[4, 2] : vector<16xf32> from vector<12x8x16xf32>2426 return %2 : vector<16xf32>2427}2428 2429// -----2430 2431// CHECK-LABEL: extract_from_extract_chain_should_not_fold_dynamic_extracts2432// CHECK-SAME: (%[[VEC:.*]]: vector<2x4xf32>, %[[IDX:.*]]: index)2433// CHECK: %[[A:.*]] = vector.extract %[[VEC]][%[[IDX]]] : vector<4xf32> from vector<2x4xf32>2434// CHECK: %[[B:.*]] = vector.extract %[[A]][1] : f32 from vector<4xf32>2435func.func @extract_from_extract_chain_should_not_fold_dynamic_extracts(%v: vector<2x4xf32>, %index: index) -> f32 {2436 %0 = vector.extract %v[%index] : vector<4xf32> from vector<2x4xf32>2437 %1 = vector.extract %0[1] : f32 from vector<4xf32>2438 return %1 : f322439}2440 2441// -----2442 2443// CHECK-LABEL: extract_extract_strided22444// CHECK-SAME: %[[A:.*]]: vector<2x4xf32>2445// CHECK: %[[V:.*]] = vector.extract %[[A]][1] : vector<4xf32> from vector<2x4xf32>2446// CHECK: return %[[V]] : vector<4xf32>2447func.func @extract_extract_strided2(%A: vector<2x4xf32>)2448 -> (vector<4xf32>) {2449 %0 = vector.extract_strided_slice %A {offsets = [1, 0], sizes = [1, 4], strides = [1, 1]} : vector<2x4xf32> to vector<1x4xf32>2450 %1 = vector.extract %0[0] : vector<4xf32> from vector<1x4xf32>2451 return %1 : vector<4xf32>2452}2453 2454// -----2455 2456// CHECK-LABEL: func @splatlike_fold2457// CHECK-NEXT: [[V:%.*]] = arith.constant dense<1.000000e+00> : vector<4xf32>2458// CHECK-NEXT: return [[V]] : vector<4xf32>2459func.func @splatlike_fold() -> vector<4xf32> {2460 %c = arith.constant 1.0 : f322461 %v = vector.broadcast %c : f32 to vector<4xf32>2462 return %v : vector<4xf32>2463 2464}2465 2466// -----2467 2468// CHECK-LABEL: func @shuffle_1d2469// CHECK: %[[V:.+]] = arith.constant dense<[3, 2, 5, 1]> : vector<4xi32>2470// CHECK: return %[[V]]2471func.func @shuffle_1d() -> vector<4xi32> {2472 %v0 = arith.constant dense<[0, 1, 2]> : vector<3xi32>2473 %v1 = arith.constant dense<[3, 4, 5]> : vector<3xi32>2474 %shuffle = vector.shuffle %v0, %v1 [3, 2, 5, 1] : vector<3xi32>, vector<3xi32>2475 return %shuffle : vector<4xi32>2476}2477 2478// -----2479 2480// Ensure shuffle dense resource elements not crash.2481 2482// CHECK-LABEL: func.func @shuffle_1d_dense_resource2483// CHECK: vector.shuffle2484func.func @shuffle_1d_dense_resource() -> vector<4xi32> {2485 %v0 = arith.constant dense_resource<__elided__> : vector<3xi32>2486 %v1 = arith.constant dense_resource<__elided__> : vector<3xi32>2487 %shuffle = vector.shuffle %v0, %v1 [3, 2, 5, 1] : vector<3xi32>, vector<3xi32>2488 return %shuffle : vector<4xi32>2489}2490 2491// -----2492 2493// Check that poison indices pick the first element of the first non-poison2494// input vector. That is, %v[0] (i.e., 5) in this test.2495 2496// CHECK-LABEL: func @shuffle_1d_poison_idx2497// CHECK: %[[V:.+]] = arith.constant dense<[13, 10, 15, 10]> : vector<4xi32>2498// CHECK: return %[[V]]2499func.func @shuffle_1d_poison_idx() -> vector<4xi32> {2500 %v0 = arith.constant dense<[10, 11, 12]> : vector<3xi32>2501 %v1 = arith.constant dense<[13, 14, 15]> : vector<3xi32>2502 %shuffle = vector.shuffle %v0, %v1 [3, -1, 5, -1] : vector<3xi32>, vector<3xi32>2503 return %shuffle : vector<4xi32>2504}2505 2506// -----2507 2508// CHECK-LABEL: func @shuffle_1d_rhs_lhs_poison2509// CHECK-NOT: vector.shuffle2510// CHECK: %[[V:.+]] = ub.poison : vector<4xi32>2511// CHECK: return %[[V]]2512func.func @shuffle_1d_rhs_lhs_poison() -> vector<4xi32> {2513 %v0 = ub.poison : vector<3xi32>2514 %v1 = ub.poison : vector<3xi32>2515 %shuffle = vector.shuffle %v0, %v1 [3, 1, 5, 4] : vector<3xi32>, vector<3xi32>2516 return %shuffle : vector<4xi32>2517}2518 2519// -----2520 2521// CHECK-LABEL: func @shuffle_1d_lhs_poison2522// CHECK-NOT: vector.shuffle2523// CHECK: %[[V:.+]] = arith.constant dense<[11, 12, 11, 11]> : vector<4xi32>2524// CHECK: return %[[V]]2525func.func @shuffle_1d_lhs_poison() -> vector<4xi32> {2526 %v0 = arith.constant dense<[11, 12, 13]> : vector<3xi32>2527 %v1 = ub.poison : vector<3xi32>2528 %shuffle = vector.shuffle %v0, %v1 [3, 1, 5, 4] : vector<3xi32>, vector<3xi32>2529 return %shuffle : vector<4xi32>2530}2531 2532// -----2533 2534// CHECK-LABEL: func @shuffle_1d_rhs_poison2535// CHECK-NOT: vector.shuffle2536// CHECK: %[[V:.+]] = arith.constant dense<[11, 11, 13, 12]> : vector<4xi32>2537// CHECK: return %[[V]]2538func.func @shuffle_1d_rhs_poison() -> vector<4xi32> {2539 %v0 = ub.poison : vector<3xi32>2540 %v1 = arith.constant dense<[11, 12, 13]> : vector<3xi32>2541 %shuffle = vector.shuffle %v0, %v1 [3, 1, 5, 4] : vector<3xi32>, vector<3xi32>2542 return %shuffle : vector<4xi32>2543}2544 2545// -----2546 2547// CHECK-LABEL: func @shuffle_canonicalize_0d2548func.func @shuffle_canonicalize_0d(%v0 : vector<i32>, %v1 : vector<i32>) -> vector<1xi32> {2549 // CHECK: vector.broadcast %{{.*}} : vector<i32> to vector<1xi32>2550 %shuffle = vector.shuffle %v0, %v1 [0] : vector<i32>, vector<i32>2551 return %shuffle : vector<1xi32>2552}2553 2554// -----2555 2556// CHECK-LABEL: func @shuffle_fold12557// CHECK: %arg0 : vector<4xi32>2558func.func @shuffle_fold1(%v0 : vector<4xi32>, %v1 : vector<2xi32>) -> vector<4xi32> {2559 %shuffle = vector.shuffle %v0, %v1 [0, 1, 2, 3] : vector<4xi32>, vector<2xi32>2560 return %shuffle : vector<4xi32>2561}2562 2563// -----2564 2565// CHECK-LABEL: func @shuffle_fold22566// CHECK: %arg1 : vector<2xi32>2567func.func @shuffle_fold2(%v0 : vector<4xi32>, %v1 : vector<2xi32>) -> vector<2xi32> {2568 %shuffle = vector.shuffle %v0, %v1 [4, 5] : vector<4xi32>, vector<2xi32>2569 return %shuffle : vector<2xi32>2570}2571 2572// -----2573 2574// CHECK-LABEL: func @shuffle_fold32575// CHECK: return %arg0 : vector<4x5x6xi32>2576func.func @shuffle_fold3(%v0 : vector<4x5x6xi32>, %v1 : vector<2x5x6xi32>) -> vector<4x5x6xi32> {2577 %shuffle = vector.shuffle %v0, %v1 [0, 1, 2, 3] : vector<4x5x6xi32>, vector<2x5x6xi32>2578 return %shuffle : vector<4x5x6xi32>2579}2580 2581// -----2582 2583// CHECK-LABEL: func @shuffle_fold42584// CHECK: return %arg1 : vector<2x5x6xi32>2585func.func @shuffle_fold4(%v0 : vector<4x5x6xi32>, %v1 : vector<2x5x6xi32>) -> vector<2x5x6xi32> {2586 %shuffle = vector.shuffle %v0, %v1 [4, 5] : vector<4x5x6xi32>, vector<2x5x6xi32>2587 return %shuffle : vector<2x5x6xi32>2588}2589 2590// -----2591 2592// CHECK-LABEL: func @shuffle_nofold12593// CHECK: %[[V:.+]] = vector.shuffle %arg0, %arg1 [0, 1, 2, 3, 4] : vector<4xi32>, vector<2xi32>2594// CHECK: return %[[V]]2595func.func @shuffle_nofold1(%v0 : vector<4xi32>, %v1 : vector<2xi32>) -> vector<5xi32> {2596 %shuffle = vector.shuffle %v0, %v1 [0, 1, 2, 3, 4] : vector<4xi32>, vector<2xi32>2597 return %shuffle : vector<5xi32>2598}2599 2600// -----2601 2602// CHECK-LABEL: func @transpose_splatlike_constant2603// CHECK: %[[CST:.+]] = arith.constant dense<5.000000e+00> : vector<8x4xf32>2604// CHECK: return %[[CST]]2605func.func @transpose_splatlike_constant() -> vector<8x4xf32> {2606 %cst = arith.constant dense<5.0> : vector<4x8xf32>2607 %0 = vector.transpose %cst, [1, 0] : vector<4x8xf32> to vector<8x4xf32>2608 return %0 : vector<8x4xf32>2609}2610 2611// -----2612 2613// CHECK-LABEL: func @transpose_splatlike2(2614// CHECK-SAME: %[[VAL_0:.*]]: f32) -> vector<3x4xf32> {2615// CHECK: %[[VAL_1:.*]] = vector.broadcast %[[VAL_0]] : f32 to vector<3x4xf32>2616// CHECK: return %[[VAL_1]] : vector<3x4xf32>2617// CHECK: }2618func.func @transpose_splatlike2(%arg : f32) -> vector<3x4xf32> {2619 %splat = vector.broadcast %arg : f32 to vector<4x3xf32>2620 %0 = vector.transpose %splat, [1, 0] : vector<4x3xf32> to vector<3x4xf32>2621 return %0 : vector<3x4xf32>2622}2623 2624// -----2625 2626// CHECK-LABEL: transpose_poison2627// CHECK: %[[POISON:.*]] = ub.poison : vector<4x6xi8>2628// CHECK: return %[[POISON]] : vector<4x6xi8>2629func.func @transpose_poison() -> vector<4x6xi8> {2630 %poison = ub.poison : vector<6x4xi8>2631 %transpose = vector.transpose %poison, [1, 0] : vector<6x4xi8> to vector<4x6xi8>2632 return %transpose : vector<4x6xi8>2633}2634 2635// -----2636 2637// CHECK-LABEL: func.func @insert_1d_constant2638// CHECK-DAG: %[[ACST:.*]] = arith.constant dense<[9, 1, 2]> : vector<3xi32>2639// CHECK-DAG: %[[BCST:.*]] = arith.constant dense<[0, 9, 2]> : vector<3xi32>2640// CHECK-DAG: %[[CCST:.*]] = arith.constant dense<[0, 1, 9]> : vector<3xi32>2641// CHECK-NEXT: return %[[ACST]], %[[BCST]], %[[CCST]] : vector<3xi32>, vector<3xi32>, vector<3xi32>2642func.func @insert_1d_constant() -> (vector<3xi32>, vector<3xi32>, vector<3xi32>) {2643 %vcst = arith.constant dense<[0, 1, 2]> : vector<3xi32>2644 %icst = arith.constant 9 : i322645 %a = vector.insert %icst, %vcst[0] : i32 into vector<3xi32>2646 %b = vector.insert %icst, %vcst[1] : i32 into vector<3xi32>2647 %c = vector.insert %icst, %vcst[2] : i32 into vector<3xi32>2648 return %a, %b, %c : vector<3xi32>, vector<3xi32>, vector<3xi32>2649}2650 2651// -----2652 2653// CHECK-LABEL: func.func @insert_2d_constant2654// CHECK-DAG: %[[ACST:.*]] = arith.constant dense<{{\[\[99, 1, 2\], \[3, 4, 5\]\]}}> : vector<2x3xi32>2655// CHECK-DAG: %[[BCST:.*]] = arith.constant dense<{{\[\[0, 1, 2\], \[3, 4, 99\]\]}}> : vector<2x3xi32>2656// CHECK-DAG: %[[CCST:.*]] = arith.constant dense<{{\[\[90, 91, 92\], \[3, 4, 5\]\]}}> : vector<2x3xi32>2657// CHECK-DAG: %[[DCST:.*]] = arith.constant dense<{{\[\[0, 1, 2\], \[90, 91, 92\]\]}}> : vector<2x3xi32>2658// CHECK-NEXT: return %[[ACST]], %[[BCST]], %[[CCST]], %[[DCST]]2659func.func @insert_2d_constant() -> (vector<2x3xi32>, vector<2x3xi32>, vector<2x3xi32>, vector<2x3xi32>) {2660 %vcst = arith.constant dense<[[0, 1, 2], [3, 4, 5]]> : vector<2x3xi32>2661 %cst_scalar = arith.constant 99 : i322662 %cst_1d = arith.constant dense<[90, 91, 92]> : vector<3xi32>2663 %a = vector.insert %cst_scalar, %vcst[0, 0] : i32 into vector<2x3xi32>2664 %b = vector.insert %cst_scalar, %vcst[1, 2] : i32 into vector<2x3xi32>2665 %c = vector.insert %cst_1d, %vcst[0] : vector<3xi32> into vector<2x3xi32>2666 %d = vector.insert %cst_1d, %vcst[1] : vector<3xi32> into vector<2x3xi32>2667 return %a, %b, %c, %d : vector<2x3xi32>, vector<2x3xi32>, vector<2x3xi32>, vector<2x3xi32>2668}2669 2670// -----2671 2672// +---------------------------------------------------------------------------2673// Tests for InsertChainFullyInitialized .2674// +---------------------------------------------------------------------------2675// This pattern should fire when all vector elements are overwritten by vector.insert2676// at static positions, replacing the insert chain with vector.from_elements.2677// CHECK-LABEL: func.func @fully_insert_scalar_to_vector(2678// CHECK-SAME: %[[DEST:.+]]: vector<2xi64>, %[[SRC1:.+]]: i64, %[[SRC2:.+]]: i64)2679// CHECK: %[[RES:.+]] = vector.from_elements %[[SRC1]], %[[SRC2]] : vector<2xi64>2680// CHECK-NEXT: return %[[RES]]2681func.func @fully_insert_scalar_to_vector(%dest : vector<2xi64>, %src1 : i64, %src2 : i64) -> vector<2xi64> {2682 %v1 = vector.insert %src1, %dest[0] : i64 into vector<2xi64>2683 %v2 = vector.insert %src2, %v1[1] : i64 into vector<2xi64>2684 return %v2 : vector<2xi64>2685}2686 2687// -----2688 2689// Same as the above test, but with vector insertions.2690// CHECK-LABEL: func.func @fully_insert_vector_to_vector(2691// CHECK-SAME: %[[DEST:.+]]: vector<2x2xi64>, %[[SRC1:.+]]: vector<2xi64>, %[[SRC2:.+]]: vector<2xi64>)2692// CHECK: %[[ELE1:.+]]:2 = vector.to_elements %[[SRC1]] : vector<2xi64>2693// CHECK: %[[ELE2:.+]]:2 = vector.to_elements %[[SRC2]] : vector<2xi64>2694// CHECK: %[[RES:.+]] = vector.from_elements %[[ELE1]]#0, %[[ELE1]]#1, %[[ELE2]]#0, %[[ELE2]]#1 : vector<2x2xi64>2695// CHECK-NEXT: return %[[RES]]2696func.func @fully_insert_vector_to_vector(%dest : vector<2x2xi64>, %src1 : vector<2xi64>, %src2 : vector<2xi64>) -> vector<2x2xi64> {2697 %v1 = vector.insert %src1, %dest[0] : vector<2xi64> into vector<2x2xi64>2698 %v2 = vector.insert %src2, %v1[1] : vector<2xi64> into vector<2x2xi64>2699 return %v2 : vector<2x2xi64>2700}2701 2702// -----2703 2704// Test InsertChainFullyInitialized pattern with overlapping insertions.2705// 1. The first op inserts %src2 at [0,0].2706// 2. The second op inserts %src1 at [0,0], [0,1], overwriting %src2 at [0,0].2707// 3. The third op inserts %src1 at [1,0], [1,1].2708// 4. The fourth op inserts %src2 at [1,1], overwriting the existing value at [1,1].2709// CHECK-LABEL: func.func @fully_insert_to_vector_overlap_1(2710// CHECK-SAME: %[[DEST:.+]]: vector<2x2xi64>, %[[SRC1:.+]]: vector<2xi64>, %[[SRC2:.+]]: i64)2711// CHECK: %[[ELE1:.+]]:2 = vector.to_elements %[[SRC1]] : vector<2xi64>2712// CHECK: %[[ELE2:.+]]:2 = vector.to_elements %[[SRC1]] : vector<2xi64>2713// CHECK: %[[RES:.+]] = vector.from_elements %[[ELE1]]#0, %[[ELE1]]#1, %[[ELE2]]#0, %[[SRC2]] : vector<2x2xi64>2714// CHECK-NEXT: return %[[RES]]2715func.func @fully_insert_to_vector_overlap_1(%dest : vector<2x2xi64>, %src1 : vector<2xi64>, %src2 : i64) -> vector<2x2xi64> {2716 %v0 = vector.insert %src2, %dest[0, 0] : i64 into vector<2x2xi64>2717 %v1 = vector.insert %src1, %v0[0] : vector<2xi64> into vector<2x2xi64>2718 %v2 = vector.insert %src1, %v1[1] : vector<2xi64> into vector<2x2xi64>2719 %v3 = vector.insert %src2, %v2[1, 1] : i64 into vector<2x2xi64>2720 return %v3 : vector<2x2xi64>2721}2722 2723// -----2724 2725// Test InsertChainFullyInitialized pattern with overlapping insertions.2726// The vector inserted at last should overwrite the previously inserted scalars.2727// CHECK-LABEL: func.func @fully_insert_to_vector_overlap_2(2728// CHECK-SAME: %[[DEST:.+]]: vector<2x2xi64>, %[[SRC1:.+]]: i64, %[[SRC2:.+]]: i64, %[[SRC3:.+]]: vector<2xi64>, %[[SRC4:.+]]: vector<2xi64>)2729// CHECK: %[[ELE1:.+]]:2 = vector.to_elements %[[SRC3]] : vector<2xi64>2730// CHECK: %[[ELE2:.+]]:2 = vector.to_elements %[[SRC4]] : vector<2xi64>2731// CHECK: %[[RES:.+]] = vector.from_elements %[[ELE1]]#0, %[[ELE1]]#1, %[[ELE2]]#0, %[[ELE2]]#1 : vector<2x2xi64>2732// CHECK-NEXT: return %[[RES]]2733func.func @fully_insert_to_vector_overlap_2(%dest : vector<2x2xi64>, %src1 : i64, %src2 : i64, %src3 : vector<2xi64>, %src4 : vector<2xi64>) -> vector<2x2xi64> {2734 %v0 = vector.insert %src1, %dest[0, 0] : i64 into vector<2x2xi64>2735 %v1 = vector.insert %src2, %v0[0, 1] : i64 into vector<2x2xi64>2736 %v2 = vector.insert %src3, %v1[0] : vector<2xi64> into vector<2x2xi64>2737 %v3 = vector.insert %src4, %v2[1] : vector<2xi64> into vector<2x2xi64>2738 return %v3 : vector<2x2xi64>2739}2740 2741// -----2742 2743// Negative test for InsertChainFullyInitialized pattern when only some elements are overwritten.2744// CHECK-LABEL: func.func @negative_partially_insert_vector_to_vector(2745// CHECK-SAME: %[[DEST:.+]]: vector<2x2xi64>, %[[SRC1:.+]]: vector<2xi64>, %[[SRC2:.+]]: i64)2746// CHECK: %[[V0:.+]] = vector.insert %[[SRC1]], %[[DEST]] [0] : vector<2xi64> into vector<2x2xi64>2747// CHECK: %[[V1:.+]] = vector.insert %[[SRC2]], %[[V0]] [0, 0] : i64 into vector<2x2xi64>2748// CHECK: return %[[V1]]2749func.func @negative_partially_insert_vector_to_vector(%dest : vector<2x2xi64>, %src1 : vector<2xi64>, %src2 : i64) -> vector<2x2xi64> {2750 %v1 = vector.insert %src1, %dest[0] : vector<2xi64> into vector<2x2xi64>2751 %v2 = vector.insert %src2, %v1[0, 0] : i64 into vector<2x2xi64>2752 return %v2 : vector<2x2xi64>2753}2754 2755// -----2756 2757// Negative test when intermediate results have more than one user.2758// CHECK-LABEL: func.func @negative_intermediate_insert_multiple_users(2759// CHECK-SAME: %[[DEST:.+]]: vector<3xi64>, %[[SRC1:.+]]: i64, %[[SRC2:.+]]: i64, %[[SRC3:.+]]: i64, %[[SRC4:.+]]: i64)2760// CHECK: %[[V0:.+]] = vector.insert %[[SRC1]], %[[DEST]] [0] : i64 into vector<3xi64>2761// CHECK: %[[V1:.+]] = vector.insert %[[SRC2]], %[[V0]] [1] : i64 into vector<3xi64>2762// CHECK: %[[V2:.+]] = vector.insert %[[SRC3]], %[[V1]] [2] : i64 into vector<3xi64>2763// CHECK: %[[V3:.+]] = vector.insert %[[SRC4]], %[[V1]] [2] : i64 into vector<3xi64>2764func.func @negative_intermediate_insert_multiple_users(%dest : vector<3xi64>, %src1 : i64, %src2 : i64, %src3 : i64, %src4 : i64) -> (vector<3xi64>, vector<3xi64>) {2765 %v1 = vector.insert %src1, %dest[0] : i64 into vector<3xi64>2766 %v2 = vector.insert %src2, %v1[1] : i64 into vector<3xi64>2767 %v3_0 = vector.insert %src3, %v2[2] : i64 into vector<3xi64>2768 %v3_1 = vector.insert %src4, %v2[2] : i64 into vector<3xi64>2769 return %v3_0, %v3_1 : vector<3xi64>, vector<3xi64>2770}2771 2772// +---------------------------------------------------------------------------2773// End of Tests For InsertChainFullyInitialized.2774// +---------------------------------------------------------------------------2775 2776// -----2777 2778// CHECK-LABEL: func.func @insert_2d_splat_constant2779// CHECK-DAG: %[[ACST:.*]] = arith.constant dense<0> : vector<2x3xi32>2780// CHECK-DAG: %[[BCST:.*]] = arith.constant dense<{{\[\[99, 0, 0\], \[0, 0, 0\]\]}}> : vector<2x3xi32>2781// CHECK-DAG: %[[CCST:.*]] = arith.constant dense<{{\[\[0, 0, 0\], \[0, 99, 0\]\]}}> : vector<2x3xi32>2782// CHECK-DAG: %[[DCST:.*]] = arith.constant dense<{{\[\[33, 33, 33\], \[0, 0, 0\]\]}}> : vector<2x3xi32>2783// CHECK-DAG: %[[ECST:.*]] = arith.constant dense<{{\[\[0, 0, 0\], \[33, 33, 33\]\]}}> : vector<2x3xi32>2784// CHECK-NEXT: return %[[ACST]], %[[BCST]], %[[CCST]], %[[DCST]], %[[ECST]]2785func.func @insert_2d_splat_constant()2786 -> (vector<2x3xi32>, vector<2x3xi32>, vector<2x3xi32>, vector<2x3xi32>, vector<2x3xi32>) {2787 %vcst = arith.constant dense<0> : vector<2x3xi32>2788 %cst_zero = arith.constant 0 : i322789 %cst_scalar = arith.constant 99 : i322790 %cst_1d = arith.constant dense<33> : vector<3xi32>2791 %a = vector.insert %cst_zero, %vcst[0, 0] : i32 into vector<2x3xi32>2792 %b = vector.insert %cst_scalar, %vcst[0, 0] : i32 into vector<2x3xi32>2793 %c = vector.insert %cst_scalar, %vcst[1, 1] : i32 into vector<2x3xi32>2794 %d = vector.insert %cst_1d, %vcst[0] : vector<3xi32> into vector<2x3xi32>2795 %e = vector.insert %cst_1d, %vcst[1] : vector<3xi32> into vector<2x3xi32>2796 return %a, %b, %c, %d, %e : vector<2x3xi32>, vector<2x3xi32>, vector<2x3xi32>, vector<2x3xi32>, vector<2x3xi32>2797}2798 2799// -----2800 2801// CHECK-LABEL: func @reduce_one_element_vector_extract2802// CHECK-SAME: (%[[V:.+]]: vector<1xf32>)2803// CHECK: %[[S:.+]] = vector.extract %[[V]][0] : f32 from vector<1xf32>2804// CHECK: return %[[S]] : f322805func.func @reduce_one_element_vector_extract(%a : vector<1xf32>) -> f32 {2806 %s = vector.reduction <add>, %a : vector<1xf32> into f322807 return %s : f322808}2809 2810// -----2811 2812// CHECK-LABEL: func @masked_reduce_one_element_vector_extract2813// CHECK-SAME: %[[VAL_0:.*]]: vector<1xf32>, %[[VAL_1:.*]]: vector<1xi1>)2814func.func @masked_reduce_one_element_vector_extract(%a : vector<1xf32>, %mask : vector<1xi1>) -> f32 {2815// CHECK: %[[VAL_2:.*]] = vector.extract %[[VAL_0]][0] : f32 from vector<1xf32>2816 %s = vector.mask %mask { vector.reduction <add>, %a : vector<1xf32> into f32 }2817 : vector<1xi1> -> f322818 return %s : f322819}2820 2821// -----2822 2823// CHECK-LABEL: func @reduce_one_element_vector_addf2824// CHECK-SAME: (%[[V:.+]]: vector<1xf32>, %[[B:.+]]: f32)2825// CHECK: %[[A:.+]] = vector.extract %[[V]][0] : f32 from vector<1xf32>2826// CHECK: %[[S:.+]] = arith.addf %[[A]], %arg1 : f322827// CHECK: return %[[S]]2828func.func @reduce_one_element_vector_addf(%a : vector<1xf32>, %b: f32) -> f32 {2829 %s = vector.reduction <add>, %a, %b : vector<1xf32> into f322830 return %s : f322831}2832 2833// -----2834 2835// CHECK-LABEL: func @reduce_one_element_vector_addf_fastmath2836// CHECK-SAME: (%[[V:.+]]: vector<1xf32>, %[[B:.+]]: f32)2837// CHECK: %[[A:.+]] = vector.extract %[[V]][0] : f32 from vector<1xf32>2838// CHECK: %[[S:.+]] = arith.addf %[[A]], %arg1 fastmath<nnan,ninf> : f322839// CHECK: return %[[S]]2840func.func @reduce_one_element_vector_addf_fastmath(%a : vector<1xf32>, %b: f32) -> f32 {2841 %s = vector.reduction <add>, %a, %b fastmath<nnan,ninf> : vector<1xf32> into f322842 return %s : f322843}2844 2845// -----2846 2847// CHECK-LABEL: func @masked_reduce_one_element_vector_addf2848// CHECK-SAME: %[[VAL_0:.*]]: vector<1xf32>, %[[VAL_1:.*]]: f32,2849// CHECK-SAME: %[[VAL_2:.*]]: vector<1xi1>)2850func.func @masked_reduce_one_element_vector_addf(%a: vector<1xf32>,2851 %b: f32,2852 %mask: vector<1xi1>) -> f32 {2853// CHECK: %[[VAL_3:.*]] = vector.extract %[[VAL_2]][0] : i1 from vector<1xi1>2854// CHECK: %[[VAL_4:.*]] = vector.extract %[[VAL_0]][0] : f32 from vector<1xf32>2855// CHECK: %[[VAL_5:.*]] = arith.addf %[[VAL_4]], %[[VAL_1]] : f322856// CHECK: %[[VAL_6:.*]] = arith.select %[[VAL_3]], %[[VAL_5]], %[[VAL_1]] : f322857 %s = vector.mask %mask { vector.reduction <add>, %a, %b : vector<1xf32> into f32 }2858 : vector<1xi1> -> f322859 return %s : f322860}2861 2862// -----2863 2864// CHECK-LABEL: func @reduce_one_element_vector_mulf2865// CHECK-SAME: (%[[V:.+]]: vector<1xf32>, %[[B:.+]]: f32)2866// CHECK: %[[A:.+]] = vector.extract %[[V]][0] : f32 from vector<1xf32>2867// CHECK: %[[S:.+]] = arith.mulf %[[A]], %arg1 : f322868// CHECK: return %[[S]]2869func.func @reduce_one_element_vector_mulf(%a : vector<1xf32>, %b: f32) -> f32 {2870 %s = vector.reduction <mul>, %a, %b : vector<1xf32> into f322871 return %s : f322872}2873 2874// -----2875 2876// CHECK-LABEL: func @dont_reduce_one_element_vector2877// CHECK: vector.reduction2878func.func @dont_reduce_one_element_vector(%a : vector<4xf32>) -> f32 {2879 %s = vector.reduction <add>, %a : vector<4xf32> into f322880 return %s : f322881}2882 2883// -----2884 2885// CHECK-LABEL: func @reduce_one_element_vector_maximumf2886// CHECK-SAME: (%[[V:.+]]: vector<1xf32>, %[[B:.+]]: f32)2887// CHECK: %[[A:.+]] = vector.extract %[[V]][0] : f32 from vector<1xf32>2888// CHECK: %[[S:.+]] = arith.maximumf %[[A]], %[[B]] : f322889// CHECK: return %[[S]]2890func.func @reduce_one_element_vector_maximumf(%a : vector<1xf32>, %b: f32) -> f32 {2891 %s = vector.reduction <maximumf>, %a, %b : vector<1xf32> into f322892 return %s : f322893}2894 2895// -----2896 2897// CHECK-LABEL: func @bitcast(2898// CHECK-SAME: %[[ARG:.*]]: vector<4x8xf32>) -> vector<4x16xi16> {2899// CHECK: vector.bitcast %[[ARG:.*]] : vector<4x8xf32> to vector<4x16xi16>2900func.func @bitcast(%a: vector<4x8xf32>) -> vector<4x16xi16> {2901 %0 = vector.bitcast %a : vector<4x8xf32> to vector<4x8xi32>2902 %1 = vector.bitcast %0 : vector<4x8xi32> to vector<4x16xi16>2903 return %1 : vector<4x16xi16>2904}2905 2906// -----2907 2908// CHECK-LABEL: @insert_strided_slice_splatlike2909// CHECK-SAME: (%[[ARG:.*]]: f32)2910// CHECK-NEXT: %[[SPLAT:.*]] = vector.broadcast %[[ARG]] : f32 to vector<8x16xf32>2911// CHECK-NEXT: return %[[SPLAT]] : vector<8x16xf32>2912func.func @insert_strided_slice_splatlike(%x: f32) -> (vector<8x16xf32>) {2913 %splat0 = vector.broadcast %x : f32 to vector<4x4xf32>2914 %splat1 = vector.broadcast %x : f32 to vector<8x16xf32>2915 %0 = vector.insert_strided_slice %splat0, %splat1 {offsets = [2, 2], strides = [1, 1]}2916 : vector<4x4xf32> into vector<8x16xf32>2917 return %0 : vector<8x16xf32>2918}2919 2920 2921// -----2922 2923// CHECK-LABEL: @insert_extract_strided_slice2924// CHECK-SAME: (%[[ARG:.*]]: vector<8x16xf32>)2925// CHECK-NEXT: return %[[ARG]] : vector<8x16xf32>2926func.func @insert_extract_strided_slice(%x: vector<8x16xf32>) -> (vector<8x16xf32>) {2927 %0 = vector.extract_strided_slice %x {offsets = [0, 8], sizes = [2, 4], strides = [1, 1]}2928 : vector<8x16xf32> to vector<2x4xf32>2929 %1 = vector.insert_strided_slice %0, %x {offsets = [0, 8], strides = [1, 1]}2930 : vector<2x4xf32> into vector<8x16xf32>2931 return %1 : vector<8x16xf32>2932}2933 2934// -----2935 2936// CHECK-LABEL: func.func @insert_strided_1d_constant2937// CHECK-DAG: %[[ACST:.*]] = arith.constant dense<[4, 1, 2]> : vector<3xi32>2938// CHECK-DAG: %[[BCST:.*]] = arith.constant dense<[0, 1, 4]> : vector<3xi32>2939// CHECK-DAG: %[[CCST:.*]] = arith.constant dense<[5, 6, 2]> : vector<3xi32>2940// CHECK-DAG: %[[DCST:.*]] = arith.constant dense<[0, 5, 6]> : vector<3xi32>2941// CHECK-DAG: %[[ECST:.*]] = arith.constant dense<[7, 8, 9]> : vector<3xi32>2942// CHECK-NEXT: return %[[ACST]], %[[BCST]], %[[CCST]], %[[DCST]], %[[ECST]]2943func.func @insert_strided_1d_constant() ->2944 (vector<3xi32>, vector<3xi32>, vector<3xi32>, vector<3xi32>, vector<3xi32>) {2945 %vcst = arith.constant dense<[0, 1, 2]> : vector<3xi32>2946 %cst_1 = arith.constant dense<4> : vector<1xi32>2947 %cst_2 = arith.constant dense<[5, 6]> : vector<2xi32>2948 %cst_3 = arith.constant dense<[7, 8, 9]> : vector<3xi32>2949 %a = vector.insert_strided_slice %cst_1, %vcst {offsets = [0], strides = [1]} : vector<1xi32> into vector<3xi32>2950 %b = vector.insert_strided_slice %cst_1, %vcst {offsets = [2], strides = [1]} : vector<1xi32> into vector<3xi32>2951 %c = vector.insert_strided_slice %cst_2, %vcst {offsets = [0], strides = [1]} : vector<2xi32> into vector<3xi32>2952 %d = vector.insert_strided_slice %cst_2, %vcst {offsets = [1], strides = [1]} : vector<2xi32> into vector<3xi32>2953 %e = vector.insert_strided_slice %cst_3, %vcst {offsets = [0], strides = [1]} : vector<3xi32> into vector<3xi32>2954 return %a, %b, %c, %d, %e : vector<3xi32>, vector<3xi32>, vector<3xi32>, vector<3xi32>, vector<3xi32>2955}2956 2957// -----2958 2959// CHECK-LABEL: func.func @insert_strided_2d_constant2960// CHECK-DAG: %[[ACST:.*]] = arith.constant dense<{{\[\[0, 1\], \[9, 3\], \[4, 5\]\]}}> : vector<3x2xi32>2961// CHECK-DAG: %[[BCST:.*]] = arith.constant dense<{{\[\[0, 1\], \[2, 3\], \[4, 9\]\]}}> : vector<3x2xi32>2962// CHECK-DAG: %[[CCST:.*]] = arith.constant dense<{{\[\[18, 19\], \[2, 3\], \[4, 5\]\]}}> : vector<3x2xi32>2963// CHECK-DAG: %[[DCST:.*]] = arith.constant dense<{{\[\[0, 1\], \[18, 19\], \[4, 5\]\]}}> : vector<3x2xi32>2964// CHECK-DAG: %[[ECST:.*]] = arith.constant dense<{{\[\[0, 1\], \[2, 3\], \[18, 19\]\]}}> : vector<3x2xi32>2965// CHECK-DAG: %[[FCST:.*]] = arith.constant dense<{{\[\[28, 29\], \[38, 39\], \[4, 5\]\]}}> : vector<3x2xi32>2966// CHECK-DAG: %[[GCST:.*]] = arith.constant dense<{{\[\[0, 1\], \[28, 29\], \[38, 39\]\]}}> : vector<3x2xi32>2967// CHECK-NEXT: return %[[ACST]], %[[BCST]], %[[CCST]], %[[DCST]], %[[ECST]], %[[FCST]], %[[GCST]]2968func.func @insert_strided_2d_constant() ->2969 (vector<3x2xi32>, vector<3x2xi32>, vector<3x2xi32>, vector<3x2xi32>, vector<3x2xi32>, vector<3x2xi32>, vector<3x2xi32>) {2970 %vcst = arith.constant dense<[[0, 1], [2, 3], [4, 5]]> : vector<3x2xi32>2971 %cst_1 = arith.constant dense<9> : vector<1xi32>2972 %cst_2 = arith.constant dense<[18, 19]> : vector<2xi32>2973 %cst_3 = arith.constant dense<[[28, 29], [38, 39]]> : vector<2x2xi32>2974 %a = vector.insert_strided_slice %cst_1, %vcst {offsets = [1, 0], strides = [1]} : vector<1xi32> into vector<3x2xi32>2975 %b = vector.insert_strided_slice %cst_1, %vcst {offsets = [2, 1], strides = [1]} : vector<1xi32> into vector<3x2xi32>2976 %c = vector.insert_strided_slice %cst_2, %vcst {offsets = [0, 0], strides = [1]} : vector<2xi32> into vector<3x2xi32>2977 %d = vector.insert_strided_slice %cst_2, %vcst {offsets = [1, 0], strides = [1]} : vector<2xi32> into vector<3x2xi32>2978 %e = vector.insert_strided_slice %cst_2, %vcst {offsets = [2, 0], strides = [1]} : vector<2xi32> into vector<3x2xi32>2979 %f = vector.insert_strided_slice %cst_3, %vcst {offsets = [0, 0], strides = [1, 1]} : vector<2x2xi32> into vector<3x2xi32>2980 %g = vector.insert_strided_slice %cst_3, %vcst {offsets = [1, 0], strides = [1, 1]} : vector<2x2xi32> into vector<3x2xi32>2981 return %a, %b, %c, %d, %e, %f, %g :2982 vector<3x2xi32>, vector<3x2xi32>, vector<3x2xi32>, vector<3x2xi32>, vector<3x2xi32>, vector<3x2xi32>, vector<3x2xi32>2983}2984 2985// -----2986 2987// CHECK-LABEL: func @shuffle_splatlike2988// CHECK-SAME: (%[[ARG:.*]]: i32)2989// CHECK-NEXT: %[[SPLAT:.*]] = vector.broadcast %[[ARG]] : i32 to vector<4xi32>2990// CHECK-NEXT: return %[[SPLAT]] : vector<4xi32>2991func.func @shuffle_splatlike(%x : i32) -> vector<4xi32> {2992 %v0 = vector.broadcast %x : i32 to vector<4xi32>2993 %v1 = vector.broadcast %x : i32 to vector<2xi32>2994 %shuffle = vector.shuffle %v0, %v1 [2, 3, 4, 5] : vector<4xi32>, vector<2xi32>2995 return %shuffle : vector<4xi32>2996}2997 2998 2999// -----3000 3001// CHECK-LABEL: func @insert_splatlike3002// CHECK-SAME: (%[[ARG:.*]]: i32)3003// CHECK-NEXT: %[[SPLAT:.*]] = vector.broadcast %[[ARG]] : i32 to vector<2x4x3xi32>3004// CHECK-NEXT: return %[[SPLAT]] : vector<2x4x3xi32>3005func.func @insert_splatlike(%x : i32) -> vector<2x4x3xi32> {3006 %v0 = vector.broadcast %x : i32 to vector<4x3xi32>3007 %v1 = vector.broadcast %x : i32 to vector<2x4x3xi32>3008 %insert = vector.insert %v0, %v1[0] : vector<4x3xi32> into vector<2x4x3xi32>3009 return %insert : vector<2x4x3xi32>3010}3011 3012// -----3013 3014// CHECK-LABEL: func.func @transfer_read_from_rank_reducing_extract_slice3015// CHECK: tensor.extract_slice3016// CHECK: vector.transfer_read3017func.func @transfer_read_from_rank_reducing_extract_slice(%src: tensor<1x8x8x8xf32>, %i1: index, %i2: index, %i3: index, %i4: index) -> vector<4xf32> {3018 %c0 = arith.constant 0 : index3019 %f0 = arith.constant 0.000000e+00 : f323020 %0 = tensor.extract_slice %src[0, %i1, %i2, %i3] [1, 4, 1, 4] [1, 1, 1, 1] : tensor<1x8x8x8xf32> to tensor<1x4x4xf32>3021 %1 = vector.transfer_read %0[%c0, %i4, %c0], %f0 {in_bounds = [true]} : tensor<1x4x4xf32>, vector<4xf32>3022 return %1 : vector<4xf32>3023}3024 3025// -----3026 3027// CHECK-LABEL: func.func @extract_from_broadcast3028func.func @extract_from_broadcast(%src: vector<1x1x1xf32>) -> vector<1xf32> {3029 %0 = vector.broadcast %src : vector<1x1x1xf32> to vector<1x1x32x1xf32>3030 3031 // CHECK-NEXT: %0 = vector.extract {{.*}}[0, 0] : vector<1xf32> from vector<1x1x1xf32>3032 // CHECK-NEXT: return %0 : vector<1xf32>3033 %1 = vector.extract %0[0, 0, 31] : vector<1xf32> from vector<1x1x32x1xf32>3034 return %1: vector<1xf32>3035}3036 3037// CHECK-LABEL: func.func @extract_from_stretch_broadcast3038func.func @extract_from_stretch_broadcast(%src: vector<3x1x2xf32>) -> f32 {3039 // CHECK-NEXT: %0 = vector.extract {{.*}}[0, 0, 0] : f32 from vector<3x1x2xf32>3040 // CHECK-NEXT: return %0 : f323041 %0 = vector.broadcast %src : vector<3x1x2xf32> to vector<3x4x2xf32>3042 %1 = vector.extract %0[0, 2, 0] : f32 from vector<3x4x2xf32>3043 return %1: f323044}3045 3046// -----3047// CHECK-LABEL: func.func @extract_strided_slice_of_constant_mask3048func.func @extract_strided_slice_of_constant_mask() -> vector<5x7xi1>{3049 // CHECK-NEXT: %[[RES:.*]] = vector.constant_mask [5, 4] : vector<5x7xi1>3050 // CHECK-NEXT: return %[[RES]] : vector<5x7xi1>3051 %c4 = arith.constant 4 : index3052 %c10 = arith.constant 10 : index3053 %mask = vector.create_mask %c10, %c4 : vector<12x7xi1>3054 %res = vector.extract_strided_slice %mask {offsets = [3], sizes = [5], strides = [1]} : vector<12x7xi1> to vector<5x7xi1>3055 return %res : vector<5x7xi1>3056}3057 3058// -----3059 3060// CHECK-LABEL: func.func @fold_0d_vector_reduction3061func.func @fold_0d_vector_reduction(%arg0: vector<f32>) -> f32 {3062 // CHECK-NEXT: %[[RES:.*]] = vector.extract %arg{{.*}}[] : f32 from vector<f32>3063 // CHECK-NEXT: return %[[RES]] : f323064 %0 = vector.reduction <add>, %arg0 : vector<f32> into f323065 return %0 : f323066}3067 3068// -----3069 3070// CHECK-LABEL: func @empty_vector_mask3071func.func @empty_vector_mask(%mask : vector<8xi1>) {3072// CHECK-NOT: vector.mask3073 vector.mask %mask { } : vector<8xi1>3074 return3075}3076 3077// -----3078 3079// CHECK-LABEL: func @empty_vector_mask_with_return3080// CHECK-SAME: %[[IN:.*]]: vector<8xf32>3081func.func @empty_vector_mask_with_return(%a : vector<8xf32>, %mask : vector<8xi1>) -> vector<8xf32> {3082// CHECK-NOT: vector.mask3083// CHECK: return %[[IN]] : vector<8xf32>3084 %0 = vector.mask %mask { vector.yield %a : vector<8xf32> } : vector<8xi1> -> vector<8xf32>3085 return %0 : vector<8xf32>3086}3087 3088// -----3089 3090// CHECK-LABEL: func @empty_vector_mask_with_passthru3091// CHECK-SAME: %[[IN:.*]]: vector<8xf32>, %[[MASK:.*]]: vector<8xi1>, %[[PASSTHRU:.*]]: vector<8xf32>3092func.func @empty_vector_mask_with_passthru(%a : vector<8xf32>, %mask : vector<8xi1>,3093 %passthru : vector<8xf32>) -> vector<8xf32> {3094// CHECK-NOT: vector.mask3095// CHECK: %[[SEL:.*]] = arith.select %[[MASK]], %[[IN]], %[[PASSTHRU]] : vector<8xi1>, vector<8xf32>3096// CHECK: return %[[SEL]] : vector<8xf32>3097 %0 = vector.mask %mask, %passthru { vector.yield %a : vector<8xf32> } : vector<8xi1> -> vector<8xf32>3098 return %0 : vector<8xf32>3099}3100 3101// -----3102 3103// CHECK-LABEL: func @all_true_vector_mask3104// CHECK-SAME: %[[IN:.*]]: tensor<3x4xf32>3105func.func @all_true_vector_mask(%ta : tensor<3x4xf32>) -> vector<3x4xf32> {3106// CHECK-NOT: vector.mask3107// CHECK: %[[LD:.*]] = vector.transfer_read %[[IN]]3108// CHECK: return %[[LD]] : vector<3x4xf32>3109 %c0 = arith.constant 0 : index3110 %cf0 = arith.constant 0.0 : f323111 %all_true = vector.constant_mask [3, 4] : vector<3x4xi1>3112 %0 = vector.mask %all_true { vector.transfer_read %ta[%c0, %c0], %cf0 : tensor<3x4xf32>, vector<3x4xf32> } : vector<3x4xi1> -> vector<3x4xf32>3113 return %0 : vector<3x4xf32>3114}3115 3116// -----3117 3118// CHECK-LABEL: func @all_true_vector_mask_no_result(3119func.func @all_true_vector_mask_no_result(%a : vector<3x4xf32>, %m : memref<3x4xf32>) {3120// CHECK-NOT: vector.mask3121// CHECK: vector.transfer_write3122 %c0 = arith.constant 0 : index3123 %all_true = vector.constant_mask [3, 4] : vector<3x4xi1>3124 vector.mask %all_true { vector.transfer_write %a, %m[%c0, %c0] : vector<3x4xf32>, memref<3x4xf32> } : vector<3x4xi1>3125 return3126}3127 3128// -----3129 3130// CHECK-LABEL: func.func @fold_shape_cast_with_mask(3131// CHECK-SAME: %[[VAL_0:.*]]: tensor<1x?xf32>) -> vector<1x4xi1> {3132func.func @fold_shape_cast_with_mask(%arg0: tensor<1x?xf32>) -> vector<1x4xi1> {3133// CHECK-NOT: vector.shape_cast3134// CHECK: %[[VAL_1:.*]] = arith.constant 1 : index3135// CHECK: %[[VAL_2:.*]] = tensor.dim %[[VAL_0]], %[[VAL_1]] : tensor<1x?xf32>3136// CHECK: %[[VAL_3:.*]] = vector.create_mask %[[VAL_1]], %[[VAL_2]] : vector<1x4xi1>3137// CHECK: return %[[VAL_3]] : vector<1x4xi1>3138 %c1 = arith.constant 1 : index3139 %dim = tensor.dim %arg0, %c1 : tensor<1x?xf32>3140 %1 = vector.create_mask %c1, %dim, %c1, %c1 : vector<1x4x1x1xi1>3141 %2 = vector.shape_cast %1 : vector<1x4x1x1xi1> to vector<1x4xi1>3142 return %2 : vector<1x4xi1>3143}3144 3145// -----3146 3147// CHECK-LABEL: func.func @fold_shape_cast_with_mask_scalable(3148// CHECK-SAME: %[[VAL_0:.*]]: tensor<1x?xf32>) -> vector<1x[4]xi1> {3149func.func @fold_shape_cast_with_mask_scalable(%arg0: tensor<1x?xf32>) -> vector<1x[4]xi1> {3150// CHECK-NOT: vector.shape_cast3151// CHECK: %[[VAL_1:.*]] = arith.constant 1 : index3152// CHECK: %[[VAL_2:.*]] = tensor.dim %[[VAL_0]], %[[VAL_1]] : tensor<1x?xf32>3153// CHECK: %[[VAL_3:.*]] = vector.create_mask %[[VAL_1]], %[[VAL_2]] : vector<1x[4]xi1>3154// CHECK: return %[[VAL_3]] : vector<1x[4]xi1>3155 %c1 = arith.constant 1 : index3156 %dim = tensor.dim %arg0, %c1 : tensor<1x?xf32>3157 %1 = vector.create_mask %c1, %dim, %c1, %c1 : vector<1x[4]x1x1xi1>3158 %2 = vector.shape_cast %1 : vector<1x[4]x1x1xi1> to vector<1x[4]xi1>3159 return %2 : vector<1x[4]xi1>3160}3161 3162// -----3163 3164// Check that scalable "1" (i.e. [1]) is not folded3165// CHECK-LABEL: func.func @fold_shape_cast_with_mask_scalable_one(3166// CHECK-SAME: %[[VAL_0:.*]]: tensor<1x?xf32>) -> vector<1x[1]xi1> {3167func.func @fold_shape_cast_with_mask_scalable_one(%arg0: tensor<1x?xf32>) -> vector<1x[1]xi1>{3168// CHECK: %[[VAL_1:.*]] = arith.constant 1 : index3169// CHECK: %[[VAL_2:.*]] = tensor.dim %[[VAL_0]], %[[VAL_1]] : tensor<1x?xf32>3170// CHECK: %[[VAL_3:.*]] = vector.create_mask %[[VAL_1]], %[[VAL_2]] : vector<1x[1]xi1>3171// CHECK: return %[[VAL_3]] : vector<1x[1]xi1>3172 %c1 = arith.constant 1 : index3173 %dim = tensor.dim %arg0, %c1 : tensor<1x?xf32>3174 %1 = vector.create_mask %c1, %dim, %c1 : vector<1x[1]x1xi1>3175 %2 = vector.shape_cast %1 : vector<1x[1]x1xi1> to vector<1x[1]xi1>3176 return %2 : vector<1x[1]xi1>3177}3178 3179// -----3180 3181// CHECK-LABEL: func.func @fold_shape_cast_with_constant_mask() -> vector<4xi1> {3182func.func @fold_shape_cast_with_constant_mask() -> vector<4xi1>{3183// CHECK-NOT: vector.shape_cast3184// CHECK: %[[VAL_0:.*]] = vector.constant_mask [1] : vector<4xi1>3185// CHECK: return %[[VAL_0]] : vector<4xi1>3186 %1 = vector.constant_mask [1, 1, 1] : vector<4x1x1xi1>3187 %2 = vector.shape_cast %1 : vector<4x1x1xi1> to vector<4xi1>3188 return %2 : vector<4xi1>3189}3190 3191// -----3192 3193// TODO: This IR could be canonicalized but the canonicalization pattern is not3194// smart enough. For now, just make sure that we do not crash.3195 3196// CHECK-LABEL: func.func @load_store_forwarding_rank_mismatch(3197// CHECK: vector.transfer_write3198// CHECK: vector.transfer_read3199func.func @load_store_forwarding_rank_mismatch(%v0: vector<4x1x1xf32>, %arg0: tensor<4x4x4xf32>) -> (vector<1x100x4x5xf32>) {3200 %c0 = arith.constant 0 : index3201 %cf0 = arith.constant 0.0 : f323202 // d0 is explicitly written.3203 %w0 = vector.transfer_write %v0, %arg0[%c0, %c0, %c0]3204 {in_bounds = [true, true, true],3205 permutation_map = affine_map<(d0, d1, d2) -> (d2, d1, d0)>} :3206 vector<4x1x1xf32>, tensor<4x4x4xf32>3207 // d0 is implicitly read (rank-reduction of unit dim).3208 %r = vector.transfer_read %w0[%c0, %c0, %c0], %cf03209 {in_bounds = [true, true, true, true],3210 permutation_map = affine_map<(d0, d1, d2) -> (d1, 0, d2, 0)>} :3211 tensor<4x4x4xf32>, vector<1x100x4x5xf32>3212 return %r : vector<1x100x4x5xf32>3213}3214 3215// -----3216 3217// CHECK-LABEL: func.func @rank_0_shuffle_to_interleave(3218// CHECK-SAME: %[[LHS:.*]]: vector<f64>, %[[RHS:.*]]: vector<f64>)3219func.func @rank_0_shuffle_to_interleave(%arg0: vector<f64>, %arg1: vector<f64>) -> vector<2xf64> {3220 // CHECK: %[[ZIP:.*]] = vector.interleave %[[LHS]], %[[RHS]] : vector<f64> -> vector<2xf64>3221 // CHECK: return %[[ZIP]]3222 %0 = vector.shuffle %arg0, %arg1 [0, 1] : vector<f64>, vector<f64>3223 return %0 : vector<2xf64>3224}3225 3226// -----3227 3228// CHECK-LABEL: func.func @rank_1_shuffle_to_interleave(3229// CHECK-SAME: %[[LHS:.*]]: vector<6xi32>, %[[RHS:.*]]: vector<6xi32>)3230func.func @rank_1_shuffle_to_interleave(%arg0: vector<6xi32>, %arg1: vector<6xi32>) -> vector<12xi32> {3231 // CHECK: %[[ZIP:.*]] = vector.interleave %[[LHS]], %[[RHS]] : vector<6xi32> -> vector<12xi32>3232 // CHECK: return %[[ZIP]]3233 %0 = vector.shuffle %arg0, %arg1 [0, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11] : vector<6xi32>, vector<6xi32>3234 return %0 : vector<12xi32>3235}3236 3237// -----3238 3239// CHECK-LABEL: func @extract_from_splatlike_broadcast(3240// CHECK-SAME: %[[A:.*]]: f32, %[[B:.*]]: vector<f32>, %[[C:.*]]: vector<2xf32>)3241func.func @extract_from_splatlike_broadcast(%a: f32, %b: vector<f32>, %c: vector<2xf32>) -> (f32, f32, f32, f32, vector<6x7xf32>, vector<3xf32>) {3242 // Broadcast scalar to 0D and extract scalar.3243 %0 = vector.broadcast %a : f32 to vector<f32>3244 %1 = vector.extract %0[] : f32 from vector<f32>3245 3246 // Broadcast 0D to 3D and extract scalar.3247 // CHECK: %[[EXTRACT1:.*]] = vector.extract %[[B]][] : f32 from vector<f32>3248 %4 = vector.broadcast %b : vector<f32> to vector<1x2x4xf32>3249 %5 = vector.extract %4[0, 0, 1] : f32 from vector<1x2x4xf32>3250 3251 // Broadcast scalar to 2D and extract scalar.3252 %6 = vector.broadcast %a : f32 to vector<2x3xf32>3253 %7 = vector.extract %6[0, 1] : f32 from vector<2x3xf32>3254 3255 // Broadcast scalar to 3D and extract scalar.3256 %8 = vector.broadcast %a : f32 to vector<5x6x7xf32>3257 %9 = vector.extract %8[2, 1, 5] : f32 from vector<5x6x7xf32>3258 3259 // Extract 2D from 3D that was broadcasted from a scalar.3260 // CHECK: %[[EXTRACT2:.*]] = vector.broadcast %[[A]] : f32 to vector<6x7xf32>3261 %10 = vector.extract %8[2] : vector<6x7xf32> from vector<5x6x7xf32>3262 3263 // Extract 1D from 2D that was splat'ed from a scalar.3264 // CHECK: %[[EXTRACT3:.*]] = vector.broadcast %[[A]] : f32 to vector<3xf32>3265 %11 = vector.extract %6[1] : vector<3xf32> from vector<2x3xf32>3266 3267 // CHECK: return %[[A]], %[[EXTRACT1]], %[[A]], %[[A]], %[[EXTRACT2]], %[[EXTRACT3]]3268 return %1, %5, %7, %9, %10, %11 : f32, f32, f32, f32, vector<6x7xf32>, vector<3xf32>3269}3270 3271// -----3272 3273// CHECK-LABEL: func @to_elements_from_elements_no_op(3274// CHECK-SAME: %[[A:.*]]: f32, %[[B:.*]]: f323275func.func @to_elements_from_elements_no_op(%a: f32, %b: f32) -> (f32, f32) {3276 // CHECK-NOT: vector.from_elements3277 // CHECK-NOT: vector.to_elements3278 %0 = vector.from_elements %b, %a : vector<2xf32>3279 %1:2 = vector.to_elements %0 : vector<2xf32>3280 // CHECK: return %[[B]], %[[A]]3281 return %1#0, %1#1 : f32, f323282}3283 3284// -----3285 3286// CHECK-LABEL: func @from_elements_to_elements_no_op(3287// CHECK-SAME: %[[A:.*]]: vector<4x2xf32>3288func.func @from_elements_to_elements_no_op(%a: vector<4x2xf32>) -> vector<4x2xf32> {3289 // CHECK-NOT: vector.from_elements3290 // CHECK-NOT: vector.to_elements3291 %0:8 = vector.to_elements %a : vector<4x2xf32>3292 %1 = vector.from_elements %0#0, %0#1, %0#2, %0#3, %0#4, %0#5, %0#6, %0#7 : vector<4x2xf32>3293 // CHECK: return %[[A]]3294 return %1 : vector<4x2xf32>3295}3296 3297// -----3298 3299// CHECK-LABEL: func @from_elements_to_elements_dup_elems(3300// CHECK-SAME: %[[A:.*]]: vector<4xf32>3301func.func @from_elements_to_elements_dup_elems(%a: vector<4xf32>) -> vector<4x2xf32> {3302 // CHECK: %[[TO_EL:.*]]:4 = vector.to_elements %[[A]]3303 // CHECK: %[[FROM_EL:.*]] = vector.from_elements %[[TO_EL]]#0, %[[TO_EL]]#1, %[[TO_EL]]#23304 %0:4 = vector.to_elements %a : vector<4xf32> // 4 elements3305 %1 = vector.from_elements %0#0, %0#1, %0#2, %0#3, %0#0, %0#1, %0#2, %0#3 : vector<4x2xf32>3306 // CHECK: return %[[FROM_EL]]3307 return %1 : vector<4x2xf32>3308}3309 3310// -----3311 3312// CHECK-LABEL: func @from_elements_to_elements_shuffle(3313// CHECK-SAME: %[[A:.*]]: vector<4x2xf32>3314func.func @from_elements_to_elements_shuffle(%a: vector<4x2xf32>) -> vector<4x2xf32> {3315 // CHECK: %[[TO_EL:.*]]:8 = vector.to_elements %[[A]]3316 // CHECK: %[[FROM_EL:.*]] = vector.from_elements %[[TO_EL]]#7, %[[TO_EL]]#0, %[[TO_EL]]#63317 %0:8 = vector.to_elements %a : vector<4x2xf32>3318 %1 = vector.from_elements %0#7, %0#0, %0#6, %0#1, %0#5, %0#2, %0#4, %0#3 : vector<4x2xf32>3319 // CHECK: return %[[FROM_EL]]3320 return %1 : vector<4x2xf32>3321}3322 3323// -----3324 3325// CHECK-LABEL: func @to_elements_of_scalar_broadcast_folds3326// CHECK-SAME: (%[[S:.*]]: f32) -> (f32, f32, f32, f32)3327func.func @to_elements_of_scalar_broadcast_folds(%s: f32) -> (f32, f32, f32, f32) {3328 %v = vector.broadcast %s : f32 to vector<4xf32>3329 %e:4 = vector.to_elements %v : vector<4xf32>3330 // CHECK-NOT: vector.broadcast3331 // CHECK-NOT: vector.to_elements3332 // CHECK: return %[[S]], %[[S]], %[[S]], %[[S]]3333 return %e#0, %e#1, %e#2, %e#3 : f32, f32, f32, f323334}3335 3336// -----3337 3338// CHECK-LABEL: func @to_elements_of_vector_broadcast3339// CHECK-SAME: (%[[VEC:.*]]: vector<2xf32>) -> (f32, f32, f32, f32, f32, f32)3340func.func @to_elements_of_vector_broadcast(%vec: vector<2xf32>) -> (f32, f32, f32, f32, f32, f32) {3341 %v = vector.broadcast %vec : vector<2xf32> to vector<3x2xf32>3342 %e:6 = vector.to_elements %v : vector<3x2xf32>3343 // CHECK-NOT: vector.broadcast3344 // CHECK: %[[SRC_ELEMS:.*]]:2 = vector.to_elements %[[VEC]]3345 // CHECK: return %[[SRC_ELEMS]]#0, %[[SRC_ELEMS]]#1, %[[SRC_ELEMS]]#0, %[[SRC_ELEMS]]#1, %[[SRC_ELEMS]]#0, %[[SRC_ELEMS]]#13346 return %e#0, %e#1, %e#2, %e#3, %e#4, %e#5 : f32, f32, f32, f32, f32, f323347}3348 3349// -----3350 3351// CHECK-LABEL: func @to_elements_of_vector_broadcast_inner_dim3352// CHECK-SAME: (%[[V:.*]]: vector<2x1x2xf32>) -> (f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32)3353func.func @to_elements_of_vector_broadcast_inner_dim(%v: vector<2x1x2xf32>) -> (f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32) {3354 %b = vector.broadcast %v : vector<2x1x2xf32> to vector<2x3x2xf32>3355 %e:12 = vector.to_elements %b : vector<2x3x2xf32>3356 // CHECK-NOT: vector.broadcast3357 // CHECK: %[[SRC:.*]]:4 = vector.to_elements %[[V]] : vector<2x1x2xf32>3358 // CHECK: return %[[SRC]]#0, %[[SRC]]#1, %[[SRC]]#0, %[[SRC]]#1, %[[SRC]]#0, %[[SRC]]#1, %[[SRC]]#2, %[[SRC]]#3, %[[SRC]]#2, %[[SRC]]#3, %[[SRC]]#2, %[[SRC]]#33359 return %e#0, %e#1, %e#2, %e#3, %e#4, %e#5, %e#6, %e#7, %e#8, %e#9, %e#10, %e#11 :3360 f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f323361}3362 3363// -----3364 3365// +---------------------------------------------------------------------------3366// Tests for foldFromElementsToConstant3367// +---------------------------------------------------------------------------3368 3369// CHECK-LABEL: func @from_elements_to_constant(3370func.func @from_elements_to_constant() -> vector<2x2xi32> {3371 %c0_i32 = arith.constant 0 : i323372 %c1_i32 = arith.constant 1 : i323373 %c2_i32 = arith.constant 2 : i323374 %c3_i32 = arith.constant 3 : i323375 // CHECK: %[[RES:.*]] = arith.constant dense<{{\[\[0, 1\], \[2, 3\]\]}}> : vector<2x2xi32>3376 %res = vector.from_elements %c0_i32, %c1_i32, %c2_i32, %c3_i32 : vector<2x2xi32>3377 // CHECK: return %[[RES]]3378 return %res : vector<2x2xi32>3379}3380 3381// -----3382 3383// One of the elements is not a constant, the folder should fail.3384 3385// CHECK-LABEL: func @negative_from_elements_to_constant(3386// CHECK-SAME: %[[A:.*]]: f323387func.func @negative_from_elements_to_constant(%arg0: f32) -> vector<2xf32> {3388 // CHECK: %[[C:.*]] = arith.constant 1.000000e+00 : f323389 %c = arith.constant 1.0 : f323390 // CHECK: %[[RES:.*]] = vector.from_elements %[[A]], %[[C]] : vector<2xf32>3391 %res = vector.from_elements %arg0, %c : vector<2xf32>3392 // CHECK: return %[[RES]]3393 return %res : vector<2xf32>3394}3395 3396// -----3397 3398// While all inputs in this example are constant, we cannot create a3399// DenselElemAttr containing llvm.mlir.addressof. Instead,3400// `foldFromElementsToConstant` bails out. Note that in this case, a different3401// folder is applied (`rewriteFromElementsAsBroadcast`).3402llvm.mlir.global constant @my_symbol() : i323403 3404// CHECK-LABEL: func @negative_from_elements_to_constant3405// CHECK: %[[A:.*]] = llvm.mlir.addressof @my_symbol3406// CHECK: %[[B:.*]] = vector.broadcast %[[A]] : !llvm.ptr to vector<1x!llvm.ptr>3407// CHECK: return %[[B]]3408func.func @negative_from_elements_to_constant() -> vector<1x!llvm.ptr> {3409 %a = llvm.mlir.addressof @my_symbol : !llvm.ptr3410 %b = vector.from_elements %a : vector<1x!llvm.ptr>3411 return %b : vector<1x!llvm.ptr>3412}3413 3414// -----3415 3416// `foldFromElementsToConstant` does not support `ub.poison`, so it bails out.3417// Instead, other folders apply here (e.g. `rewriteFromElementsAsBroadcast`).3418 3419// CHECK-LABEL: @negative_from_elements_poison3420// CHECK: %[[VAL:.*]] = ub.poison : vector<2xf32>3421// CHECK: return %[[VAL]] : vector<2xf32>3422func.func @negative_from_elements_poison_f32() -> vector<2xf32> {3423 %0 = ub.poison : f323424 %1 = vector.from_elements %0, %0 : vector<2xf32>3425 return %1 : vector<2xf32>3426}3427 3428// -----3429 3430// `foldFromElementsToConstant` does not support `ub.poison`, so it bails out.3431// Instead, other folders apply here (e.g. `rewriteFromElementsAsBroadcast`).3432 3433// CHECK-LABEL: @negative_from_elements_poison_i323434// CHECK: %[[VAL:.*]] = ub.poison : vector<2xi32>3435// CHECK: return %[[VAL]] : vector<2xi32>3436func.func @negative_from_elements_poison_i32() -> vector<2xi32> {3437 %0 = ub.poison : i323438 %1 = vector.from_elements %0, %0 : vector<2xi32>3439 return %1 : vector<2xi32>3440}3441 3442// -----3443 3444// `foldFromElementsToConstant` does not support `ub.poison`, so it bails out.3445// Instead, other folders apply here (e.g. `rewriteFromElementsAsBroadcast`).3446 3447// CHECK-LABEL: @negative_from_elements_poison_constant_mix3448// CHECK: %[[POISON:.*]] = ub.poison : f323449// CHECK: %[[CONST:.*]] = arith.constant 1.000000e+00 : f323450// CHECK: %[[RES:.*]] = vector.from_elements %[[POISON]], %[[CONST]] : vector<2xf32>3451// CHECK: return %[[RES]] : vector<2xf32>3452func.func @negative_from_elements_poison_constant_mix() -> vector<2xf32> {3453 %0 = ub.poison : f323454 %c = arith.constant 1.0 : f323455 %1 = vector.from_elements %0, %c : vector<2xf32>3456 return %1 : vector<2xf32>3457}3458 3459// -----3460 3461// CHECK-LABEL: func @from_elements_float8_to_i8_conversion(3462// CHECK-NEXT: %[[CST:.*]] = arith.constant dense<[0, 56, -72, 69, 127, -1]> : vector<6xi8>3463// CHECK-NEXT: return %[[CST]] : vector<6xi8>3464func.func @from_elements_float8_to_i8_conversion() -> vector<6xi8> {3465 %cst0 = llvm.mlir.constant(0.0 : f8E4M3FN) : i83466 %cst1 = llvm.mlir.constant(1.0 : f8E4M3FN) : i83467 %cst_neg1 = llvm.mlir.constant(-1.0 : f8E4M3FN) : i83468 %cst_pi = llvm.mlir.constant(3.14 : f8E4M3FN) : i83469 %cst_inf = llvm.mlir.constant(0x7F : f8E4M3FN) : i83470 %cst_neg_inf = llvm.mlir.constant(0xFF : f8E4M3FN) : i83471 %v = vector.from_elements %cst0, %cst1, %cst_neg1, %cst_pi, %cst_inf, %cst_neg_inf : vector<6xi8>3472 return %v : vector<6xi8>3473}3474 3475// CHECK-LABEL: func @from_elements_float16_to_i16_conversion(3476// CHECK-NEXT: %[[CST:.*]] = arith.constant dense<[0, 15360, -17408, 16968, 31743, -1025]> : vector<6xi16>3477// CHECK-NEXT: return %[[CST]] : vector<6xi16>3478func.func @from_elements_float16_to_i16_conversion() -> vector<6xi16> {3479 %cst0 = llvm.mlir.constant(0.0 : f16) : i163480 %cst1 = llvm.mlir.constant(1.0 : f16) : i163481 %cst_neg1 = llvm.mlir.constant(-1.0 : f16) : i163482 %cst_pi = llvm.mlir.constant(3.14 : f16) : i163483 %cst_max = llvm.mlir.constant(65504.0 : f16) : i163484 %cst_min = llvm.mlir.constant(-65504.0 : f16) : i163485 %v = vector.from_elements %cst0, %cst1, %cst_neg1, %cst_pi, %cst_max, %cst_min : vector<6xi16>3486 return %v : vector<6xi16>3487}3488 3489// CHECK-LABEL: func @from_elements_f64_to_i64_conversion(3490// CHECK-NEXT: %[[CST:.*]] = arith.constant dense<[0, 4607182418800017408, -4616189618054758400, 4614253070214989087, 9218868437227405311, -4503599627370497]> : vector<6xi64>3491// CHECK-NEXT: return %[[CST]] : vector<6xi64>3492func.func @from_elements_f64_to_i64_conversion() -> vector<6xi64> {3493 %cst0 = llvm.mlir.constant(0.0 : f64) : i643494 %cst1 = llvm.mlir.constant(1.0 : f64) : i643495 %cst_neg1 = llvm.mlir.constant(-1.0 : f64) : i643496 %cst_pi = llvm.mlir.constant(3.14 : f64) : i643497 %cst_max = llvm.mlir.constant(1.7976931348623157e+308 : f64) : i643498 %cst_min = llvm.mlir.constant(-1.7976931348623157e+308 : f64) : i643499 %v = vector.from_elements %cst0, %cst1, %cst_neg1, %cst_pi, %cst_max, %cst_min : vector<6xi64>3500 return %v : vector<6xi64>3501}3502 3503// -----3504 3505// CHECK-LABEL: func @from_elements_i1_to_i8_conversion(3506// CHECK-NEXT: %[[CST:.*]] = arith.constant dense<0> : vector<1xi8>3507// CHECK-NEXT: return %[[CST]] : vector<1xi8>3508func.func @from_elements_i1_to_i8_conversion() -> vector<1xi8> {3509 %cst = llvm.mlir.constant(0: i1) : i83510 %v = vector.from_elements %cst : vector<1xi8>3511 return %v : vector<1xi8>3512}3513 3514// -----3515 3516// CHECK-LABEL: func @from_elements_index_to_i64_conversion(3517// CHECK-NEXT: %[[CST:.*]] = arith.constant dense<[0, 1, 42]> : vector<3xi64>3518// CHECK-NEXT: return %[[CST]] : vector<3xi64>3519func.func @from_elements_index_to_i64_conversion() -> vector<3xi64> {3520 %cst0 = llvm.mlir.constant(0 : index) : i643521 %cst1 = llvm.mlir.constant(1 : index) : i643522 %cst42 = llvm.mlir.constant(42 : index) : i643523 %v = vector.from_elements %cst0, %cst1, %cst42 : vector<3xi64>3524 return %v : vector<3xi64>3525}3526 3527// +---------------------------------------------------------------------------3528// End of Tests for foldFromElementsToConstant3529// +---------------------------------------------------------------------------3530 3531// -----3532 3533// +---------------------------------------------------------------------------3534// Tests for FoldTransposeFromElements3535// +---------------------------------------------------------------------------3536 3537// CHECK-LABEL: transpose_from_elements_1d3538// CHECK-SAME: %[[EL_0:.*]]: i32, %[[EL_1:.*]]: i32 3539func.func @transpose_from_elements_1d(%el_0: i32, %el_1: i32) -> vector<2xi32> {3540 %v = vector.from_elements %el_0, %el_1 : vector<2xi32>3541 %t = vector.transpose %v, [0] : vector<2xi32> to vector<2xi32>3542 return %t : vector<2xi32>3543 // CHECK: %[[R:.*]] = vector.from_elements %[[EL_0]], %[[EL_1]] : vector<2xi32>3544 // CHECK-NOT: vector.transpose3545 // CHECK: return %[[R]]3546}3547 3548// CHECK-LABEL: transpose_from_elements_2d3549// CHECK-SAME: %[[EL_0_0:.*]]: i32, %[[EL_0_1:.*]]: i32, %[[EL_0_2:.*]]: i32, %[[EL_1_0:.*]]: i32, %[[EL_1_1:.*]]: i32, %[[EL_1_2:.*]]: i32 3550func.func @transpose_from_elements_2d(3551 %el_0_0: i32, %el_0_1: i32, %el_0_2: i32,3552 %el_1_0: i32, %el_1_1: i32, %el_1_2: i323553) -> vector<3x2xi32> {3554 %v = vector.from_elements %el_0_0, %el_0_1, %el_0_2, %el_1_0, %el_1_1, %el_1_2 : vector<2x3xi32>3555 %t = vector.transpose %v, [1, 0] : vector<2x3xi32> to vector<3x2xi32>3556 return %t : vector<3x2xi32>3557 // CHECK: %[[R:.*]] = vector.from_elements %[[EL_0_0:.*]], %[[EL_1_0:.*]], %[[EL_0_1:.*]], %[[EL_1_1:.*]], %[[EL_0_2:.*]], %[[EL_1_2:.*]] : vector<3x2xi32>3558 // CHECK-NOT: vector.transpose3559 // CHECK: return %[[R]]3560}3561 3562// CHECK-LABEL: transpose_from_elements_3d3563// CHECK-SAME: %[[EL_0_0_0:.*]]: i32, %[[EL_0_0_1:.*]]: i32, %[[EL_0_1_0:.*]]: i32, %[[EL_0_1_1:.*]]: i32, %[[EL_0_2_0:.*]]: i32, %[[EL_0_2_1:.*]]: i32, %[[EL_1_0_0:.*]]: i32, %[[EL_1_0_1:.*]]: i32, %[[EL_1_1_0:.*]]: i32, %[[EL_1_1_1:.*]]: i32, %[[EL_1_2_0:.*]]: i32, %[[EL_1_2_1:.*]]: i32 3564func.func @transpose_from_elements_3d(3565 %el_0_0_0: i32, %el_0_0_1: i32, %el_0_1_0: i32, %el_0_1_1: i32, %el_0_2_0: i32, %el_0_2_1: i32,3566 %el_1_0_0: i32, %el_1_0_1: i32, %el_1_1_0: i32, %el_1_1_1: i32, %el_1_2_0: i32, %el_1_2_1: i323567) -> vector<2x2x3xi32> {3568 %v = vector.from_elements3569 %el_0_0_0, %el_0_0_1,3570 %el_0_1_0, %el_0_1_1,3571 %el_0_2_0, %el_0_2_1,3572 %el_1_0_0, %el_1_0_1,3573 %el_1_1_0, %el_1_1_1,3574 %el_1_2_0, %el_1_2_13575 : vector<2x3x2xi32>3576 %t = vector.transpose %v, [0, 2, 1] : vector<2x3x2xi32> to vector<2x2x3xi32>3577 return %t : vector<2x2x3xi32>3578 // CHECK: %[[R:.*]] = vector.from_elements %[[EL_0_0_0:.*]], %[[EL_0_1_0:.*]], %[[EL_0_2_0:.*]], %[[EL_0_0_1:.*]], %[[EL_0_1_1:.*]], %[[EL_0_2_1:.*]], %[[EL_1_0_0:.*]], %[[EL_1_1_0:.*]], %[[EL_1_2_0:.*]], %[[EL_1_0_1:.*]], %[[EL_1_1_1:.*]], %[[EL_1_2_1:.*]] : vector<2x2x3xi32>3579 // CHECK-NOT: vector.transpose3580 // CHECK: return %[[R]]3581}3582 3583// +---------------------------------------------------------------------------3584// End of Tests for FoldTransposeFromElements3585// +---------------------------------------------------------------------------3586 3587// -----3588 3589// Not a DenseElementsAttr, don't fold.3590 3591// CHECK-LABEL: func @negative_insert_llvm_undef(3592// CHECK: llvm.mlir.undef3593// CHECK: vector.insert3594func.func @negative_insert_llvm_undef(%arg0: i8) -> vector<4xi8> {3595 %0 = llvm.mlir.undef : vector<4xi8>3596 %1 = vector.insert %arg0, %0 [0] : i8 into vector<4xi8>3597 return %1 : vector<4xi8>3598}3599 3600// -----3601 3602// Insert a poison value shouldn't be folded as the resulting vector is not3603// fully poison.3604 3605// CHECK-LABEL: @insert_scalar_poison3606func.func @insert_scalar_poison(%a: vector<4x8xf32>)3607 -> vector<4x8xf32> {3608 // CHECK-NEXT: %[[UB:.*]] = ub.poison : f323609 // CHECK-NEXT: %[[RES:.*]] = vector.insert %[[UB]]3610 // CHECK-NEXT: return %[[RES]] : vector<4x8xf32>3611 %0 = ub.poison : f323612 %1 = vector.insert %0, %a[2, 3] : f32 into vector<4x8xf32>3613 return %1 : vector<4x8xf32>3614}3615 3616// -----3617 3618// Insert a poison value shouldn't be folded as the resulting vector is not3619// fully poison.3620 3621// CHECK-LABEL: @insert_vector_poison3622func.func @insert_vector_poison(%a: vector<4x8xf32>)3623 -> vector<4x8xf32> {3624 // CHECK-NEXT: %[[UB:.*]] = ub.poison : vector<8xf32>3625 // CHECK-NEXT: %[[RES:.*]] = vector.insert %[[UB]]3626 // CHECK-NEXT: return %[[RES]] : vector<4x8xf32>3627 %0 = ub.poison : vector<8xf32>3628 %1 = vector.insert %0, %a[2] : vector<8xf32> into vector<4x8xf32>3629 return %1 : vector<4x8xf32>3630}3631 3632// -----3633 3634// CHECK-LABEL: @insert_scalar_poison_idx3635func.func @insert_scalar_poison_idx(%a: vector<4x5xf32>, %b: f32)3636 -> vector<4x5xf32> {3637 // CHECK-NEXT: %[[UB:.*]] = ub.poison : vector<4x5xf32>3638 // CHECK-NOT: vector.insert3639 // CHECK-NEXT: return %[[UB]] : vector<4x5xf32>3640 %0 = vector.insert %b, %a[-1, 0] : f32 into vector<4x5xf32>3641 return %0 : vector<4x5xf32>3642}3643 3644// -----3645 3646// CHECK-LABEL: @insert_vector_poison_idx3647func.func @insert_vector_poison_idx(%a: vector<4x5xf32>, %b: vector<5xf32>)3648 -> vector<4x5xf32> {3649 // CHECK-NEXT: %[[UB:.*]] = ub.poison : vector<4x5xf32>3650 // CHECK-NOT: vector.insert3651 // CHECK-NEXT: return %[[UB]] : vector<4x5xf32>3652 %0 = vector.insert %b, %a[-1] : vector<5xf32> into vector<4x5xf32>3653 return %0 : vector<4x5xf32>3654}3655 3656// -----3657 3658// Similar to the test above, but the index is not a static constant.3659 3660// CHECK-LABEL: @insert_vector_poison_idx_non_cst3661func.func @insert_vector_poison_idx_non_cst(%a: vector<4x5xf32>, %b: vector<5xf32>)3662 -> vector<4x5xf32> {3663 // CHECK-NEXT: %[[UB:.*]] = ub.poison : vector<4x5xf32>3664 // CHECK-NOT: vector.insert3665 // CHECK-NEXT: return %[[UB]] : vector<4x5xf32>3666 %c_neg_1 = arith.constant -1 : index3667 %0 = vector.insert %b, %a[%c_neg_1] : vector<5xf32> into vector<4x5xf32>3668 return %0 : vector<4x5xf32>3669}3670 3671// -----3672 3673// Similar to test above, but now the index is out-of-bounds.3674 3675// CHECK-LABEL: @no_fold_insert_scalar_idx_oob3676func.func @no_fold_insert_scalar_idx_oob(%a: vector<4x5xf32>, %b: vector<5xf32>)3677 -> vector<4x5xf32> {3678 // CHECK: vector.insert3679 %c_neg_2 = arith.constant -2 : index3680 %0 = vector.insert %b, %a[%c_neg_2] : vector<5xf32> into vector<4x5xf32>3681 return %0 : vector<4x5xf32>3682}3683 3684// -----3685 3686// CHECK-LABEL: @insert_multiple_poison_idx3687func.func @insert_multiple_poison_idx(%a: vector<4x5x8xf32>, %b: vector<8xf32>)3688 -> vector<4x5x8xf32> {3689 // CHECK-NEXT: %[[UB:.*]] = ub.poison : vector<4x5x8xf32>3690 // CHECK-NOT: vector.insert3691 // CHECK-NEXT: return %[[UB]] : vector<4x5x8xf32>3692 %0 = vector.insert %b, %a[-1, -1] : vector<8xf32> into vector<4x5x8xf32>3693 return %0 : vector<4x5x8xf32>3694}3695 3696// -----3697 3698// CHECK-LABEL: @contiguous_extract_strided_slices_to_extract_sizes_and_outer_source_dims_overlap3699// CHECK: %[[EXTRACT:.+]] = vector.extract {{.*}}[0, 0, 0, 0, 0] : vector<4xi32> from vector<8x1x2x1x1x4xi32>3700// CHECK-NEXT: return %[[EXTRACT]] : vector<4xi32>3701func.func @contiguous_extract_strided_slices_to_extract_sizes_and_outer_source_dims_overlap(%arg0 : vector<8x1x2x1x1x4xi32>) -> vector<4xi32> {3702 %1 = vector.extract_strided_slice %arg0 {offsets = [0, 0, 0, 0, 0, 0], sizes = [1, 1, 1, 1, 1, 4], strides = [1, 1, 1, 1, 1, 1]} : vector<8x1x2x1x1x4xi32> to vector<1x1x1x1x1x4xi32>3703 %2 = vector.shape_cast %1 : vector<1x1x1x1x1x4xi32> to vector<4xi32>3704 return %2 : vector<4xi32>3705}3706 3707// -----3708 3709// CHECK-LABEL: @contiguous_extract_strided_slices_to_extract_sizes_and_outer_source_dims_no_overlap3710// CHECK: %[[EXTRACT:.+]] = vector.extract {{.*}}[0, 0] : vector<4xi32> from vector<8x2x4xi32>3711// CHECK-NEXT: return %[[EXTRACT]] : vector<4xi32>3712func.func @contiguous_extract_strided_slices_to_extract_sizes_and_outer_source_dims_no_overlap(%arg0 : vector<8x2x4xi32>) -> vector<4xi32> {3713 %1 = vector.extract_strided_slice %arg0 {offsets = [0, 0], sizes = [1, 1], strides = [1, 1]} : vector<8x2x4xi32> to vector<1x1x4xi32>3714 %2 = vector.shape_cast %1 : vector<1x1x4xi32> to vector<4xi32>3715 return %2 : vector<4xi32>3716}3717 3718// -----3719 3720// CHECK-LABEL: @contiguous_extract_strided_slices_to_extract_shorter_size_list3721// CHECK: %[[EXTRACT:.+]] = vector.extract {{.*}}[0, 0, 0, 0] : vector<1x4xi32> from vector<8x1x2x1x1x4xi32>3722// CHECK-NEXT: return %[[EXTRACT]] : vector<1x4xi32>3723func.func @contiguous_extract_strided_slices_to_extract_shorter_size_list(%arg0 : vector<8x1x2x1x1x4xi32>) -> vector<1x4xi32> {3724 %1 = vector.extract_strided_slice %arg0 {offsets = [0, 0, 0, 0, 0], sizes = [1, 1, 1, 1, 1], strides = [1, 1, 1, 1, 1]} : vector<8x1x2x1x1x4xi32> to vector<1x1x1x1x1x4xi32>3725 %2 = vector.shape_cast %1 : vector<1x1x1x1x1x4xi32> to vector<1x4xi32>3726 return %2 : vector<1x4xi32>3727}3728 3729// -----3730 3731// CHECK-LABEL: @contiguous_extract_strided_slices_to_extract_failure_non_unit_outer_size3732// CHECK-NEXT: vector.extract_strided_slice3733func.func @contiguous_extract_strided_slices_to_extract_failure_non_unit_outer_size(%arg0 : vector<8x1x2x1x1x4xi32>) -> vector<8x1x1x1x1x4xi32> {3734 %1 = vector.extract_strided_slice %arg0 {offsets = [0, 0, 0, 0, 0, 0], sizes = [8, 1, 1, 1, 1, 4], strides = [1, 1, 1, 1, 1, 1]} : vector<8x1x2x1x1x4xi32> to vector<8x1x1x1x1x4xi32>3735 return %1 : vector<8x1x1x1x1x4xi32>3736}3737 3738// -----3739 3740// CHECK-LABEL: @contiguous_extract_strided_slices_to_extract_failure_non_full_size3741// CHECK-NEXT: vector.extract_strided_slice3742func.func @contiguous_extract_strided_slices_to_extract_failure_non_full_size(%arg0 : vector<8x1x2x1x1x4xi32>) -> vector<1x1x1x1x1x2xi32> {3743 %1 = vector.extract_strided_slice %arg0 {offsets = [0, 0, 0, 0, 0, 0], sizes = [1, 1, 1, 1, 1, 2], strides = [1, 1, 1, 1, 1, 1]} : vector<8x1x2x1x1x4xi32> to vector<1x1x1x1x1x2xi32>3744 return %1 : vector<1x1x1x1x1x2xi32>3745}3746 3747// -----3748 3749// CHECK-LABEL: @contiguous_extract_strided_slices_to_extract_failure_non_full_inner_size3750// CHECK-NEXT: vector.extract_strided_slice3751func.func @contiguous_extract_strided_slices_to_extract_failure_non_full_inner_size(%arg0 : vector<8x1x2x1x1x4xi32>) -> vector<1x1x2x1x1x1xi32> {3752 %1 = vector.extract_strided_slice %arg0 {offsets = [0, 0, 0, 0, 0, 0], sizes = [1, 1, 2, 1, 1, 1], strides = [1, 1, 1, 1, 1, 1]} : vector<8x1x2x1x1x4xi32> to vector<1x1x2x1x1x1xi32>3753 return %1 : vector<1x1x2x1x1x1xi32>3754}3755 3756// -----3757 3758// CHECK-LABEL: @contiguous_gather3759// CHECK-SAME: (%[[BASE:.*]]: memref<?xf32>, %[[MASK:.*]]: vector<16xi1>, %[[PASSTHRU:.*]]: vector<16xf32>)3760// CHECK: %[[C0:.*]] = arith.constant 0 : index3761// CHECK: %[[R:.*]] = vector.maskedload %[[BASE]][%[[C0]]], %[[MASK]], %[[PASSTHRU]] : memref<?xf32>, vector<16xi1>, vector<16xf32> into vector<16xf32>3762// CHECK: return %[[R]]3763func.func @contiguous_gather(%base: memref<?xf32>,3764 %mask: vector<16xi1>, %passthru: vector<16xf32>) -> vector<16xf32> {3765 %c0 = arith.constant 0 : index3766 %indices = arith.constant dense<[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]> : vector<16xi32>3767 %1 = vector.gather %base[%c0][%indices], %mask, %passthru :3768 memref<?xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32> into vector<16xf32>3769 return %1 : vector<16xf32>3770}3771 3772// -----3773 3774// CHECK-LABEL: @contiguous_gather_non_zero_start(3775// TODO: Non-zero start is not supported yet.3776// CHECK: %[[R:.*]] = vector.gather3777// CHECK: return %[[R]]3778func.func @contiguous_gather_non_zero_start(%base: memref<?xf32>,3779 %mask: vector<16xi1>,3780 %passthru: vector<16xf32>) -> vector<16xf32> {3781 %c0 = arith.constant 0 : index3782 %indices = arith.constant dense<[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]> : vector<16xi32>3783 %1 = vector.gather %base[%c0][%indices], %mask, %passthru :3784 memref<?xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32> into vector<16xf32>3785 return %1 : vector<16xf32>3786}3787 3788// -----3789 3790// CHECK-LABEL: @contiguous_gather_2d(3791// TODO: Only 1D vectors are supported.3792// CHECK: %[[R:.*]] = vector.gather3793// CHECK: return %[[R]]3794func.func @contiguous_gather_2d(%base: memref<?x?xf32>,3795 %mask: vector<4x4xi1>, %passthru: vector<4x4xf32>) -> vector<4x4xf32> {3796 %c0 = arith.constant 0 : index3797 %indices = arith.constant dense<[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]> : vector<4x4xi32>3798 %1 = vector.gather %base[%c0, %c0][%indices], %mask, %passthru :3799 memref<?x?xf32>, vector<4x4xi32>, vector<4x4xi1>, vector<4x4xf32> into vector<4x4xf32>3800 return %1 : vector<4x4xf32>3801}3802 3803// -----3804 3805// CHECK-LABEL: @contiguous_gather_const_mask3806// CHECK-SAME: (%[[BASE:.*]]: memref<?xf32>, %[[PASSTHRU:.*]]: vector<16xf32>)3807// CHECK: %[[C0:.*]] = arith.constant 0 : index3808// CHECK: %[[R:.*]] = vector.load %[[BASE]][%[[C0]]] : memref<?xf32>, vector<16xf32>3809// CHECK: return %[[R]]3810func.func @contiguous_gather_const_mask(%base: memref<?xf32>,3811 %passthru: vector<16xf32>) -> vector<16xf32> {3812 %c0 = arith.constant 0 : index3813 %indices = arith.constant dense<[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]> : vector<16xi32>3814 %mask = arith.constant dense<true> : vector<16xi1>3815 %1 = vector.gather %base[%c0][%indices], %mask, %passthru :3816 memref<?xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32> into vector<16xf32>3817 return %1 : vector<16xf32>3818}3819 3820// -----3821 3822// CHECK-LABEL: @contiguous_gather_step3823// CHECK-SAME: (%[[BASE:.*]]: memref<?xf32>, %[[MASK:.*]]: vector<16xi1>, %[[PASSTHRU:.*]]: vector<16xf32>)3824// CHECK: %[[C0:.*]] = arith.constant 0 : index3825// CHECK: %[[R:.*]] = vector.maskedload %[[BASE]][%[[C0]]], %[[MASK]], %[[PASSTHRU]] : memref<?xf32>, vector<16xi1>, vector<16xf32> into vector<16xf32>3826// CHECK: return %[[R]]3827func.func @contiguous_gather_step(%base: memref<?xf32>,3828 %mask: vector<16xi1>, %passthru: vector<16xf32>) -> vector<16xf32> {3829 %c0 = arith.constant 0 : index3830 %indices = vector.step : vector<16xindex>3831 %1 = vector.gather %base[%c0][%indices], %mask, %passthru :3832 memref<?xf32>, vector<16xindex>, vector<16xi1>, vector<16xf32> into vector<16xf32>3833 return %1 : vector<16xf32>3834}3835 3836// -----3837 3838// CHECK-LABEL: @no_fold_contiguous_gather_tensor3839func.func @no_fold_contiguous_gather_tensor(%base: tensor<8xf32>, %mask: vector<4xi1>, %pass_thru: vector<4xf32>) -> vector<4xf32> {3840 %c0 = arith.constant 0 : index3841 %indices = arith.constant dense<[0, 1, 2, 3]> : vector<4xindex>3842 // CHECK: vector.gather3843 // CHECK-NOT: vector.maskedload3844 %0 = vector.gather %base[%c0][%indices], %mask, %pass_thru :3845 tensor<8xf32>, vector<4xindex>, vector<4xi1>, vector<4xf32> into vector<4xf32>3846 return %0 : vector<4xf32>3847}3848 3849// -----3850 3851// CHECK-LABEL: @gather_broadcast(3852// TODO: Broadcast is not supported yet3853// CHECK: %[[R:.*]] = vector.gather3854// CHECK: return %[[R]]3855func.func @gather_broadcast(%base: memref<?xf32>,3856 %mask: vector<16xi1>, %passthru: vector<16xf32>) -> vector<16xf32> {3857 %c0 = arith.constant 0 : index3858 %indices = arith.constant dense<0> : vector<16xi32>3859 %1 = vector.gather %base[%c0][%indices], %mask, %passthru :3860 memref<?xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32> into vector<16xf32>3861 return %1 : vector<16xf32>3862}3863 3864// -----3865 3866// CHECK-LABEL: @contiguous_scatter3867// CHECK-SAME: (%[[BASE:.*]]: memref<?xf32>, %[[MASK:.*]]: vector<16xi1>, %[[VALUE:.*]]: vector<16xf32>)3868// CHECK: %[[C0:.*]] = arith.constant 0 : index3869// CHECK: vector.maskedstore %[[BASE]][%[[C0]]], %[[MASK]], %[[VALUE]] : memref<?xf32>, vector<16xi1>, vector<16xf32>3870func.func @contiguous_scatter(%base: memref<?xf32>,3871 %mask: vector<16xi1>, %value: vector<16xf32>) {3872 %c0 = arith.constant 0 : index3873 %indices = arith.constant dense<[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]> : vector<16xi32>3874 vector.scatter %base[%c0][%indices], %mask, %value :3875 memref<?xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32>3876 return3877}3878 3879// -----3880 3881// CHECK-LABEL: @contiguous_scatter_const_mask3882// CHECK-SAME: (%[[BASE:.*]]: memref<?xf32>, %[[VALUE:.*]]: vector<16xf32>)3883// CHECK: %[[C0:.*]] = arith.constant 0 : index3884// CHECK: vector.store %[[VALUE]], %[[BASE]][%[[C0]]] : memref<?xf32>, vector<16xf32>3885func.func @contiguous_scatter_const_mask(%base: memref<?xf32>,3886 %value: vector<16xf32>) {3887 %c0 = arith.constant 0 : index3888 %indices = arith.constant dense<[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]> : vector<16xi32>3889 %mask = vector.constant_mask [16] : vector<16xi1>3890 vector.scatter %base[%c0][%indices], %mask, %value :3891 memref<?xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32>3892 return3893}3894 3895// -----3896 3897// CHECK-LABEL: @contiguous_scatter_step3898// CHECK-SAME: (%[[BASE:.*]]: memref<?xf32>, %[[MASK:.*]]: vector<16xi1>, %[[VALUE:.*]]: vector<16xf32>)3899// CHECK: %[[C0:.*]] = arith.constant 0 : index3900// CHECK: vector.maskedstore %[[BASE]][%[[C0]]], %[[MASK]], %[[VALUE]] : memref<?xf32>, vector<16xi1>, vector<16xf32>3901func.func @contiguous_scatter_step(%base: memref<?xf32>,3902 %mask: vector<16xi1>, %value: vector<16xf32>) {3903 %c0 = arith.constant 0 : index3904 %indices = vector.step : vector<16xindex>3905 vector.scatter %base[%c0][%indices], %mask, %value :3906 memref<?xf32>, vector<16xindex>, vector<16xi1>, vector<16xf32>3907 return3908}3909 3910// -----3911 3912// CHECK-LABEL: @fold_extract_constant_indices3913// CHECK-SAME: %[[ARG:.*]]: vector<32x1xi32>) -> i32 {3914// CHECK: %[[RES:.*]] = vector.extract %[[ARG]][0, 0] : i32 from vector<32x1xi32>3915// CHECK: return %[[RES]] : i323916func.func @fold_extract_constant_indices(%arg : vector<32x1xi32>) -> i32 {3917 %0 = arith.constant 0 : index3918 %1 = vector.extract %arg[%0, %0] : i32 from vector<32x1xi32>3919 return %1 : i323920}3921 3922// -----3923 3924// CHECK-LABEL: @fold_insert_constant_indices3925// CHECK-SAME: %[[ARG:.*]]: vector<4x1xi32>) -> vector<4x1xi32> {3926// CHECK: %[[VAL:.*]] = arith.constant 1 : i323927// CHECK: %[[RES:.*]] = vector.insert %[[VAL]], %[[ARG]] [0, 0] : i32 into vector<4x1xi32>3928// CHECK: return %[[RES]] : vector<4x1xi32>3929func.func @fold_insert_constant_indices(%arg : vector<4x1xi32>) -> vector<4x1xi32> {3930 %0 = arith.constant 0 : index3931 %1 = arith.constant 1 : i323932 %res = vector.insert %1, %arg[%0, %0] : i32 into vector<4x1xi32>3933 return %res : vector<4x1xi32>3934}3935 3936// -----3937 3938// CHECK-LABEL: @fold_insert_use_chain(3939// CHECK-SAME: %[[ARG:.*]]: vector<4x4xf32>,3940// CHECK-SAME: %[[VAL:.*]]: f32,3941// CHECK-SAME: %[[POS:.*]]: index) -> vector<4x4xf32> {3942// CHECK-NEXT: %[[RES:.*]] = vector.insert %[[VAL]], %[[ARG]] {{\[}}%[[POS]], 0] : f32 into vector<4x4xf32>3943// CHECK-NEXT: return %[[RES]] : vector<4x4xf32>3944func.func @fold_insert_use_chain(%arg : vector<4x4xf32>, %val : f32, %pos: index) -> vector<4x4xf32> {3945 %v_0 = vector.insert %val, %arg[%pos, 0] : f32 into vector<4x4xf32>3946 %v_1 = vector.insert %val, %v_0[%pos, 0] : f32 into vector<4x4xf32>3947 %v_2 = vector.insert %val, %v_1[%pos, 0] : f32 into vector<4x4xf32>3948 return %v_2 : vector<4x4xf32>3949}3950 3951// -----3952 3953// CHECK-LABEL: @no_fold_insert_use_chain_mismatch_static_position(3954// CHECK-SAME: %[[ARG:.*]]: vector<4xf32>,3955// CHECK-SAME: %[[VAL:.*]]: f32) -> vector<4xf32> {3956// CHECK: %[[V_0:.*]] = vector.insert %[[VAL]], %[[ARG]] [0] : f32 into vector<4xf32>3957// CHECK: %[[V_1:.*]] = vector.insert %[[VAL]], %[[V_0]] [1] : f32 into vector<4xf32>3958// CHECK: return %[[V_1]] : vector<4xf32>3959func.func @no_fold_insert_use_chain_mismatch_static_position(%arg : vector<4xf32>, %val : f32) -> vector<4xf32> {3960 %v_0 = vector.insert %val, %arg[0] : f32 into vector<4xf32>3961 %v_1 = vector.insert %val, %v_0[1] : f32 into vector<4xf32>3962 return %v_1 : vector<4xf32>3963}3964