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