llvm-project/flang/test/HLFIR/associate-codegen.fir
Jean Perier 319f0221ee [flang] hlfir.associate and hlfir.end_associate codegen
Add hlfir.associate and hlfir.end_associate codegen.
To properly allow reusing the bufferized expression storage for the
newly created variable, bufferization of hlfir.expr has to be updated
so that hlfir.expr are translated to a variable and a boolean to
indicate if the variable storage needs to be freed after the expression
was used. That way the responsibility to free the bufferized expression
can be passed to the variable user, and applied in the
hlfir.end_associate.

Right now, not of the bufferized expression are heap allocated, so
generating the conditional freemem in hlfir.end_associate is left as
a TODO for when it can be tested.

Differential Revision: https://reviews.llvm.org/D139020
2022-12-01 17:58:28 +01:00

86 lines
4.4 KiB
Plaintext

// Test hlfir.associate/hlfir.end_associate operation code generation to FIR.
// RUN: fir-opt %s -bufferize-hlfir | FileCheck %s
func.func @associate_int() {
%c42_i32 = arith.constant 42 : i32
%0:3 = hlfir.associate %c42_i32 {uniq_name = "x"} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
fir.call @take_i4(%0#0) : (!fir.ref<i32>) -> ()
hlfir.end_associate %0#1, %0#2 : !fir.ref<i32>, i1
return
}
// CHECK-LABEL: func.func @associate_int() {
// CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "x"}
// CHECK: %[[VAL_1:.*]] = arith.constant 42 : i32
// CHECK: fir.store %[[VAL_1]] to %[[VAL_0]] : !fir.ref<i32>
// CHECK: %[[VAL_2:.*]] = arith.constant false
// CHECK: fir.call @take_i4(%[[VAL_0]]) : (!fir.ref<i32>) -> ()
// CHECK-NOT: fir.freemem
func.func @associate_real() {
%cst = arith.constant 4.200000e-01 : f32
%0:3 = hlfir.associate %cst {uniq_name = "x"} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
fir.call @take_r4(%0#0) : (!fir.ref<f32>) -> ()
hlfir.end_associate %0#1, %0#2 : !fir.ref<f32>, i1
return
}
// CHECK-LABEL: func.func @associate_real() {
// CHECK: %[[VAL_0:.*]] = fir.alloca f32 {bindc_name = "x"}
// CHECK: %[[VAL_1:.*]] = arith.constant 4.200000e-01 : f32
// CHECK: fir.store %[[VAL_1]] to %[[VAL_0]] : !fir.ref<f32>
// CHECK: %[[VAL_2:.*]] = arith.constant false
// CHECK: fir.call @take_r4(%[[VAL_0]]) : (!fir.ref<f32>) -> ()
// CHECK-NOT: fir.freemem
func.func @associate_logical() {
%true = arith.constant true
%0 = fir.convert %true : (i1) -> !fir.logical<4>
%1:3 = hlfir.associate %0 {uniq_name = "x"} : (!fir.logical<4>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>, i1)
fir.call @take_l4(%1#0) : (!fir.ref<!fir.logical<4>>) -> ()
hlfir.end_associate %1#1, %1#2 : !fir.ref<!fir.logical<4>>, i1
return
}
// CHECK-LABEL: func.func @associate_logical() {
// CHECK: %[[VAL_0:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x"}
// CHECK: %[[VAL_1:.*]] = arith.constant true
// CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4>
// CHECK: fir.store %[[VAL_2]] to %[[VAL_0]] : !fir.ref<!fir.logical<4>>
// CHECK: %[[VAL_3:.*]] = arith.constant false
// CHECK: fir.call @take_l4(%[[VAL_0]]) : (!fir.ref<!fir.logical<4>>) -> ()
// CHECK-NOT: fir.freemem
func.func @associate_char(%arg0: !fir.boxchar<1> ) {
%0:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
%1:2 = hlfir.declare %0#0 typeparams %0#1 {uniq_name = "x"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
%2 = arith.addi %0#1, %0#1 : index
%3 = hlfir.concat %1#0, %1#0 len %2 : (!fir.boxchar<1>, !fir.boxchar<1>, index) -> !hlfir.expr<!fir.char<1,?>>
%4:3 = hlfir.associate %3 typeparams %2 {uniq_name = "x"} : (!hlfir.expr<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>, i1)
fir.call @take_c(%4#0) : (!fir.boxchar<1>) -> ()
hlfir.end_associate %4#1, %4#2 : !fir.ref<!fir.char<1,?>>, i1
return
}
// CHECK-LABEL: func.func @associate_char(
// CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1>) {
// CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
// CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 {uniq_name = "x"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
// CHECK: %[[VAL_3:.*]] = arith.addi %[[VAL_1]]#1, %[[VAL_1]]#1 : index
// CHECK: %[[VAL_4:.*]] = arith.addi %[[VAL_1]]#1, %[[VAL_1]]#1 : index
// CHECK: %[[VAL_5:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_4]] : index) {bindc_name = ".chrtmp"}
// CHECK: fir.call @llvm.memmove.p0.p0.i64
// CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_4]] {uniq_name = "tmp"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
// CHECK: %[[VAL_22:.*]] = arith.constant false
// CHECK: %[[VAL_23:.*]] = fir.undefined tuple<!fir.boxchar<1>, i1>
// CHECK: %[[VAL_24:.*]] = fir.insert_value %[[VAL_23]], %[[VAL_22]], [1 : index] : (tuple<!fir.boxchar<1>, i1>, i1) -> tuple<!fir.boxchar<1>, i1>
// CHECK: %[[VAL_25:.*]] = fir.insert_value %[[VAL_24]], %[[VAL_21]]#0, [0 : index] : (tuple<!fir.boxchar<1>, i1>, !fir.boxchar<1>) -> tuple<!fir.boxchar<1>, i1>
// CHECK: fir.call @take_c(%[[VAL_21]]#0) : (!fir.boxchar<1>) -> ()
// CHECK-NOT: fir.freemem
func.func private @take_i4(!fir.ref<i32>)
func.func private @take_r4(!fir.ref<f32>)
func.func private @take_l4(!fir.ref<!fir.logical<4>>)
func.func private @take_c(!fir.boxchar<1>)