1*460f828fSValentin Clement! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s
2*460f828fSValentin Clement
3*460f828fSValentin Clement! Test statement function lowering
4*460f828fSValentin Clement
5*460f828fSValentin Clement! Simple case
6*460f828fSValentin Clement  ! CHECK-LABEL: func @_QPtest_stmt_0(
7*460f828fSValentin Clement  ! CHECK-SAME: %{{.*}}: !fir.ref<f32>{{.*}}) -> f32
8*460f828fSValentin Clementreal function test_stmt_0(x)
9*460f828fSValentin Clement  real :: x, func, arg
10*460f828fSValentin Clement  func(arg) = arg + 0.123456
11*460f828fSValentin Clement
12*460f828fSValentin Clement  ! CHECK-DAG: %[[x:.*]] = fir.load %arg0
13*460f828fSValentin Clement  ! CHECK-DAG: %[[cst:.*]] = arith.constant 1.234560e-01
14*460f828fSValentin Clement  ! CHECK: %[[eval:.*]] = arith.addf %[[x]], %[[cst]]
15*460f828fSValentin Clement  ! CHECK: fir.store %[[eval]] to %[[resmem:.*]] : !fir.ref<f32>
16*460f828fSValentin Clement  test_stmt_0 = func(x)
17*460f828fSValentin Clement
18*460f828fSValentin Clement  ! CHECK: %[[res:.*]] = fir.load %[[resmem]]
19*460f828fSValentin Clement  ! CHECK: return %[[res]]
20*460f828fSValentin Clementend function
21*460f828fSValentin Clement
22*460f828fSValentin Clement! Check this is not lowered as a simple macro: e.g. argument is only
23*460f828fSValentin Clement! evaluated once even if it appears in several placed inside the
24*460f828fSValentin Clement! statement function expression
25*460f828fSValentin Clement! CHECK-LABEL: func @_QPtest_stmt_only_eval_arg_once() -> f32
26*460f828fSValentin Clementreal(4) function test_stmt_only_eval_arg_once()
27*460f828fSValentin Clement  real(4) :: only_once, x1
28*460f828fSValentin Clement  func(x1) = x1 + x1
29*460f828fSValentin Clement  ! CHECK: %[[x2:.*]] = fir.alloca f32 {adapt.valuebyref}
30*460f828fSValentin Clement  ! CHECK: %[[x1:.*]] = fir.call @_QPonly_once()
31*460f828fSValentin Clement  ! Note: using -emit-fir, so the faked pass-by-reference is exposed
32*460f828fSValentin Clement  ! CHECK: fir.store %[[x1]] to %[[x2]]
33*460f828fSValentin Clement  ! CHECK: addf %{{.*}}, %{{.*}}
34*460f828fSValentin Clement  test_stmt_only_eval_arg_once = func(only_once())
35*460f828fSValentin Clementend function
36*460f828fSValentin Clement
37*460f828fSValentin Clement! Test nested statement function (note that they cannot be recursively
38*460f828fSValentin Clement! nested as per F2018 C1577).
39*460f828fSValentin Clementreal function test_stmt_1(x, a)
40*460f828fSValentin Clement  real :: y, a, b, foo
41*460f828fSValentin Clement  real :: func1, arg1, func2, arg2
42*460f828fSValentin Clement  real :: res1, res2
43*460f828fSValentin Clement  func1(arg1) = a + foo(arg1)
44*460f828fSValentin Clement  func2(arg2) = func1(arg2) + b
45*460f828fSValentin Clement  ! CHECK-DAG: %[[bmem:.*]] = fir.alloca f32 {{{.*}}uniq_name = "{{.*}}Eb"}
46*460f828fSValentin Clement  ! CHECK-DAG: %[[res1:.*]] = fir.alloca f32 {{{.*}}uniq_name = "{{.*}}Eres1"}
47*460f828fSValentin Clement  ! CHECK-DAG: %[[res2:.*]] = fir.alloca f32 {{{.*}}uniq_name = "{{.*}}Eres2"}
48*460f828fSValentin Clement
49*460f828fSValentin Clement  b = 5
50*460f828fSValentin Clement
51*460f828fSValentin Clement  ! CHECK-DAG: %[[cst_8:.*]] = arith.constant 8.000000e+00
52*460f828fSValentin Clement  ! CHECK-DAG: fir.store %[[cst_8]] to %[[tmp1:.*]] : !fir.ref<f32>
53*460f828fSValentin Clement  ! CHECK-DAG: %[[foocall1:.*]] = fir.call @_QPfoo(%[[tmp1]])
54*460f828fSValentin Clement  ! CHECK-DAG: %[[aload1:.*]] = fir.load %arg1
55*460f828fSValentin Clement  ! CHECK: %[[add1:.*]] = arith.addf %[[aload1]], %[[foocall1]]
56*460f828fSValentin Clement  ! CHECK: fir.store %[[add1]] to %[[res1]]
57*460f828fSValentin Clement  res1 =  func1(8.)
58*460f828fSValentin Clement
59*460f828fSValentin Clement  ! CHECK-DAG: %[[a2:.*]] = fir.load %arg1
60*460f828fSValentin Clement  ! CHECK-DAG: %[[foocall2:.*]] = fir.call @_QPfoo(%arg0)
61*460f828fSValentin Clement  ! CHECK-DAG: %[[add2:.*]] = arith.addf %[[a2]], %[[foocall2]]
62*460f828fSValentin Clement  ! CHECK-DAG: %[[b:.*]] = fir.load %[[bmem]]
63*460f828fSValentin Clement  ! CHECK: %[[add3:.*]] = arith.addf %[[add2]], %[[b]]
64*460f828fSValentin Clement  ! CHECK: fir.store %[[add3]] to %[[res2]]
65*460f828fSValentin Clement  res2 = func2(x)
66*460f828fSValentin Clement
67*460f828fSValentin Clement  ! CHECK-DAG: %[[res12:.*]] = fir.load %[[res1]]
68*460f828fSValentin Clement  ! CHECK-DAG: %[[res22:.*]] = fir.load %[[res2]]
69*460f828fSValentin Clement  ! CHECK: = arith.addf %[[res12]], %[[res22]] : f32
70*460f828fSValentin Clement  test_stmt_1 = res1 + res2
71*460f828fSValentin Clement  ! CHECK: return %{{.*}} : f32
72*460f828fSValentin Clementend function
73*460f828fSValentin Clement
74*460f828fSValentin Clement
75*460f828fSValentin Clement! Test statement functions with no argument.
76*460f828fSValentin Clement! Test that they are not pre-evaluated.
77*460f828fSValentin Clement! CHECK-LABEL: func @_QPtest_stmt_no_args
78*460f828fSValentin Clementreal function test_stmt_no_args(x, y)
79*460f828fSValentin Clement  func() = x + y
80*460f828fSValentin Clement  ! CHECK: addf
81*460f828fSValentin Clement  a = func()
82*460f828fSValentin Clement  ! CHECK: fir.call @_QPfoo_may_modify_xy
83*460f828fSValentin Clement  call foo_may_modify_xy(x, y)
84*460f828fSValentin Clement  ! CHECK: addf
85*460f828fSValentin Clement  ! CHECK: addf
86*460f828fSValentin Clement  test_stmt_no_args = func() + a
87*460f828fSValentin Clementend function
88*460f828fSValentin Clement
89*460f828fSValentin Clement! Test statement function with character arguments
90*460f828fSValentin Clement! CHECK-LABEL: @_QPtest_stmt_character
91*460f828fSValentin Clementinteger function test_stmt_character(c, j)
92*460f828fSValentin Clement  integer :: i, j, func, argj
93*460f828fSValentin Clement  character(10) :: c, argc
94*460f828fSValentin Clement  ! CHECK-DAG: %[[unboxed:.*]]:2 = fir.unboxchar %arg0 :
95*460f828fSValentin Clement  ! CHECK-DAG: %[[c10:.*]] = arith.constant 10 :
96*460f828fSValentin Clement  ! CHECK: %[[c10_cast:.*]] = fir.convert %[[c10]] : (i32) -> index
97*460f828fSValentin Clement  ! CHECK: %[[c:.*]] = fir.emboxchar %[[unboxed]]#0, %[[c10_cast]]
98*460f828fSValentin Clement
99*460f828fSValentin Clement  func(argc, argj) = len_trim(argc, 4) + argj
100*460f828fSValentin Clement  ! CHECK: addi %{{.*}}, %{{.*}} : i
101*460f828fSValentin Clement  test_stmt_character = func(c, j)
102*460f828fSValentin Clementend function
103*460f828fSValentin Clement
104*460f828fSValentin Clement! Test statement function with a character actual argument whose
105*460f828fSValentin Clement! length may be different than the dummy length (the dummy length
106*460f828fSValentin Clement! must be used inside the statement function).
107*460f828fSValentin Clement! CHECK-LABEL: @_QPtest_stmt_character_with_different_length(
108*460f828fSValentin Clement! CHECK-SAME: %[[arg0:.*]]: !fir.boxchar<1>
109*460f828fSValentin Clementinteger function test_stmt_character_with_different_length(c)
110*460f828fSValentin Clement  integer :: func, ifoo
111*460f828fSValentin Clement  character(10) :: argc
112*460f828fSValentin Clement  character(*) :: c
113*460f828fSValentin Clement  ! CHECK-DAG: %[[unboxed:.*]]:2 = fir.unboxchar %[[arg0]] :
114*460f828fSValentin Clement  ! CHECK-DAG: %[[c10:.*]] = arith.constant 10 :
115*460f828fSValentin Clement  ! CHECK: %[[c10_cast:.*]] = fir.convert %[[c10]] : (i32) -> index
116*460f828fSValentin Clement  ! CHECK: %[[argc:.*]] = fir.emboxchar %[[unboxed]]#0, %[[c10_cast]]
117*460f828fSValentin Clement  ! CHECK: fir.call @_QPifoo(%[[argc]]) : (!fir.boxchar<1>) -> i32
118*460f828fSValentin Clement  func(argc) = ifoo(argc)
119*460f828fSValentin Clement  test_stmt_character = func(c)
120*460f828fSValentin Clementend function
121*460f828fSValentin Clement
122*460f828fSValentin Clement! CHECK-LABEL: @_QPtest_stmt_character_with_different_length_2(
123*460f828fSValentin Clement! CHECK-SAME: %[[arg0:.*]]: !fir.boxchar<1>{{.*}}, %[[arg1:.*]]: !fir.ref<i32>
124*460f828fSValentin Clementinteger function test_stmt_character_with_different_length_2(c, n)
125*460f828fSValentin Clement  integer :: func, ifoo
126*460f828fSValentin Clement  character(n) :: argc
127*460f828fSValentin Clement  character(*) :: c
128*460f828fSValentin Clement  ! CHECK: %[[unboxed:.*]]:2 = fir.unboxchar %[[arg0]] :
129*460f828fSValentin Clement  ! CHECK: fir.load %[[arg1]] : !fir.ref<i32>
130*460f828fSValentin Clement  ! CHECK: %[[n:.*]] = fir.load %[[arg1]] : !fir.ref<i32>
131*460f828fSValentin Clement  ! CHECK: %[[n_is_positive:.*]] = arith.cmpi sgt, %[[n]], %c0{{.*}} : i32
132*460f828fSValentin Clement  ! CHECK: %[[len:.*]] = arith.select %[[n_is_positive]], %[[n]], %c0{{.*}} : i32
133*460f828fSValentin Clement  ! CHECK: %[[lenCast:.*]] = fir.convert %[[len]] : (i32) -> index
134*460f828fSValentin Clement  ! CHECK: %[[argc:.*]] = fir.emboxchar %[[unboxed]]#0, %[[lenCast]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
135*460f828fSValentin Clement  ! CHECK: fir.call @_QPifoo(%[[argc]]) : (!fir.boxchar<1>) -> i32
136*460f828fSValentin Clement  func(argc) = ifoo(argc)
137*460f828fSValentin Clement  test_stmt_character = func(c)
138*460f828fSValentin Clementend function
139*460f828fSValentin Clement
140*460f828fSValentin Clement! issue #247
141*460f828fSValentin Clement! CHECK-LABEL: @_QPbug247
142*460f828fSValentin Clementsubroutine bug247(r)
143*460f828fSValentin Clement  I(R) = R
144*460f828fSValentin Clement  ! CHECK: fir.call {{.*}}OutputInteger
145*460f828fSValentin Clement  PRINT *, I(2.5)
146*460f828fSValentin Clement  ! CHECK: fir.call {{.*}}EndIo
147*460f828fSValentin ClementEND subroutine bug247
148