1! RUN: bbc -o - -emit-fir %s | FileCheck %s 2 3! Test lowering of operations sub-expression inside elemental call arguments. 4! This tests array contexts where an address is needed for each element (for 5! the argument), but part of the array sub-expression must be lowered by value 6! (for the operation) 7 8module test_ops 9 interface 10 integer elemental function elem_func(i) 11 integer, intent(in) :: i 12 end function 13 integer elemental function elem_func_logical(l) 14 logical(8), intent(in) :: l 15 end function 16 integer elemental function elem_func_logical4(l) 17 logical, intent(in) :: l 18 end function 19 integer elemental function elem_func_real(x) 20 real(8), value :: x 21 end function 22 end interface 23 integer :: i(10), j(10), iscalar 24 logical(8) :: a(10), b(10) 25 real(8) :: x(10), y(10) 26 complex(8) :: z1(10), z2 27 28contains 29! CHECK-LABEL: func @_QMtest_opsPcheck_binary_ops() { 30subroutine check_binary_ops() 31 print *, elem_func(i+j) 32! CHECK: %[[VAL_0:.*]] = fir.alloca i32 33! CHECK: fir.do_loop 34! CHECK: %[[VAL_25:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xi32>, index) -> i32 35! CHECK: %[[VAL_26:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xi32>, index) -> i32 36! CHECK: %[[VAL_27:.*]] = arith.addi %[[VAL_25]], %[[VAL_26]] : i32 37! CHECK: fir.store %[[VAL_27]] to %[[VAL_0]] : !fir.ref<i32> 38! CHECK: fir.call @_QPelem_func(%[[VAL_0]]) : (!fir.ref<i32>) -> i32 39end subroutine 40 41! CHECK-LABEL: func @_QMtest_opsPcheck_binary_ops_2() { 42subroutine check_binary_ops_2() 43 print *, elem_func(i*iscalar) 44! CHECK: %[[VAL_0:.*]] = fir.alloca i32 45! CHECK: %[[VAL_13:.*]] = fir.load %{{.*}} : !fir.ref<i32> 46! CHECK: fir.do_loop 47! CHECK: %[[VAL_25:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xi32>, index) -> i32 48! CHECK: %[[VAL_27:.*]] = arith.muli %[[VAL_25]], %[[VAL_13]] : i32 49! CHECK: fir.store %[[VAL_27]] to %[[VAL_0]] : !fir.ref<i32> 50! CHECK: fir.call @_QPelem_func(%[[VAL_0]]) : (!fir.ref<i32>) -> i32 51end subroutine 52 53! CHECK-LABEL: func @_QMtest_opsPcheck_negate() { 54subroutine check_negate() 55 print *, elem_func(-i) 56! CHECK: %[[VAL_0:.*]] = fir.alloca i32 57! CHECK: fir.do_loop 58! CHECK: %[[VAL_21:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xi32>, index) -> i32 59! CHECK: %[[VAL_22:.*]] = arith.constant 0 : i32 60! CHECK: %[[VAL_23:.*]] = arith.subi %[[VAL_22]], %[[VAL_21]] : i32 61! CHECK: fir.store %[[VAL_23]] to %[[VAL_0]] : !fir.ref<i32> 62! CHECK: fir.call @_QPelem_func(%[[VAL_0]]) : (!fir.ref<i32>) -> i32 63end subroutine 64 65! CHECK-LABEL: func @_QMtest_opsPcheck_convert() { 66subroutine check_convert() 67 print *, elem_func(int(x)) 68! CHECK: %[[VAL_0:.*]] = fir.alloca i32 69! CHECK: fir.do_loop 70! CHECK: %[[VAL_21:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xf64>, index) -> f64 71! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_21]] : (f64) -> i32 72! CHECK: fir.store %[[VAL_22]] to %[[VAL_0]] : !fir.ref<i32> 73! CHECK: fir.call @_QPelem_func(%[[VAL_0]]) : (!fir.ref<i32>) -> i32 74end subroutine 75 76! CHECK-LABEL: func @_QMtest_opsPcheck_exteremum() { 77subroutine check_exteremum() 78 print *, elem_func(min(i, j)) 79! CHECK: %[[VAL_0:.*]] = fir.alloca i32 80! CHECK: fir.do_loop 81! CHECK: %[[VAL_25:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xi32>, index) -> i32 82! CHECK: %[[VAL_26:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xi32>, index) -> i32 83! CHECK: %[[VAL_27:.*]] = arith.cmpi slt, %[[VAL_25]], %[[VAL_26]] : i32 84! CHECK: %[[VAL_28:.*]] = arith.select %[[VAL_27]], %[[VAL_25]], %[[VAL_26]] : i32 85! CHECK: fir.store %[[VAL_28]] to %[[VAL_0]] : !fir.ref<i32> 86! CHECK: fir.call @_QPelem_func(%[[VAL_0]]) : (!fir.ref<i32>) -> i32 87end subroutine 88 89! CHECK-LABEL: func @_QMtest_opsPcheck_logical_unary_ops() { 90subroutine check_logical_unary_ops() 91 print *, elem_func_logical(.not.b) 92! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.logical<8> 93! CHECK: %[[VAL_12:.*]] = arith.constant true 94! CHECK: fir.do_loop 95! CHECK: %[[VAL_22:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10x!fir.logical<8>>, index) -> !fir.logical<8> 96! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<8>) -> i1 97! CHECK: %[[VAL_24:.*]] = arith.xori %[[VAL_23]], %[[VAL_12]] : i1 98! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (i1) -> !fir.logical<8> 99! CHECK: fir.store %[[VAL_25]] to %[[VAL_0]] : !fir.ref<!fir.logical<8>> 100! CHECK: fir.call @_QPelem_func_logical(%[[VAL_0]]) : (!fir.ref<!fir.logical<8>>) -> i32 101end subroutine 102 103! CHECK-LABEL: func @_QMtest_opsPcheck_logical_binary_ops() { 104subroutine check_logical_binary_ops() 105 print *, elem_func_logical(a.eqv.b) 106! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.logical<8> 107! CHECK: fir.do_loop 108! CHECK: %[[VAL_25:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10x!fir.logical<8>>, index) -> !fir.logical<8> 109! CHECK: %[[VAL_26:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10x!fir.logical<8>>, index) -> !fir.logical<8> 110! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_25]] : (!fir.logical<8>) -> i1 111! CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_26]] : (!fir.logical<8>) -> i1 112! CHECK: %[[VAL_29:.*]] = arith.cmpi eq, %[[VAL_27]], %[[VAL_28]] : i1 113! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_29]] : (i1) -> !fir.logical<8> 114! CHECK: fir.store %[[VAL_30]] to %[[VAL_0]] : !fir.ref<!fir.logical<8>> 115! CHECK: fir.call @_QPelem_func_logical(%[[VAL_0]]) : (!fir.ref<!fir.logical<8>>) -> i32 116end subroutine 117 118! CHECK-LABEL: func @_QMtest_opsPcheck_compare() { 119subroutine check_compare() 120 print *, elem_func_logical4(x.lt.y) 121! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.logical<4> 122! CHECK: fir.do_loop 123! CHECK: %[[VAL_25:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xf64>, index) -> f64 124! CHECK: %[[VAL_26:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xf64>, index) -> f64 125! CHECK: %[[VAL_27:.*]] = arith.cmpf olt, %[[VAL_25]], %[[VAL_26]] : f64 126! CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_27]] : (i1) -> !fir.logical<4> 127! CHECK: fir.store %[[VAL_28]] to %[[VAL_0]] : !fir.ref<!fir.logical<4>> 128! CHECK: fir.call @_QPelem_func_logical4(%[[VAL_0]]) : (!fir.ref<!fir.logical<4>>) -> i32 129end subroutine 130 131! CHECK-LABEL: func @_QMtest_opsPcheck_pow() { 132subroutine check_pow() 133 print *, elem_func_real(x**y) 134! CHECK: %[[VAL_0:.*]] = fir.alloca f64 135! CHECK: fir.do_loop 136! CHECK: %[[VAL_25:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xf64>, index) -> f64 137! CHECK: %[[VAL_26:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xf64>, index) -> f64 138! CHECK: %[[VAL_27:.*]] = math.powf %[[VAL_25]], %[[VAL_26]] : f64 139! CHECK: fir.store %[[VAL_27]] to %[[VAL_0]] : !fir.ref<f64> 140! CHECK: %[[VAL_28:.*]] = fir.call @_QPelem_func_real(%[[VAL_0]]) : (!fir.ref<f64>) -> i32 141end subroutine 142 143! CHECK-LABEL: func @_QMtest_opsPcheck_cmplx_part() { 144subroutine check_cmplx_part() 145 print *, elem_func_real(AIMAG(z1 + z2)) 146! CHECK: %[[VAL_0:.*]] = fir.alloca f64 147! CHECK: %[[VAL_13:.*]] = fir.load %{{.*}} : !fir.ref<!fir.complex<8>> 148! CHECK: fir.do_loop 149! CHECK: %[[VAL_23:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10x!fir.complex<8>>, index) -> !fir.complex<8> 150! CHECK: %[[VAL_24:.*]] = fir.addc %[[VAL_23]], %[[VAL_13]] : !fir.complex<8> 151! CHECK: %[[VAL_25:.*]] = fir.extract_value %[[VAL_24]], [1 : index] : (!fir.complex<8>) -> f64 152! CHECK: fir.store %[[VAL_25]] to %[[VAL_0]] : !fir.ref<f64> 153! CHECK: fir.call @_QPelem_func_real(%[[VAL_0]]) : (!fir.ref<f64>) -> i32 154end subroutine 155 156! CHECK-LABEL: func @_QMtest_opsPcheck_parentheses() { 157subroutine check_parentheses() 158 print *, elem_func_real((x)) 159! CHECK: %[[VAL_0:.*]] = fir.alloca f64 160! CHECK: fir.do_loop 161! CHECK: %[[VAL_21:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xf64>, index) -> f64 162! CHECK: %[[VAL_22:.*]] = fir.no_reassoc %[[VAL_21]] : f64 163! CHECK: fir.store %[[VAL_22]] to %[[VAL_0]] : !fir.ref<f64> 164! CHECK: fir.call @_QPelem_func_real(%[[VAL_0]]) : (!fir.ref<f64>) -> i32 165end subroutine 166 167! CHECK-LABEL: func @_QMtest_opsPcheck_parentheses_logical() { 168subroutine check_parentheses_logical() 169 print *, elem_func_logical((a)) 170! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.logical<8> 171! CHECK: fir.do_loop 172! CHECK: %[[VAL_21:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10x!fir.logical<8>>, index) -> !fir.logical<8> 173! CHECK: %[[VAL_22:.*]] = fir.no_reassoc %[[VAL_21]] : !fir.logical<8> 174! CHECK: fir.store %[[VAL_22]] to %[[VAL_0]] : !fir.ref<!fir.logical<8>> 175! CHECK: fir.call @_QPelem_func_logical(%[[VAL_0]]) : (!fir.ref<!fir.logical<8>>) -> i32 176end subroutine 177 178subroutine check_parentheses_derived(a) 179 type t 180 integer :: i 181 end type 182 interface 183 integer elemental function elem_func_derived(x) 184 import :: t 185 type(t), intent(in) :: x 186 end function 187 end interface 188 type(t), pointer :: a(:) 189 print *, elem_func_derived((a)) 190! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.type<_QMtest_opsFcheck_parentheses_derivedTt{i:i32}> 191! CHECK: fir.do_loop 192! CHECK: %[[VAL_21:.*]] = fir.array_access %{{.}}, %{{.*}} 193! CHECK: %[[VAL_22:.*]] = fir.no_reassoc %[[VAL_21]] : !fir.ref<!fir.type<_QMtest_opsFcheck_parentheses_derivedTt{i:i32}>> 194! CHECK: %[[FIELD:.*]] = fir.field_index i, !fir.type<_QMtest_opsFcheck_parentheses_derivedTt{i:i32}> 195! CHECK: %[[FROM:.*]] = fir.coordinate_of %[[VAL_22]], %[[FIELD]] : (!fir.ref<!fir.type<_QMtest_opsFcheck_parentheses_derivedTt{i:i32}>>, !fir.field) -> !fir.ref<i32> 196! CHECK: %[[FIELD2:.*]] = fir.field_index i, !fir.type<_QMtest_opsFcheck_parentheses_derivedTt{i:i32}> 197! CHECK: %[[TO:.*]] = fir.coordinate_of %[[VAL_0]], %[[FIELD2]] : (!fir.ref<!fir.type<_QMtest_opsFcheck_parentheses_derivedTt{i:i32}>>, !fir.field) -> !fir.ref<i32> 198! CHECK: %[[VAL:.*]] = fir.load %[[FROM]] : !fir.ref<i32> 199! CHECK: fir.store %[[VAL]] to %[[TO]] : !fir.ref<i32> 200! CHECK: %{{.*}} = fir.call @_QPelem_func_derived(%[[VAL_0]]) : (!fir.ref<!fir.type<_QMtest_opsFcheck_parentheses_derivedTt{i:i32}>>) -> i32 201end subroutine 202end module 203