[flang-commits] [flang] 34d3f3f - [flang] Lower symbols to hlfir.declare

Jean Perier via flang-commits flang-commits at lists.llvm.org
Tue Nov 15 00:50:38 PST 2022


Author: Jean Perier
Date: 2022-11-15T09:50:00+01:00
New Revision: 34d3f3fbedc0cc1db5acca5b7eb6a3e304316b13

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

LOG: [flang] Lower symbols to hlfir.declare

Update lowering to generate hlfir.declare instead of fir.declare.
Introduce the hlfir::Entity class that will be used to work with
Fortran objects in HLFIR transformation.

Fix lower bounds that where swapped with extents in fir.declare
generation.

Update tests that expected fir.declare.

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

Added: 
    

Modified: 
    flang/include/flang/Optimizer/Builder/HLFIRTools.h
    flang/lib/Lower/ConvertVariable.cpp
    flang/lib/Optimizer/Builder/HLFIRTools.cpp
    flang/test/Lower/HLFIR/constant.f90
    flang/test/Lower/HLFIR/convert-variable.f90
    flang/test/Lower/HLFIR/expr-addr.f90
    flang/test/Lower/HLFIR/expr-box.f90
    flang/test/Lower/HLFIR/expr-value.f90
    flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
index a23f9ce8712fe..834c410ecb469 100644
--- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h
+++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
@@ -41,6 +41,12 @@ inline bool isFortranValue(mlir::Value value) {
 /// original source or can be legally defined: temporaries created to store
 /// expression values are considered to be variables, and so are PARAMETERs
 /// global constant address.
+inline bool isFortranEntity(mlir::Value value) {
+  return isFortranValue(value) || isFortranVariableType(value.getType());
+}
+
+/// Is this a Fortran variable for which the defining op carrying the Fortran
+/// attributes is visible?
 inline bool isFortranVariableWithAttributes(mlir::Value value) {
   return value.getDefiningOp<fir::FortranVariableOpInterface>();
 }
@@ -51,25 +57,78 @@ inline bool isFortranEntityWithAttributes(mlir::Value value) {
   return isFortranValue(value) || isFortranVariableWithAttributes(value);
 }
 
+class Entity : public mlir::Value {
+public:
+  explicit Entity(mlir::Value value) : mlir::Value(value) {
+    assert(isFortranEntity(value) &&
+           "must be a value representing a Fortran value or variable like");
+  }
+  Entity(fir::FortranVariableOpInterface variable)
+      : mlir::Value(variable.getBase()) {}
+  bool isValue() const { return isFortranValue(*this); }
+  bool isVariable() const { return !isValue(); }
+  bool isMutableBox() const {
+    mlir::Type type = fir::dyn_cast_ptrEleTy(getType());
+    return type && type.isa<fir::BaseBoxType>();
+  }
+  bool isArray() const {
+    mlir::Type type = fir::unwrapPassByRefType(fir::unwrapRefType(getType()));
+    if (type.isa<fir::SequenceType>())
+      return true;
+    if (auto exprType = type.dyn_cast<hlfir::ExprType>())
+      return exprType.isArray();
+    return false;
+  }
+  bool isScalar() const { return !isArray(); }
+
+  mlir::Type getFortranElementType() const {
+    mlir::Type type = fir::unwrapSequenceType(
+        fir::unwrapPassByRefType(fir::unwrapRefType(getType())));
+    if (auto exprType = type.dyn_cast<hlfir::ExprType>())
+      return exprType.getEleTy();
+    return type;
+  }
+
+  bool hasLengthParameters() const {
+    mlir::Type eleTy = getFortranElementType();
+    return eleTy.isa<fir::CharacterType>() ||
+           fir::isRecordWithTypeParameters(eleTy);
+  }
+
+  fir::FortranVariableOpInterface getIfVariableInterface() const {
+    return this->getDefiningOp<fir::FortranVariableOpInterface>();
+  }
+
+  // Get the entity as an mlir SSA value containing all the shape, type
+  // parameters and dynamic shape information.
+  mlir::Value getBase() const { return *this; }
+
+  // Get the entity as a FIR base. This may not carry the shape and type
+  // parameters information, and even when it is a box with shape information.
+  // it will not contain the local lower bounds of the entity. This should
+  // be used with care when generating FIR code that does not need this
+  // information, or has access to it in other ways. Its advantage is that
+  // it will never be a fir.box for explicit shape arrays, leading to simpler
+  // FIR code generation.
+  mlir::Value getFirBase() const;
+};
+
 /// Wrapper over an mlir::Value that can be viewed as a Fortran entity.
 /// This provides some Fortran specific helpers as well as a guarantee
 /// in the compiler source that a certain mlir::Value must be a Fortran
 /// entity, and if it is a variable, its defining operation carrying its
 /// Fortran attributes must be visible.
-class EntityWithAttributes : public mlir::Value {
+class EntityWithAttributes : public Entity {
 public:
-  explicit EntityWithAttributes(mlir::Value value) : mlir::Value(value) {
+  explicit EntityWithAttributes(mlir::Value value) : Entity(value) {
     assert(isFortranEntityWithAttributes(value) &&
            "must be a value representing a Fortran value or variable");
   }
   EntityWithAttributes(fir::FortranVariableOpInterface variable)
-      : mlir::Value(variable.getBase()) {}
-  bool isValue() const { return isFortranValue(*this); }
-  bool isVariable() const { return !isValue(); }
+      : Entity(variable) {}
   fir::FortranVariableOpInterface getIfVariable() const {
-    return this->getDefiningOp<fir::FortranVariableOpInterface>();
+    return getIfVariableInterface();
   }
-  mlir::Value getBase() const { return *this; }
 };
 
 /// Functions to translate hlfir::EntityWithAttributes to fir::ExtendedValue.
@@ -80,7 +139,7 @@ class EntityWithAttributes : public mlir::Value {
 using CleanupFunction = std::function<void()>;
 std::pair<fir::ExtendedValue, llvm::Optional<CleanupFunction>>
 translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder,
-                         EntityWithAttributes entity);
+                         Entity entity);
 
 /// Function to translate FortranVariableOpInterface to fir::ExtendedValue.
 /// It does not generate any IR, and is a simple packaging operation.
@@ -93,6 +152,12 @@ EntityWithAttributes genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
                                 llvm::StringRef name,
                                 fir::FortranVariableFlagsAttr flags);
 
+/// If the entity is a variable, load its value (dereference pointers and
+/// allocatables if needed). Do nothing if the entity os already a variable or
+/// if it is not a scalar entity of numerical or logical type.
+Entity loadTrivialScalar(mlir::Location loc, fir::FirOpBuilder &builder,
+                         Entity entity);
+
 } // namespace hlfir
 
 #endif // FORTRAN_OPTIMIZER_BUILDER_HLFIRTOOLS_H

diff  --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 0479fc0f4929b..af75e6050b872 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -17,6 +17,7 @@
 #include "flang/Lower/CallInterface.h"
 #include "flang/Lower/ConvertConstant.h"
 #include "flang/Lower/ConvertExpr.h"
+#include "flang/Lower/ConvertExprToHLFIR.h"
 #include "flang/Lower/IntrinsicCall.h"
 #include "flang/Lower/Mangler.h"
 #include "flang/Lower/PFTBuilder.h"
@@ -25,11 +26,13 @@
 #include "flang/Lower/SymbolMap.h"
 #include "flang/Optimizer/Builder/Character.h"
 #include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/HLFIRTools.h"
 #include "flang/Optimizer/Builder/Runtime/Derived.h"
 #include "flang/Optimizer/Builder/Todo.h"
 #include "flang/Optimizer/Dialect/FIRAttr.h"
 #include "flang/Optimizer/Dialect/FIRDialect.h"
 #include "flang/Optimizer/Dialect/FIROps.h"
+#include "flang/Optimizer/HLFIR/HLFIROps.h"
 #include "flang/Optimizer/Support/FIRContext.h"
 #include "flang/Optimizer/Support/FatalError.h"
 #include "flang/Semantics/runtime-type-info.h"
@@ -46,6 +49,13 @@ static mlir::Value genScalarValue(Fortran::lower::AbstractConverter &converter,
                                   Fortran::lower::StatementContext &context) {
   // This does not use the AbstractConverter member function to override the
   // symbol mapping to be used expression lowering.
+  if (converter.getLoweringOptions().getLowerToHighLevelFIR()) {
+    hlfir::EntityWithAttributes loweredExpr =
+        Fortran::lower::convertExprToHLFIR(loc, converter, expr, symMap,
+                                           context);
+    return hlfir::loadTrivialScalar(loc, converter.getFirOpBuilder(),
+                                    loweredExpr);
+  }
   return fir::getBase(Fortran::lower::createSomeExtendedExpression(
       loc, converter, expr, symMap, context));
 }
@@ -1345,7 +1355,7 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
     const mlir::Location loc = genLocation(converter, sym);
     mlir::Value shapeOrShift;
     if (!shape.empty() && !lbounds.empty())
-      shapeOrShift = builder.genShape(loc, shape, lbounds);
+      shapeOrShift = builder.genShape(loc, lbounds, shape);
     else if (!shape.empty())
       shapeOrShift = builder.genShape(loc, shape);
     else if (!lbounds.empty())
@@ -1353,13 +1363,11 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
     llvm::SmallVector<mlir::Value> lenParams;
     if (len)
       lenParams.emplace_back(len);
-    auto name = mlir::StringAttr::get(builder.getContext(),
-                                      Fortran::lower::mangle::mangleName(sym));
+    auto name = Fortran::lower::mangle::mangleName(sym);
     fir::FortranVariableFlagsAttr attributes =
         translateSymbolAttributes(builder.getContext(), sym);
-    auto newBase = builder.create<fir::DeclareOp>(
-        loc, base.getType(), base, shapeOrShift, lenParams, name, attributes);
-    base = newBase;
+    auto newBase = builder.create<hlfir::DeclareOp>(
+        loc, base, name, shapeOrShift, lenParams, attributes);
     symMap.addVariableDefinition(sym, newBase, force);
     return;
   }
@@ -1390,11 +1398,20 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
 static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
                              Fortran::lower::SymMap &symMap,
                              const Fortran::semantics::Symbol &sym,
-                             const fir::ExtendedValue &exv) {
-  if (converter.getLoweringOptions().getLowerToHighLevelFIR())
-    TODO(genLocation(converter, sym),
-         "generate fir.declare from ExtendedValue");
-  symMap.addSymbol(sym, exv);
+                             const fir::ExtendedValue &exv,
+                             bool force = false) {
+  if (converter.getLoweringOptions().getLowerToHighLevelFIR()) {
+    fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+    const mlir::Location loc = genLocation(converter, sym);
+    fir::FortranVariableFlagsAttr attributes =
+        translateSymbolAttributes(builder.getContext(), sym);
+    auto name = Fortran::lower::mangle::mangleName(sym);
+    hlfir::EntityWithAttributes declare =
+        hlfir::genDeclare(loc, builder, exv, name, attributes);
+    symMap.addVariableDefinition(sym, declare.getIfVariableInterface(), force);
+    return;
+  }
+  symMap.addSymbol(sym, exv, force);
 }
 
 /// Map an allocatable or pointer symbol to its FIR address and evaluated
@@ -1419,8 +1436,11 @@ static void genBoxDeclare(Fortran::lower::AbstractConverter &converter,
                           llvm::ArrayRef<mlir::Value> explicitParams,
                           llvm::ArrayRef<mlir::Value> explicitExtents,
                           bool replace = false) {
-  if (converter.getLoweringOptions().getLowerToHighLevelFIR())
-    TODO(genLocation(converter, sym), "generate fir.declare for box");
+  if (converter.getLoweringOptions().getLowerToHighLevelFIR()) {
+    fir::BoxValue boxValue{box, lbounds, explicitParams, explicitExtents};
+    genDeclareSymbol(converter, symMap, sym, std::move(boxValue), replace);
+    return;
+  }
   symMap.addBoxSymbol(sym, box, lbounds, explicitParams, explicitExtents,
                       replace);
 }

diff  --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index 845717b463cb0..cd88118717249 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -12,7 +12,9 @@
 
 #include "flang/Optimizer/Builder/HLFIRTools.h"
 #include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/MutableBox.h"
 #include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/HLFIR/HLFIROps.h"
 
 // Return explicit extents. If the base is a fir.box, this won't read it to
 // return the extents and will instead return an empty vector.
@@ -68,34 +70,48 @@ getExplicitTypeParams(fir::FortranVariableOpInterface var) {
 
 std::pair<fir::ExtendedValue, llvm::Optional<hlfir::CleanupFunction>>
 hlfir::translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &,
-                                hlfir::EntityWithAttributes entity) {
-  if (auto variable = entity.getIfVariable())
+                                hlfir::Entity entity) {
+  if (auto variable = entity.getIfVariableInterface())
     return {hlfir::translateToExtendedValue(variable), {}};
+  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
   return {{static_cast<mlir::Value>(entity)}, {}};
 }
 
+mlir::Value hlfir::Entity::getFirBase() const {
+  if (fir::FortranVariableOpInterface variable = getIfVariableInterface())
+    if (auto declareOp =
+            mlir::dyn_cast<hlfir::DeclareOp>(variable.getOperation()))
+      return declareOp.getOriginalBase();
+  return getBase();
+}
+
 fir::ExtendedValue
 hlfir::translateToExtendedValue(fir::FortranVariableOpInterface variable) {
+  /// When going towards FIR, use the original base value to avoid
+  /// introducing descriptors at runtime when they are not required.
+  mlir::Value firBase = Entity{variable}.getFirBase();
   if (variable.isPointer() || variable.isAllocatable())
     TODO(variable->getLoc(), "pointer or allocatable "
                              "FortranVariableOpInterface to extendedValue");
-  if (variable.getBase().getType().isa<fir::BaseBoxType>())
-    return fir::BoxValue(variable.getBase(), getExplicitLbounds(variable),
-                         getExplicitTypeParams(variable),
-                         getExplicitExtents(variable));
+  if (firBase.getType().isa<fir::BaseBoxType>())
+    return fir::BoxValue(firBase, getExplicitLbounds(variable),
+                         getExplicitTypeParams(variable));
+
   if (variable.isCharacter()) {
     if (variable.isArray())
-      return fir::CharArrayBoxValue(
-          variable.getBase(), variable.getExplicitCharLen(),
-          getExplicitExtents(variable), getExplicitLbounds(variable));
-    return fir::CharBoxValue(variable.getBase(), variable.getExplicitCharLen());
+      return fir::CharArrayBoxValue(firBase, variable.getExplicitCharLen(),
+                                    getExplicitExtents(variable),
+                                    getExplicitLbounds(variable));
+    return fir::CharBoxValue(firBase, variable.getExplicitCharLen());
   }
   if (variable.isArray())
-    return fir::ArrayBoxValue(variable.getBase(), getExplicitExtents(variable),
+    return fir::ArrayBoxValue(firBase, getExplicitExtents(variable),
                               getExplicitLbounds(variable));
-  return variable.getBase();
+  return firBase;
 }
 
 hlfir::EntityWithAttributes
@@ -130,8 +146,22 @@ hlfir::genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
                          box.nonDeferredLenParams().end());
       },
       [](const auto &) {});
-  auto nameAttr = mlir::StringAttr::get(builder.getContext(), name);
-  auto declareOp = builder.create<fir::DeclareOp>(
-      loc, base.getType(), base, shapeOrShift, lenParams, nameAttr, flags);
+  auto declareOp = builder.create<hlfir::DeclareOp>(
+      loc, base, name, shapeOrShift, lenParams, flags);
   return mlir::cast<fir::FortranVariableOpInterface>(declareOp.getOperation());
 }
+
+/// If the entity is a variable, load its value (dereference pointers and
+/// allocatables if needed). Do nothing if the entity os already a variable or
+/// if it is not a scalar entity of numerical or logical type.
+hlfir::Entity hlfir::loadTrivialScalar(mlir::Location loc,
+                                       fir::FirOpBuilder &builder,
+                                       Entity entity) {
+  if (entity.isVariable() && entity.isScalar() &&
+      fir::isa_trivial(entity.getFortranElementType())) {
+    if (entity.isMutableBox())
+      TODO(loc, "load pointer/allocatable scalar");
+    return Entity{builder.create<fir::LoadOp>(loc, entity)};
+  }
+  return entity;
+}

diff  --git a/flang/test/Lower/HLFIR/constant.f90 b/flang/test/Lower/HLFIR/constant.f90
index 3ee7308ad3b3f..fcde5aa3fca6d 100644
--- a/flang/test/Lower/HLFIR/constant.f90
+++ b/flang/test/Lower/HLFIR/constant.f90
@@ -16,7 +16,7 @@ subroutine test_constant_scalar_char()
   print *, "hello"
 ! CHECK:  %[[VAL_5:.*]] = fir.address_of(@[[name:.*]]) : !fir.ref<!fir.char<1,5>>
 ! CHECK:  %[[VAL_6:.*]] = arith.constant 5 : index
-! CHECK:  fir.declare %[[VAL_5]] typeparams %[[VAL_6]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "[[name]]"} : (!fir.ref<!fir.char<1,5>>, index) -> !fir.ref<!fir.char<1,5>>
+! CHECK:  hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "[[name]]"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtest_constant_array()
@@ -25,7 +25,7 @@ subroutine test_constant_array()
 ! CHECK:  %[[VAL_5:.*]] = fir.address_of(@[[name:.*]]) : !fir.ref<!fir.array<3xf32>>
 ! CHECK:  %[[VAL_6:.*]] = arith.constant 3 : index
 ! CHECK:  %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
-! CHECK:  fir.declare %[[VAL_5]](%[[VAL_7]]) {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "[[name]]"} : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<3xf32>>
+! CHECK:  hlfir.declare %[[VAL_5]](%[[VAL_7]]) {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "[[name]]"} : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<3xf32>>, !fir.ref<!fir.array<3xf32>>)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtest_constant_array_char()
@@ -35,7 +35,7 @@ subroutine test_constant_array_char()
 ! CHECK:  %[[VAL_6:.*]] = arith.constant 2 : index
 ! CHECK:  %[[VAL_7:.*]] = arith.constant 3 : index
 ! CHECK:  %[[VAL_8:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
-! CHECK:  fir.declare %[[VAL_5]](%[[VAL_8]]) typeparams %[[VAL_7]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "[[name]]"} : (!fir.ref<!fir.array<2x!fir.char<1,3>>>, !fir.shape<1>, index) -> !fir.ref<!fir.array<2x!fir.char<1,3>>>
+! CHECK:  hlfir.declare %[[VAL_5]](%[[VAL_8]]) typeparams %[[VAL_7]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "[[name]]"} : (!fir.ref<!fir.array<2x!fir.char<1,3>>>, !fir.shape<1>, index) -> (!fir.ref<!fir.array<2x!fir.char<1,3>>>, !fir.ref<!fir.array<2x!fir.char<1,3>>>)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtest_constant_with_lower_bounds()
@@ -48,5 +48,5 @@ subroutine test_constant_with_lower_bounds()
 ! CHECK:  %[[VAL_15:.*]] = arith.constant -1 : index
 ! CHECK:  %[[VAL_16:.*]] = arith.constant -1 : index
 ! CHECK:  %[[VAL_17:.*]] = fir.shape_shift %[[VAL_15]], %[[VAL_13]], %[[VAL_16]], %[[VAL_14]] : (index, index, index, index) -> !fir.shapeshift<2>
-! CHECK:  fir.declare %[[VAL_12]](%[[VAL_17]]) {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro[[name]]"} : (!fir.ref<!fir.array<2x2xi32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<2x2xi32>>
+! CHECK:  hlfir.declare %[[VAL_12]](%[[VAL_17]]) {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro[[name]]"} : (!fir.ref<!fir.array<2x2xi32>>, !fir.shapeshift<2>) -> (!fir.box<!fir.array<2x2xi32>>, !fir.ref<!fir.array<2x2xi32>>)
 end subroutine

diff  --git a/flang/test/Lower/HLFIR/convert-variable.f90 b/flang/test/Lower/HLFIR/convert-variable.f90
index 6c4623250341e..ab9425afe3f1e 100644
--- a/flang/test/Lower/HLFIR/convert-variable.f90
+++ b/flang/test/Lower/HLFIR/convert-variable.f90
@@ -6,7 +6,7 @@ subroutine scalar_numeric(x)
 end subroutine
 ! CHECK-LABEL: func.func @_QPscalar_numeric(
 ! CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<i32>
-! CHECK:  %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "_QFscalar_numericEx"} : (!fir.ref<i32>) -> !fir.ref<i32>
+! CHECK:  %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] {uniq_name = "_QFscalar_numericEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 
 subroutine scalar_character(c)
   character(*) :: c
@@ -14,7 +14,7 @@ subroutine scalar_character(c)
 ! CHECK-LABEL: func.func @_QPscalar_character(
 ! CHECK-SAME:    %[[VAL_0:.*]]: !fir.boxchar<1>
 ! CHECK:  %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
-! CHECK:  %[[VAL_2:.*]] = fir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 {uniq_name = "_QFscalar_characterEc"} : (!fir.ref<!fir.char<1,?>>, index) -> !fir.ref<!fir.char<1,?>>
+! CHECK:  %[[VAL_2:.*]] = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 {uniq_name = "_QFscalar_characterEc"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
 
 subroutine scalar_character_cst_len(c)
   character(10) :: c
@@ -23,7 +23,7 @@ subroutine scalar_character_cst_len(c)
 ! CHECK-SAME:    %[[VAL_0:.*]]: !fir.boxchar<1>
 ! CHECK:  %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
 ! CHECK:  %[[VAL_2:.*]] = arith.constant 10 : index
-! CHECK:  %[[VAL_3:.*]] = fir.declare %[[VAL_1]]#0 typeparams %[[VAL_2]] {uniq_name = "_QFscalar_character_cst_lenEc"} : (!fir.ref<!fir.char<1,?>>, index) -> !fir.ref<!fir.char<1,?>>
+! CHECK:  %[[VAL_3:.*]] = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_2]] {uniq_name = "_QFscalar_character_cst_lenEc"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
 
 subroutine array_numeric(x)
   integer :: x(10, 20)
@@ -33,7 +33,7 @@ subroutine array_numeric(x)
 ! CHECK:  %[[VAL_1:.*]] = arith.constant 10 : index
 ! CHECK:  %[[VAL_2:.*]] = arith.constant 20 : index
 ! CHECK:  %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2>
-! CHECK:  %[[VAL_4:.*]] = fir.declare %[[VAL_0]](%[[VAL_3]]) {uniq_name = "_QFarray_numericEx"} : (!fir.ref<!fir.array<10x20xi32>>, !fir.shape<2>) -> !fir.ref<!fir.array<10x20xi32>>
+! CHECK:  %[[VAL_4:.*]] = hlfir.declare %[[VAL_0]](%[[VAL_3]]) {uniq_name = "_QFarray_numericEx"} : (!fir.ref<!fir.array<10x20xi32>>, !fir.shape<2>) -> (!fir.ref<!fir.array<10x20xi32>>, !fir.ref<!fir.array<10x20xi32>>)
 
 
 subroutine array_numeric_lbounds(x)
@@ -45,8 +45,8 @@ subroutine array_numeric_lbounds(x)
 ! CHECK:  %[[VAL_2:.*]] = arith.constant 12 : index
 ! CHECK:  %[[VAL_3:.*]] = arith.constant -2 : index
 ! CHECK:  %[[VAL_4:.*]] = arith.constant 23 : index
-! CHECK:  %[[VAL_5:.*]] = fir.shape_shift %[[VAL_2]], %[[VAL_1]], %[[VAL_4]], %[[VAL_3]] : (index, index, index, index) -> !fir.shapeshift<2>
-! CHECK:  %[[VAL_6:.*]] = fir.declare %[[VAL_0]](%[[VAL_5]]) {uniq_name = "_QFarray_numeric_lboundsEx"} : (!fir.ref<!fir.array<12x23xi32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<12x23xi32>>
+! CHECK:  %[[VAL_5:.*]] = fir.shape_shift %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_4]] : (index, index, index, index) -> !fir.shapeshift<2>
+! CHECK:  %[[VAL_6:.*]] = hlfir.declare %[[VAL_0]](%[[VAL_5]]) {uniq_name = "_QFarray_numeric_lboundsEx"} : (!fir.ref<!fir.array<12x23xi32>>, !fir.shapeshift<2>) -> (!fir.box<!fir.array<12x23xi32>>, !fir.ref<!fir.array<12x23xi32>>)
 
 subroutine array_character(c)
   character(*) :: c(50)
@@ -57,14 +57,14 @@ subroutine array_character(c)
 ! CHECK:  %[[VAL_2:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<50x!fir.char<1,?>>>
 ! CHECK:  %[[VAL_3:.*]] = arith.constant 50 : index
 ! CHECK:  %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1>
-! CHECK:  %[[VAL_5:.*]] = fir.declare %[[VAL_2]](%[[VAL_4]]) typeparams %[[VAL_1]]#1 {uniq_name = "_QFarray_characterEc"} : (!fir.ref<!fir.array<50x!fir.char<1,?>>>, !fir.shape<1>, index) -> !fir.ref<!fir.array<50x!fir.char<1,?>>>
+! CHECK:  %[[VAL_5:.*]] = hlfir.declare %[[VAL_2]](%[[VAL_4]]) typeparams %[[VAL_1]]#1 {uniq_name = "_QFarray_characterEc"} : (!fir.ref<!fir.array<50x!fir.char<1,?>>>, !fir.shape<1>, index) -> (!fir.box<!fir.array<50x!fir.char<1,?>>>, !fir.ref<!fir.array<50x!fir.char<1,?>>>)
 
 subroutine scalar_numeric_attributes(x)
   integer, optional, target, intent(in) :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPscalar_numeric_attributes(
 ! CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<i32>
-! CHECK:  %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in, optional, target>, uniq_name = "_QFscalar_numeric_attributesEx"} : (!fir.ref<i32>) -> !fir.ref<i32>
+! CHECK:  %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in, optional, target>, uniq_name = "_QFscalar_numeric_attributesEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 
 subroutine scalar_numeric_attributes_2(x)
   real(16), value :: x(100)
@@ -73,25 +73,25 @@ subroutine scalar_numeric_attributes_2(x)
 ! CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.array<100xf128>>
 ! CHECK:  %[[VAL_1:.*]] = arith.constant 100 : index
 ! CHECK:  %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1>
-! CHECK:  %[[VAL_3:.*]] = fir.declare %[[VAL_0]](%[[VAL_2]]) {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFscalar_numeric_attributes_2Ex"} : (!fir.ref<!fir.array<100xf128>>, !fir.shape<1>) -> !fir.ref<!fir.array<100xf128>>
+! CHECK:  %[[VAL_3:.*]] = hlfir.declare %[[VAL_0]](%[[VAL_2]]) {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFscalar_numeric_attributes_2Ex"} : (!fir.ref<!fir.array<100xf128>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf128>>, !fir.ref<!fir.array<100xf128>>)
 
 subroutine scalar_numeric_attributes_3(x)
   real, intent(in) :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPscalar_numeric_attributes_3(
 ! CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<f32>
-! CHECK:  %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFscalar_numeric_attributes_3Ex"} : (!fir.ref<f32>) -> !fir.ref<f32>
+! CHECK:  %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFscalar_numeric_attributes_3Ex"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
 
 subroutine scalar_numeric_attributes_4(x)
   logical(8), intent(out) :: x
 end subroutine
 ! CHECK-LABEL: func.func @_QPscalar_numeric_attributes_4(
 ! CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.logical<8>>
-! CHECK:  %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QFscalar_numeric_attributes_4Ex"} : (!fir.ref<!fir.logical<8>>) -> !fir.ref<!fir.logical<8>>
+! CHECK:  %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QFscalar_numeric_attributes_4Ex"} : (!fir.ref<!fir.logical<8>>) -> (!fir.ref<!fir.logical<8>>, !fir.ref<!fir.logical<8>>)
 
 subroutine scalar_numeric_parameter()
   integer, parameter :: p = 42
 end subroutine
 ! CHECK-LABEL: func.func @_QPscalar_numeric_parameter() {
 ! CHECK:  %[[VAL_0:.*]] = fir.address_of(@_QFscalar_numeric_parameterECp) : !fir.ref<i32>
-! CHECK:  %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QFscalar_numeric_parameterECp"} : (!fir.ref<i32>) -> !fir.ref<i32>
+! CHECK:  %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QFscalar_numeric_parameterECp"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)

diff  --git a/flang/test/Lower/HLFIR/expr-addr.f90 b/flang/test/Lower/HLFIR/expr-addr.f90
index 5900d4a971273..c1ecd58d3a3c3 100644
--- a/flang/test/Lower/HLFIR/expr-addr.f90
+++ b/flang/test/Lower/HLFIR/expr-addr.f90
@@ -6,7 +6,7 @@
 subroutine foo(x)
   integer :: x
   read (*,*) x
-  ! CHECK: %[[x:.]] = fir.declare %[[arg0]] {uniq_name = "_QFfooEx"} : (!fir.ref<i32>) -> !fir.ref<i32>
-  ! CHECK: %[[x_cast:.*]] = fir.convert %[[x]] : (!fir.ref<i32>) -> !fir.ref<i64>
+  ! CHECK: %[[x:.]]:2 = hlfir.declare %[[arg0]] {uniq_name = "_QFfooEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+  ! 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

diff  --git a/flang/test/Lower/HLFIR/expr-box.f90 b/flang/test/Lower/HLFIR/expr-box.f90
index b55456a81c1fd..b87190731ea14 100644
--- a/flang/test/Lower/HLFIR/expr-box.f90
+++ b/flang/test/Lower/HLFIR/expr-box.f90
@@ -8,7 +8,7 @@ subroutine foo(x)
   print *, x 
 ! CHECK-DAG:  %[[VAL_3:.*]] = arith.constant 21 : index
 ! CHECK-DAG:  %[[VAL_4:.*]] = arith.constant 10 : index
-! CHECK:  %[[VAL_5:.*]] = fir.shape_shift %[[VAL_4]], %[[VAL_3]] : (index, index) -> !fir.shapeshift<1>
-! CHECK:  %[[VAL_6:.*]] = fir.declare %[[VAL_0]](%[[VAL_5]]) {uniq_name = "_QFfooEx"} : (!fir.ref<!fir.array<10xi32>>, !fir.shapeshift<1>) -> !fir.ref<!fir.array<10xi32>>
-! CHECK:  fir.embox %[[VAL_6]](%[[VAL_5]]) : (!fir.ref<!fir.array<10xi32>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<10xi32>>
+! CHECK:  %[[VAL_5:.*]] = fir.shape_shift %[[VAL_3]], %[[VAL_4]] : (index, index) -> !fir.shapeshift<1>
+! CHECK:  %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) {uniq_name = "_QFfooEx"} : (!fir.ref<!fir.array<10xi32>>, !fir.shapeshift<1>) -> (!fir.box<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>)
+! CHECK:  fir.embox %[[VAL_6]]#1(%[[VAL_5]]) : (!fir.ref<!fir.array<10xi32>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<10xi32>>
 end subroutine

diff  --git a/flang/test/Lower/HLFIR/expr-value.f90 b/flang/test/Lower/HLFIR/expr-value.f90
index 2a634d424bb53..6fdcd5f76efa5 100644
--- a/flang/test/Lower/HLFIR/expr-value.f90
+++ b/flang/test/Lower/HLFIR/expr-value.f90
@@ -11,8 +11,8 @@ subroutine foo()
 ! CHECK-LABEL: func.func @_QPfoo_designator(
 ! CHECK-SAME: %[[arg0:.*]]: !fir.ref<i32>
 subroutine foo_designator(n)
-  !CHECK:  %[[n:.*]] = fir.declare %[[arg0]] {uniq_name = "_QFfoo_designatorEn"} : (!fir.ref<i32>) -> !fir.ref<i32>
+  !CHECK:  %[[n:.*]]:2 = hlfir.declare %[[arg0]] {uniq_name = "_QFfoo_designatorEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
   print *, n
-  ! CHECK: %[[nval:.*]] = fir.load %[[n]] : !fir.ref<i32>
+  ! CHECK: %[[nval:.*]] = fir.load %[[n]]#1 : !fir.ref<i32>
   ! CHECK: fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[nval]]) : (!fir.ref<i8>, i32) -> i1
 end subroutine

diff  --git a/flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp b/flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp
index 55b25969fe216..22d580feda724 100644
--- a/flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp
+++ b/flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp
@@ -36,33 +36,8 @@ struct HLFIRToolsTest : public testing::Test {
   }
 
   mlir::Value createDeclare(fir::ExtendedValue exv) {
-    mlir::Value addr = fir::getBase(exv);
-    mlir::Location loc = getLoc();
-    mlir::Value shape;
-    if (exv.rank() > 0)
-      shape = firBuilder->createShape(loc, exv);
-    llvm::SmallVector<mlir::Value> typeParams;
-    exv.match(
-        [&](const fir::CharBoxValue &x) {
-          typeParams.emplace_back(x.getLen());
-        },
-        [&](const fir::CharArrayBoxValue &x) {
-          typeParams.emplace_back(x.getLen());
-        },
-        [&](const fir::BoxValue &x) {
-          typeParams.append(x.getExplicitParameters().begin(),
-              x.getExplicitParameters().end());
-        },
-        [&](const fir::MutableBoxValue &x) {
-          typeParams.append(
-              x.nonDeferredLenParams().begin(), x.nonDeferredLenParams().end());
-        },
-        [](const auto &) {});
-    auto name =
-        mlir::StringAttr::get(&context, "x" + std::to_string(varCounter++));
-    return firBuilder->create<fir::DeclareOp>(loc, addr.getType(), addr, shape,
-        typeParams, name,
-        /*fortran_attrs=*/fir::FortranVariableFlagsAttr{});
+    return hlfir::genDeclare(getLoc(), *firBuilder, exv,
+        "x" + std::to_string(varCounter++), fir::FortranVariableFlagsAttr{});
   }
 
   mlir::Value createConstant(std::int64_t cst) {
@@ -92,7 +67,7 @@ TEST_F(HLFIRToolsTest, testScalarRoundTrip) {
   auto *unboxed = scalarf32Result.getUnboxed();
   EXPECT_FALSE(cleanup.has_value());
   ASSERT_NE(unboxed, nullptr);
-  EXPECT_TRUE(*unboxed == scalarf32Entity.getBase());
+  EXPECT_TRUE(*unboxed == scalarf32Entity.getFirBase());
   EXPECT_TRUE(scalarf32Entity.isVariable());
   EXPECT_FALSE(scalarf32Entity.isValue());
 }
@@ -118,7 +93,7 @@ TEST_F(HLFIRToolsTest, testArrayRoundTrip) {
   ASSERT_NE(res, nullptr);
   // gtest has a terrible time printing mlir::Value in case of failing
   // EXPECT_EQ(mlir::Value, mlir::Value). So use EXPECT_TRUE instead.
-  EXPECT_TRUE(fir::getBase(*res) == arrayf32Entity.getBase());
+  EXPECT_TRUE(fir::getBase(*res) == arrayf32Entity.getFirBase());
   ASSERT_EQ(res->getExtents().size(), arrayf32.getExtents().size());
   for (unsigned i = 0; i < arrayf32.getExtents().size(); ++i)
     EXPECT_TRUE(res->getExtents()[i] == arrayf32.getExtents()[i]);
@@ -144,7 +119,7 @@ TEST_F(HLFIRToolsTest, testScalarCharRoundTrip) {
   auto *res = scalarCharResult.getBoxOf<fir::CharBoxValue>();
   EXPECT_FALSE(cleanup.has_value());
   ASSERT_NE(res, nullptr);
-  EXPECT_TRUE(fir::getBase(*res) == scalarCharEntity.getBase());
+  EXPECT_TRUE(fir::getBase(*res) == scalarCharEntity.getFirBase());
   EXPECT_TRUE(res->getLen() == scalarChar.getLen());
   EXPECT_TRUE(scalarCharEntity.isVariable());
   EXPECT_FALSE(scalarCharEntity.isValue());
@@ -171,7 +146,7 @@ TEST_F(HLFIRToolsTest, testArrayCharRoundTrip) {
   ASSERT_NE(res, nullptr);
   // gtest has a terrible time printing mlir::Value in case of failing
   // EXPECT_EQ(mlir::Value, mlir::Value). So use EXPECT_TRUE instead.
-  EXPECT_TRUE(fir::getBase(*res) == arrayCharEntity.getBase());
+  EXPECT_TRUE(fir::getBase(*res) == arrayCharEntity.getFirBase());
   EXPECT_TRUE(res->getLen() == arrayChar.getLen());
   ASSERT_EQ(res->getExtents().size(), arrayChar.getExtents().size());
   for (unsigned i = 0; i < arrayChar.getExtents().size(); ++i)
@@ -204,7 +179,7 @@ TEST_F(HLFIRToolsTest, testArrayCharBoxRoundTrip) {
   ASSERT_NE(res, nullptr);
   // gtest has a terrible time printing mlir::Value in case of failing
   // EXPECT_EQ(mlir::Value, mlir::Value). So use EXPECT_TRUE instead.
-  EXPECT_TRUE(fir::getBase(*res) == arrayCharEntity.getBase());
+  EXPECT_TRUE(fir::getBase(*res) == arrayCharEntity.getFirBase());
   ASSERT_EQ(res->getExplicitParameters().size(),
       arrayChar.getExplicitParameters().size());
   for (unsigned i = 0; i < arrayChar.getExplicitParameters().size(); ++i)


        


More information about the flang-commits mailing list