Revert "Move HIP fatbin sections farther away from .text"
[llvm-project.git] / flang / test / Transforms / stack-arrays.fir
blob4a417ed981ab1537f1bb651cb869a3daa24a9fbf
1 // RUN: fir-opt --stack-arrays %s | FileCheck %s
3 // Simplest transformation
4 func.func @simple() {
5   %0 = fir.allocmem !fir.array<42xi32>
6   fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
7   return
9 // CHECK: func.func @simple() {
10 // CHECK-NEXT: fir.alloca !fir.array<42xi32>
11 // CHECK-NEXT: return
12 // CHECK-NEXT: }
14 // Check fir.must_be_heap allocations are not moved
15 func.func @must_be_heap() {
16   %0 = fir.allocmem !fir.array<42xi32> {fir.must_be_heap = true}
17   fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
18   return
20 // CHECK:      func.func @must_be_heap() {
21 // CHECK-NEXT:   %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32> {fir.must_be_heap = true}
22 // CHECK-NEXT:   fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<42xi32>>
23 // CHECK-NEXT:   return
24 // CHECK-NEXT: }
26 // Check the data-flow-analysis can detect cases where we aren't sure if memory
27 // is freed by the end of the function
28 func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) {
29   %7 = arith.constant 42 : index
30   %8 = fir.allocmem !fir.array<?xi32>, %7 {uniq_name = "_QFdfa1Earr.alloc"}
31   %9 = fir.load %arg0 : !fir.ref<!fir.logical<4>>
32   %10 = fir.convert %9 : (!fir.logical<4>) -> i1
33   fir.if %10 {
34     fir.freemem %8 : !fir.heap<!fir.array<?xi32>>
35   } else {
36   }
37   return
39 // CHECK:      func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) {
40 // CHECK-NEXT:   %[[C42:.*]] = arith.constant 42 : index
41 // CHECK-NEXT:   %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[C42]] {uniq_name = "_QFdfa1Earr.alloc"}
42 // CHECK-NEXT:   %[[LOGICAL:.*]] = fir.load %arg0 : !fir.ref<!fir.logical<4>>
43 // CHECK-NEXT:   %[[BOOL:.*]] = fir.convert %[[LOGICAL]] : (!fir.logical<4>) -> i1
44 // CHECK-NEXT:   fir.if %[[BOOL]] {
45 // CHECK-NEXT:     fir.freemem %[[MEM]] : !fir.heap<!fir.array<?xi32>>
46 // CHECK-NEXT:   } else {
47 // CHECK-NEXT:   }
48 // CHECK-NEXT:   return
49 // CHECK-NEXT: }
51 // Check scf.if
52 func.func @dfa2(%arg0: i1) {
53   %a = fir.allocmem !fir.array<1xi8>
54   scf.if %arg0 {
55     fir.freemem %a : !fir.heap<!fir.array<1xi8>>
56   } else {
57   }
58   return
60 // CHECK:     func.func @dfa2(%arg0: i1) {
61 // CHECK-NEXT:  %[[MEM:.*]] = fir.allocmem !fir.array<1xi8>
62 // CHECK-NEXT:  scf.if %arg0 {
63 // CHECK-NEXT:    fir.freemem %[[MEM]] : !fir.heap<!fir.array<1xi8>>
64 // CHECK-NEXT:  } else {
65 // CHECK-NEXT:  }
66 // CHECK-NEXT:  return
67 // CHECK-NEXT:  }
69 // Check freemem in both regions
70 func.func @dfa3(%arg0: i1) {
71   %a = fir.allocmem !fir.array<1xi8>
72   fir.if %arg0 {
73     fir.freemem %a : !fir.heap<!fir.array<1xi8>>
74   } else {
75     fir.freemem %a : !fir.heap<!fir.array<1xi8>>
76   }
77   return
79 // CHECK:     func.func @dfa3(%arg0: i1) {
80 // CHECK-NEXT:  %[[MEM:.*]] = fir.alloca !fir.array<1xi8>
81 // CHECK-NEXT:  fir.if %arg0 {
82 // CHECK-NEXT:  } else {
83 // CHECK-NEXT:  }
84 // CHECK-NEXT:  return
85 // CHECK-NEXT:  }
87 func.func private @dfa3a_foo(!fir.ref<!fir.array<1xi8>>) -> ()
88 func.func private @dfa3a_bar(!fir.ref<!fir.array<1xi8>>) -> ()
90 // Check freemem in both regions, with other uses
91 func.func @dfa3a(%arg0: i1) {
92   %a = fir.allocmem !fir.array<1xi8>
93   fir.if %arg0 {
94     %ref = fir.convert %a : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>>
95     func.call @dfa3a_foo(%ref) : (!fir.ref<!fir.array<1xi8>>) -> ()
96     fir.freemem %a : !fir.heap<!fir.array<1xi8>>
97   } else {
98     %ref = fir.convert %a : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>>
99     func.call @dfa3a_bar(%ref) : (!fir.ref<!fir.array<1xi8>>) -> ()
100     fir.freemem %a : !fir.heap<!fir.array<1xi8>>
101   }
102   return
104 // CHECK:     func.func @dfa3a(%arg0: i1) {
105 // CHECK-NEXT:  %[[MEM:.*]] = fir.alloca !fir.array<1xi8>
106 // CHECK-NEXT:  %[[HEAP:.*]] = fir.convert %[[MEM]] : (!fir.ref<!fir.array<1xi8>>) -> !fir.heap<!fir.array<1xi8>>
107 // CHECK-NEXT:  fir.if %arg0 {
108 // CHECK-NEXT:    %[[REF:.*]] = fir.convert %[[HEAP]] : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>>
109 // CHECK-NEXT:    func.call @dfa3a_foo(%[[REF]])
110 // CHECK-NEXT:  } else {
111 // CHECK-NEXT:    %[[REF:.*]] = fir.convert %[[HEAP]] : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>>
112 // CHECK-NEXT:    func.call @dfa3a_bar(%[[REF]])
113 // CHECK-NEXT:  }
114 // CHECK-NEXT:  return
115 // CHECK-NEXT:  }
117 // check the alloca is placed after all operands become available
118 func.func @placement1() {
119   // do some stuff with other ssa values
120   %1 = arith.constant 1 : index
121   %2 = arith.constant 2 : index
122   %3 = arith.addi %1, %2 : index
123   // operand is now available
124   %4 = fir.allocmem !fir.array<?xi32>, %3
125   // ...
126   fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
127   return
129 // CHECK:      func.func @placement1() {
130 // CHECK-NEXT:   %[[ARG:.*]] = arith.constant 3 : index
131 // CHECK-NEXT:   %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[ARG]]
132 // CHECK-NEXT:   return
133 // CHECK-NEXT: }
135 // check that if there are no operands, then the alloca is placed early
136 func.func @placement2() {
137   // do some stuff with other ssa values
138   %1 = arith.constant 1 : index
139   %2 = arith.constant 2 : index
140   %3 = arith.addi %1, %2 : index
141   %4 = fir.allocmem !fir.array<42xi32>
142   // ...
143   fir.freemem %4 : !fir.heap<!fir.array<42xi32>>
144   return
146 // CHECK:      func.func @placement2() {
147 // CHECK-NEXT:   %[[MEM:.*]] = fir.alloca !fir.array<42xi32>
148 // CHECK-NEXT:   %[[ONE:.*]] = arith.constant 1 : index
149 // CHECK-NEXT:   %[[TWO:.*]] = arith.constant 2 : index
150 // CHECK-NEXT:   %[[SUM:.*]] = arith.addi %[[ONE]], %[[TWO]] : index
151 // CHECK-NEXT:   return
152 // CHECK-NEXT: }
154 // check that stack allocations which must be placed in loops use stacksave
155 func.func @placement3() {
156   %c1 = arith.constant 1 : index
157   %c1_i32 = fir.convert %c1 : (index) -> i32
158   %c2 = arith.constant 2 : index
159   %c10 = arith.constant 10 : index
160   %0:2 = fir.do_loop %arg0 = %c1 to %c10 step %c1 iter_args(%arg1 = %c1_i32) -> (index, i32) {
161     %3 = arith.addi %c1, %c2 : index
162     // operand is now available
163     %4 = fir.allocmem !fir.array<?xi32>, %3
164     // ...
165     fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
166     fir.result %3, %c1_i32 : index, i32
167   }
168   return
170 // CHECK:      func.func @placement3() {
171 // CHECK-NEXT:   %[[C1:.*]] = arith.constant 1 : index
172 // CHECK-NEXT:   %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
173 // CHECK-NEXT:   %[[C2:.*]] = arith.constant 2 : index
174 // CHECK-NEXT:   %[[C10:.*]] = arith.constant 10 : index
175 // CHECK-NEXT:   fir.do_loop
176 // CHECK-NEXT:     %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index
177 // CHECK-NEXT:     %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr
178 // CHECK-NEXT:     %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[SUM]]
179 // CHECK-NEXT:     llvm.intr.stackrestore %[[SP]] : !llvm.ptr
180 // CHECK-NEXT:     fir.result
181 // CHECK-NEXT:   }
182 // CHECK-NEXT:   return
183 // CHECK-NEXT: }
185 // check that stack save/restore are used in CFG loops
186 func.func @placement4(%arg0 : i1) {
187   %c1 = arith.constant 1 : index
188   %c1_i32 = fir.convert %c1 : (index) -> i32
189   %c2 = arith.constant 2 : index
190   %c10 = arith.constant 10 : index
191   cf.br ^bb1
192 ^bb1:
193   %3 = arith.addi %c1, %c2 : index
194   // operand is now available
195   %4 = fir.allocmem !fir.array<?xi32>, %3
196   // ...
197   fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
198   cf.cond_br %arg0, ^bb1, ^bb2
199 ^bb2:
200   return
202 // CHECK:      func.func @placement4(%arg0: i1) {
203 // CHECK-NEXT:   %[[C1:.*]] = arith.constant 1 : index
204 // CHECK-NEXT:   %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
205 // CHECK-NEXT:   %[[C10:.*]] = arith.constant 10 : index
206 // CHECK-NEXT:   cf.br ^bb1
207 // CHECK-NEXT: ^bb1:
208 // CHECK-NEXT:   %[[C3:.*]] = arith.constant 3 : index
209 // CHECK-NEXT:   %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr
210 // CHECK-NEXT:   %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[C3]]
211 // CHECK-NEXT:   llvm.intr.stackrestore %[[SP]] : !llvm.ptr
212 // CHECK-NEXT:   cf.cond_br %arg0, ^bb1, ^bb2
213 // CHECK-NEXT: ^bb2:
214 // CHECK-NEXT:   return
215 // CHECK-NEXT: }
217 // check that stacksave is not used when there is an intervening alloca
218 func.func @placement5() {
219   %c1 = arith.constant 1 : index
220   %c1_i32 = fir.convert %c1 : (index) -> i32
221   %c2 = arith.constant 2 : index
222   %c10 = arith.constant 10 : index
223   %0:2 = fir.do_loop %arg0 = %c1 to %c10 step %c1 iter_args(%arg1 = %c1_i32) -> (index, i32) {
224     %3 = arith.addi %c1, %c2 : index
225     // operand is now available
226     %4 = fir.allocmem !fir.array<?xi32>, %3
227     %5 = fir.alloca i32
228     fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
229     fir.result %3, %c1_i32 : index, i32
230   }
231   return
233 // CHECK:      func.func @placement5() {
234 // CHECK-NEXT:   %[[C1:.*]] = arith.constant 1 : index
235 // CHECK-NEXT:   %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
236 // CHECK-NEXT:   %[[C2:.*]] = arith.constant 2 : index
237 // CHECK-NEXT:   %[[C10:.*]] = arith.constant 10 : index
238 // CHECK-NEXT:   fir.do_loop
239 // CHECK-NEXT:     %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index
240 // CHECK-NEXT:     %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[SUM]]
241 // CHECK-NEXT:     %[[IDX:.*]] = fir.alloca i32
242 // CHECK-NEXT:     fir.freemem %[[MEM]] : !fir.heap<!fir.array<?xi32>>
243 // CHECK-NEXT:     fir.result
244 // CHECK-NEXT:   }
245 // CHECK-NEXT:   return
246 // CHECK-NEXT: }
248 // check that stack save/restore are not used when the memalloc and freemem are
249 // in different blocks
250 func.func @placement6(%arg0: i1) {
251   %c1 = arith.constant 1 : index
252   %c1_i32 = fir.convert %c1 : (index) -> i32
253   %c2 = arith.constant 2 : index
254   %c10 = arith.constant 10 : index
255   cf.br ^bb1
256 ^bb1:
257   %3 = arith.addi %c1, %c2 : index
258   // operand is now available
259   %4 = fir.allocmem !fir.array<?xi32>, %3
260   // ...
261   cf.cond_br %arg0, ^bb2, ^bb3
262 ^bb2:
263   // ...
264   fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
265   cf.br ^bb1
266 ^bb3:
267   // ...
268   fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
269   cf.br ^bb1
271 // CHECK:      func.func @placement6(%arg0: i1) {
272 // CHECK-NEXT:   %[[c1:.*]] = arith.constant 1 : index
273 // CHECK-NEXT:   %[[c1_i32:.*]] = fir.convert %[[c1]] : (index) -> i32
274 // CHECK-NEXT:   %[[c2:.*]] = arith.constant 2 : index
275 // CHECK-NEXT:   %[[c10:.*]] = arith.constant 10 : index
276 // CHECK-NEXT:   cf.br ^bb1
277 // CHECK-NEXT: ^bb1:
278 // CHECK-NEXT:   %[[ADD:.*]] = arith.addi %[[c1]], %[[c2]] : index
279 // CHECK-NEXT:   %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[ADD]]
280 // CHECK-NEXT:   cf.cond_br %arg0, ^bb2, ^bb3
281 // CHECK-NEXT: ^bb2:
282 // CHECK-NEXT:   fir.freemem %[[MEM]] : !fir.heap<!fir.array<?xi32>>
283 // CHECK-NEXT:   cf.br ^bb1
284 // CHECK-NEXT: ^bb3:
285 // CHECK-NEXT:   fir.freemem %[[MEM]] : !fir.heap<!fir.array<?xi32>>
286 // CHECK-NEXT:   cf.br ^bb1
287 // CHECK-NEXT: }
289 // Check multiple returns, where the memory is always freed
290 func.func @returns(%arg0: i1) {
291   %0 = fir.allocmem !fir.array<42xi32>
292   cf.cond_br %arg0, ^bb1, ^bb2
293 ^bb1:
294   fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
295   return
296 ^bb2:
297   fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
298   return
300 // CHECK:      func.func @returns(%[[COND:.*]]: i1) {
301 // CHECK-NEXT:   %[[ALLOC:.*]] = fir.alloca !fir.array<42xi32>
302 // CHECK-NEXT:   cf.cond_br %[[COND]], ^bb1, ^bb2
303 // CHECK-NEXT: ^bb1:
304 // CHECK-NEXT:   return
305 // CHECK-NEXT: ^bb2:
306 // CHECK-NEXT:   return
307 // CHECK-NEXT: }
309 // Check multiple returns, where the memory is not freed on one branch
310 func.func @returns2(%arg0: i1) {
311   %0 = fir.allocmem !fir.array<42xi32>
312   cf.cond_br %arg0, ^bb1, ^bb2
313 ^bb1:
314   fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
315   return
316 ^bb2:
317   return
319 // CHECK:      func.func @returns2(%[[COND:.*]]: i1) {
320 // CHECK-NEXT:   %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32>
321 // CHECK-NEXT:   cf.cond_br %[[COND]], ^bb1, ^bb2
322 // CHECK-NEXT: ^bb1:
323 // CHECK-NEXT:   fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<42xi32>>
324 // CHECK-NEXT:   return
325 // CHECK-NEXT: ^bb2:
326 // CHECK-NEXT:   return
327 // CHECK-NEXT: }
329 // Check allocations are not moved outside of an omp region
330 func.func @omp_placement1() {
331   omp.sections {
332     omp.section {
333       %mem = fir.allocmem !fir.array<42xi32>
334       fir.freemem %mem : !fir.heap<!fir.array<42xi32>>
335       omp.terminator
336     }
337     omp.terminator
338   }
339   return
341 // CHECK:      func.func @omp_placement1() {
342 // CHECK-NEXT:   %[[MEM:.*]] = fir.alloca !fir.array<42xi32>
343 // CHECK-NEXT:   %[[MEM_CONV:.*]] = fir.convert %[[MEM]] : (!fir.ref<!fir.array<42xi32>>) -> !fir.heap<!fir.array<42xi32>>
344 // CHECK-NEXT:   omp.sections {
345 // CHECK-NEXT:     omp.section {
346 // CHECK-NEXT:       omp.terminator
347 // CHECK-NEXT:     }
348 // CHECK-NEXT:     omp.terminator
349 // CHECK-NEXT:   }
350 // CHECK-NEXT:   return
351 // CHECK-NEXT: }
353 // function terminated by stop statement
354 func.func @stop_terminator() {
355   %0 = fir.allocmem !fir.array<42xi32>
356   fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
357   %c0_i32 = arith.constant 0 : i32
358   %false = arith.constant false
359   fir.call @_FortranAStopStatement(%c0_i32, %false, %false) : (i32, i1, i1) -> ()
360   fir.unreachable
362 // CHECK: func.func @stop_terminator() {
363 // CHECK-NEXT: fir.alloca !fir.array<42xi32>
364 // CHECK-NEXT:  %[[ZERO:.*]] = arith.constant 0 : i32
365 // CHECK-NEXT:  %[[FALSE:.*]] = arith.constant false
366 // CHECK-NEXT:  fir.call @_FortranAStopStatement(%[[ZERO]], %[[FALSE]], %[[FALSE]]) : (i32, i1, i1) -> ()
367 // CHECK-NEXT:  fir.unreachable
368 // CHECK-NEXT: }
371 // check that stack allocations that use fir.declare which must be placed in loops
372 // use stacksave
373 func.func @placement_loop_declare() {
374   %c1 = arith.constant 1 : index
375   %c1_i32 = fir.convert %c1 : (index) -> i32
376   %c2 = arith.constant 2 : index
377   %c10 = arith.constant 10 : index
378   %0:2 = fir.do_loop %arg0 = %c1 to %c10 step %c1 iter_args(%arg1 = %c1_i32) -> (index, i32) {
379     %3 = arith.addi %c1, %c2 : index
380     // operand is now available
381     %4 = fir.allocmem !fir.array<?xi32>, %3
382     %shape = fir.shape %3 : (index) -> !fir.shape<1>
383     %5 = fir.declare %4(%shape) {uniq_name = "temp"} : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.heap<!fir.array<?xi32>>
384     // ...
385     fir.freemem %5 : !fir.heap<!fir.array<?xi32>>
386     fir.result %3, %c1_i32 : index, i32
387   }
388   return
390 // CHECK:      func.func @placement_loop_declare() {
391 // CHECK-NEXT:   %[[C1:.*]] = arith.constant 1 : index
392 // CHECK-NEXT:   %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
393 // CHECK-NEXT:   %[[C2:.*]] = arith.constant 2 : index
394 // CHECK-NEXT:   %[[C10:.*]] = arith.constant 10 : index
395 // CHECK-NEXT:   fir.do_loop
396 // CHECK-NEXT:     %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index
397 // CHECK-NEXT:     %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr
398 // CHECK-NEXT:     %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[SUM]]
399 // CHECK:          llvm.intr.stackrestore %[[SP]] : !llvm.ptr
400 // CHECK-NEXT:     fir.result
401 // CHECK-NEXT:   }
402 // CHECK-NEXT:   return
403 // CHECK-NEXT: }
405 // Can we look through fir.convert and fir.declare?
406 func.func @lookthrough() {
407   %0 = fir.allocmem !fir.array<42xi32>
408   %c42 = arith.constant 42 : index
409   %shape = fir.shape %c42 : (index) -> !fir.shape<1>
410   %1 = fir.declare %0(%shape) {uniq_name = "name"} : (!fir.heap<!fir.array<42xi32>>, !fir.shape<1>) -> !fir.heap<!fir.array<42xi32>>
411   %2 = fir.convert %1 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>
412   // use the ref so the converts aren't folded
413   %3 = fir.load %2 : !fir.ref<!fir.array<42xi32>>
414   %4 = fir.convert %2 : (!fir.ref<!fir.array<42xi32>>) -> !fir.heap<!fir.array<42xi32>>
415   fir.freemem %4 : !fir.heap<!fir.array<42xi32>>
416   return
418 // CHECK: func.func @lookthrough() {
419 // CHECK:     fir.alloca !fir.array<42xi32>
420 // CHECK-NOT: fir.freemem
422 // StackArrays is better to find fir.freemem ops corresponding to fir.allocmem
423 // using the same look through mechanism as during the allocation analysis,
424 // looking through fir.convert and fir.declare.
425 func.func @finding_freemem_in_block() {
426   %c0 = arith.constant 0 : index
427   %c10_i32 = arith.constant 10 : i32
428   %c1_i32 = arith.constant 1 : i32
429   %0 = fir.alloca i32 {bindc_name = "k", uniq_name = "k"}
430   %1 = fir.declare %0 {uniq_name = "k"} : (!fir.ref<i32>) -> !fir.ref<i32>
431   fir.store %c1_i32 to %1 : !fir.ref<i32>
432   cf.br ^bb1
433 ^bb1:  // 2 preds: ^bb0, ^bb2
434   %2 = fir.load %1 : !fir.ref<i32>
435   %3 = arith.cmpi sle, %2, %c10_i32 : i32
436   cf.cond_br %3, ^bb2, ^bb3
437 ^bb2:  // pred: ^bb1
438   %4 = fir.declare %1 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "x"} : (!fir.ref<i32>) -> !fir.ref<i32>
439   %5 = fir.load %4 : !fir.ref<i32>
440   %6 = fir.convert %5 : (i32) -> index
441   %7 = arith.cmpi sgt, %6, %c0 : index
442   %8 = arith.select %7, %6, %c0 : index
443   %9 = fir.shape %8 : (index) -> !fir.shape<1>
444   %10 = fir.allocmem !fir.array<?xi32>, %8 {bindc_name = ".tmp.expr_result", uniq_name = ""}
445   %11 = fir.convert %10 : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
446   %12 = fir.declare %11(%9) {uniq_name = ".tmp.expr_result"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.ref<!fir.array<?xi32>>
447   %13 = fir.embox %12(%9) : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>>
448   %14 = fir.call @_QPfunc(%1) fastmath<fast> : (!fir.ref<i32>) -> !fir.array<?xi32>
449   fir.save_result %14 to %12(%9) : !fir.array<?xi32>, !fir.ref<!fir.array<?xi32>>, !fir.shape<1>
450   fir.call @_QPsub(%13) fastmath<fast> : (!fir.box<!fir.array<?xi32>>) -> ()
451   %15 = fir.convert %12 : (!fir.ref<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>>
452   fir.freemem %15 : !fir.heap<!fir.array<?xi32>>
453   %16 = fir.load %1 : !fir.ref<i32>
454   %17 = arith.addi %16, %c1_i32 : i32
455   fir.store %17 to %1 : !fir.ref<i32>
456   cf.br ^bb1
457 ^bb3:  // pred: ^bb1
458   return
460 // CHECK: func.func @finding_freemem_in_block() {
461 // CHECK:     fir.alloca !fir.array<?xi32>
462 // CHECK-NOT: fir.freemem