[flang-commits] [flang] 788960d - [flang] Allow conversion from hlfir.expr to fir::ExtendedValue

Jean Perier via flang-commits flang-commits at lists.llvm.org
Tue Dec 6 04:53:44 PST 2022


Author: Jean Perier
Date: 2022-12-06T13:53:16+01:00
New Revision: 788960d6286325c59d1e8e8e85743dafd4a61476

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

LOG: [flang] Allow conversion from hlfir.expr to fir::ExtendedValue

For now at least, the plan is to keep hlfir.expr usage limited as
sub-expression operand, assignment rhs, and a few other contexts (
e.g. Associate statements). The rest of lowering (statements lowering
in the bridge) will still expect to get and manipulate characters and
arrays in memory. That means that hlfir.expr must be converted to
variable in converter.genExprAddr/converter.genExprBox.

This is done using an hlfir.associate, and generating the related
hlfir.end_associate in the statement context.

hlfir::getFirBase of is updated to avoid bringing in the HLFIR
fir.boxchar/fir.box into FIR when the entity was created with
hlfir::AssociateOp.

Differential Revision: https://reviews.llvm.org/D139328

Added: 
    

Modified: 
    flang/lib/Lower/Bridge.cpp
    flang/lib/Optimizer/Builder/HLFIRTools.cpp
    flang/test/Lower/HLFIR/calls-f77.f90
    flang/test/Lower/HLFIR/expr-addr.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 8913cb8aff7e8..b9e489b5a5f4c 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -508,12 +508,16 @@ class FirConverter : public Fortran::lower::AbstractConverter {
       hlfir::EntityWithAttributes loweredExpr =
           Fortran::lower::convertExprToHLFIR(loc, *this, expr, localSymbols,
                                              context);
-      if (fir::FortranVariableOpInterface variable =
-              loweredExpr.getIfVariable())
-        if (!variable.isBox())
-          return translateToExtendedValue(loc, loweredExpr, context);
-      TODO(loc, "lower expr that is not a scalar or explicit shape array "
-                "variable to HLFIR address");
+      if (expr.Rank() > 0 &&
+          !Fortran::evaluate::IsSimplyContiguous(expr, getFoldingContext()))
+        TODO(loc, "genExprAddr of non contiguous variables in HLFIR");
+      fir::ExtendedValue exv =
+          translateToExtendedValue(loc, loweredExpr, context);
+      if (fir::isa_trivial(fir::getBase(exv).getType()))
+        TODO(loc, "place trivial in memory");
+      if (const auto *mutableBox = exv.getBoxOf<fir::MutableBoxValue>())
+        exv = fir::factory::genMutableBoxRead(*builder, loc, *mutableBox);
+      return exv;
     }
     return Fortran::lower::createSomeExtendedAddress(loc, *this, expr,
                                                      localSymbols, context);
@@ -564,14 +568,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
       hlfir::EntityWithAttributes loweredExpr =
           Fortran::lower::convertExprToHLFIR(loc, *this, expr, localSymbols,
                                              stmtCtx);
-      if (fir::FortranVariableOpInterface variable =
-              loweredExpr.getIfVariable())
-        if (variable.isBoxValue() || !variable.isBoxAddress()) {
-          auto exv = translateToExtendedValue(loc, loweredExpr, stmtCtx);
-          return fir::factory::createBoxValue(getFirOpBuilder(), loc, exv);
-        }
-      TODO(loc,
-           "lower expression value or pointer and allocatable to HLFIR box");
+      auto exv = translateToExtendedValue(loc, loweredExpr, stmtCtx);
+      if (fir::isa_trivial(fir::getBase(exv).getType()))
+        TODO(loc, "place trivial in memory");
+      return fir::factory::createBoxValue(getFirOpBuilder(), loc, exv);
     }
     return Fortran::lower::createBoxValue(loc, *this, expr, localSymbols,
                                           stmtCtx);

diff  --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index aa6e90e98e727..4a6dd9a472f6a 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -76,16 +76,28 @@ hlfir::translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder,
   if (entity.isVariable())
     TODO(loc, "HLFIR variable to fir::ExtendedValue without a "
               "FortranVariableOpInterface");
-  if (entity.getType().isa<hlfir::ExprType>())
-    TODO(loc, "hlfir.expr to fir::ExtendedValue"); // use hlfir.associate
+  if (entity.getType().isa<hlfir::ExprType>()) {
+    hlfir::AssociateOp associate = hlfir::genAssociateExpr(
+        loc, builder, entity, entity.getType(), "adapt.valuebyref");
+    auto *bldr = &builder;
+    hlfir::CleanupFunction cleanup = [bldr, loc, associate]() -> void {
+      bldr->create<hlfir::EndAssociateOp>(loc, associate);
+    };
+    hlfir::Entity temp{associate.getBase()};
+    return {translateToExtendedValue(loc, builder, temp).first, cleanup};
+  }
   return {{static_cast<mlir::Value>(entity)}, {}};
 }
 
 mlir::Value hlfir::Entity::getFirBase() const {
-  if (fir::FortranVariableOpInterface variable = getIfVariableInterface())
+  if (fir::FortranVariableOpInterface variable = getIfVariableInterface()) {
     if (auto declareOp =
             mlir::dyn_cast<hlfir::DeclareOp>(variable.getOperation()))
       return declareOp.getOriginalBase();
+    if (auto associateOp =
+            mlir::dyn_cast<hlfir::AssociateOp>(variable.getOperation()))
+      return associateOp.getFirBase();
+  }
   return getBase();
 }
 

diff  --git a/flang/test/Lower/HLFIR/calls-f77.f90 b/flang/test/Lower/HLFIR/calls-f77.f90
index c830d2a92c746..b24c49abcce85 100644
--- a/flang/test/Lower/HLFIR/calls-f77.f90
+++ b/flang/test/Lower/HLFIR/calls-f77.f90
@@ -27,7 +27,7 @@ subroutine call_int_arg_expr()
 ! CHECK-LABEL: func.func @_QPcall_int_arg_expr() {
 ! CHECK:  %[[VAL_0:.*]] = arith.constant 42 : i32
 ! CHECK:  %[[VAL_1:.*]]:3 = hlfir.associate %[[VAL_0]] {uniq_name = "adapt.valuebyref"} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
-! CHECK:  fir.call @_QPtake_i4(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<i32>) -> ()
+! CHECK:  fir.call @_QPtake_i4(%[[VAL_1]]#1) fastmath<contract> : (!fir.ref<i32>) -> ()
 ! CHECK:  hlfir.end_associate %[[VAL_1]]#1, %[[VAL_1]]#2 : !fir.ref<i32>, i1
 
 subroutine call_real_arg_expr()
@@ -36,7 +36,7 @@ subroutine call_real_arg_expr()
 ! CHECK-LABEL: func.func @_QPcall_real_arg_expr() {
 ! CHECK:  %[[VAL_0:.*]] = arith.constant 4.200000e-01 : f32
 ! CHECK:  %[[VAL_1:.*]]:3 = hlfir.associate %[[VAL_0]] {uniq_name = "adapt.valuebyref"} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
-! CHECK:  fir.call @_QPtake_r4(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<f32>) -> ()
+! CHECK:  fir.call @_QPtake_r4(%[[VAL_1]]#1) fastmath<contract> : (!fir.ref<f32>) -> ()
 ! CHECK:  hlfir.end_associate %[[VAL_1]]#1, %[[VAL_1]]#2 : !fir.ref<f32>, i1
 
 subroutine call_real_arg_var(x)
@@ -64,7 +64,7 @@ subroutine call_logical_arg_expr()
 ! CHECK:  %[[VAL_0:.*]] = arith.constant true
 ! CHECK:  %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (i1) -> !fir.logical<4>
 ! CHECK:  %[[VAL_2:.*]]:3 = hlfir.associate %[[VAL_1]] {uniq_name = "adapt.valuebyref"} : (!fir.logical<4>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>, i1)
-! CHECK:  fir.call @_QPtake_l4(%[[VAL_2]]#0) fastmath<contract> : (!fir.ref<!fir.logical<4>>) -> ()
+! CHECK:  fir.call @_QPtake_l4(%[[VAL_2]]#1) fastmath<contract> : (!fir.ref<!fir.logical<4>>) -> ()
 ! CHECK:  hlfir.end_associate %[[VAL_2]]#1, %[[VAL_2]]#2 : !fir.ref<!fir.logical<4>>, i1
 
 subroutine call_logical_arg_expr_2()
@@ -74,7 +74,7 @@ subroutine call_logical_arg_expr_2()
 ! CHECK:  %[[VAL_0:.*]] = arith.constant true
 ! CHECK:  %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (i1) -> !fir.logical<8>
 ! CHECK:  %[[VAL_2:.*]]:3 = hlfir.associate %[[VAL_1]] {uniq_name = "adapt.valuebyref"} : (!fir.logical<8>) -> (!fir.ref<!fir.logical<8>>, !fir.ref<!fir.logical<8>>, i1)
-! CHECK:  fir.call @_QPtake_l8(%[[VAL_2]]#0) fastmath<contract> : (!fir.ref<!fir.logical<8>>) -> ()
+! CHECK:  fir.call @_QPtake_l8(%[[VAL_2]]#1) fastmath<contract> : (!fir.ref<!fir.logical<8>>) -> ()
 ! CHECK:  hlfir.end_associate %[[VAL_2]]#1, %[[VAL_2]]#2 : !fir.ref<!fir.logical<8>>, i1
 
 subroutine call_char_arg_var(x)

diff  --git a/flang/test/Lower/HLFIR/expr-addr.f90 b/flang/test/Lower/HLFIR/expr-addr.f90
index c019c552aea29..3c69cdf88b383 100644
--- a/flang/test/Lower/HLFIR/expr-addr.f90
+++ b/flang/test/Lower/HLFIR/expr-addr.f90
@@ -10,3 +10,16 @@ subroutine foo(x)
   ! CHECK: %[[x_cast:.*]] = fir.convert %[[x]]#1 : (!fir.ref<i32>) -> !fir.ref<i64>
   ! CHECK: fir.call @_FortranAioInputInteger(%{{.*}}, %[[x_cast]], %{{.*}}) {{.*}}: (!fir.ref<i8>, !fir.ref<i64>, i32) -> i1
 end subroutine
+
+subroutine expr_to_var(c)
+  character(*) :: c
+  print *, c//c
+end subroutine
+
+! CHECK-LABEL: func.func @_QPexpr_to_var(
+! CHECK:  %[[VAL_9:.*]] = hlfir.concat %{{.*}}, %{{.*}} len %[[VAL_8:.*]] : (!fir.boxchar<1>, !fir.boxchar<1>, index) -> !hlfir.expr<!fir.char<1,?>>
+! CHECK:  %[[VAL_10:.*]]:3 = hlfir.associate %[[VAL_9]] typeparams %[[VAL_8]] {uniq_name = "adapt.valuebyref"} : (!hlfir.expr<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>, i1)
+! CHECK:  %[[VAL_11:.*]] = fir.convert %[[VAL_10]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
+! CHECK:  %[[VAL_12:.*]] = fir.convert %[[VAL_8]] : (index) -> i64
+! CHECK:  %[[VAL_13:.*]] = fir.call @_FortranAioOutputAscii(%{{.*}}, %[[VAL_11]], %[[VAL_12]]) {{.*}} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1
+! CHECK:  hlfir.end_associate %[[VAL_10]]#1, %[[VAL_10]]#2 : !fir.ref<!fir.char<1,?>>, i1


        


More information about the flang-commits mailing list