[flang-commits] [flang] ed8e858 - [flang][hlfir] deref pointers before lowering assignment to hlfir.assign

Jean Perier via flang-commits flang-commits at lists.llvm.org
Mon Feb 6 06:14:52 PST 2023


Author: Jean Perier
Date: 2023-02-06T15:14:22+01:00
New Revision: ed8e858a1478d18d321f104a86a579e03ba1886e

URL: https://github.com/llvm/llvm-project/commit/ed8e858a1478d18d321f104a86a579e03ba1886e
DIFF: https://github.com/llvm/llvm-project/commit/ed8e858a1478d18d321f104a86a579e03ba1886e.diff

LOG: [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

Added: 
    

Modified: 
    flang/lib/Lower/Bridge.cpp
    flang/lib/Optimizer/Builder/HLFIRTools.cpp
    flang/test/Lower/HLFIR/allocatable-and-pointer-subparts.f90
    flang/test/Lower/HLFIR/assignment-intrinsics.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 578553934ee1..8e509136bb75 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -2731,12 +2731,15 @@ class FirConverter : public Fortran::lower::AbstractConverter {
                 Fortran::lower::StatementContext stmtCtx;
                 if (Fortran::lower::isWholeAllocatable(assign.lhs))
                   TODO(loc, "HLFIR assignment to whole allocatable");
-                hlfir::EntityWithAttributes rhs =
-                    Fortran::lower::convertExprToHLFIR(loc, *this, assign.rhs,
-                                                       localSymbols, stmtCtx);
-                hlfir::EntityWithAttributes lhs =
-                    Fortran::lower::convertExprToHLFIR(loc, *this, assign.lhs,
-                                                       localSymbols, stmtCtx);
+                hlfir::Entity rhs = Fortran::lower::convertExprToHLFIR(
+                    loc, *this, assign.rhs, localSymbols, stmtCtx);
+                // Dereference pointers and allocatables RHS: the target is
+                // being assigned from.
+                rhs = hlfir::derefPointersAndAllocatables(loc, builder, rhs);
+                hlfir::Entity lhs = Fortran::lower::convertExprToHLFIR(
+                    loc, *this, assign.lhs, localSymbols, stmtCtx);
+                // Dereference pointers LHS: the target is being assigned to.
+                lhs = hlfir::derefPointersAndAllocatables(loc, builder, lhs);
                 builder.create<hlfir::AssignOp>(loc, rhs, lhs);
               },
               // [2] User defined assignment. If the context is a scalar

diff  --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index 0e49445eabcd..7272779ac433 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -570,9 +570,9 @@ hlfir::Entity hlfir::derefPointersAndAllocatables(mlir::Location loc,
   if (entity.isMutableBox()) {
     hlfir::Entity boxLoad{builder.create<fir::LoadOp>(loc, entity)};
     if (entity.isScalar()) {
-      mlir::Type elementType = boxLoad.getFortranElementType();
-      if (fir::isa_trivial(elementType))
+      if (!entity.isPolymorphic() && !entity.hasLengthParameters())
         return hlfir::Entity{builder.create<fir::BoxAddrOp>(loc, boxLoad)};
+      mlir::Type elementType = boxLoad.getFortranElementType();
       if (auto charType = elementType.dyn_cast<fir::CharacterType>()) {
         mlir::Value base = builder.create<fir::BoxAddrOp>(loc, boxLoad);
         if (charType.hasConstantLen())
@@ -585,7 +585,10 @@ hlfir::Entity hlfir::derefPointersAndAllocatables(mlir::Location loc,
                 .getResult()};
       }
     }
-    // Keep the entity boxed for now.
+    // Otherwise, the entity is either an array, a polymorphic entity, or a
+    // derived type with length parameters. All these entities require a fir.box
+    // or fir.class to hold bounds, dynamic type or length parameter
+    // information. Keep them boxed.
     return boxLoad;
   }
   return entity;

diff  --git a/flang/test/Lower/HLFIR/allocatable-and-pointer-subparts.f90 b/flang/test/Lower/HLFIR/allocatable-and-pointer-subparts.f90
index 842b79115a4b..fea2a5ef27af 100644
--- a/flang/test/Lower/HLFIR/allocatable-and-pointer-subparts.f90
+++ b/flang/test/Lower/HLFIR/allocatable-and-pointer-subparts.f90
@@ -26,7 +26,8 @@ subroutine test_pointer_component_followed_by_component_ref(x)
 ! CHECK:  %[[VAL_1:.*]]:2 = hlfir.declare %{{.*}} {{.*}}Ex
 ! 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}>>>>
 ! CHECK:  %[[VAL_3:.*]] = fir.load %[[VAL_2]] : !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMmTt1{x:f32}>>>>
-! CHECK:  %[[VAL_4:.*]] = hlfir.designate %[[VAL_3]]{"x"}   : (!fir.box<!fir.ptr<!fir.type<_QMmTt1{x:f32}>>>) -> !fir.ref<f32>
+! CHECK:  %[[VAL_4:.*]] = fir.box_addr %[[VAL_3:.*]] : (!fir.box<!fir.ptr<!fir.type<_QMmTt1{x:f32}>>>) -> !fir.ptr<!fir.type<_QMmTt1{x:f32}>>
+! CHECK:  hlfir.designate %[[VAL_4]]{"x"}   : (!fir.ptr<!fir.type<_QMmTt1{x:f32}>>) -> !fir.ref<f32>
 
 subroutine test_symbol_followed_by_ref(x)
   character(:), allocatable :: x(:)

diff  --git a/flang/test/Lower/HLFIR/assignment-intrinsics.f90 b/flang/test/Lower/HLFIR/assignment-intrinsics.f90
index 159a3f41fc43..c3af0dfe43d4 100644
--- a/flang/test/Lower/HLFIR/assignment-intrinsics.f90
+++ b/flang/test/Lower/HLFIR/assignment-intrinsics.f90
@@ -135,6 +135,17 @@ subroutine array_character(x, y)
 ! 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,?>>>)
 ! 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,?>>>
 
+subroutine array_pointer(x, y)
+  real, pointer :: x(:), y(:)
+  x = y
+end subroutine
+! CHECK-LABEL: func.func @_QParray_pointer(
+! CHECK:  %[[VAL_1:.*]]:2 = hlfir.declare %{{.*}}Ex
+! CHECK:  %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}}Ey
+! CHECK:  %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK:  %[[VAL_4:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK:  hlfir.assign %[[VAL_3]] to %[[VAL_4]] : !fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.box<!fir.ptr<!fir.array<?xf32>>>
+
 ! -----------------------------------------------------------------------------
 !     Test assignments with array LHS and scalar RHS
 ! -----------------------------------------------------------------------------


        


More information about the flang-commits mailing list