614 lines · plain
1// RUN: mlir-opt -promote-buffers-to-stack -split-input-file %s | FileCheck %s --check-prefix=CHECK --check-prefix DEFINDEX2// RUN: mlir-opt -promote-buffers-to-stack="max-alloc-size-in-bytes=64" -split-input-file %s | FileCheck %s --check-prefix=CHECK --check-prefix LOWLIMIT3// RUN: mlir-opt -promote-buffers-to-stack="max-rank-of-allocated-memref=2" -split-input-file %s | FileCheck %s --check-prefix=CHECK --check-prefix RANK4 5// This file checks the behavior of PromoteBuffersToStack pass for converting6// AllocOps into AllocaOps, if possible.7 8// Test Case:9// bb010// / \11// bb1 bb2 <- Initial position of AllocOp12// \ /13// bb314// PromoteBuffersToStack expected behavior: It should convert %0 into an15// AllocaOp.16 17// CHECK-LABEL: func @condBranch18func.func @condBranch(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {19 cf.cond_br %arg0, ^bb1, ^bb220^bb1:21 cf.br ^bb3(%arg1 : memref<2xf32>)22^bb2:23 %0 = memref.alloc() : memref<2xf32>24 test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)25 cf.br ^bb3(%0 : memref<2xf32>)26^bb3(%1: memref<2xf32>):27 test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)28 return29}30 31// CHECK-NEXT: cf.cond_br {{.*}}32// CHECK: ^bb233// CHECK-NEXT: %[[ALLOCA:.*]] = memref.alloca()34// CHECK: test.copy35// CHECK-NEXT: return36 37// -----38 39// Test Case:40// bb041// / \42// bb1 bb2 <- Initial position of AllocOp43// \ /44// bb345// PromoteBuffersToStack expected behavior:46// Since the alloc has dynamic type, it is not converted into an alloca.47 48// CHECK-LABEL: func @condBranchDynamicType49func.func @condBranchDynamicType(50 %arg0: i1,51 %arg1: memref<?xf32>,52 %arg2: memref<?xf32>,53 %arg3: index) {54 cf.cond_br %arg0, ^bb1, ^bb2(%arg3: index)55^bb1:56 cf.br ^bb3(%arg1 : memref<?xf32>)57^bb2(%0: index):58 %1 = memref.alloc(%0) : memref<?xf32>59 test.buffer_based in(%arg1: memref<?xf32>) out(%1: memref<?xf32>)60 cf.br ^bb3(%1 : memref<?xf32>)61^bb3(%2: memref<?xf32>):62 test.copy(%2, %arg2) : (memref<?xf32>, memref<?xf32>)63 return64}65 66// CHECK-NEXT: cf.cond_br67// CHECK: ^bb268// CHECK: ^bb2(%[[IDX:.*]]:{{.*}})69// CHECK-NEXT: %[[ALLOC0:.*]] = memref.alloc(%[[IDX]])70// CHECK-NEXT: test.buffer_based71// CHECK: cf.br ^bb372// CHECK-NEXT: ^bb3(%[[ALLOC0:.*]]:{{.*}})73// CHECK: test.copy(%[[ALLOC0]],74// CHECK-NEXT: return75 76// -----77 78// CHECK-LABEL: func @dynamicRanked79func.func @dynamicRanked(%memref: memref<*xf32>) {80 %0 = memref.rank %memref : memref<*xf32>81 %1 = memref.alloc(%0) : memref<?xindex>82 return83}84 85// CHECK-NEXT: %[[RANK:.*]] = memref.rank %{{.*}} : memref<*xf32>86// CHECK-NEXT: %[[ALLOCA:.*]] = memref.alloca(%[[RANK]])87 88// -----89 90// CHECK-LABEL: func @dynamicRanked2D91func.func @dynamicRanked2D(%memref: memref<*xf32>) {92 %0 = memref.rank %memref : memref<*xf32>93 %1 = memref.alloc(%0, %0) : memref<?x?xindex>94 return95}96 97// CHECK-NEXT: %[[RANK:.*]] = memref.rank %{{.*}} : memref<*xf32>98// RANK-NEXT: %[[ALLOC:.*]] = memref.alloca(%[[RANK]], %[[RANK]])99// DEFINDEX-NEXT: %[[ALLOC:.*]] = memref.alloc(%[[RANK]], %[[RANK]])100 101// -----102 103// CHECK-LABEL: func @dynamicNoRank104func.func @dynamicNoRank(%arg0: index) {105 %0 = memref.alloc(%arg0) : memref<?xindex>106 return107}108 109// CHECK-NEXT: %[[ALLOC:.*]] = memref.alloc110 111// -----112 113// Test Case: Existing AllocOp with no users.114// PromoteBuffersToStack expected behavior: It should convert it to an115// AllocaOp.116 117// CHECK-LABEL: func @emptyUsesValue118func.func @emptyUsesValue(%arg0: memref<4xf32>) {119 %0 = memref.alloc() : memref<4xf32>120 return121}122// CHECK-NEXT: %[[ALLOCA:.*]] = memref.alloca()123// CHECK-NEXT: return124 125// -----126 127// Test Case:128// bb0129// / \130// | bb1 <- Initial position of AllocOp131// \ /132// bb2133// PromoteBuffersToStack expected behavior: It should convert it into an134// AllocaOp.135 136// CHECK-LABEL: func @criticalEdge137func.func @criticalEdge(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {138 cf.cond_br %arg0, ^bb1, ^bb2(%arg1 : memref<2xf32>)139^bb1:140 %0 = memref.alloc() : memref<2xf32>141 test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)142 cf.br ^bb2(%0 : memref<2xf32>)143^bb2(%1: memref<2xf32>):144 test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)145 return146}147 148// CHECK-NEXT: cf.cond_br {{.*}}149// CHECK: ^bb1150// CHECK-NEXT: %[[ALLOCA:.*]] = memref.alloca()151// CHECK: test.copy152// CHECK-NEXT: return153 154// -----155 156// Test Case:157// bb0 <- Initial position of AllocOp158// / \159// | bb1160// \ /161// bb2162// PromoteBuffersToStack expected behavior: It converts the alloc in an alloca.163 164// CHECK-LABEL: func @invCriticalEdge165func.func @invCriticalEdge(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {166 %0 = memref.alloc() : memref<2xf32>167 test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)168 cf.cond_br %arg0, ^bb1, ^bb2(%arg1 : memref<2xf32>)169^bb1:170 cf.br ^bb2(%0 : memref<2xf32>)171^bb2(%1: memref<2xf32>):172 test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)173 return174}175 176// CHECK-NEXT: %[[ALLOCA:.*]] = memref.alloca()177// CHECK: cf.cond_br178// CHECK: test.copy179// CHECK-NEXT: return180 181// -----182 183// Test Case:184// bb0 <- Initial position of the first AllocOp185// / \186// bb1 bb2187// \ /188// bb3 <- Initial position of the second AllocOp189// PromoteBuffersToStack expected behavior: It converts the allocs into allocas.190 191// CHECK-LABEL: func @ifElse192func.func @ifElse(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {193 %0 = memref.alloc() : memref<2xf32>194 test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)195 cf.cond_br %arg0,196 ^bb1(%arg1, %0 : memref<2xf32>, memref<2xf32>),197 ^bb2(%0, %arg1 : memref<2xf32>, memref<2xf32>)198^bb1(%1: memref<2xf32>, %2: memref<2xf32>):199 cf.br ^bb3(%1, %2 : memref<2xf32>, memref<2xf32>)200^bb2(%3: memref<2xf32>, %4: memref<2xf32>):201 cf.br ^bb3(%3, %4 : memref<2xf32>, memref<2xf32>)202^bb3(%5: memref<2xf32>, %6: memref<2xf32>):203 %7 = memref.alloc() : memref<2xf32>204 test.buffer_based in(%5: memref<2xf32>) out(%7: memref<2xf32>)205 test.copy(%7, %arg2) : (memref<2xf32>, memref<2xf32>)206 return207}208 209// CHECK-NEXT: %[[ALLOCA0:.*]] = memref.alloca()210// CHECK-NEXT: test.buffer_based211// CHECK: %[[ALLOCA1:.*]] = memref.alloca()212// CHECK: test.buffer_based213// CHECK: test.copy(%[[ALLOCA1]]214// CHECK-NEXT: return215 216// -----217 218// Test Case: No users for buffer in if-else CFG219// bb0 <- Initial position of AllocOp220// / \221// bb1 bb2222// \ /223// bb3224// PromoteBuffersToStack expected behavior: It converts the alloc into alloca.225 226// CHECK-LABEL: func @ifElseNoUsers227func.func @ifElseNoUsers(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {228 %0 = memref.alloc() : memref<2xf32>229 test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)230 cf.cond_br %arg0,231 ^bb1(%arg1, %0 : memref<2xf32>, memref<2xf32>),232 ^bb2(%0, %arg1 : memref<2xf32>, memref<2xf32>)233^bb1(%1: memref<2xf32>, %2: memref<2xf32>):234 cf.br ^bb3(%1, %2 : memref<2xf32>, memref<2xf32>)235^bb2(%3: memref<2xf32>, %4: memref<2xf32>):236 cf.br ^bb3(%3, %4 : memref<2xf32>, memref<2xf32>)237^bb3(%5: memref<2xf32>, %6: memref<2xf32>):238 test.copy(%arg1, %arg2) : (memref<2xf32>, memref<2xf32>)239 return240}241 242// CHECK-NEXT: %[[ALLOCA:.*]] = memref.alloca()243// CHECK: return244 245// -----246 247// Test Case:248// bb0 <- Initial position of the first AllocOp249// / \250// bb1 bb2251// | / \252// | bb3 bb4253// \ \ /254// \ /255// bb5 <- Initial position of the second AllocOp256// PromoteBuffersToStack expected behavior: The two allocs should be converted257// into allocas.258 259// CHECK-LABEL: func @ifElseNested260func.func @ifElseNested(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {261 %0 = memref.alloc() : memref<2xf32>262 test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)263 cf.cond_br %arg0,264 ^bb1(%arg1, %0 : memref<2xf32>, memref<2xf32>),265 ^bb2(%0, %arg1 : memref<2xf32>, memref<2xf32>)266^bb1(%1: memref<2xf32>, %2: memref<2xf32>):267 cf.br ^bb5(%1, %2 : memref<2xf32>, memref<2xf32>)268^bb2(%3: memref<2xf32>, %4: memref<2xf32>):269 cf.cond_br %arg0, ^bb3(%3 : memref<2xf32>), ^bb4(%4 : memref<2xf32>)270^bb3(%5: memref<2xf32>):271 cf.br ^bb5(%5, %3 : memref<2xf32>, memref<2xf32>)272^bb4(%6: memref<2xf32>):273 cf.br ^bb5(%3, %6 : memref<2xf32>, memref<2xf32>)274^bb5(%7: memref<2xf32>, %8: memref<2xf32>):275 %9 = memref.alloc() : memref<2xf32>276 test.buffer_based in(%7: memref<2xf32>) out(%9: memref<2xf32>)277 test.copy(%9, %arg2) : (memref<2xf32>, memref<2xf32>)278 return279}280 281// CHECK-NEXT: %[[ALLOCA0:.*]] = memref.alloca()282// CHECK-NEXT: test.buffer_based283// CHECK: %[[ALLOCA1:.*]] = memref.alloca()284// CHECK: test.buffer_based285// CHECK: test.copy(%[[ALLOCA1]]286// CHECK-NEXT: return287 288// -----289 290// Test Case: Dead operations in a single block.291// PromoteBuffersToStack expected behavior: It converts the two AllocOps into292// allocas.293 294// CHECK-LABEL: func @redundantOperations295func.func @redundantOperations(%arg0: memref<2xf32>) {296 %0 = memref.alloc() : memref<2xf32>297 test.buffer_based in(%arg0: memref<2xf32>) out(%0: memref<2xf32>)298 %1 = memref.alloc() : memref<2xf32>299 test.buffer_based in(%0: memref<2xf32>) out(%1: memref<2xf32>)300 return301}302 303// CHECK: (%[[ARG0:.*]]: {{.*}})304// CHECK-NEXT: %[[ALLOCA0:.*]] = memref.alloca()305// CHECK-NEXT: test.buffer_based in(%[[ARG0]]{{.*}} out(%[[ALLOCA0]]306// CHECK: %[[ALLOCA1:.*]] = memref.alloca()307// CHECK-NEXT: test.buffer_based in(%[[ALLOCA0]]{{.*}} out(%[[ALLOCA1]]308// CHECK: return309 310// -----311 312// Test Case:313// bb0314// / \315// Initial pos of the 1st AllocOp -> bb1 bb2 <- Initial pos of the 2nd AllocOp316// \ /317// bb3318// PromoteBuffersToStack expected behavior: Both AllocOps are converted into319// allocas.320 321// CHECK-LABEL: func @moving_alloc_and_inserting_missing_dealloc322func.func @moving_alloc_and_inserting_missing_dealloc(323 %cond: i1,324 %arg0: memref<2xf32>,325 %arg1: memref<2xf32>) {326 cf.cond_br %cond, ^bb1, ^bb2327^bb1:328 %0 = memref.alloc() : memref<2xf32>329 test.buffer_based in(%arg0: memref<2xf32>) out(%0: memref<2xf32>)330 cf.br ^exit(%0 : memref<2xf32>)331^bb2:332 %1 = memref.alloc() : memref<2xf32>333 test.buffer_based in(%arg0: memref<2xf32>) out(%1: memref<2xf32>)334 cf.br ^exit(%1 : memref<2xf32>)335^exit(%arg2: memref<2xf32>):336 test.copy(%arg2, %arg1) : (memref<2xf32>, memref<2xf32>)337 return338}339 340// CHECK-NEXT: cf.cond_br {{.*}}341// CHECK: ^bb1342// CHECK-NEXT: %{{.*}} = memref.alloca()343// CHECK: ^bb2344// CHECK-NEXT: %{{.*}} = memref.alloca()345// CHECK: test.copy346// CHECK-NEXT: return347 348// -----349 350// Test Case: Nested regions - This test defines a BufferBasedOp inside the351// region of a RegionBufferBasedOp.352// PromoteBuffersToStack expected behavior: The AllocOps are converted into353// allocas.354 355// CHECK-LABEL: func @nested_regions_and_cond_branch356func.func @nested_regions_and_cond_branch(357 %arg0: i1,358 %arg1: memref<2xf32>,359 %arg2: memref<2xf32>) {360 cf.cond_br %arg0, ^bb1, ^bb2361^bb1:362 cf.br ^bb3(%arg1 : memref<2xf32>)363^bb2:364 %0 = memref.alloc() : memref<2xf32>365 test.region_buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>) {366 ^bb0(%gen1_arg0: f32, %gen1_arg1: f32):367 %1 = memref.alloc() : memref<2xf32>368 test.buffer_based in(%arg1: memref<2xf32>) out(%1: memref<2xf32>)369 %tmp1 = math.exp %gen1_arg0 : f32370 test.region_yield %tmp1 : f32371 }372 cf.br ^bb3(%0 : memref<2xf32>)373^bb3(%1: memref<2xf32>):374 test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)375 return376}377 378// CHECK-NEXT: cf.cond_br {{.*}}379// CHECK: ^bb2380// CHECK-NEXT: %[[ALLOCA0:.*]] = memref.alloca()381// CHECK: ^bb0382// CHECK-NEXT: %[[ALLOCA1:.*]] = memref.alloc()383 384// -----385 386// Test Case: buffer deallocation escaping387// PromoteBuffersToStack expected behavior: The first alloc is returned, so388// there is no conversion allowed. The second alloc is converted, since it389// only remains in the scope of the function.390 391// CHECK-LABEL: func @memref_in_function_results392func.func @memref_in_function_results(393 %arg0: memref<5xf32>,394 %arg1: memref<10xf32>,395 %arg2: memref<5xf32>) -> (memref<10xf32>, memref<15xf32>) {396 %x = memref.alloc() : memref<15xf32>397 %y = memref.alloc() : memref<5xf32>398 test.buffer_based in(%arg0: memref<5xf32>) out(%y: memref<5xf32>)399 test.copy(%y, %arg2) : (memref<5xf32>, memref<5xf32>)400 return %arg1, %x : memref<10xf32>, memref<15xf32>401}402// CHECK: (%[[ARG0:.*]]: memref<5xf32>, %[[ARG1:.*]]: memref<10xf32>,403// CHECK-SAME: %[[RESULT:.*]]: memref<5xf32>)404// CHECK: %[[ALLOC:.*]] = memref.alloc()405// CHECK: %[[ALLOCA:.*]] = memref.alloca()406// CHECK: test.copy407// CHECK: return %[[ARG1]], %[[ALLOC]]408 409// -----410 411// Test Case: nested region control flow412// The allocation in the nested if branch cannot be converted to an alloca413// due to its dynamic memory allocation behavior.414 415// CHECK-LABEL: func @nested_region_control_flow416func.func @nested_region_control_flow(417 %arg0 : index,418 %arg1 : index) -> memref<?x?xf32> {419 %0 = arith.cmpi eq, %arg0, %arg1 : index420 %1 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>421 %2 = scf.if %0 -> (memref<?x?xf32>) {422 scf.yield %1 : memref<?x?xf32>423 } else {424 %3 = memref.alloc(%arg0, %arg1) : memref<?x?xf32>425 scf.yield %1 : memref<?x?xf32>426 }427 return %2 : memref<?x?xf32>428}429 430// CHECK: %[[ALLOC0:.*]] = memref.alloc(%arg0, %arg0)431// CHECK-NEXT: %[[ALLOC1:.*]] = scf.if432// CHECK: scf.yield %[[ALLOC0]]433// CHECK: %[[ALLOC2:.*]] = memref.alloc(%arg0, %arg1)434// CHECK-NEXT: scf.yield %[[ALLOC0]]435// CHECK: return %[[ALLOC1]]436 437// -----438 439// Test Case: nested region control flow within a region interface.440// The alloc %0 does not need to be converted in this case since the441// allocation finally escapes the method.442 443// CHECK-LABEL: func @inner_region_control_flow444func.func @inner_region_control_flow(%arg0 : index) -> memref<2x2xf32> {445 %0 = memref.alloc() : memref<2x2xf32>446 %1 = test.region_if %0 : memref<2x2xf32> -> (memref<2x2xf32>) then {447 ^bb0(%arg1 : memref<2x2xf32>):448 test.region_if_yield %arg1 : memref<2x2xf32>449 } else {450 ^bb0(%arg1 : memref<2x2xf32>):451 test.region_if_yield %arg1 : memref<2x2xf32>452 } join {453 ^bb0(%arg1 : memref<2x2xf32>):454 test.region_if_yield %arg1 : memref<2x2xf32>455 }456 return %1 : memref<2x2xf32>457}458 459// CHECK: %[[ALLOC0:.*]] = memref.alloc()460// CHECK-NEXT: %[[ALLOC1:.*]] = test.region_if461// CHECK-NEXT: ^bb0(%[[ALLOC2:.*]]:{{.*}}):462// CHECK-NEXT: test.region_if_yield %[[ALLOC2]]463// CHECK: ^bb0(%[[ALLOC3:.*]]:{{.*}}):464// CHECK-NEXT: test.region_if_yield %[[ALLOC3]]465// CHECK: ^bb0(%[[ALLOC4:.*]]:{{.*}}):466// CHECK-NEXT: test.region_if_yield %[[ALLOC4]]467// CHECK: return %[[ALLOC1]]468 469// -----470 471// Test Case: structured control-flow loop using a nested alloc.472// Alloc %0 will be converted to an alloca. %3 is not transformed.473 474// CHECK-LABEL: func @loop_alloc475func.func @loop_alloc(476 %lb: index,477 %ub: index,478 %step: index,479 %buf: memref<2xf32>,480 %res: memref<2xf32>) {481 %0 = memref.alloc() : memref<2xf32>482 %1 = scf.for %i = %lb to %ub step %step483 iter_args(%iterBuf = %buf) -> memref<2xf32> {484 %2 = arith.cmpi eq, %i, %ub : index485 %3 = memref.alloc() : memref<2xf32>486 scf.yield %3 : memref<2xf32>487 }488 test.copy(%1, %res) : (memref<2xf32>, memref<2xf32>)489 return490}491 492// CHECK-NEXT: %[[ALLOCA:.*]] = memref.alloca()493// CHECK-NEXT: scf.for494// CHECK: %[[ALLOC:.*]] = memref.alloc()495 496// -----497 498// Test Case: structured control-flow loop with a nested if operation.499// The loop yields buffers that have been defined outside of the loop and the500// backedges only use the iteration arguments (or one of its aliases).501// Therefore, we do not have to (and are not allowed to) free any buffers502// that are passed via the backedges. The alloc is converted to an AllocaOp.503 504// CHECK-LABEL: func @loop_nested_if_no_alloc505func.func @loop_nested_if_no_alloc(506 %lb: index,507 %ub: index,508 %step: index,509 %buf: memref<2xf32>,510 %res: memref<2xf32>) {511 %0 = memref.alloc() : memref<2xf32>512 %1 = scf.for %i = %lb to %ub step %step513 iter_args(%iterBuf = %buf) -> memref<2xf32> {514 %2 = arith.cmpi eq, %i, %ub : index515 %3 = scf.if %2 -> (memref<2xf32>) {516 scf.yield %0 : memref<2xf32>517 } else {518 scf.yield %iterBuf : memref<2xf32>519 }520 scf.yield %3 : memref<2xf32>521 }522 test.copy(%1, %res) : (memref<2xf32>, memref<2xf32>)523 return524}525 526// CHECK: %[[ALLOCA0:.*]] = memref.alloca()527// CHECK-NEXT: %[[ALLOCA1:.*]] = scf.for {{.*}} iter_args(%[[IALLOCA:.*]] =528// CHECK: %[[ALLOCA2:.*]] = scf.if529// CHECK: scf.yield %[[ALLOCA0]]530// CHECK: scf.yield %[[IALLOCA]]531// CHECK: scf.yield %[[ALLOCA2]]532// CHECK: test.copy(%[[ALLOCA1]], %arg4)533 534// -----535 536// Test Case: structured control-flow loop with a nested if operation using537// a deeply nested buffer allocation.538// The allocs are not converted in this case.539 540// CHECK-LABEL: func @loop_nested_if_alloc541func.func @loop_nested_if_alloc(542 %lb: index,543 %ub: index,544 %step: index,545 %buf: memref<2xf32>) -> memref<2xf32> {546 %0 = memref.alloc() : memref<2xf32>547 %1 = scf.for %i = %lb to %ub step %step548 iter_args(%iterBuf = %buf) -> memref<2xf32> {549 %2 = arith.cmpi eq, %i, %ub : index550 %3 = scf.if %2 -> (memref<2xf32>) {551 %4 = memref.alloc() : memref<2xf32>552 scf.yield %4 : memref<2xf32>553 } else {554 scf.yield %0 : memref<2xf32>555 }556 scf.yield %3 : memref<2xf32>557 }558 return %1 : memref<2xf32>559}560 561// CHECK: %[[ALLOC0:.*]] = memref.alloc()562// CHECK-NEXT: %[[ALLOC1:.*]] = scf.for {{.*}}563// CHECK: %[[ALLOC2:.*]] = scf.if564// CHECK: %[[ALLOC3:.*]] = memref.alloc()565// CHECK-NEXT: scf.yield %[[ALLOC3]]566// CHECK: scf.yield %[[ALLOC0]]567// CHECK: scf.yield %[[ALLOC2]]568// CHECK: return %[[ALLOC1]]569 570// -----571 572// Test Case: The allocated buffer is too large and, hence, it is not573// converted. In the actual implementation the largest size is 1KB.574 575// CHECK-LABEL: func @large_buffer_allocation576func.func @large_buffer_allocation(%arg0: memref<2048xf32>) {577 %0 = memref.alloc() : memref<2048xf32>578 test.copy(%0, %arg0) : (memref<2048xf32>, memref<2048xf32>)579 return580}581 582// CHECK-NEXT: %[[ALLOC:.*]] = memref.alloc()583// CHECK-NEXT: test.copy584 585// -----586 587// Test Case: AllocOp with element type index.588// PromoteBuffersToStack expected behavior: It should convert it to an589// AllocaOp.590 591// CHECK-LABEL: func @indexElementType592func.func @indexElementType() {593 %0 = memref.alloc() : memref<4xindex>594 return595}596// DEFINDEX-NEXT: memref.alloca()597// LOWLIMIT-NEXT: memref.alloca()598// RANK-NEXT: memref.alloca()599// CHECK-NEXT: return600 601// -----602 603// CHECK-LABEL: func @bigIndexElementType604module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 256>>} {605 func.func @bigIndexElementType() {606 %0 = memref.alloc() {alignment = 64 : i64, custom_attr} : memref<4xindex>607 return608 }609}610// DEFINDEX-NEXT: memref.alloca() {alignment = 64 : i64, custom_attr}611// LOWLIMIT-NEXT: memref.alloc() {alignment = 64 : i64, custom_attr}612// RANK-NEXT: memref.alloca() {alignment = 64 : i64, custom_attr}613// CHECK-NEXT: return614