brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.2 KiB · 25fc731 Raw
500 lines · plain
1// RUN: fir-opt --stack-arrays %s | FileCheck %s2 3// Simplest transformation4func.func @simple() {5  %0 = fir.allocmem !fir.array<42xi32>6  %c0_s = arith.constant 0 : index7  %c0_i32_s = arith.constant 0 : i328  %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>11  fir.freemem %0 : !fir.heap<!fir.array<42xi32>>12  return13}14// CHECK: func.func @simple()15// CHECK: fir.alloca !fir.array<42xi32>16// CHECK: return17 18// Check fir.must_be_heap allocations are not moved19func.func @must_be_heap() {20  %0 = fir.allocmem !fir.array<42xi32> {fir.must_be_heap = true}21  fir.freemem %0 : !fir.heap<!fir.array<42xi32>>22  return23}24// CHECK-LABEL: func.func @must_be_heap()25// CHECK-NEXT:   %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32> {fir.must_be_heap = true}26// CHECK-NEXT:   fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<42xi32>>27// CHECK-NEXT:   return28// CHECK-NEXT: }29 30// Check the data-flow-analysis can detect cases where we aren't sure if memory31// is freed by the end of the function32func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) {33  %7 = arith.constant 42 : index34  %8 = fir.allocmem !fir.array<?xi32>, %7 {uniq_name = "_QFdfa1Earr.alloc"}35  %9 = fir.load %arg0 : !fir.ref<!fir.logical<4>>36  %10 = fir.convert %9 : (!fir.logical<4>) -> i137  fir.if %10 {38    fir.freemem %8 : !fir.heap<!fir.array<?xi32>>39  } else {40  }41  return42}43// CHECK-LABEL: func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"})44// CHECK-NEXT:   %[[C42:.*]] = arith.constant 42 : index45// CHECK-NEXT:   %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[C42]] {uniq_name = "_QFdfa1Earr.alloc"}46// CHECK-NEXT:   %[[LOGICAL:.*]] = fir.load %arg0 : !fir.ref<!fir.logical<4>>47// CHECK-NEXT:   %[[BOOL:.*]] = fir.convert %[[LOGICAL]] : (!fir.logical<4>) -> i148// CHECK-NEXT:   fir.if %[[BOOL]] {49// CHECK-NEXT:     fir.freemem %[[MEM]] : !fir.heap<!fir.array<?xi32>>50// CHECK-NEXT:   } else {51// CHECK-NEXT:   }52// CHECK-NEXT:   return53// CHECK-NEXT: }54 55// Check scf.if56func.func @dfa2(%arg0: i1) {57  %a = fir.allocmem !fir.array<1xi8>58  scf.if %arg0 {59    fir.freemem %a : !fir.heap<!fir.array<1xi8>>60  } else {61  }62  return63}64// CHECK-LABEL: func.func @dfa2(%arg0: i1)65// CHECK-NEXT:  %[[MEM:.*]] = fir.allocmem !fir.array<1xi8>66// CHECK-NEXT:  scf.if %arg0 {67// CHECK-NEXT:    fir.freemem %[[MEM]] : !fir.heap<!fir.array<1xi8>>68// CHECK-NEXT:  } else {69// CHECK-NEXT:  }70// CHECK-NEXT:  return71// CHECK-NEXT:  }72 73// Check freemem in both regions74func.func @dfa3(%arg0: i1) {75  %a = fir.allocmem !fir.array<1xi8>76  fir.if %arg0 {77    fir.freemem %a : !fir.heap<!fir.array<1xi8>>78  } else {79    fir.freemem %a : !fir.heap<!fir.array<1xi8>>80  }81  %c0_d3 = arith.constant 0 : index82  %c0_i8_d3 = arith.constant 0 : i883  %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>86  return87}88// CHECK: func.func @dfa3(%arg0: i1)89// CHECK:  %[[MEM:.*]] = fir.alloca !fir.array<1xi8>90// CHECK:  return91 92func.func private @dfa3a_foo(!fir.ref<!fir.array<1xi8>>) -> ()93func.func private @dfa3a_bar(!fir.ref<!fir.array<1xi8>>) -> ()94 95// Check freemem in both regions, with other uses96func.func @dfa3a(%arg0: i1) {97  %a = fir.allocmem !fir.array<1xi8>98  fir.if %arg0 {99    %ref = fir.convert %a : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>>100    func.call @dfa3a_foo(%ref) : (!fir.ref<!fir.array<1xi8>>) -> ()101    fir.freemem %a : !fir.heap<!fir.array<1xi8>>102  } else {103    %ref = fir.convert %a : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>>104    func.call @dfa3a_bar(%ref) : (!fir.ref<!fir.array<1xi8>>) -> ()105    fir.freemem %a : !fir.heap<!fir.array<1xi8>>106  }107  return108}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:  return120// CHECK-NEXT:  }121 122// check the alloca is placed after all operands become available123func.func @placement1() {124  // do some stuff with other ssa values125  %1 = arith.constant 1 : index126  %2 = arith.constant 2 : index127  %3 = arith.addi %1, %2 : index128  // operand is now available129  %4 = fir.allocmem !fir.array<?xi32>, %3130  // ...131  %c0 = arith.constant 0 : index132  %c0_i32 = arith.constant 0 : i32133  %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>136  fir.freemem %4 : !fir.heap<!fir.array<?xi32>>137  return138}139// CHECK-LABEL: func.func @placement1()140// CHECK-NEXT:   %[[ARG:.*]] = arith.constant 3 : index141// CHECK-NEXT:   %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[ARG]]142// CHECK:   return143// CHECK-NEXT: }144 145// check that if there are no operands, then the alloca is placed early146func.func @placement2() {147  // do some stuff with other ssa values148  %1 = arith.constant 1 : index149  %2 = arith.constant 2 : index150  %3 = arith.addi %1, %2 : index151  %4 = fir.allocmem !fir.array<42xi32>152  // ...153  %c0_p2 = arith.constant 0 : index154  %c0_i32_p2 = arith.constant 0 : i32155  %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>158  fir.freemem %4 : !fir.heap<!fir.array<42xi32>>159  return160}161// CHECK-LABEL: func.func @placement2()162// CHECK:   %[[MEM:.*]] = fir.alloca !fir.array<42xi32>163// CHECK:   %[[ONE:.*]] = arith.constant 1 : index164// CHECK:   %[[TWO:.*]] = arith.constant 2 : index165// CHECK:   %[[SUM:.*]] = arith.addi %[[ONE]], %[[TWO]] : index166// CHECK:   return167// CHECK: }168 169// check that stack allocations which must be placed in loops use stacksave170func.func @placement3() {171  %c1 = arith.constant 1 : index172  %c1_i32 = fir.convert %c1 : (index) -> i32173  %c2 = arith.constant 2 : index174  %c10 = arith.constant 10 : index175  %0:2 = fir.do_loop %arg0 = %c1 to %c10 step %c1 iter_args(%arg1 = %c1_i32) -> (index, i32) {176    %3 = arith.addi %c1, %c2 : index177    // operand is now available178    %4 = fir.allocmem !fir.array<?xi32>, %3179    // ...180    %c0 = arith.constant 0 : index181    %c0_i32 = arith.constant 0 : i32182    %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>185    fir.freemem %4 : !fir.heap<!fir.array<?xi32>>186    fir.result %3, %c1_i32 : index, i32187  }188  return189}190// CHECK-LABEL: func.func @placement3()191// CHECK-NEXT:   %[[C1:.*]] = arith.constant 1 : index192// CHECK-NEXT:   %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32193// CHECK-NEXT:   %[[C2:.*]] = arith.constant 2 : index194// CHECK-NEXT:   %[[C10:.*]] = arith.constant 10 : index195// CHECK-NEXT:   fir.do_loop196// CHECK-NEXT:     %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index197// CHECK-NEXT:     %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr198// CHECK-NEXT:     %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[SUM]]199// CHECK:     llvm.intr.stackrestore %[[SP]] : !llvm.ptr200// CHECK-NEXT:     fir.result201// CHECK-NEXT:   }202// CHECK-NEXT:   return203// CHECK-NEXT: }204 205// check that stack save/restore are used in CFG loops206func.func @placement4(%arg0 : i1) {207  %c1 = arith.constant 1 : index208  %c1_i32 = fir.convert %c1 : (index) -> i32209  %c2 = arith.constant 2 : index210  %c10 = arith.constant 10 : index211  cf.br ^bb1212^bb1:213  %3 = arith.addi %c1, %c2 : index214  // operand is now available215  %4 = fir.allocmem !fir.array<?xi32>, %3216  // ...217  %c0 = arith.constant 0 : index218  %c0_i32 = arith.constant 0 : i32219  %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>222  fir.freemem %4 : !fir.heap<!fir.array<?xi32>>223  cf.cond_br %arg0, ^bb1, ^bb2224^bb2:225  return226}227// CHECK-LABEL: func.func @placement4(%arg0: i1)228// CHECK-NEXT:   %[[C1:.*]] = arith.constant 1 : index229// CHECK-NEXT:   %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32230// CHECK-NEXT:   %[[C10:.*]] = arith.constant 10 : index231// CHECK-NEXT:   cf.br ^bb1232// CHECK-NEXT: ^bb1:233// CHECK-NEXT:   %[[C3:.*]] = arith.constant 3 : index234// CHECK-NEXT:   %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr235// CHECK-NEXT:   %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[C3]]236// CHECK:   llvm.intr.stackrestore %[[SP]] : !llvm.ptr237// CHECK-NEXT:   cf.cond_br %arg0, ^bb1, ^bb2238// CHECK-NEXT: ^bb2:239// CHECK-NEXT:   return240// CHECK-NEXT: }241 242// check that stacksave is not used when there is an intervening alloca243func.func @placement5() {244  %c1 = arith.constant 1 : index245  %c1_i32 = fir.convert %c1 : (index) -> i32246  %c2 = arith.constant 2 : index247  %c10 = arith.constant 10 : index248  %0:2 = fir.do_loop %arg0 = %c1 to %c10 step %c1 iter_args(%arg1 = %c1_i32) -> (index, i32) {249    %3 = arith.addi %c1, %c2 : index250    // operand is now available251    %4 = fir.allocmem !fir.array<?xi32>, %3252    %5 = fir.alloca i32253    fir.freemem %4 : !fir.heap<!fir.array<?xi32>>254    fir.result %3, %c1_i32 : index, i32255  }256  return257}258// CHECK-LABEL: func.func @placement5()259// CHECK-NEXT:   %[[C1:.*]] = arith.constant 1 : index260// CHECK-NEXT:   %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32261// CHECK-NEXT:   %[[C2:.*]] = arith.constant 2 : index262// CHECK-NEXT:   %[[C10:.*]] = arith.constant 10 : index263// CHECK-NEXT:   fir.do_loop264// CHECK-NEXT:     %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index265// CHECK-NEXT:     %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[SUM]]266// CHECK-NEXT:     %[[IDX:.*]] = fir.alloca i32267// CHECK-NEXT:     fir.freemem %[[MEM]] : !fir.heap<!fir.array<?xi32>>268// CHECK-NEXT:     fir.result269// CHECK-NEXT:   }270// CHECK-NEXT:   return271// CHECK-NEXT: }272 273// check that stack save/restore are not used when the memalloc and freemem are274// in different blocks275func.func @placement6(%arg0: i1) {276  %c1 = arith.constant 1 : index277  %c1_i32 = fir.convert %c1 : (index) -> i32278  %c2 = arith.constant 2 : index279  %c10 = arith.constant 10 : index280  cf.br ^bb1281^bb1:282  %3 = arith.addi %c1, %c2 : index283  // operand is now available284  %4 = fir.allocmem !fir.array<?xi32>, %3285  // ...286  cf.cond_br %arg0, ^bb2, ^bb3287^bb2:288  // ...289  fir.freemem %4 : !fir.heap<!fir.array<?xi32>>290  cf.br ^bb1291^bb3:292  // ...293  fir.freemem %4 : !fir.heap<!fir.array<?xi32>>294  cf.br ^bb1295}296// CHECK-LABEL: func.func @placement6(%arg0: i1)297// CHECK-NEXT:   %[[c1:.*]] = arith.constant 1 : index298// CHECK-NEXT:   %[[c1_i32:.*]] = fir.convert %[[c1]] : (index) -> i32299// CHECK-NEXT:   %[[c2:.*]] = arith.constant 2 : index300// CHECK-NEXT:   %[[c10:.*]] = arith.constant 10 : index301// CHECK-NEXT:   cf.br ^bb1302// CHECK-NEXT: ^bb1:303// CHECK-NEXT:   %[[ADD:.*]] = arith.addi %[[c1]], %[[c2]] : index304// CHECK-NEXT:   %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[ADD]]305// CHECK-NEXT:   cf.cond_br %arg0, ^bb2, ^bb3306// CHECK-NEXT: ^bb2:307// CHECK-NEXT:   fir.freemem %[[MEM]] : !fir.heap<!fir.array<?xi32>>308// CHECK-NEXT:   cf.br ^bb1309// CHECK-NEXT: ^bb3:310// CHECK-NEXT:   fir.freemem %[[MEM]] : !fir.heap<!fir.array<?xi32>>311// CHECK-NEXT:   cf.br ^bb1312// CHECK-NEXT: }313 314// Check multiple returns, where the memory is always freed315func.func @returns(%arg0: i1) {316  %0 = fir.allocmem !fir.array<42xi32>317  %c0_ret = arith.constant 0 : index318  %c0_i32_ret = arith.constant 0 : i32319  %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>322  cf.cond_br %arg0, ^bb1, ^bb2323^bb1:324  fir.freemem %0 : !fir.heap<!fir.array<42xi32>>325  return326^bb2:327  fir.freemem %0 : !fir.heap<!fir.array<42xi32>>328  return329}330// CHECK-LABEL: func.func @returns(331// CHECK:   %[[ALLOC:.*]] = fir.alloca !fir.array<42xi32>332// CHECK:   cf.cond_br %{{.*}}, ^bb1, ^bb2333// CHECK-NEXT: ^bb1:334// CHECK-NEXT:   return335// CHECK-NEXT: ^bb2:336// CHECK-NEXT:   return337// CHECK-NEXT: }338 339// Check multiple returns, where the memory is not freed on one branch340func.func @returns2(%arg0: i1) {341  %0 = fir.allocmem !fir.array<42xi32>342  %c0_ret2 = arith.constant 0 : index343  %c0_i32_ret2 = arith.constant 0 : i32344  %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>347  cf.cond_br %arg0, ^bb1, ^bb2348^bb1:349  fir.freemem %0 : !fir.heap<!fir.array<42xi32>>350  return351^bb2:352  return353}354// CHECK-LABEL: func.func @returns2(355// CHECK:   %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32>356// CHECK:   cf.cond_br %{{.*}}, ^bb1, ^bb2357// CHECK-NEXT: ^bb1:358// CHECK-NEXT:   fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<42xi32>>359// CHECK-NEXT:   return360// CHECK-NEXT: ^bb2:361// CHECK-NEXT:   return362// CHECK-NEXT: }363 364// Check allocations are not moved outside of an omp region365func.func @omp_placement1() {366  omp.sections {367    omp.section {368      %mem = fir.allocmem !fir.array<42xi32>369      fir.freemem %mem : !fir.heap<!fir.array<42xi32>>370      omp.terminator371    }372    omp.terminator373  }374  return375}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.terminator382// CHECK-NEXT:     }383// CHECK-NEXT:     omp.terminator384// CHECK-NEXT:   }385// CHECK-NEXT:   return386// CHECK-NEXT: }387 388// function terminated by stop statement389func.func @stop_terminator() {390  %0 = fir.allocmem !fir.array<42xi32>391  %c0 = arith.constant 0 : index392  %c0_i32_st = arith.constant 0 : i32393  %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>396  fir.freemem %0 : !fir.heap<!fir.array<42xi32>>397  %c0_i32 = arith.constant 0 : i32398  %false = arith.constant false399  fir.call @_FortranAStopStatement(%c0_i32, %false, %false) : (i32, i1, i1) -> ()400  fir.unreachable401}402// CHECK-LABEL: func.func @stop_terminator()403// CHECK: fir.alloca !fir.array<42xi32>404// CHECK: fir.call @_FortranAStopStatement(405// CHECK: fir.unreachable406 407 408// check that stack allocations that use fir.declare which must be placed in loops409// use stacksave410func.func @placement_loop_declare() {411  %c1 = arith.constant 1 : index412  %c1_i32 = fir.convert %c1 : (index) -> i32413  %c2 = arith.constant 2 : index414  %c10 = arith.constant 10 : index415  %0:2 = fir.do_loop %arg0 = %c1 to %c10 step %c1 iter_args(%arg1 = %c1_i32) -> (index, i32) {416    %3 = arith.addi %c1, %c2 : index417    // operand is now available418    %4 = fir.allocmem !fir.array<?xi32>, %3419    %shape = fir.shape %3 : (index) -> !fir.shape<1>420    %5 = fir.declare %4(%shape) {uniq_name = "temp"} : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.heap<!fir.array<?xi32>>421    // ...422    fir.freemem %5 : !fir.heap<!fir.array<?xi32>>423    fir.result %3, %c1_i32 : index, i32424  }425  return426}427// CHECK-LABEL: func.func @placement_loop_declare()428// CHECK-NEXT:   %[[C1:.*]] = arith.constant 1 : index429// CHECK-NEXT:   %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32430// CHECK-NEXT:   %[[C2:.*]] = arith.constant 2 : index431// CHECK-NEXT:   %[[C10:.*]] = arith.constant 10 : index432// CHECK-NEXT:   fir.do_loop433// CHECK-NEXT:     %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index434// CHECK-NEXT:     %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr435// CHECK-NEXT:     %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[SUM]]436// CHECK:          llvm.intr.stackrestore %[[SP]] : !llvm.ptr437// CHECK-NEXT:     fir.result438// CHECK-NEXT:   }439// CHECK-NEXT:   return440// CHECK-NEXT: }441 442// Can we look through fir.convert and fir.declare?443func.func @lookthrough() {444  %0 = fir.allocmem !fir.array<42xi32>445  %c42 = arith.constant 42 : index446  %shape = fir.shape %c42 : (index) -> !fir.shape<1>447  %1 = fir.declare %0(%shape) {uniq_name = "name"} : (!fir.heap<!fir.array<42xi32>>, !fir.shape<1>) -> !fir.heap<!fir.array<42xi32>>448  %2 = fir.convert %1 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>449  // use the ref so the converts aren't folded450  %3 = fir.load %2 : !fir.ref<!fir.array<42xi32>>451  %4 = fir.convert %2 : (!fir.ref<!fir.array<42xi32>>) -> !fir.heap<!fir.array<42xi32>>452  fir.freemem %4 : !fir.heap<!fir.array<42xi32>>453  return454}455// CHECK-LABEL: func.func @lookthrough()456// CHECK:     fir.alloca !fir.array<42xi32>457// CHECK-NOT: fir.freemem458 459// StackArrays is better to find fir.freemem ops corresponding to fir.allocmem460// using the same look through mechanism as during the allocation analysis,461// looking through fir.convert and fir.declare.462func.func @finding_freemem_in_block() {463  %c0 = arith.constant 0 : index464  %c10_i32 = arith.constant 10 : i32465  %c1_i32 = arith.constant 1 : i32466  %0 = fir.alloca i32 {bindc_name = "k", uniq_name = "k"}467  %1 = fir.declare %0 {uniq_name = "k"} : (!fir.ref<i32>) -> !fir.ref<i32>468  fir.store %c1_i32 to %1 : !fir.ref<i32>469  cf.br ^bb1470^bb1:  // 2 preds: ^bb0, ^bb2471  %2 = fir.load %1 : !fir.ref<i32>472  %3 = arith.cmpi sle, %2, %c10_i32 : i32473  cf.cond_br %3, ^bb2, ^bb3474^bb2:  // pred: ^bb1475  %4 = fir.declare %1 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "x"} : (!fir.ref<i32>) -> !fir.ref<i32>476  %5 = fir.load %4 : !fir.ref<i32>477  %6 = fir.convert %5 : (i32) -> index478  %7 = arith.cmpi sgt, %6, %c0 : index479  %8 = arith.select %7, %6, %c0 : index480  %9 = fir.shape %8 : (index) -> !fir.shape<1>481  %10 = fir.allocmem !fir.array<?xi32>, %8 {bindc_name = ".tmp.expr_result", uniq_name = ""}482  %11 = fir.convert %10 : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>483  %12 = fir.declare %11(%9) {uniq_name = ".tmp.expr_result"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.ref<!fir.array<?xi32>>484  %13 = fir.embox %12(%9) : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>>485  %14 = fir.call @_QPfunc(%1) fastmath<fast> : (!fir.ref<i32>) -> !fir.array<?xi32>486  fir.save_result %14 to %12(%9) : !fir.array<?xi32>, !fir.ref<!fir.array<?xi32>>, !fir.shape<1>487  fir.call @_QPsub(%13) fastmath<fast> : (!fir.box<!fir.array<?xi32>>) -> ()488  %15 = fir.convert %12 : (!fir.ref<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>>489  fir.freemem %15 : !fir.heap<!fir.array<?xi32>>490  %16 = fir.load %1 : !fir.ref<i32>491  %17 = arith.addi %16, %c1_i32 : i32492  fir.store %17 to %1 : !fir.ref<i32>493  cf.br ^bb1494^bb3:  // pred: ^bb1495  return496}497// CHECK-LABEL: func.func @finding_freemem_in_block()498// CHECK:     fir.alloca !fir.array<?xi32>499// CHECK-NOT: fir.freemem500