llvm-project/flang/test/Lower/HLFIR/array-ctor-as-elemental.f90
jeanPerier 3be8e3ad0c
[flang] translate pure and elemental attribute in FIR (#109954)
Follow-up from a previous patch that turned bind_c into an enum for
procedure attribute.

This patch carries the elemental and pure Fortran attribute into FIR so
that the optimizer can leverage that info in the future (I think debug
info may also need to know these aspects since DWARF has DW_AT_elemental
and DW_AT_pure nodes).

SIMPLE from F2023 will be translated once it is handled in the
front-end.

NON_RECURSIVE is only meaningful on func.func since we are not
guaranteed to know that aspect on the caller side (it is not part of
Fortran characteristics). There is a DW_AT_recursive DWARF node. I will
do it while dealing with func.func attributes.
2024-09-25 16:45:47 +02:00

161 lines
11 KiB
Fortran

! Test lowering of array constructors as hlfir.elemental.
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
subroutine test_as_simple_elemental(n)
integer :: n
call takes_int([(n+i, i=1,4)])
end subroutine
! CHECK-LABEL: func.func @_QPtest_as_simple_elemental(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) {
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_as_simple_elementalEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_2:.*]] = arith.constant 4 : index
! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i64
! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i64) -> index
! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i64
! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i64) -> index
! CHECK: %[[VAL_8:.*]] = arith.constant 1 : index
! CHECK: %[[VAL_9:.*]] = hlfir.elemental %[[VAL_3]] unordered : (!fir.shape<1>) -> !hlfir.expr<4xi32> {
! CHECK: ^bb0(%[[VAL_10:.*]]: index):
! CHECK: %[[VAL_11:.*]] = arith.subi %[[VAL_10]], %[[VAL_8]] : index
! CHECK: %[[VAL_12:.*]] = arith.muli %[[VAL_11]], %[[VAL_7]] : index
! CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_5]], %[[VAL_12]] : index
! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_13]] : (index) -> i64
! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i64) -> i32
! CHECK: %[[VAL_17:.*]] = arith.addi %[[VAL_14]], %[[VAL_16]] : i32
! CHECK: hlfir.yield_element %[[VAL_17]] : i32
! CHECK: }
! CHECK: %[[VAL_18:.*]]:3 = hlfir.associate %[[VAL_19:.*]](%[[VAL_3]]) {adapt.valuebyref} : (!hlfir.expr<4xi32>, !fir.shape<1>) -> (!fir.ref<!fir.array<4xi32>>, !fir.ref<!fir.array<4xi32>>, i1)
! CHECK: fir.call @_QPtakes_int(%[[VAL_18]]#1) fastmath<contract> : (!fir.ref<!fir.array<4xi32>>) -> ()
! CHECK: hlfir.end_associate %[[VAL_18]]#1, %[[VAL_18]]#2 : !fir.ref<!fir.array<4xi32>>, i1
! CHECK: hlfir.destroy %[[VAL_19]] : !hlfir.expr<4xi32>
! CHECK: return
! CHECK: }
subroutine test_as_strided_elemental(lb, ub, stride)
integer(8) :: lb, ub, stride
call takes_int([(i, i=lb,ub,stride)])
end subroutine
! CHECK-LABEL: func.func @_QPtest_as_strided_elemental(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i64> {fir.bindc_name = "lb"},
! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i64> {fir.bindc_name = "ub"},
! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i64> {fir.bindc_name = "stride"}) {
! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest_as_strided_elementalElb"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest_as_strided_elementalEstride"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest_as_strided_elementalEub"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_9:.*]] = arith.subi %[[VAL_7]], %[[VAL_8]] : i64
! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_9]], %[[VAL_10]] : i64
! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_13:.*]] = arith.divsi %[[VAL_11]], %[[VAL_12]] : i64
! CHECK: %[[VAL_14:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_15:.*]] = arith.cmpi sgt, %[[VAL_13]], %[[VAL_14]] : i64
! CHECK: %[[VAL_16:.*]] = arith.select %[[VAL_15]], %[[VAL_13]], %[[VAL_14]] : i64
! CHECK: %[[VAL_17:.*]] = arith.addi %[[VAL_6]], %[[VAL_16]] : i64
! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_17]] : (i64) -> index
! CHECK: %[[VAL_19:.*]] = fir.shape %[[VAL_18]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i64) -> index
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_22]] : (i64) -> index
! CHECK: %[[VAL_24:.*]] = arith.constant 1 : index
! CHECK: %[[VAL_25:.*]] = hlfir.elemental %[[VAL_19]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xi32> {
! CHECK: ^bb0(%[[VAL_26:.*]]: index):
! CHECK: %[[VAL_27:.*]] = arith.subi %[[VAL_26]], %[[VAL_24]] : index
! CHECK: %[[VAL_28:.*]] = arith.muli %[[VAL_27]], %[[VAL_23]] : index
! CHECK: %[[VAL_29:.*]] = arith.addi %[[VAL_21]], %[[VAL_28]] : index
! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_29]] : (index) -> i64
! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_30]] : (i64) -> i32
! CHECK: hlfir.yield_element %[[VAL_31]] : i32
! CHECK: }
! CHECK: %[[VAL_32:.*]]:3 = hlfir.associate %[[VAL_33:.*]](%[[VAL_19]]) {adapt.valuebyref} : (!hlfir.expr<?xi32>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>, i1)
! CHECK: %[[VAL_34:.*]] = fir.convert %[[VAL_32]]#1 : (!fir.ref<!fir.array<?xi32>>) -> !fir.ref<!fir.array<4xi32>>
! CHECK: fir.call @_QPtakes_int(%[[VAL_34]]) fastmath<contract> : (!fir.ref<!fir.array<4xi32>>) -> ()
! CHECK: hlfir.end_associate %[[VAL_32]]#1, %[[VAL_32]]#2 : !fir.ref<!fir.array<?xi32>>, i1
! CHECK: hlfir.destroy %[[VAL_33]] : !hlfir.expr<?xi32>
! CHECK: return
! CHECK: }
subroutine test_as_elemental_with_pure_call(n)
interface
integer pure function foo(i)
integer, value :: i
end function
end interface
integer :: n
call takes_int([(foo(i), i=1,4)])
end subroutine
! CHECK-LABEL: func.func @_QPtest_as_elemental_with_pure_call(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) {
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_as_elemental_with_pure_callEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_2:.*]] = arith.constant 4 : index
! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i64
! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i64) -> index
! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i64
! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i64) -> index
! CHECK: %[[VAL_8:.*]] = arith.constant 1 : index
! CHECK: %[[VAL_9:.*]] = hlfir.elemental %[[VAL_3]] unordered : (!fir.shape<1>) -> !hlfir.expr<4xi32> {
! CHECK: ^bb0(%[[VAL_10:.*]]: index):
! CHECK: %[[VAL_11:.*]] = arith.subi %[[VAL_10]], %[[VAL_8]] : index
! CHECK: %[[VAL_12:.*]] = arith.muli %[[VAL_11]], %[[VAL_7]] : index
! CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_5]], %[[VAL_12]] : index
! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (index) -> i64
! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i64) -> i32
! CHECK: %[[VAL_16:.*]] = fir.call @_QPfoo(%[[VAL_15]]) proc_attrs<pure> fastmath<contract> : (i32) -> i32
! CHECK: hlfir.yield_element %[[VAL_16]] : i32
! CHECK: }
! CHECK: %[[VAL_17:.*]]:3 = hlfir.associate %[[VAL_18:.*]](%[[VAL_3]]) {adapt.valuebyref} : (!hlfir.expr<4xi32>, !fir.shape<1>) -> (!fir.ref<!fir.array<4xi32>>, !fir.ref<!fir.array<4xi32>>, i1)
! CHECK: fir.call @_QPtakes_int(%[[VAL_17]]#1) fastmath<contract> : (!fir.ref<!fir.array<4xi32>>) -> ()
! CHECK: hlfir.end_associate %[[VAL_17]]#1, %[[VAL_17]]#2 : !fir.ref<!fir.array<4xi32>>, i1
! CHECK: hlfir.destroy %[[VAL_18]] : !hlfir.expr<4xi32>
! CHECK: return
! CHECK: }
! CHECK-LABEL: func.func @_QPtest_with_impure_call(
subroutine test_with_impure_call(n)
interface
integer function impure_foo(i)
integer, value :: i
end function
end interface
integer :: n
call takes_int([(impure_foo(i), i=1,4)])
end subroutine
! CHECK-NOT: hlfir.elemental
! CHECK: return
! Test that the hlfir.expr result of the outer intrinsic call
! is not destructed.
subroutine test_hlfir_expr_result_destruction
character(4) :: a(21)
a = (/ (repeat(repeat(char(i),2),2),i=1,n) /)
end subroutine
! CHECK-LABEL: func.func @_QPtest_hlfir_expr_result_destruction() {
! CHECK: %[[VAL_36:.*]] = hlfir.elemental %{{.*}} typeparams %{{.*}} unordered : (!fir.shape<1>, index) -> !hlfir.expr<?x!fir.char<1,?>> {
! CHECK: %[[VAL_48:.*]] = hlfir.as_expr %{{.*}} move %{{.*}} : (!fir.ref<!fir.char<1>>, i1) -> !hlfir.expr<!fir.char<1>>
! CHECK: %[[VAL_51:.*]]:3 = hlfir.associate %[[VAL_48]] typeparams %{{.*}} {adapt.valuebyref} : (!hlfir.expr<!fir.char<1>>, index) -> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>, i1)
! CHECK: %[[VAL_64:.*]]:2 = hlfir.declare %{{.*}} typeparams %{{.*}} {uniq_name = ".tmp.intrinsic_result"} : (!fir.heap<!fir.char<1,2>>, index) -> (!fir.heap<!fir.char<1,2>>, !fir.heap<!fir.char<1,2>>)
! CHECK: %[[VAL_66:.*]] = hlfir.as_expr %[[VAL_64]]#0 move %{{.*}} : (!fir.heap<!fir.char<1,2>>, i1) -> !hlfir.expr<!fir.char<1,2>>
! CHECK: %[[VAL_68:.*]]:3 = hlfir.associate %[[VAL_66]] typeparams %{{.*}} {adapt.valuebyref} : (!hlfir.expr<!fir.char<1,2>>, index) -> (!fir.ref<!fir.char<1,2>>, !fir.ref<!fir.char<1,2>>, i1)
! CHECK: %[[VAL_81:.*]]:2 = hlfir.declare %{{.*}} typeparams %{{.*}} {uniq_name = ".tmp.intrinsic_result"} : (!fir.heap<!fir.char<1,4>>, index) -> (!fir.heap<!fir.char<1,4>>, !fir.heap<!fir.char<1,4>>)
! CHECK: %[[VAL_83:.*]] = hlfir.as_expr %[[VAL_81]]#0 move %{{.*}} : (!fir.heap<!fir.char<1,4>>, i1) -> !hlfir.expr<!fir.char<1,4>>
! CHECK-NOT: hlfir.destroy %[[VAL_83]]
! CHECK: hlfir.end_associate %[[VAL_68]]#1, %[[VAL_68]]#2 : !fir.ref<!fir.char<1,2>>, i1
! CHECK-NOT: hlfir.destroy %[[VAL_83]]
! CHECK: hlfir.destroy %[[VAL_66]] : !hlfir.expr<!fir.char<1,2>>
! CHECK-NOT: hlfir.destroy %[[VAL_83]]
! CHECK: hlfir.end_associate %[[VAL_51]]#1, %[[VAL_51]]#2 : !fir.ref<!fir.char<1>>, i1
! CHECK-NOT: hlfir.destroy %[[VAL_83]]
! CHECK: hlfir.destroy %[[VAL_48]] : !hlfir.expr<!fir.char<1>>
! CHECK-NOT: hlfir.destroy %[[VAL_83]]
! CHECK: hlfir.yield_element %[[VAL_83]] : !hlfir.expr<!fir.char<1,4>>
! CHECK-NOT: hlfir.destroy %[[VAL_83]]
! CHECK: }
! CHECK-NOT: hlfir.destroy %[[VAL_83]]