Skip to content

Commit ed8e858

Browse files
committed
[flang][hlfir] deref pointers before lowering assignment to hlfir.assign
There is little point not to dereference pointers LHS and RHS before before emitting an hlfir.assign when lowering an assignment. This pushes complexity and descriptor read side effects that are better expressed in a load before the assignment. Differential Revision: https://reviews.llvm.org/D143372
1 parent d041833 commit ed8e858

File tree

4 files changed

+28
-10
lines changed

4 files changed

+28
-10
lines changed

flang/lib/Lower/Bridge.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2731,12 +2731,15 @@ class FirConverter : public Fortran::lower::AbstractConverter {
27312731
Fortran::lower::StatementContext stmtCtx;
27322732
if (Fortran::lower::isWholeAllocatable(assign.lhs))
27332733
TODO(loc, "HLFIR assignment to whole allocatable");
2734-
hlfir::EntityWithAttributes rhs =
2735-
Fortran::lower::convertExprToHLFIR(loc, *this, assign.rhs,
2736-
localSymbols, stmtCtx);
2737-
hlfir::EntityWithAttributes lhs =
2738-
Fortran::lower::convertExprToHLFIR(loc, *this, assign.lhs,
2739-
localSymbols, stmtCtx);
2734+
hlfir::Entity rhs = Fortran::lower::convertExprToHLFIR(
2735+
loc, *this, assign.rhs, localSymbols, stmtCtx);
2736+
// Dereference pointers and allocatables RHS: the target is
2737+
// being assigned from.
2738+
rhs = hlfir::derefPointersAndAllocatables(loc, builder, rhs);
2739+
hlfir::Entity lhs = Fortran::lower::convertExprToHLFIR(
2740+
loc, *this, assign.lhs, localSymbols, stmtCtx);
2741+
// Dereference pointers LHS: the target is being assigned to.
2742+
lhs = hlfir::derefPointersAndAllocatables(loc, builder, lhs);
27402743
builder.create<hlfir::AssignOp>(loc, rhs, lhs);
27412744
},
27422745
// [2] User defined assignment. If the context is a scalar

flang/lib/Optimizer/Builder/HLFIRTools.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -570,9 +570,9 @@ hlfir::Entity hlfir::derefPointersAndAllocatables(mlir::Location loc,
570570
if (entity.isMutableBox()) {
571571
hlfir::Entity boxLoad{builder.create<fir::LoadOp>(loc, entity)};
572572
if (entity.isScalar()) {
573-
mlir::Type elementType = boxLoad.getFortranElementType();
574-
if (fir::isa_trivial(elementType))
573+
if (!entity.isPolymorphic() && !entity.hasLengthParameters())
575574
return hlfir::Entity{builder.create<fir::BoxAddrOp>(loc, boxLoad)};
575+
mlir::Type elementType = boxLoad.getFortranElementType();
576576
if (auto charType = elementType.dyn_cast<fir::CharacterType>()) {
577577
mlir::Value base = builder.create<fir::BoxAddrOp>(loc, boxLoad);
578578
if (charType.hasConstantLen())
@@ -585,7 +585,10 @@ hlfir::Entity hlfir::derefPointersAndAllocatables(mlir::Location loc,
585585
.getResult()};
586586
}
587587
}
588-
// Keep the entity boxed for now.
588+
// Otherwise, the entity is either an array, a polymorphic entity, or a
589+
// derived type with length parameters. All these entities require a fir.box
590+
// or fir.class to hold bounds, dynamic type or length parameter
591+
// information. Keep them boxed.
589592
return boxLoad;
590593
}
591594
return entity;

flang/test/Lower/HLFIR/allocatable-and-pointer-subparts.f90

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ subroutine test_pointer_component_followed_by_component_ref(x)
2626
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %{{.*}} {{.*}}Ex
2727
! CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTt2{p:!fir.box<!fir.ptr<!fir.type<_QMmTt1{x:f32}>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMmTt1{x:f32}>>>>
2828
! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]] : !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMmTt1{x:f32}>>>>
29-
! CHECK: %[[VAL_4:.*]] = hlfir.designate %[[VAL_3]]{"x"} : (!fir.box<!fir.ptr<!fir.type<_QMmTt1{x:f32}>>>) -> !fir.ref<f32>
29+
! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3:.*]] : (!fir.box<!fir.ptr<!fir.type<_QMmTt1{x:f32}>>>) -> !fir.ptr<!fir.type<_QMmTt1{x:f32}>>
30+
! CHECK: hlfir.designate %[[VAL_4]]{"x"} : (!fir.ptr<!fir.type<_QMmTt1{x:f32}>>) -> !fir.ref<f32>
3031

3132
subroutine test_symbol_followed_by_ref(x)
3233
character(:), allocatable :: x(:)

flang/test/Lower/HLFIR/assignment-intrinsics.f90

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,17 @@ subroutine array_character(x, y)
135135
! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFarray_characterEy"} : (!fir.ref<!fir.array<10x!fir.char<1,?>>>, !fir.shape<1>, index) -> (!fir.box<!fir.array<10x!fir.char<1,?>>>, !fir.ref<!fir.array<10x!fir.char<1,?>>>)
136136
! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_6]]#0 : !fir.box<!fir.array<10x!fir.char<1,?>>>, !fir.box<!fir.array<10x!fir.char<1,?>>>
137137

138+
subroutine array_pointer(x, y)
139+
real, pointer :: x(:), y(:)
140+
x = y
141+
end subroutine
142+
! CHECK-LABEL: func.func @_QParray_pointer(
143+
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %{{.*}}Ex
144+
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}}Ey
145+
! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
146+
! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
147+
! CHECK: hlfir.assign %[[VAL_3]] to %[[VAL_4]] : !fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.box<!fir.ptr<!fir.array<?xf32>>>
148+
138149
! -----------------------------------------------------------------------------
139150
! Test assignments with array LHS and scalar RHS
140151
! -----------------------------------------------------------------------------

0 commit comments

Comments
 (0)