1cc14bf22STom Eccles// RUN: fir-opt --stack-arrays %s | FileCheck %s 2cc14bf22STom Eccles 3cc14bf22STom Eccles// Simplest transformation 4cc14bf22STom Ecclesfunc.func @simple() { 5cc14bf22STom Eccles %0 = fir.allocmem !fir.array<42xi32> 6cc14bf22STom Eccles fir.freemem %0 : !fir.heap<!fir.array<42xi32>> 7cc14bf22STom Eccles return 8cc14bf22STom Eccles} 9cc14bf22STom Eccles// CHECK: func.func @simple() { 10cc14bf22STom Eccles// CHECK-NEXT: fir.alloca !fir.array<42xi32> 11cc14bf22STom Eccles// CHECK-NEXT: return 12cc14bf22STom Eccles// CHECK-NEXT: } 13cc14bf22STom Eccles 14cc14bf22STom Eccles// Check fir.must_be_heap allocations are not moved 15cc14bf22STom Ecclesfunc.func @must_be_heap() { 16cc14bf22STom Eccles %0 = fir.allocmem !fir.array<42xi32> {fir.must_be_heap = true} 17cc14bf22STom Eccles fir.freemem %0 : !fir.heap<!fir.array<42xi32>> 18cc14bf22STom Eccles return 19cc14bf22STom Eccles} 20cc14bf22STom Eccles// CHECK: func.func @must_be_heap() { 21cc14bf22STom Eccles// CHECK-NEXT: %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32> {fir.must_be_heap = true} 22cc14bf22STom Eccles// CHECK-NEXT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<42xi32>> 23cc14bf22STom Eccles// CHECK-NEXT: return 24cc14bf22STom Eccles// CHECK-NEXT: } 25cc14bf22STom Eccles 26cc14bf22STom Eccles// Check the data-flow-analysis can detect cases where we aren't sure if memory 27cc14bf22STom Eccles// is freed by the end of the function 28cc14bf22STom Ecclesfunc.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) { 29cc14bf22STom Eccles %7 = arith.constant 42 : index 30cc14bf22STom Eccles %8 = fir.allocmem !fir.array<?xi32>, %7 {uniq_name = "_QFdfa1Earr.alloc"} 31cc14bf22STom Eccles %9 = fir.load %arg0 : !fir.ref<!fir.logical<4>> 32cc14bf22STom Eccles %10 = fir.convert %9 : (!fir.logical<4>) -> i1 33cc14bf22STom Eccles fir.if %10 { 34cc14bf22STom Eccles fir.freemem %8 : !fir.heap<!fir.array<?xi32>> 35cc14bf22STom Eccles } else { 36cc14bf22STom Eccles } 37cc14bf22STom Eccles return 38cc14bf22STom Eccles} 39cc14bf22STom Eccles// CHECK: func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) { 40cc14bf22STom Eccles// CHECK-NEXT: %[[C42:.*]] = arith.constant 42 : index 41cc14bf22STom Eccles// CHECK-NEXT: %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[C42]] {uniq_name = "_QFdfa1Earr.alloc"} 42cc14bf22STom Eccles// CHECK-NEXT: %[[LOGICAL:.*]] = fir.load %arg0 : !fir.ref<!fir.logical<4>> 43cc14bf22STom Eccles// CHECK-NEXT: %[[BOOL:.*]] = fir.convert %[[LOGICAL]] : (!fir.logical<4>) -> i1 44cc14bf22STom Eccles// CHECK-NEXT: fir.if %[[BOOL]] { 45cc14bf22STom Eccles// CHECK-NEXT: fir.freemem %[[MEM]] : !fir.heap<!fir.array<?xi32>> 46cc14bf22STom Eccles// CHECK-NEXT: } else { 47cc14bf22STom Eccles// CHECK-NEXT: } 48cc14bf22STom Eccles// CHECK-NEXT: return 49cc14bf22STom Eccles// CHECK-NEXT: } 50cc14bf22STom Eccles 511b0ec398SSacha Ballantyne// Check scf.if 52cc14bf22STom Ecclesfunc.func @dfa2(%arg0: i1) { 53cc14bf22STom Eccles %a = fir.allocmem !fir.array<1xi8> 54cc14bf22STom Eccles scf.if %arg0 { 55cc14bf22STom Eccles fir.freemem %a : !fir.heap<!fir.array<1xi8>> 56cc14bf22STom Eccles } else { 57cc14bf22STom Eccles } 58cc14bf22STom Eccles return 59cc14bf22STom Eccles} 60cc14bf22STom Eccles// CHECK: func.func @dfa2(%arg0: i1) { 61cc14bf22STom Eccles// CHECK-NEXT: %[[MEM:.*]] = fir.allocmem !fir.array<1xi8> 62cc14bf22STom Eccles// CHECK-NEXT: scf.if %arg0 { 63cc14bf22STom Eccles// CHECK-NEXT: fir.freemem %[[MEM]] : !fir.heap<!fir.array<1xi8>> 64cc14bf22STom Eccles// CHECK-NEXT: } else { 65cc14bf22STom Eccles// CHECK-NEXT: } 66cc14bf22STom Eccles// CHECK-NEXT: return 67cc14bf22STom Eccles// CHECK-NEXT: } 68cc14bf22STom Eccles 691b0ec398SSacha Ballantyne// Check freemem in both regions 701b0ec398SSacha Ballantynefunc.func @dfa3(%arg0: i1) { 711b0ec398SSacha Ballantyne %a = fir.allocmem !fir.array<1xi8> 721b0ec398SSacha Ballantyne fir.if %arg0 { 731b0ec398SSacha Ballantyne fir.freemem %a : !fir.heap<!fir.array<1xi8>> 741b0ec398SSacha Ballantyne } else { 751b0ec398SSacha Ballantyne fir.freemem %a : !fir.heap<!fir.array<1xi8>> 761b0ec398SSacha Ballantyne } 771b0ec398SSacha Ballantyne return 781b0ec398SSacha Ballantyne} 791b0ec398SSacha Ballantyne// CHECK: func.func @dfa3(%arg0: i1) { 801b0ec398SSacha Ballantyne// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<1xi8> 811b0ec398SSacha Ballantyne// CHECK-NEXT: fir.if %arg0 { 821b0ec398SSacha Ballantyne// CHECK-NEXT: } else { 831b0ec398SSacha Ballantyne// CHECK-NEXT: } 841b0ec398SSacha Ballantyne// CHECK-NEXT: return 851b0ec398SSacha Ballantyne// CHECK-NEXT: } 861b0ec398SSacha Ballantyne 87408f4196STom Ecclesfunc.func private @dfa3a_foo(!fir.ref<!fir.array<1xi8>>) -> () 88408f4196STom Ecclesfunc.func private @dfa3a_bar(!fir.ref<!fir.array<1xi8>>) -> () 89408f4196STom Eccles 90408f4196STom Eccles// Check freemem in both regions, with other uses 91408f4196STom Ecclesfunc.func @dfa3a(%arg0: i1) { 92408f4196STom Eccles %a = fir.allocmem !fir.array<1xi8> 93408f4196STom Eccles fir.if %arg0 { 94408f4196STom Eccles %ref = fir.convert %a : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>> 95408f4196STom Eccles func.call @dfa3a_foo(%ref) : (!fir.ref<!fir.array<1xi8>>) -> () 96408f4196STom Eccles fir.freemem %a : !fir.heap<!fir.array<1xi8>> 97408f4196STom Eccles } else { 98408f4196STom Eccles %ref = fir.convert %a : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>> 99408f4196STom Eccles func.call @dfa3a_bar(%ref) : (!fir.ref<!fir.array<1xi8>>) -> () 100408f4196STom Eccles fir.freemem %a : !fir.heap<!fir.array<1xi8>> 101408f4196STom Eccles } 102408f4196STom Eccles return 103408f4196STom Eccles} 104408f4196STom Eccles// CHECK: func.func @dfa3a(%arg0: i1) { 105408f4196STom Eccles// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<1xi8> 106775de675STom Eccles// CHECK-NEXT: %[[HEAP:.*]] = fir.convert %[[MEM]] : (!fir.ref<!fir.array<1xi8>>) -> !fir.heap<!fir.array<1xi8>> 107408f4196STom Eccles// CHECK-NEXT: fir.if %arg0 { 108775de675STom Eccles// CHECK-NEXT: %[[REF:.*]] = fir.convert %[[HEAP]] : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>> 109775de675STom Eccles// CHECK-NEXT: func.call @dfa3a_foo(%[[REF]]) 110408f4196STom Eccles// CHECK-NEXT: } else { 111775de675STom Eccles// CHECK-NEXT: %[[REF:.*]] = fir.convert %[[HEAP]] : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>> 112775de675STom Eccles// CHECK-NEXT: func.call @dfa3a_bar(%[[REF]]) 113408f4196STom Eccles// CHECK-NEXT: } 114408f4196STom Eccles// CHECK-NEXT: return 115408f4196STom Eccles// CHECK-NEXT: } 116408f4196STom Eccles 117cc14bf22STom Eccles// check the alloca is placed after all operands become available 118cc14bf22STom Ecclesfunc.func @placement1() { 119cc14bf22STom Eccles // do some stuff with other ssa values 120cc14bf22STom Eccles %1 = arith.constant 1 : index 121cc14bf22STom Eccles %2 = arith.constant 2 : index 122cc14bf22STom Eccles %3 = arith.addi %1, %2 : index 123cc14bf22STom Eccles // operand is now available 124cc14bf22STom Eccles %4 = fir.allocmem !fir.array<?xi32>, %3 125cc14bf22STom Eccles // ... 126cc14bf22STom Eccles fir.freemem %4 : !fir.heap<!fir.array<?xi32>> 127cc14bf22STom Eccles return 128cc14bf22STom Eccles} 129cc14bf22STom Eccles// CHECK: func.func @placement1() { 130ddc98929Smlevesquedion// CHECK-NEXT: %[[ARG:.*]] = arith.constant 3 : index 131cc14bf22STom Eccles// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[ARG]] 132cc14bf22STom Eccles// CHECK-NEXT: return 133cc14bf22STom Eccles// CHECK-NEXT: } 134cc14bf22STom Eccles 135cc14bf22STom Eccles// check that if there are no operands, then the alloca is placed early 136cc14bf22STom Ecclesfunc.func @placement2() { 137cc14bf22STom Eccles // do some stuff with other ssa values 138cc14bf22STom Eccles %1 = arith.constant 1 : index 139cc14bf22STom Eccles %2 = arith.constant 2 : index 140cc14bf22STom Eccles %3 = arith.addi %1, %2 : index 141cc14bf22STom Eccles %4 = fir.allocmem !fir.array<42xi32> 142cc14bf22STom Eccles // ... 143cc14bf22STom Eccles fir.freemem %4 : !fir.heap<!fir.array<42xi32>> 144cc14bf22STom Eccles return 145cc14bf22STom Eccles} 146cc14bf22STom Eccles// CHECK: func.func @placement2() { 147cc14bf22STom Eccles// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<42xi32> 148cc14bf22STom Eccles// CHECK-NEXT: %[[ONE:.*]] = arith.constant 1 : index 149cc14bf22STom Eccles// CHECK-NEXT: %[[TWO:.*]] = arith.constant 2 : index 150cc14bf22STom Eccles// CHECK-NEXT: %[[SUM:.*]] = arith.addi %[[ONE]], %[[TWO]] : index 151cc14bf22STom Eccles// CHECK-NEXT: return 152cc14bf22STom Eccles// CHECK-NEXT: } 153cc14bf22STom Eccles 154cc14bf22STom Eccles// check that stack allocations which must be placed in loops use stacksave 155cc14bf22STom Ecclesfunc.func @placement3() { 156cc14bf22STom Eccles %c1 = arith.constant 1 : index 157cc14bf22STom Eccles %c1_i32 = fir.convert %c1 : (index) -> i32 158cc14bf22STom Eccles %c2 = arith.constant 2 : index 159cc14bf22STom Eccles %c10 = arith.constant 10 : index 160cc14bf22STom Eccles %0:2 = fir.do_loop %arg0 = %c1 to %c10 step %c1 iter_args(%arg1 = %c1_i32) -> (index, i32) { 161cc14bf22STom Eccles %3 = arith.addi %c1, %c2 : index 162cc14bf22STom Eccles // operand is now available 163cc14bf22STom Eccles %4 = fir.allocmem !fir.array<?xi32>, %3 164cc14bf22STom Eccles // ... 165cc14bf22STom Eccles fir.freemem %4 : !fir.heap<!fir.array<?xi32>> 166cc14bf22STom Eccles fir.result %3, %c1_i32 : index, i32 167cc14bf22STom Eccles } 168cc14bf22STom Eccles return 169cc14bf22STom Eccles} 170cc14bf22STom Eccles// CHECK: func.func @placement3() { 171cc14bf22STom Eccles// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index 172cc14bf22STom Eccles// CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32 173cc14bf22STom Eccles// CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index 174cc14bf22STom Eccles// CHECK-NEXT: %[[C10:.*]] = arith.constant 10 : index 175cc14bf22STom Eccles// CHECK-NEXT: fir.do_loop 176cc14bf22STom Eccles// CHECK-NEXT: %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index 1775aaf384bSTom Eccles// CHECK-NEXT: %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr 178cc14bf22STom Eccles// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[SUM]] 1795aaf384bSTom Eccles// CHECK-NEXT: llvm.intr.stackrestore %[[SP]] : !llvm.ptr 180cc14bf22STom Eccles// CHECK-NEXT: fir.result 181cc14bf22STom Eccles// CHECK-NEXT: } 182cc14bf22STom Eccles// CHECK-NEXT: return 183cc14bf22STom Eccles// CHECK-NEXT: } 184cc14bf22STom Eccles 185cc14bf22STom Eccles// check that stack save/restore are used in CFG loops 186cc14bf22STom Ecclesfunc.func @placement4(%arg0 : i1) { 187cc14bf22STom Eccles %c1 = arith.constant 1 : index 188cc14bf22STom Eccles %c1_i32 = fir.convert %c1 : (index) -> i32 189cc14bf22STom Eccles %c2 = arith.constant 2 : index 190cc14bf22STom Eccles %c10 = arith.constant 10 : index 191cc14bf22STom Eccles cf.br ^bb1 192cc14bf22STom Eccles^bb1: 193cc14bf22STom Eccles %3 = arith.addi %c1, %c2 : index 194cc14bf22STom Eccles // operand is now available 195cc14bf22STom Eccles %4 = fir.allocmem !fir.array<?xi32>, %3 196cc14bf22STom Eccles // ... 197cc14bf22STom Eccles fir.freemem %4 : !fir.heap<!fir.array<?xi32>> 198cc14bf22STom Eccles cf.cond_br %arg0, ^bb1, ^bb2 199cc14bf22STom Eccles^bb2: 200cc14bf22STom Eccles return 201cc14bf22STom Eccles} 202cc14bf22STom Eccles// CHECK: func.func @placement4(%arg0: i1) { 203cc14bf22STom Eccles// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index 204cc14bf22STom Eccles// CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32 205cc14bf22STom Eccles// CHECK-NEXT: %[[C10:.*]] = arith.constant 10 : index 206cc14bf22STom Eccles// CHECK-NEXT: cf.br ^bb1 207cc14bf22STom Eccles// CHECK-NEXT: ^bb1: 208ddc98929Smlevesquedion// CHECK-NEXT: %[[C3:.*]] = arith.constant 3 : index 2095aaf384bSTom Eccles// CHECK-NEXT: %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr 210ddc98929Smlevesquedion// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[C3]] 2115aaf384bSTom Eccles// CHECK-NEXT: llvm.intr.stackrestore %[[SP]] : !llvm.ptr 212cc14bf22STom Eccles// CHECK-NEXT: cf.cond_br %arg0, ^bb1, ^bb2 213cc14bf22STom Eccles// CHECK-NEXT: ^bb2: 214cc14bf22STom Eccles// CHECK-NEXT: return 215cc14bf22STom Eccles// CHECK-NEXT: } 216cc14bf22STom Eccles 217cc14bf22STom Eccles// check that stacksave is not used when there is an intervening alloca 218cc14bf22STom Ecclesfunc.func @placement5() { 219cc14bf22STom Eccles %c1 = arith.constant 1 : index 220cc14bf22STom Eccles %c1_i32 = fir.convert %c1 : (index) -> i32 221cc14bf22STom Eccles %c2 = arith.constant 2 : index 222cc14bf22STom Eccles %c10 = arith.constant 10 : index 223cc14bf22STom Eccles %0:2 = fir.do_loop %arg0 = %c1 to %c10 step %c1 iter_args(%arg1 = %c1_i32) -> (index, i32) { 224cc14bf22STom Eccles %3 = arith.addi %c1, %c2 : index 225cc14bf22STom Eccles // operand is now available 226cc14bf22STom Eccles %4 = fir.allocmem !fir.array<?xi32>, %3 227cc14bf22STom Eccles %5 = fir.alloca i32 228cc14bf22STom Eccles fir.freemem %4 : !fir.heap<!fir.array<?xi32>> 229cc14bf22STom Eccles fir.result %3, %c1_i32 : index, i32 230cc14bf22STom Eccles } 231cc14bf22STom Eccles return 232cc14bf22STom Eccles} 233cc14bf22STom Eccles// CHECK: func.func @placement5() { 234cc14bf22STom Eccles// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index 235cc14bf22STom Eccles// CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32 236cc14bf22STom Eccles// CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index 237cc14bf22STom Eccles// CHECK-NEXT: %[[C10:.*]] = arith.constant 10 : index 238cc14bf22STom Eccles// CHECK-NEXT: fir.do_loop 239cc14bf22STom Eccles// CHECK-NEXT: %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index 240cc14bf22STom Eccles// CHECK-NEXT: %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[SUM]] 241cc14bf22STom Eccles// CHECK-NEXT: %[[IDX:.*]] = fir.alloca i32 242cc14bf22STom Eccles// CHECK-NEXT: fir.freemem %[[MEM]] : !fir.heap<!fir.array<?xi32>> 243cc14bf22STom Eccles// CHECK-NEXT: fir.result 244cc14bf22STom Eccles// CHECK-NEXT: } 245cc14bf22STom Eccles// CHECK-NEXT: return 246cc14bf22STom Eccles// CHECK-NEXT: } 247cc14bf22STom Eccles 248cc14bf22STom Eccles// check that stack save/restore are not used when the memalloc and freemem are 249cc14bf22STom Eccles// in different blocks 250cc14bf22STom Ecclesfunc.func @placement6(%arg0: i1) { 251cc14bf22STom Eccles %c1 = arith.constant 1 : index 252cc14bf22STom Eccles %c1_i32 = fir.convert %c1 : (index) -> i32 253cc14bf22STom Eccles %c2 = arith.constant 2 : index 254cc14bf22STom Eccles %c10 = arith.constant 10 : index 255cc14bf22STom Eccles cf.br ^bb1 256cc14bf22STom Eccles^bb1: 257cc14bf22STom Eccles %3 = arith.addi %c1, %c2 : index 258cc14bf22STom Eccles // operand is now available 259cc14bf22STom Eccles %4 = fir.allocmem !fir.array<?xi32>, %3 260cc14bf22STom Eccles // ... 261cc14bf22STom Eccles cf.cond_br %arg0, ^bb2, ^bb3 262cc14bf22STom Eccles^bb2: 263cc14bf22STom Eccles // ... 264cc14bf22STom Eccles fir.freemem %4 : !fir.heap<!fir.array<?xi32>> 265cc14bf22STom Eccles cf.br ^bb1 266cc14bf22STom Eccles^bb3: 267cc14bf22STom Eccles // ... 268cc14bf22STom Eccles fir.freemem %4 : !fir.heap<!fir.array<?xi32>> 269cc14bf22STom Eccles cf.br ^bb1 270cc14bf22STom Eccles} 271cc14bf22STom Eccles// CHECK: func.func @placement6(%arg0: i1) { 272cc14bf22STom Eccles// CHECK-NEXT: %[[c1:.*]] = arith.constant 1 : index 273cc14bf22STom Eccles// CHECK-NEXT: %[[c1_i32:.*]] = fir.convert %[[c1]] : (index) -> i32 274cc14bf22STom Eccles// CHECK-NEXT: %[[c2:.*]] = arith.constant 2 : index 275cc14bf22STom Eccles// CHECK-NEXT: %[[c10:.*]] = arith.constant 10 : index 276cc14bf22STom Eccles// CHECK-NEXT: cf.br ^bb1 277cc14bf22STom Eccles// CHECK-NEXT: ^bb1: 278cc14bf22STom Eccles// CHECK-NEXT: %[[ADD:.*]] = arith.addi %[[c1]], %[[c2]] : index 279cc14bf22STom Eccles// CHECK-NEXT: %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[ADD]] 280cc14bf22STom Eccles// CHECK-NEXT: cf.cond_br %arg0, ^bb2, ^bb3 281cc14bf22STom Eccles// CHECK-NEXT: ^bb2: 282cc14bf22STom Eccles// CHECK-NEXT: fir.freemem %[[MEM]] : !fir.heap<!fir.array<?xi32>> 283cc14bf22STom Eccles// CHECK-NEXT: cf.br ^bb1 284cc14bf22STom Eccles// CHECK-NEXT: ^bb3: 285cc14bf22STom Eccles// CHECK-NEXT: fir.freemem %[[MEM]] : !fir.heap<!fir.array<?xi32>> 286cc14bf22STom Eccles// CHECK-NEXT: cf.br ^bb1 287cc14bf22STom Eccles// CHECK-NEXT: } 288cc14bf22STom Eccles 289cc14bf22STom Eccles// Check multiple returns, where the memory is always freed 290cc14bf22STom Ecclesfunc.func @returns(%arg0: i1) { 291cc14bf22STom Eccles %0 = fir.allocmem !fir.array<42xi32> 292cc14bf22STom Eccles cf.cond_br %arg0, ^bb1, ^bb2 293cc14bf22STom Eccles^bb1: 294cc14bf22STom Eccles fir.freemem %0 : !fir.heap<!fir.array<42xi32>> 295cc14bf22STom Eccles return 296cc14bf22STom Eccles^bb2: 297cc14bf22STom Eccles fir.freemem %0 : !fir.heap<!fir.array<42xi32>> 298cc14bf22STom Eccles return 299cc14bf22STom Eccles} 300cc14bf22STom Eccles// CHECK: func.func @returns(%[[COND:.*]]: i1) { 301cc14bf22STom Eccles// CHECK-NEXT: %[[ALLOC:.*]] = fir.alloca !fir.array<42xi32> 302cc14bf22STom Eccles// CHECK-NEXT: cf.cond_br %[[COND]], ^bb1, ^bb2 303cc14bf22STom Eccles// CHECK-NEXT: ^bb1: 304cc14bf22STom Eccles// CHECK-NEXT: return 305cc14bf22STom Eccles// CHECK-NEXT: ^bb2: 306cc14bf22STom Eccles// CHECK-NEXT: return 307cc14bf22STom Eccles// CHECK-NEXT: } 308cc14bf22STom Eccles 309cc14bf22STom Eccles// Check multiple returns, where the memory is not freed on one branch 310cc14bf22STom Ecclesfunc.func @returns2(%arg0: i1) { 311cc14bf22STom Eccles %0 = fir.allocmem !fir.array<42xi32> 312cc14bf22STom Eccles cf.cond_br %arg0, ^bb1, ^bb2 313cc14bf22STom Eccles^bb1: 314cc14bf22STom Eccles fir.freemem %0 : !fir.heap<!fir.array<42xi32>> 315cc14bf22STom Eccles return 316cc14bf22STom Eccles^bb2: 317cc14bf22STom Eccles return 318cc14bf22STom Eccles} 319cc14bf22STom Eccles// CHECK: func.func @returns2(%[[COND:.*]]: i1) { 320cc14bf22STom Eccles// CHECK-NEXT: %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32> 321cc14bf22STom Eccles// CHECK-NEXT: cf.cond_br %[[COND]], ^bb1, ^bb2 322cc14bf22STom Eccles// CHECK-NEXT: ^bb1: 323cc14bf22STom Eccles// CHECK-NEXT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<42xi32>> 324cc14bf22STom Eccles// CHECK-NEXT: return 325cc14bf22STom Eccles// CHECK-NEXT: ^bb2: 326cc14bf22STom Eccles// CHECK-NEXT: return 327cc14bf22STom Eccles// CHECK-NEXT: } 328cc14bf22STom Eccles 329cc14bf22STom Eccles// Check allocations are not moved outside of an omp region 330cc14bf22STom Ecclesfunc.func @omp_placement1() { 331cc14bf22STom Eccles omp.sections { 332cc14bf22STom Eccles omp.section { 333cc14bf22STom Eccles %mem = fir.allocmem !fir.array<42xi32> 334cc14bf22STom Eccles fir.freemem %mem : !fir.heap<!fir.array<42xi32>> 335cc14bf22STom Eccles omp.terminator 336cc14bf22STom Eccles } 337cc14bf22STom Eccles omp.terminator 338cc14bf22STom Eccles } 339cc14bf22STom Eccles return 340cc14bf22STom Eccles} 341cc14bf22STom Eccles// CHECK: func.func @omp_placement1() { 342464d321eSKareem Ergawy// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<42xi32> 343464d321eSKareem Ergawy// CHECK-NEXT: %[[MEM_CONV:.*]] = fir.convert %[[MEM]] : (!fir.ref<!fir.array<42xi32>>) -> !fir.heap<!fir.array<42xi32>> 344cc14bf22STom Eccles// CHECK-NEXT: omp.sections { 345cc14bf22STom Eccles// CHECK-NEXT: omp.section { 346cc14bf22STom Eccles// CHECK-NEXT: omp.terminator 347cc14bf22STom Eccles// CHECK-NEXT: } 348cc14bf22STom Eccles// CHECK-NEXT: omp.terminator 349cc14bf22STom Eccles// CHECK-NEXT: } 350cc14bf22STom Eccles// CHECK-NEXT: return 351cc14bf22STom Eccles// CHECK-NEXT: } 3527a49d50fSTom Eccles 3537a49d50fSTom Eccles// function terminated by stop statement 3547a49d50fSTom Ecclesfunc.func @stop_terminator() { 3557a49d50fSTom Eccles %0 = fir.allocmem !fir.array<42xi32> 3567a49d50fSTom Eccles fir.freemem %0 : !fir.heap<!fir.array<42xi32>> 3577a49d50fSTom Eccles %c0_i32 = arith.constant 0 : i32 3587a49d50fSTom Eccles %false = arith.constant false 359*12ba74e1SValentin Clement (バレンタイン クレメン) fir.call @_FortranAStopStatement(%c0_i32, %false, %false) : (i32, i1, i1) -> () 3607a49d50fSTom Eccles fir.unreachable 3617a49d50fSTom Eccles} 3627a49d50fSTom Eccles// CHECK: func.func @stop_terminator() { 3637a49d50fSTom Eccles// CHECK-NEXT: fir.alloca !fir.array<42xi32> 3647a49d50fSTom Eccles// CHECK-NEXT: %[[ZERO:.*]] = arith.constant 0 : i32 3657a49d50fSTom Eccles// CHECK-NEXT: %[[FALSE:.*]] = arith.constant false 366*12ba74e1SValentin Clement (バレンタイン クレメン)// CHECK-NEXT: fir.call @_FortranAStopStatement(%[[ZERO]], %[[FALSE]], %[[FALSE]]) : (i32, i1, i1) -> () 3677a49d50fSTom Eccles// CHECK-NEXT: fir.unreachable 3687a49d50fSTom Eccles// CHECK-NEXT: } 369464d321eSKareem Ergawy 370464d321eSKareem Ergawy 371464d321eSKareem Ergawy// check that stack allocations that use fir.declare which must be placed in loops 372464d321eSKareem Ergawy// use stacksave 373464d321eSKareem Ergawyfunc.func @placement_loop_declare() { 374464d321eSKareem Ergawy %c1 = arith.constant 1 : index 375464d321eSKareem Ergawy %c1_i32 = fir.convert %c1 : (index) -> i32 376464d321eSKareem Ergawy %c2 = arith.constant 2 : index 377464d321eSKareem Ergawy %c10 = arith.constant 10 : index 378464d321eSKareem Ergawy %0:2 = fir.do_loop %arg0 = %c1 to %c10 step %c1 iter_args(%arg1 = %c1_i32) -> (index, i32) { 379464d321eSKareem Ergawy %3 = arith.addi %c1, %c2 : index 380464d321eSKareem Ergawy // operand is now available 381464d321eSKareem Ergawy %4 = fir.allocmem !fir.array<?xi32>, %3 382303249c4STom Eccles %shape = fir.shape %3 : (index) -> !fir.shape<1> 383303249c4STom Eccles %5 = fir.declare %4(%shape) {uniq_name = "temp"} : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.heap<!fir.array<?xi32>> 384464d321eSKareem Ergawy // ... 385464d321eSKareem Ergawy fir.freemem %5 : !fir.heap<!fir.array<?xi32>> 386464d321eSKareem Ergawy fir.result %3, %c1_i32 : index, i32 387464d321eSKareem Ergawy } 388464d321eSKareem Ergawy return 389464d321eSKareem Ergawy} 390464d321eSKareem Ergawy// CHECK: func.func @placement_loop_declare() { 391464d321eSKareem Ergawy// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index 392464d321eSKareem Ergawy// CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32 393464d321eSKareem Ergawy// CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index 394464d321eSKareem Ergawy// CHECK-NEXT: %[[C10:.*]] = arith.constant 10 : index 395464d321eSKareem Ergawy// CHECK-NEXT: fir.do_loop 396464d321eSKareem Ergawy// CHECK-NEXT: %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index 3975aaf384bSTom Eccles// CHECK-NEXT: %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr 398464d321eSKareem Ergawy// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[SUM]] 3995aaf384bSTom Eccles// CHECK: llvm.intr.stackrestore %[[SP]] : !llvm.ptr 400464d321eSKareem Ergawy// CHECK-NEXT: fir.result 401464d321eSKareem Ergawy// CHECK-NEXT: } 402464d321eSKareem Ergawy// CHECK-NEXT: return 403464d321eSKareem Ergawy// CHECK-NEXT: } 404303249c4STom Eccles 405303249c4STom Eccles// Can we look through fir.convert and fir.declare? 406303249c4STom Ecclesfunc.func @lookthrough() { 407303249c4STom Eccles %0 = fir.allocmem !fir.array<42xi32> 408303249c4STom Eccles %c42 = arith.constant 42 : index 409303249c4STom Eccles %shape = fir.shape %c42 : (index) -> !fir.shape<1> 410303249c4STom Eccles %1 = fir.declare %0(%shape) {uniq_name = "name"} : (!fir.heap<!fir.array<42xi32>>, !fir.shape<1>) -> !fir.heap<!fir.array<42xi32>> 411303249c4STom Eccles %2 = fir.convert %1 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>> 412303249c4STom Eccles // use the ref so the converts aren't folded 413303249c4STom Eccles %3 = fir.load %2 : !fir.ref<!fir.array<42xi32>> 414303249c4STom Eccles %4 = fir.convert %2 : (!fir.ref<!fir.array<42xi32>>) -> !fir.heap<!fir.array<42xi32>> 415303249c4STom Eccles fir.freemem %4 : !fir.heap<!fir.array<42xi32>> 416303249c4STom Eccles return 417303249c4STom Eccles} 418303249c4STom Eccles// CHECK: func.func @lookthrough() { 419303249c4STom Eccles// CHECK: fir.alloca !fir.array<42xi32> 420303249c4STom Eccles// CHECK-NOT: fir.freemem 421e3cd88a7SSlava Zakharin 422e3cd88a7SSlava Zakharin// StackArrays is better to find fir.freemem ops corresponding to fir.allocmem 423e3cd88a7SSlava Zakharin// using the same look through mechanism as during the allocation analysis, 424e3cd88a7SSlava Zakharin// looking through fir.convert and fir.declare. 425e3cd88a7SSlava Zakharinfunc.func @finding_freemem_in_block() { 426e3cd88a7SSlava Zakharin %c0 = arith.constant 0 : index 427e3cd88a7SSlava Zakharin %c10_i32 = arith.constant 10 : i32 428e3cd88a7SSlava Zakharin %c1_i32 = arith.constant 1 : i32 429e3cd88a7SSlava Zakharin %0 = fir.alloca i32 {bindc_name = "k", uniq_name = "k"} 430e3cd88a7SSlava Zakharin %1 = fir.declare %0 {uniq_name = "k"} : (!fir.ref<i32>) -> !fir.ref<i32> 431e3cd88a7SSlava Zakharin fir.store %c1_i32 to %1 : !fir.ref<i32> 432e3cd88a7SSlava Zakharin cf.br ^bb1 433e3cd88a7SSlava Zakharin^bb1: // 2 preds: ^bb0, ^bb2 434e3cd88a7SSlava Zakharin %2 = fir.load %1 : !fir.ref<i32> 435e3cd88a7SSlava Zakharin %3 = arith.cmpi sle, %2, %c10_i32 : i32 436e3cd88a7SSlava Zakharin cf.cond_br %3, ^bb2, ^bb3 437e3cd88a7SSlava Zakharin^bb2: // pred: ^bb1 438e3cd88a7SSlava Zakharin %4 = fir.declare %1 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "x"} : (!fir.ref<i32>) -> !fir.ref<i32> 439e3cd88a7SSlava Zakharin %5 = fir.load %4 : !fir.ref<i32> 440e3cd88a7SSlava Zakharin %6 = fir.convert %5 : (i32) -> index 441e3cd88a7SSlava Zakharin %7 = arith.cmpi sgt, %6, %c0 : index 442e3cd88a7SSlava Zakharin %8 = arith.select %7, %6, %c0 : index 443e3cd88a7SSlava Zakharin %9 = fir.shape %8 : (index) -> !fir.shape<1> 444e3cd88a7SSlava Zakharin %10 = fir.allocmem !fir.array<?xi32>, %8 {bindc_name = ".tmp.expr_result", uniq_name = ""} 445e3cd88a7SSlava Zakharin %11 = fir.convert %10 : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>> 446e3cd88a7SSlava Zakharin %12 = fir.declare %11(%9) {uniq_name = ".tmp.expr_result"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.ref<!fir.array<?xi32>> 447e3cd88a7SSlava Zakharin %13 = fir.embox %12(%9) : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>> 448e3cd88a7SSlava Zakharin %14 = fir.call @_QPfunc(%1) fastmath<fast> : (!fir.ref<i32>) -> !fir.array<?xi32> 449e3cd88a7SSlava Zakharin fir.save_result %14 to %12(%9) : !fir.array<?xi32>, !fir.ref<!fir.array<?xi32>>, !fir.shape<1> 450e3cd88a7SSlava Zakharin fir.call @_QPsub(%13) fastmath<fast> : (!fir.box<!fir.array<?xi32>>) -> () 451e3cd88a7SSlava Zakharin %15 = fir.convert %12 : (!fir.ref<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>> 452e3cd88a7SSlava Zakharin fir.freemem %15 : !fir.heap<!fir.array<?xi32>> 453e3cd88a7SSlava Zakharin %16 = fir.load %1 : !fir.ref<i32> 454e3cd88a7SSlava Zakharin %17 = arith.addi %16, %c1_i32 : i32 455e3cd88a7SSlava Zakharin fir.store %17 to %1 : !fir.ref<i32> 456e3cd88a7SSlava Zakharin cf.br ^bb1 457e3cd88a7SSlava Zakharin^bb3: // pred: ^bb1 458e3cd88a7SSlava Zakharin return 459e3cd88a7SSlava Zakharin} 460e3cd88a7SSlava Zakharin// CHECK: func.func @finding_freemem_in_block() { 461e3cd88a7SSlava Zakharin// CHECK: fir.alloca !fir.array<?xi32> 462e3cd88a7SSlava Zakharin// CHECK-NOT: fir.freemem 463