33// Simplest transformation
44func.func @simple() {
55 %0 = fir.allocmem !fir.array<42xi32>
6- %c0 = arith.constant 0 : index
7- %c0_i32 = arith.constant 0 : i32
8- %ref = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>
9- %elt = fir.coordinate_of %ref , %c0 : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
10- fir.store %c0_i32 to %elt : !fir.ref<i32>
6+ %c0_s = arith.constant 0 : index
7+ %c0_i32_s = arith.constant 0 : i32
8+ %ref_s = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>
9+ %elt_s = fir.coordinate_of %ref_s , %c0_s : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
10+ fir.store %c0_i32_s to %elt_s : !fir.ref<i32>
1111 fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
1212 return
1313}
14- // CHECK: func.func @simple() {
14+ // CHECK: func.func @simple()
1515// CHECK: fir.alloca !fir.array<42xi32>
1616// CHECK: return
17- // CHECK: }
1817
1918// Check fir.must_be_heap allocations are not moved
2019func.func @must_be_heap() {
2120 %0 = fir.allocmem !fir.array<42xi32> {fir.must_be_heap = true}
2221 fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
2322 return
2423}
25- // CHECK: func.func @must_be_heap() {
24+ // CHECK-LABEL : func.func @must_be_heap()
2625// CHECK-NEXT: %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32> {fir.must_be_heap = true}
2726// CHECK-NEXT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<42xi32>>
2827// CHECK-NEXT: return
@@ -41,7 +40,7 @@ func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) {
4140 }
4241 return
4342}
44- // CHECK: func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) {
43+ // CHECK-LABEL: func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"})
4544// CHECK-NEXT: %[[C42:.*]] = arith.constant 42 : index
4645// CHECK-NEXT: %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[C42]] {uniq_name = "_QFdfa1Earr.alloc"}
4746// CHECK-NEXT: %[[LOGICAL:.*]] = fir.load %arg0 : !fir.ref<!fir.logical<4>>
@@ -62,7 +61,7 @@ func.func @dfa2(%arg0: i1) {
6261 }
6362 return
6463}
65- // CHECK: func.func @dfa2(%arg0: i1) {
64+ // CHECK-LABEL : func.func @dfa2(%arg0: i1)
6665// CHECK-NEXT: %[[MEM:.*]] = fir.allocmem !fir.array<1xi8>
6766// CHECK-NEXT: scf.if %arg0 {
6867// CHECK-NEXT: fir.freemem %[[MEM]] : !fir.heap<!fir.array<1xi8>>
@@ -79,12 +78,16 @@ func.func @dfa3(%arg0: i1) {
7978 } else {
8079 fir.freemem %a : !fir.heap<!fir.array<1xi8>>
8180 }
81+ %c0_d3 = arith.constant 0 : index
82+ %c0_i8_d3 = arith.constant 0 : i8
83+ %ref_d3 = fir.convert %a : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>>
84+ %elt_d3 = fir.coordinate_of %ref_d3, %c0_d3 : (!fir.ref<!fir.array<1xi8>>, index) -> !fir.ref<i8>
85+ fir.store %c0_i8_d3 to %elt_d3 : !fir.ref<i8>
8286 return
8387}
84- // CHECK: func.func @dfa3(%arg0: i1) {
88+ // CHECK: func.func @dfa3(%arg0: i1)
8589// CHECK: %[[MEM:.*]] = fir.alloca !fir.array<1xi8>
8690// CHECK: return
87- // CHECK: }
8891
8992func.func private @dfa3a_foo(!fir.ref<!fir.array<1xi8>>) -> ()
9093func.func private @dfa3a_bar(!fir.ref<!fir.array<1xi8>>) -> ()
@@ -103,6 +106,18 @@ func.func @dfa3a(%arg0: i1) {
103106 }
104107 return
105108}
109+ // CHECK-LABEL: func.func @dfa3a(%arg0: i1)
110+ // CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<1xi8>
111+ // CHECK-NEXT: %[[HEAP:.*]] = fir.convert %[[MEM]] : (!fir.ref<!fir.array<1xi8>>) -> !fir.heap<!fir.array<1xi8>>
112+ // CHECK-NEXT: fir.if %arg0 {
113+ // CHECK-NEXT: %[[REF:.*]] = fir.convert %[[HEAP]] : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>>
114+ // CHECK-NEXT: func.call @dfa3a_foo(%[[REF]])
115+ // CHECK-NEXT: } else {
116+ // CHECK-NEXT: %[[REF:.*]] = fir.convert %[[HEAP]] : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>>
117+ // CHECK-NEXT: func.call @dfa3a_bar(%[[REF]])
118+ // CHECK-NEXT: }
119+ // CHECK-NEXT: return
120+ // CHECK-NEXT: }
106121
107122// check the alloca is placed after all operands become available
108123func.func @placement1() {
@@ -113,13 +128,19 @@ func.func @placement1() {
113128 // operand is now available
114129 %4 = fir.allocmem !fir.array<?xi32>, %3
115130 // ...
131+ %c0 = arith.constant 0 : index
132+ %c0_i32 = arith.constant 0 : i32
133+ %ref1 = fir.convert %4 : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
134+ %elt1 = fir.coordinate_of %ref1, %c0 : (!fir.ref<!fir.array<?xi32>>, index) -> !fir.ref<i32>
135+ fir.store %c0_i32 to %elt1 : !fir.ref<i32>
116136 fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
117137 return
118138}
119- // CHECK: func.func @placement1() {
120- // CHECK: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, {{.*}}
139+ // CHECK-LABEL: func.func @placement1()
140+ // CHECK-NEXT: %[[ARG:.*]] = arith.constant 3 : index
141+ // CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[ARG]]
121142// CHECK: return
122- // CHECK: }
143+ // CHECK-NEXT : }
123144
124145// check that if there are no operands, then the alloca is placed early
125146func.func @placement2() {
@@ -129,10 +150,15 @@ func.func @placement2() {
129150 %3 = arith.addi %1, %2 : index
130151 %4 = fir.allocmem !fir.array<42xi32>
131152 // ...
153+ %c0_p2 = arith.constant 0 : index
154+ %c0_i32_p2 = arith.constant 0 : i32
155+ %ref_p2 = fir.convert %4 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>
156+ %elt_p2 = fir.coordinate_of %ref_p2, %c0_p2 : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
157+ fir.store %c0_i32_p2 to %elt_p2 : !fir.ref<i32>
132158 fir.freemem %4 : !fir.heap<!fir.array<42xi32>>
133159 return
134160}
135- // CHECK: func.func @placement2() {
161+ // CHECK-LABEL : func.func @placement2()
136162// CHECK: %[[MEM:.*]] = fir.alloca !fir.array<42xi32>
137163// CHECK: %[[ONE:.*]] = arith.constant 1 : index
138164// CHECK: %[[TWO:.*]] = arith.constant 2 : index
@@ -151,23 +177,30 @@ func.func @placement3() {
151177 // operand is now available
152178 %4 = fir.allocmem !fir.array<?xi32>, %3
153179 // ...
180+ %c0 = arith.constant 0 : index
181+ %c0_i32 = arith.constant 0 : i32
182+ %ref2 = fir.convert %4 : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
183+ %elt2 = fir.coordinate_of %ref2, %c0 : (!fir.ref<!fir.array<?xi32>>, index) -> !fir.ref<i32>
184+ fir.store %c0_i32 to %elt2 : !fir.ref<i32>
154185 fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
155186 fir.result %3, %c1_i32 : index, i32
156187 }
157188 return
158189}
159- // CHECK: func.func @placement3() {
160- // CHECK: %[[C1:.*]] = arith.constant 1 : index
161- // CHECK: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
162- // CHECK: %[[C2:.*]] = arith.constant 2 : index
163- // CHECK: %[[C10:.*]] = arith.constant 10 : index
164- // CHECK: fir.do_loop
165- // CHECK: %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr
190+ // CHECK-LABEL: func.func @placement3()
191+ // CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index
192+ // CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
193+ // CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index
194+ // CHECK-NEXT: %[[C10:.*]] = arith.constant 10 : index
195+ // CHECK-NEXT: fir.do_loop
196+ // CHECK-NEXT: %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index
197+ // CHECK-NEXT: %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr
198+ // CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[SUM]]
166199// CHECK: llvm.intr.stackrestore %[[SP]] : !llvm.ptr
167- // CHECK: fir.result
168- // CHECK: }
169- // CHECK: return
170- // CHECK: }
200+ // CHECK-NEXT : fir.result
201+ // CHECK-NEXT : }
202+ // CHECK-NEXT : return
203+ // CHECK-NEXT : }
171204
172205// check that stack save/restore are used in CFG loops
173206func.func @placement4(%arg0 : i1) {
@@ -181,25 +214,30 @@ func.func @placement4(%arg0 : i1) {
181214 // operand is now available
182215 %4 = fir.allocmem !fir.array<?xi32>, %3
183216 // ...
217+ %c0 = arith.constant 0 : index
218+ %c0_i32 = arith.constant 0 : i32
219+ %ref3 = fir.convert %4 : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
220+ %elt3 = fir.coordinate_of %ref3, %c0 : (!fir.ref<!fir.array<?xi32>>, index) -> !fir.ref<i32>
221+ fir.store %c0_i32 to %elt3 : !fir.ref<i32>
184222 fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
185223 cf.cond_br %arg0, ^bb1, ^bb2
186224^bb2:
187225 return
188226}
189- // CHECK: func.func @placement4(%arg0: i1) {
190- // CHECK: %[[C1:.*]] = arith.constant 1 : index
191- // CHECK: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
192- // CHECK: %[[C10:.*]] = arith.constant 10 : index
193- // CHECK: cf.br ^bb1
194- // CHECK: ^bb1:
195- // CHECK: %[[C3:.*]] = arith.constant 3 : index
196- // CHECK: %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr
197- // CHECK: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[C3]]
227+ // CHECK-LABEL : func.func @placement4(%arg0: i1)
228+ // CHECK-NEXT : %[[C1:.*]] = arith.constant 1 : index
229+ // CHECK-NEXT : %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
230+ // CHECK-NEXT : %[[C10:.*]] = arith.constant 10 : index
231+ // CHECK-NEXT : cf.br ^bb1
232+ // CHECK-NEXT : ^bb1:
233+ // CHECK-NEXT : %[[C3:.*]] = arith.constant 3 : index
234+ // CHECK-NEXT : %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr
235+ // CHECK-NEXT : %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[C3]]
198236// CHECK: llvm.intr.stackrestore %[[SP]] : !llvm.ptr
199- // CHECK: cf.cond_br %arg0, ^bb1, ^bb2
200- // CHECK: ^bb2:
201- // CHECK: return
202- // CHECK: }
237+ // CHECK-NEXT : cf.cond_br %arg0, ^bb1, ^bb2
238+ // CHECK-NEXT : ^bb2:
239+ // CHECK-NEXT : return
240+ // CHECK-NEXT : }
203241
204242// check that stacksave is not used when there is an intervening alloca
205243func.func @placement5() {
@@ -217,7 +255,7 @@ func.func @placement5() {
217255 }
218256 return
219257}
220- // CHECK: func.func @placement5() {
258+ // CHECK-LABEL : func.func @placement5()
221259// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index
222260// CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
223261// CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index
@@ -255,7 +293,7 @@ func.func @placement6(%arg0: i1) {
255293 fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
256294 cf.br ^bb1
257295}
258- // CHECK: func.func @placement6(%arg0: i1) {
296+ // CHECK-LABEL : func.func @placement6(%arg0: i1)
259297// CHECK-NEXT: %[[c1:.*]] = arith.constant 1 : index
260298// CHECK-NEXT: %[[c1_i32:.*]] = fir.convert %[[c1]] : (index) -> i32
261299// CHECK-NEXT: %[[c2:.*]] = arith.constant 2 : index
@@ -276,6 +314,11 @@ func.func @placement6(%arg0: i1) {
276314// Check multiple returns, where the memory is always freed
277315func.func @returns(%arg0: i1) {
278316 %0 = fir.allocmem !fir.array<42xi32>
317+ %c0_ret = arith.constant 0 : index
318+ %c0_i32_ret = arith.constant 0 : i32
319+ %ref_ret = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>
320+ %elt_ret = fir.coordinate_of %ref_ret, %c0_ret : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
321+ fir.store %c0_i32_ret to %elt_ret : !fir.ref<i32>
279322 cf.cond_br %arg0, ^bb1, ^bb2
280323^bb1:
281324 fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
@@ -284,27 +327,39 @@ func.func @returns(%arg0: i1) {
284327 fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
285328 return
286329}
287- // CHECK: func.func @returns(%[[COND:.*]]: i1) {
330+ // CHECK-LABEL : func.func @returns(
288331// CHECK: %[[ALLOC:.*]] = fir.alloca !fir.array<42xi32>
289- // CHECK: cf.cond_br %[[COND]], ^bb1, ^bb2
290- // CHECK: return
291- // CHECK: }
332+ // CHECK: cf.cond_br %{{.*}}, ^bb1, ^bb2
333+ // CHECK-NEXT: ^bb1:
334+ // CHECK-NEXT: return
335+ // CHECK-NEXT: ^bb2:
336+ // CHECK-NEXT: return
337+ // CHECK-NEXT: }
292338
293339// Check multiple returns, where the memory is not freed on one branch
294340func.func @returns2(%arg0: i1) {
295341 %0 = fir.allocmem !fir.array<42xi32>
342+ %c0_ret2 = arith.constant 0 : index
343+ %c0_i32_ret2 = arith.constant 0 : i32
344+ %ref_ret2 = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>
345+ %elt_ret2 = fir.coordinate_of %ref_ret2, %c0_ret2 : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
346+ fir.store %c0_i32_ret2 to %elt_ret2 : !fir.ref<i32>
296347 cf.cond_br %arg0, ^bb1, ^bb2
297348^bb1:
298349 fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
299350 return
300351^bb2:
301352 return
302353}
303- // CHECK: func.func @returns2(%[[COND:.*]]: i1) {
354+ // CHECK-LABEL : func.func @returns2(
304355// CHECK: %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32>
305- // CHECK: cf.cond_br %[[COND]], ^bb1, ^bb2
306- // CHECK: return
307- // CHECK: }
356+ // CHECK: cf.cond_br %{{.*}}, ^bb1, ^bb2
357+ // CHECK-NEXT: ^bb1:
358+ // CHECK-NEXT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<42xi32>>
359+ // CHECK-NEXT: return
360+ // CHECK-NEXT: ^bb2:
361+ // CHECK-NEXT: return
362+ // CHECK-NEXT: }
308363
309364// Check allocations are not moved outside of an omp region
310365func.func @omp_placement1() {
@@ -318,29 +373,36 @@ func.func @omp_placement1() {
318373 }
319374 return
320375}
321- // CHECK: func.func @omp_placement1() {
322- // CHECK: %[[MEM:.*]] = fir.alloca !fir.array<42xi32>
323- // CHECK: %[[MEM_CONV:.*]] = fir.convert %[[MEM]] : (!fir.ref<!fir.array<42xi32>>) -> !fir.heap<!fir.array<42xi32>>
324- // CHECK: omp.sections
325- // CHECK: return
326- // CHECK: }
376+ // CHECK-LABEL: func.func @omp_placement1()
377+ // CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<42xi32>
378+ // CHECK-NEXT: %[[MEM_CONV:.*]] = fir.convert %[[MEM]] : (!fir.ref<!fir.array<42xi32>>) -> !fir.heap<!fir.array<42xi32>>
379+ // CHECK-NEXT: omp.sections {
380+ // CHECK-NEXT: omp.section {
381+ // CHECK-NEXT: omp.terminator
382+ // CHECK-NEXT: }
383+ // CHECK-NEXT: omp.terminator
384+ // CHECK-NEXT: }
385+ // CHECK-NEXT: return
386+ // CHECK-NEXT: }
327387
328388// function terminated by stop statement
329389func.func @stop _terminator () {
330390 %0 = fir.allocmem !fir.array<42xi32>
391+ %c0 = arith.constant 0 : index
392+ %c0_i32_st = arith.constant 0 : i32
393+ %ref4 = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>
394+ %elt4 = fir.coordinate_of %ref4, %c0 : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
395+ fir.store %c0_i32_st to %elt4 : !fir.ref<i32>
331396 fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
332397 %c0_i32 = arith.constant 0 : i32
333398 %false = arith.constant false
334399 fir.call @_FortranAStopStatement(%c0_i32, %false, %false) : (i32, i1, i1) -> ()
335400 fir.unreachable
336401}
337- // CHECK: func.func @stop _terminator () {
338- // CHECK-NEXT: fir.alloca !fir.array<42xi32>
339- // CHECK-NEXT: %[[ZERO:.*]] = arith.constant 0 : i32
340- // CHECK-NEXT: %[[FALSE:.*]] = arith.constant false
341- // CHECK-NEXT: fir.call @_FortranAStopStatement(%[[ZERO]], %[[FALSE]], %[[FALSE]]) : (i32, i1, i1) -> ()
342- // CHECK-NEXT: fir.unreachable
343- // CHECK-NEXT: }
402+ // CHECK-LABEL: func.func @stop _terminator ()
403+ // CHECK: fir.alloca !fir.array<42xi32>
404+ // CHECK: fir.call @_FortranAStopStatement(
405+ // CHECK: fir.unreachable
344406
345407
346408// check that stack allocations that use fir.declare which must be placed in loops
@@ -362,7 +424,7 @@ func.func @placement_loop_declare() {
362424 }
363425 return
364426}
365- // CHECK: func.func @placement_loop_declare() {
427+ // CHECK-LABEL : func.func @placement_loop_declare()
366428// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index
367429// CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
368430// CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index
@@ -390,7 +452,7 @@ func.func @lookthrough() {
390452 fir.freemem %4 : !fir.heap<!fir.array<42xi32>>
391453 return
392454}
393- // CHECK: func.func @lookthrough() {
455+ // CHECK-LABEL : func.func @lookthrough()
394456// CHECK: fir.alloca !fir.array<42xi32>
395457// CHECK-NOT: fir.freemem
396458
@@ -432,6 +494,6 @@ func.func @finding_freemem_in_block() {
432494^bb3: // pred: ^bb1
433495 return
434496}
435- // CHECK: func.func @finding_freemem_in_block() {
497+ // CHECK-LABEL : func.func @finding_freemem_in_block()
436498// CHECK: fir.alloca !fir.array<?xi32>
437499// CHECK-NOT: fir.freemem
0 commit comments