Skip to content

Commit 81ea91a

Browse files
authored
[flang][hlfir] Return function call result as AsExpr. (llvm#67769)
This should help inlining elemental into another elemental, and also will help to get rid of unnecessary deep copies in bufferization.
1 parent 2b27948 commit 81ea91a

File tree

5 files changed

+169
-8
lines changed

5 files changed

+169
-8
lines changed

flang/lib/Lower/ConvertCall.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,8 +1232,25 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
12321232

12331233
if (!fir::getBase(result))
12341234
return std::nullopt; // subroutine call.
1235-
// TODO: "move" non pointer results into hlfir.expr.
1236-
return extendedValueToHlfirEntity(loc, builder, result, ".tmp.func_result");
1235+
1236+
hlfir::Entity resultEntity =
1237+
extendedValueToHlfirEntity(loc, builder, result, ".tmp.func_result");
1238+
1239+
if (!fir::isPointerType(fir::getBase(result).getType())) {
1240+
resultEntity = loadTrivialScalar(loc, builder, resultEntity);
1241+
1242+
if (resultEntity.isVariable()) {
1243+
// Function result must not be freed, since it is allocated on the stack.
1244+
// Note that in non-elemental case, genCallOpAndResult()
1245+
// is responsible for establishing the clean-up that destroys
1246+
// the derived type result or deallocates its components
1247+
// without finalization.
1248+
auto asExpr = builder.create<hlfir::AsExprOp>(
1249+
loc, resultEntity, /*mustFree=*/builder.createBool(loc, false));
1250+
resultEntity = hlfir::EntityWithAttributes{asExpr.getResult()};
1251+
}
1252+
}
1253+
return hlfir::EntityWithAttributes{resultEntity};
12371254
}
12381255

12391256
/// Create an optional dummy argument value from an entity that may be

flang/test/Lower/HLFIR/elemental-array-ops.f90

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,10 @@ end subroutine char_return
185185
! CHECK: %[[VAL_26:.*]] = fir.call @llvm.stacksave.p0() fastmath<contract> : () -> !fir.ref<i8>
186186
! CHECK: %[[VAL_27:.*]] = fir.call @_QPcallee(%[[VAL_2]], %[[VAL_25]], %[[VAL_20]]) fastmath<contract> : (!fir.ref<!fir.char<1,3>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
187187
! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_2]] typeparams %[[VAL_25]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,3>>, index) -> (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>)
188+
! CHECK: %[[MustFree:.*]] = arith.constant false
189+
! CHECK: %[[ResultTemp:.*]] = hlfir.as_expr %[[VAL_28]]#0 move %[[MustFree]] : (!fir.ref<!fir.char<1,3>>, i1) -> !hlfir.expr<!fir.char<1,3>>
188190
! CHECK: fir.call @llvm.stackrestore.p0(%[[VAL_26]]) fastmath<contract> : (!fir.ref<i8>) -> ()
189-
! CHECK: hlfir.yield_element %[[VAL_28]]#0 : !fir.ref<!fir.char<1,3>>
191+
! CHECK: hlfir.yield_element %[[ResultTemp]] : !hlfir.expr<!fir.char<1,3>>
190192
! CHECK: }
191193
! CHECK: %[[VAL_29:.*]] = arith.constant 0 : index
192194
! CHECK: %[[VAL_30:.*]]:3 = fir.box_dims %[[VAL_10]]#0, %[[VAL_29]] : (!fir.box<!fir.array<?x!fir.char<1,3>>>, index) -> (index, index, index)
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
! RUN: bbc -emit-hlfir --polymorphic-type -o - %s -I nowhere 2>&1 | FileCheck %s
2+
3+
module types
4+
type t1
5+
end type t1
6+
end module types
7+
8+
subroutine test1
9+
integer :: i
10+
i = inner() + 1
11+
contains
12+
function inner()
13+
integer, allocatable :: inner
14+
end function inner
15+
end subroutine test1
16+
! CHECK-LABEL: func.func @_QPtest1() {
17+
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.heap<i32>> {bindc_name = ".result"}
18+
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>)
19+
! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>
20+
! CHECK: %[[VAL_6:.*]] = fir.box_addr %[[VAL_5]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32>
21+
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_6]] : !fir.heap<i32>
22+
! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32
23+
! CHECK: %[[VAL_9:.*]] = arith.addi %[[VAL_7]], %[[VAL_8]] : i32
24+
25+
subroutine test2
26+
character(len=:), allocatable :: c
27+
c = inner()
28+
contains
29+
function inner()
30+
character(len=:), allocatable :: inner
31+
end function inner
32+
end subroutine test2
33+
! CHECK-LABEL: func.func @_QPtest2() {
34+
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>)
35+
! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
36+
! CHECK: %[[VAL_9:.*]] = fir.box_addr %[[VAL_8]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>>
37+
! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
38+
! CHECK: %[[VAL_11:.*]] = fir.box_elesize %[[VAL_10]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> index
39+
! CHECK: %[[VAL_12:.*]] = fir.emboxchar %[[VAL_9]], %[[VAL_11]] : (!fir.heap<!fir.char<1,?>>, index) -> !fir.boxchar<1>
40+
! CHECK: %[[VAL_13:.*]] = arith.constant false
41+
! CHECK: %[[VAL_14:.*]] = hlfir.as_expr %[[VAL_12]] move %[[VAL_13]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
42+
! CHECK: hlfir.assign %[[VAL_14]] to %{{.*}}#0 realloc : !hlfir.expr<!fir.char<1,?>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
43+
44+
subroutine test3
45+
character(len=:), allocatable :: c
46+
c = inner()
47+
contains
48+
function inner()
49+
character(len=3), allocatable :: inner
50+
end function inner
51+
end subroutine test3
52+
! CHECK-LABEL: func.func @_QPtest3() {
53+
! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %{{.*}} typeparams %{{.*}} {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>>, index) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>>)
54+
! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_13]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>>
55+
! CHECK: %[[VAL_15:.*]] = fir.box_addr %[[VAL_14]] : (!fir.box<!fir.heap<!fir.char<1,3>>>) -> !fir.heap<!fir.char<1,3>>
56+
! CHECK: %[[VAL_16:.*]] = arith.constant false
57+
! CHECK: %[[VAL_17:.*]] = hlfir.as_expr %[[VAL_15]] move %[[VAL_16]] : (!fir.heap<!fir.char<1,3>>, i1) -> !hlfir.expr<!fir.char<1,3>>
58+
! CHECK: hlfir.assign %[[VAL_17]] to %{{.*}}#0 realloc : !hlfir.expr<!fir.char<1,3>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
59+
60+
subroutine test4
61+
class(*), allocatable :: p
62+
p = inner()
63+
contains
64+
function inner()
65+
class(*), allocatable :: inner
66+
end function inner
67+
end subroutine test4
68+
! CHECK-LABEL: func.func @_QPtest4() {
69+
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.class<!fir.heap<none>>>) -> (!fir.ref<!fir.class<!fir.heap<none>>>, !fir.ref<!fir.class<!fir.heap<none>>>)
70+
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<!fir.class<!fir.heap<none>>>
71+
! CHECK: %[[VAL_8:.*]] = arith.constant false
72+
! CHECK: %[[VAL_9:.*]] = hlfir.as_expr %[[VAL_7]] move %[[VAL_8]] : (!fir.class<!fir.heap<none>>, i1) -> !hlfir.expr<none?>
73+
! CHECK: hlfir.assign %[[VAL_9]] to %{{.*}}#0 realloc : !hlfir.expr<none?>, !fir.ref<!fir.class<!fir.heap<none>>>
74+
75+
subroutine test5
76+
use types
77+
type(t1) :: r
78+
r = inner()
79+
contains
80+
function inner()
81+
type(t1) :: inner
82+
end function inner
83+
end subroutine test5
84+
! CHECK-LABEL: func.func @_QPtest5() {
85+
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.type<_QMtypesTt1>>) -> (!fir.ref<!fir.type<_QMtypesTt1>>, !fir.ref<!fir.type<_QMtypesTt1>>)
86+
! CHECK: %[[VAL_5:.*]] = arith.constant false
87+
! CHECK: %[[VAL_6:.*]] = hlfir.as_expr %[[VAL_4]]#0 move %[[VAL_5]] : (!fir.ref<!fir.type<_QMtypesTt1>>, i1) -> !hlfir.expr<!fir.type<_QMtypesTt1>>
88+
! CHECK: hlfir.assign %[[VAL_6]] to %{{.*}}#0 : !hlfir.expr<!fir.type<_QMtypesTt1>>, !fir.ref<!fir.type<_QMtypesTt1>>
89+
90+
subroutine test6(x)
91+
character(len=:), allocatable :: c(:)
92+
integer :: x(:)
93+
c = inner(x)
94+
contains
95+
elemental function inner(x)
96+
integer, intent(in) :: x
97+
character(len=3) :: inner
98+
end function inner
99+
end subroutine test6
100+
! CHECK-LABEL: func.func @_QPtest6(
101+
! CHECK: %[[VAL_14:.*]] = hlfir.elemental
102+
! CHECK: %[[VAL_24:.*]]:2 = hlfir.declare %{{.*}} typeparams %{{.*}} {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,3>>, index) -> (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>)
103+
! CHECK: %[[VAL_25:.*]] = arith.constant false
104+
! CHECK: %[[VAL_26:.*]] = hlfir.as_expr %[[VAL_24]]#0 move %[[VAL_25]] : (!fir.ref<!fir.char<1,3>>, i1) -> !hlfir.expr<!fir.char<1,3>>
105+
! CHECK: hlfir.yield_element %[[VAL_26]] : !hlfir.expr<!fir.char<1,3>>
106+
107+
subroutine test7(x)
108+
use types
109+
integer :: x(:)
110+
class(*), allocatable :: p(:)
111+
p = inner(x)
112+
contains
113+
elemental function inner(x)
114+
integer, intent(in) :: x
115+
type(t1) :: inner
116+
end function inner
117+
end subroutine test7
118+
! CHECK-LABEL: func.func @_QPtest7(
119+
! CHECK: %[[VAL_12:.*]] = hlfir.elemental
120+
! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.type<_QMtypesTt1>>) -> (!fir.ref<!fir.type<_QMtypesTt1>>, !fir.ref<!fir.type<_QMtypesTt1>>)
121+
! CHECK: %[[VAL_17:.*]] = arith.constant false
122+
! CHECK: %[[VAL_18:.*]] = hlfir.as_expr %[[VAL_16]]#0 move %[[VAL_17]] : (!fir.ref<!fir.type<_QMtypesTt1>>, i1) -> !hlfir.expr<!fir.type<_QMtypesTt1>>
123+
! CHECK: hlfir.yield_element %[[VAL_18]] : !hlfir.expr<!fir.type<_QMtypesTt1>>
124+
125+
subroutine test8
126+
if (associated(inner())) STOP 1
127+
contains
128+
function inner()
129+
real, pointer :: inner
130+
end function inner
131+
end subroutine test8
132+
! CHECK-LABEL: func.func @_QPtest8() {
133+
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>)
134+
! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#1 : !fir.ref<!fir.box<!fir.ptr<f32>>>
135+
! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32>

flang/test/Lower/HLFIR/where.f90

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,21 @@ subroutine where_cleanup()
7979
! CHECK: %[[VAL_6:.*]] = fir.call @_QPreturn_temporary_mask() fastmath<contract> : () -> !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>
8080
! CHECK: fir.save_result %[[VAL_6]] to %[[VAL_1]] : !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
8181
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>)
82-
! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
83-
! CHECK: hlfir.yield %[[VAL_8]] : !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>> cleanup {
82+
! CHECK: %[[deref:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
83+
! CHECK: %[[MustFree:.*]] = arith.constant false
84+
! CHECK: %[[ResTemp:.*]] = hlfir.as_expr %[[deref]] move %[[MustFree]] : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, i1) -> !hlfir.expr<?x!fir.logical<4>>
85+
! CHECK: hlfir.yield %[[ResTemp]] : !hlfir.expr<?x!fir.logical<4>> cleanup {
8486
! CHECK: fir.freemem
8587
! CHECK: }
8688
! CHECK: } do {
8789
! CHECK: hlfir.region_assign {
8890
! CHECK: %[[VAL_14:.*]] = fir.call @_QPreturn_temporary_array() fastmath<contract> : () -> !fir.box<!fir.heap<!fir.array<?xf32>>>
8991
! CHECK: fir.save_result %[[VAL_14]] to %[[VAL_0]] : !fir.box<!fir.heap<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
9092
! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
91-
! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
92-
! CHECK: hlfir.yield %[[VAL_16]] : !fir.box<!fir.heap<!fir.array<?xf32>>> cleanup {
93+
! CHECK: %[[deref:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
94+
! CHECK: %[[MustFree:.*]] = arith.constant false
95+
! CHECK: %[[ResTemp:.*]] = hlfir.as_expr %[[deref]] move %[[MustFree]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, i1) -> !hlfir.expr<?xf32>
96+
! CHECK: hlfir.yield %[[ResTemp]] : !hlfir.expr<?xf32> cleanup {
9397
! CHECK: fir.freemem
9498
! CHECK: }
9599
! CHECK: } to {

flang/test/Lower/Intrinsics/storage_size-2.f90

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ function return_char(l)
1313
print*, storage_size(return_char(n))
1414
! CHECK: %[[val_16:.*]] = fir.call @_QPreturn_char(%[[res_addr:[^,]*]], %[[res_len:[^,]*]], {{.*}})
1515
! CHECK: %[[res:.*]]:2 = hlfir.declare %[[res_addr]] typeparams %[[res_len]]
16-
! CHECK: %[[val_18:.*]] = fir.embox %[[res]]#1 typeparams %[[res_len]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
16+
! CHECK: %[[false:.*]] = arith.constant false
17+
! CHECK: %[[expr:.*]] = hlfir.as_expr %[[res]]#0 move %[[false]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
18+
! CHECK: %[[assoc:.*]]:3 = hlfir.associate %[[expr]] typeparams %[[res_len]] {uniq_name = "adapt.valuebyref"} : (!hlfir.expr<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>, i1)
19+
! CHECK: %[[val_18:.*]] = fir.embox %[[assoc]]#1 typeparams %[[res_len]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
1720
! CHECK: %[[val_19:.*]] = fir.box_elesize %[[val_18]] : (!fir.box<!fir.char<1,?>>) -> i32
1821
! CHECK: %[[val_20:.*]] = arith.constant 8 : i32
1922
! CHECK: %[[val_21:.*]] = arith.muli %[[val_19]], %[[val_20]] : i32

0 commit comments

Comments
 (0)