Skip to content

Commit 09b772e

Browse files
authored
[flang] Postpone hlfir.end_associate generation for calls. (#138786)
If we generate hlfir.end_associate at the end of the statement, we get easier optimizable HLFIR, because there are no compiler generated operations with side-effects in between the call and the consumers. This allows more hlfir.eval_in_mem to reuse the LHS instead of allocating temporary buffer. I do not think the same can be done for hlfir.copy_out always, e.g.: ``` subroutine test2(x) interface function array_func2(x,y) real:: x(*), array_func2(10), y end function array_func2 end interface real :: x(:) x = array_func2(x, 1.0) end subroutine test2 ``` If we postpone the copy-out until after the assignment, then the result may be wrong.
1 parent ab60910 commit 09b772e

10 files changed

+313
-24
lines changed

flang/lib/Lower/ConvertCall.cpp

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -960,9 +960,26 @@ struct CallCleanUp {
960960
mlir::Value tempVar;
961961
mlir::Value mustFree;
962962
};
963-
void genCleanUp(mlir::Location loc, fir::FirOpBuilder &builder) {
964-
Fortran::common::visit([&](auto &c) { c.genCleanUp(loc, builder); },
963+
964+
/// Generate clean-up code.
965+
/// If \p postponeAssociates is true, the ExprAssociate clean-up
966+
/// is not generated, and instead the corresponding CallCleanUp
967+
/// object is returned as the result.
968+
std::optional<CallCleanUp> genCleanUp(mlir::Location loc,
969+
fir::FirOpBuilder &builder,
970+
bool postponeAssociates) {
971+
std::optional<CallCleanUp> postponed;
972+
Fortran::common::visit(Fortran::common::visitors{
973+
[&](CopyIn &c) { c.genCleanUp(loc, builder); },
974+
[&](ExprAssociate &c) {
975+
if (postponeAssociates)
976+
postponed = CallCleanUp{c};
977+
else
978+
c.genCleanUp(loc, builder);
979+
},
980+
},
965981
cleanUp);
982+
return postponed;
966983
}
967984
std::variant<CopyIn, ExprAssociate> cleanUp;
968985
};
@@ -1729,10 +1746,23 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
17291746
caller, callSiteType, callContext.resultType,
17301747
callContext.isElementalProcWithArrayArgs());
17311748

1732-
/// Clean-up associations and copy-in.
1733-
for (auto cleanUp : callCleanUps)
1734-
cleanUp.genCleanUp(loc, builder);
1735-
1749+
// Clean-up associations and copy-in.
1750+
// The association clean-ups are postponed to the end of the statement
1751+
// lowering. The copy-in clean-ups may be delayed as well,
1752+
// but they are done immediately after the call currently.
1753+
llvm::SmallVector<CallCleanUp> associateCleanups;
1754+
for (auto cleanUp : callCleanUps) {
1755+
auto postponed =
1756+
cleanUp.genCleanUp(loc, builder, /*postponeAssociates=*/true);
1757+
if (postponed)
1758+
associateCleanups.push_back(*postponed);
1759+
}
1760+
1761+
fir::FirOpBuilder *bldr = &builder;
1762+
callContext.stmtCtx.attachCleanup([=]() {
1763+
for (auto cleanUp : associateCleanups)
1764+
(void)cleanUp.genCleanUp(loc, *bldr, /*postponeAssociates=*/false);
1765+
});
17361766
if (auto *entity = std::get_if<hlfir::EntityWithAttributes>(&loweredResult))
17371767
return *entity;
17381768

flang/lib/Lower/OpenACC.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,8 @@ static inline void genAtomicUpdateStatement(
416416
Fortran::lower::AbstractConverter &converter, mlir::Value lhsAddr,
417417
mlir::Type varType, const Fortran::parser::Variable &assignmentStmtVariable,
418418
const Fortran::parser::Expr &assignmentStmtExpr, mlir::Location loc,
419-
mlir::Operation *atomicCaptureOp = nullptr) {
419+
mlir::Operation *atomicCaptureOp = nullptr,
420+
Fortran::lower::StatementContext *atomicCaptureStmtCtx = nullptr) {
420421
// Generate `atomic.update` operation for atomic assignment statements
421422
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
422423
mlir::Location currentLocation = converter.getCurrentLocation();
@@ -496,15 +497,24 @@ static inline void genAtomicUpdateStatement(
496497
},
497498
assignmentStmtExpr.u);
498499
Fortran::lower::StatementContext nonAtomicStmtCtx;
500+
Fortran::lower::StatementContext *stmtCtxPtr = &nonAtomicStmtCtx;
499501
if (!nonAtomicSubExprs.empty()) {
500502
// Generate non atomic part before all the atomic operations.
501503
auto insertionPoint = firOpBuilder.saveInsertionPoint();
502-
if (atomicCaptureOp)
504+
if (atomicCaptureOp) {
505+
assert(atomicCaptureStmtCtx && "must specify statement context");
503506
firOpBuilder.setInsertionPoint(atomicCaptureOp);
507+
// Any clean-ups associated with the expression lowering
508+
// must also be generated outside of the atomic update operation
509+
// and after the atomic capture operation.
510+
// The atomicCaptureStmtCtx will be finalized at the end
511+
// of the atomic capture operation generation.
512+
stmtCtxPtr = atomicCaptureStmtCtx;
513+
}
504514
mlir::Value nonAtomicVal;
505515
for (auto *nonAtomicSubExpr : nonAtomicSubExprs) {
506516
nonAtomicVal = fir::getBase(converter.genExprValue(
507-
currentLocation, *nonAtomicSubExpr, nonAtomicStmtCtx));
517+
currentLocation, *nonAtomicSubExpr, *stmtCtxPtr));
508518
exprValueOverrides.try_emplace(nonAtomicSubExpr, nonAtomicVal);
509519
}
510520
if (atomicCaptureOp)
@@ -652,7 +662,7 @@ void genAtomicCapture(Fortran::lower::AbstractConverter &converter,
652662
genAtomicCaptureStatement(converter, stmt2LHSArg, stmt1LHSArg,
653663
elementType, loc);
654664
genAtomicUpdateStatement(converter, stmt2LHSArg, stmt2VarType, stmt2Var,
655-
stmt2Expr, loc, atomicCaptureOp);
665+
stmt2Expr, loc, atomicCaptureOp, &stmtCtx);
656666
} else {
657667
// Atomic capture construct is of the form [capture-stmt, write-stmt]
658668
firOpBuilder.setInsertionPoint(atomicCaptureOp);
@@ -672,13 +682,15 @@ void genAtomicCapture(Fortran::lower::AbstractConverter &converter,
672682
*Fortran::semantics::GetExpr(stmt2Expr);
673683
mlir::Type elementType = converter.genType(fromExpr);
674684
genAtomicUpdateStatement(converter, stmt1LHSArg, stmt1VarType, stmt1Var,
675-
stmt1Expr, loc, atomicCaptureOp);
685+
stmt1Expr, loc, atomicCaptureOp, &stmtCtx);
676686
genAtomicCaptureStatement(converter, stmt1LHSArg, stmt2LHSArg, elementType,
677687
loc);
678688
}
679689
firOpBuilder.setInsertionPointToEnd(&block);
680690
firOpBuilder.create<mlir::acc::TerminatorOp>(loc);
681-
firOpBuilder.setInsertionPointToStart(&block);
691+
// The clean-ups associated with the statements inside the capture
692+
// construct must be generated after the AtomicCaptureOp.
693+
firOpBuilder.setInsertionPointAfter(atomicCaptureOp);
682694
}
683695

684696
template <typename Op>

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2816,7 +2816,8 @@ static void genAtomicUpdateStatement(
28162816
const parser::Expr &assignmentStmtExpr,
28172817
const parser::OmpAtomicClauseList *leftHandClauseList,
28182818
const parser::OmpAtomicClauseList *rightHandClauseList, mlir::Location loc,
2819-
mlir::Operation *atomicCaptureOp = nullptr) {
2819+
mlir::Operation *atomicCaptureOp = nullptr,
2820+
lower::StatementContext *atomicCaptureStmtCtx = nullptr) {
28202821
// Generate `atomic.update` operation for atomic assignment statements
28212822
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
28222823
mlir::Location currentLocation = converter.getCurrentLocation();
@@ -2890,15 +2891,24 @@ static void genAtomicUpdateStatement(
28902891
},
28912892
assignmentStmtExpr.u);
28922893
lower::StatementContext nonAtomicStmtCtx;
2894+
lower::StatementContext *stmtCtxPtr = &nonAtomicStmtCtx;
28932895
if (!nonAtomicSubExprs.empty()) {
28942896
// Generate non atomic part before all the atomic operations.
28952897
auto insertionPoint = firOpBuilder.saveInsertionPoint();
2896-
if (atomicCaptureOp)
2898+
if (atomicCaptureOp) {
2899+
assert(atomicCaptureStmtCtx && "must specify statement context");
28972900
firOpBuilder.setInsertionPoint(atomicCaptureOp);
2901+
// Any clean-ups associated with the expression lowering
2902+
// must also be generated outside of the atomic update operation
2903+
// and after the atomic capture operation.
2904+
// The atomicCaptureStmtCtx will be finalized at the end
2905+
// of the atomic capture operation generation.
2906+
stmtCtxPtr = atomicCaptureStmtCtx;
2907+
}
28982908
mlir::Value nonAtomicVal;
28992909
for (auto *nonAtomicSubExpr : nonAtomicSubExprs) {
29002910
nonAtomicVal = fir::getBase(converter.genExprValue(
2901-
currentLocation, *nonAtomicSubExpr, nonAtomicStmtCtx));
2911+
currentLocation, *nonAtomicSubExpr, *stmtCtxPtr));
29022912
exprValueOverrides.try_emplace(nonAtomicSubExpr, nonAtomicVal);
29032913
}
29042914
if (atomicCaptureOp)
@@ -3238,7 +3248,7 @@ static void genAtomicCapture(lower::AbstractConverter &converter,
32383248
genAtomicUpdateStatement(
32393249
converter, stmt2LHSArg, stmt2VarType, stmt2Var, stmt2Expr,
32403250
/*leftHandClauseList=*/nullptr,
3241-
/*rightHandClauseList=*/nullptr, loc, atomicCaptureOp);
3251+
/*rightHandClauseList=*/nullptr, loc, atomicCaptureOp, &stmtCtx);
32423252
} else {
32433253
// Atomic capture construct is of the form [capture-stmt, write-stmt]
32443254
firOpBuilder.setInsertionPoint(atomicCaptureOp);
@@ -3284,7 +3294,7 @@ static void genAtomicCapture(lower::AbstractConverter &converter,
32843294
genAtomicUpdateStatement(
32853295
converter, stmt1LHSArg, stmt1VarType, stmt1Var, stmt1Expr,
32863296
/*leftHandClauseList=*/nullptr,
3287-
/*rightHandClauseList=*/nullptr, loc, atomicCaptureOp);
3297+
/*rightHandClauseList=*/nullptr, loc, atomicCaptureOp, &stmtCtx);
32883298

32893299
if (stmt1VarType != stmt2VarType) {
32903300
mlir::Value alloca;
@@ -3316,7 +3326,9 @@ static void genAtomicCapture(lower::AbstractConverter &converter,
33163326
}
33173327
firOpBuilder.setInsertionPointToEnd(&block);
33183328
firOpBuilder.create<mlir::omp::TerminatorOp>(loc);
3319-
firOpBuilder.setInsertionPointToStart(&block);
3329+
// The clean-ups associated with the statements inside the capture
3330+
// construct must be generated after the AtomicCaptureOp.
3331+
firOpBuilder.setInsertionPointAfter(atomicCaptureOp);
33203332
}
33213333

33223334
//===----------------------------------------------------------------------===//
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
! RUN: bbc -emit-hlfir -o - %s -I nowhere | FileCheck %s
2+
3+
subroutine test1
4+
interface
5+
function array_func1(x)
6+
real:: x, array_func1(10)
7+
end function array_func1
8+
end interface
9+
real :: x(10)
10+
x = array_func1(1.0)
11+
end subroutine test1
12+
! CHECK-LABEL: func.func @_QPtest1() {
13+
! CHECK: %[[VAL_5:.*]] = arith.constant 1.000000e+00 : f32
14+
! CHECK: %[[VAL_6:.*]]:3 = hlfir.associate %[[VAL_5]] {adapt.valuebyref} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
15+
! CHECK: %[[VAL_17:.*]] = hlfir.eval_in_mem shape %{{.*}} : (!fir.shape<1>) -> !hlfir.expr<10xf32> {
16+
! CHECK: fir.call @_QParray_func1
17+
! CHECK: fir.save_result
18+
! CHECK: }
19+
! CHECK: hlfir.assign %[[VAL_17]] to %{{.*}} : !hlfir.expr<10xf32>, !fir.ref<!fir.array<10xf32>>
20+
! CHECK: hlfir.end_associate %[[VAL_6]]#1, %[[VAL_6]]#2 : !fir.ref<f32>, i1
21+
22+
subroutine test2(x)
23+
interface
24+
function array_func2(x,y)
25+
real:: x(*), array_func2(10), y
26+
end function array_func2
27+
end interface
28+
real :: x(:)
29+
x = array_func2(x, 1.0)
30+
end subroutine test2
31+
! CHECK-LABEL: func.func @_QPtest2(
32+
! CHECK: %[[VAL_3:.*]] = arith.constant 1.000000e+00 : f32
33+
! CHECK: %[[VAL_4:.*]]:2 = hlfir.copy_in %{{.*}} to %{{.*}} : (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.box<!fir.array<?xf32>>, i1)
34+
! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]]#0 : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
35+
! CHECK: %[[VAL_6:.*]]:3 = hlfir.associate %[[VAL_3]] {adapt.valuebyref} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
36+
! CHECK: %[[VAL_17:.*]] = hlfir.eval_in_mem shape %{{.*}} : (!fir.shape<1>) -> !hlfir.expr<10xf32> {
37+
! CHECK: ^bb0(%[[VAL_18:.*]]: !fir.ref<!fir.array<10xf32>>):
38+
! CHECK: %[[VAL_19:.*]] = fir.call @_QParray_func2(%[[VAL_5]], %[[VAL_6]]#0) fastmath<contract> : (!fir.ref<!fir.array<?xf32>>, !fir.ref<f32>) -> !fir.array<10xf32>
39+
! CHECK: fir.save_result %[[VAL_19]] to %[[VAL_18]](%{{.*}}) : !fir.array<10xf32>, !fir.ref<!fir.array<10xf32>>, !fir.shape<1>
40+
! CHECK: }
41+
! CHECK: hlfir.copy_out %{{.*}}, %[[VAL_4]]#1 to %{{.*}} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, i1, !fir.box<!fir.array<?xf32>>) -> ()
42+
! CHECK: hlfir.assign %[[VAL_17]] to %{{.*}} : !hlfir.expr<10xf32>, !fir.box<!fir.array<?xf32>>
43+
! CHECK: hlfir.end_associate %[[VAL_6]]#1, %[[VAL_6]]#2 : !fir.ref<f32>, i1
44+
! CHECK: hlfir.destroy %[[VAL_17]] : !hlfir.expr<10xf32>
45+
46+
subroutine test3(x)
47+
interface
48+
function array_func3(x)
49+
real :: x, array_func3(10)
50+
end function array_func3
51+
end interface
52+
logical :: x
53+
if (any(array_func3(1.0).le.array_func3(2.0))) x = .true.
54+
end subroutine test3
55+
! CHECK-LABEL: func.func @_QPtest3(
56+
! CHECK: %[[VAL_2:.*]] = arith.constant 1.000000e+00 : f32
57+
! CHECK: %[[VAL_3:.*]]:3 = hlfir.associate %[[VAL_2]] {adapt.valuebyref} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
58+
! CHECK: %[[VAL_14:.*]] = hlfir.eval_in_mem shape %{{.*}} : (!fir.shape<1>) -> !hlfir.expr<10xf32> {
59+
! CHECK: ^bb0(%[[VAL_15:.*]]: !fir.ref<!fir.array<10xf32>>):
60+
! CHECK: %[[VAL_16:.*]] = fir.call @_QParray_func3(%[[VAL_3]]#0) fastmath<contract> : (!fir.ref<f32>) -> !fir.array<10xf32>
61+
! CHECK: fir.save_result %[[VAL_16]] to %[[VAL_15]](%{{.*}}) : !fir.array<10xf32>, !fir.ref<!fir.array<10xf32>>, !fir.shape<1>
62+
! CHECK: }
63+
! CHECK: %[[VAL_17:.*]] = arith.constant 2.000000e+00 : f32
64+
! CHECK: %[[VAL_18:.*]]:3 = hlfir.associate %[[VAL_17]] {adapt.valuebyref} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
65+
! CHECK: %[[VAL_29:.*]] = hlfir.eval_in_mem shape %{{.*}} : (!fir.shape<1>) -> !hlfir.expr<10xf32> {
66+
! CHECK: ^bb0(%[[VAL_30:.*]]: !fir.ref<!fir.array<10xf32>>):
67+
! CHECK: %[[VAL_31:.*]] = fir.call @_QParray_func3(%[[VAL_18]]#0) fastmath<contract> : (!fir.ref<f32>) -> !fir.array<10xf32>
68+
! CHECK: fir.save_result %[[VAL_31]] to %[[VAL_30]](%{{.*}}) : !fir.array<10xf32>, !fir.ref<!fir.array<10xf32>>, !fir.shape<1>
69+
! CHECK: }
70+
! CHECK: %[[VAL_32:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?x!fir.logical<4>> {
71+
! CHECK: ^bb0(%[[VAL_33:.*]]: index):
72+
! CHECK: %[[VAL_34:.*]] = hlfir.apply %[[VAL_14]], %[[VAL_33]] : (!hlfir.expr<10xf32>, index) -> f32
73+
! CHECK: %[[VAL_35:.*]] = hlfir.apply %[[VAL_29]], %[[VAL_33]] : (!hlfir.expr<10xf32>, index) -> f32
74+
! CHECK: %[[VAL_36:.*]] = arith.cmpf ole, %[[VAL_34]], %[[VAL_35]] fastmath<contract> : f32
75+
! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_36]] : (i1) -> !fir.logical<4>
76+
! CHECK: hlfir.yield_element %[[VAL_37]] : !fir.logical<4>
77+
! CHECK: }
78+
! CHECK: %[[VAL_38:.*]] = hlfir.any %[[VAL_32]] : (!hlfir.expr<?x!fir.logical<4>>) -> !fir.logical<4>
79+
! CHECK: hlfir.destroy %[[VAL_32]] : !hlfir.expr<?x!fir.logical<4>>
80+
! CHECK: hlfir.end_associate %[[VAL_18]]#1, %[[VAL_18]]#2 : !fir.ref<f32>, i1
81+
! CHECK: hlfir.destroy %[[VAL_29]] : !hlfir.expr<10xf32>
82+
! CHECK: hlfir.end_associate %[[VAL_3]]#1, %[[VAL_3]]#2 : !fir.ref<f32>, i1
83+
! CHECK: hlfir.destroy %[[VAL_14]] : !hlfir.expr<10xf32>
84+
! CHECK: %[[VAL_39:.*]] = fir.convert %[[VAL_38]] : (!fir.logical<4>) -> i1
85+
! CHECK: fir.if %[[VAL_39]] {

flang/test/Lower/HLFIR/entry_return.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@ logical function f2()
5151
! CHECK: %[[VAL_6:.*]]:3 = hlfir.associate %[[VAL_4]] {adapt.valuebyref} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
5252
! CHECK: %[[VAL_7:.*]]:3 = hlfir.associate %[[VAL_5]] {adapt.valuebyref} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
5353
! CHECK: %[[VAL_8:.*]] = fir.call @_QPcomplex(%[[VAL_6]]#0, %[[VAL_7]]#0) fastmath<contract> : (!fir.ref<f32>, !fir.ref<f32>) -> f32
54-
! CHECK: hlfir.end_associate %[[VAL_6]]#1, %[[VAL_6]]#2 : !fir.ref<f32>, i1
55-
! CHECK: hlfir.end_associate %[[VAL_7]]#1, %[[VAL_7]]#2 : !fir.ref<f32>, i1
5654
! CHECK: %[[VAL_9:.*]] = arith.constant 0.000000e+00 : f32
5755
! CHECK: %[[VAL_10:.*]] = fir.undefined complex<f32>
5856
! CHECK: %[[VAL_11:.*]] = fir.insert_value %[[VAL_10]], %[[VAL_8]], [0 : index] : (complex<f32>, f32) -> complex<f32>
5957
! CHECK: %[[VAL_12:.*]] = fir.insert_value %[[VAL_11]], %[[VAL_9]], [1 : index] : (complex<f32>, f32) -> complex<f32>
6058
! CHECK: hlfir.assign %[[VAL_12]] to %[[VAL_1]]#0 : complex<f32>, !fir.ref<complex<f32>>
59+
! CHECK: hlfir.end_associate %[[VAL_6]]#1, %[[VAL_6]]#2 : !fir.ref<f32>, i1
60+
! CHECK: hlfir.end_associate %[[VAL_7]]#1, %[[VAL_7]]#2 : !fir.ref<f32>, i1
6161
! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.logical<4>>
6262
! CHECK: return %[[VAL_13]] : !fir.logical<4>
6363
! CHECK: }
@@ -74,13 +74,13 @@ logical function f2()
7474
! CHECK: %[[VAL_6:.*]]:3 = hlfir.associate %[[VAL_4]] {adapt.valuebyref} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
7575
! CHECK: %[[VAL_7:.*]]:3 = hlfir.associate %[[VAL_5]] {adapt.valuebyref} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
7676
! CHECK: %[[VAL_8:.*]] = fir.call @_QPcomplex(%[[VAL_6]]#0, %[[VAL_7]]#0) fastmath<contract> : (!fir.ref<f32>, !fir.ref<f32>) -> f32
77-
! CHECK: hlfir.end_associate %[[VAL_6]]#1, %[[VAL_6]]#2 : !fir.ref<f32>, i1
78-
! CHECK: hlfir.end_associate %[[VAL_7]]#1, %[[VAL_7]]#2 : !fir.ref<f32>, i1
7977
! CHECK: %[[VAL_9:.*]] = arith.constant 0.000000e+00 : f32
8078
! CHECK: %[[VAL_10:.*]] = fir.undefined complex<f32>
8179
! CHECK: %[[VAL_11:.*]] = fir.insert_value %[[VAL_10]], %[[VAL_8]], [0 : index] : (complex<f32>, f32) -> complex<f32>
8280
! CHECK: %[[VAL_12:.*]] = fir.insert_value %[[VAL_11]], %[[VAL_9]], [1 : index] : (complex<f32>, f32) -> complex<f32>
8381
! CHECK: hlfir.assign %[[VAL_12]] to %[[VAL_1]]#0 : complex<f32>, !fir.ref<complex<f32>>
82+
! CHECK: hlfir.end_associate %[[VAL_6]]#1, %[[VAL_6]]#2 : !fir.ref<f32>, i1
83+
! CHECK: hlfir.end_associate %[[VAL_7]]#1, %[[VAL_7]]#2 : !fir.ref<f32>, i1
8484
! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<complex<f32>>
8585
! CHECK: return %[[VAL_13]] : complex<f32>
8686
! CHECK: }

flang/test/Lower/HLFIR/proc-pointer-comp-nopass.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ real function test1(x)
3232
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_6]] : !fir.ref<!fir.boxproc<(!fir.ref<f32>) -> f32>>
3333
! CHECK: %[[VAL_8:.*]] = fir.box_addr %[[VAL_7]] : (!fir.boxproc<(!fir.ref<f32>) -> f32>) -> ((!fir.ref<f32>) -> f32)
3434
! CHECK: %[[VAL_9:.*]] = fir.call %[[VAL_8]](%[[VAL_5]]#0) fastmath<contract> : (!fir.ref<f32>) -> f32
35-
! CHECK: hlfir.end_associate %[[VAL_5]]#1, %[[VAL_5]]#2 : !fir.ref<f32>, i1
3635
! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_2]]#0 : f32, !fir.ref<f32>
36+
! CHECK: hlfir.end_associate %[[VAL_5]]#1, %[[VAL_5]]#2 : !fir.ref<f32>, i1
3737

3838
subroutine test2(x)
3939
use proc_comp_defs, only : t, iface

0 commit comments

Comments
 (0)