[flang-commits] [flang] ca0a0bf - [flang] optionally lower scalar and explicit shape with fir.declare

Jean Perier via flang-commits flang-commits at lists.llvm.org
Thu Oct 20 01:32:00 PDT 2022


Author: Jean Perier
Date: 2022-10-20T10:31:12+02:00
New Revision: ca0a0bf9638c9705862ef2684aba192376c7d7cb

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

LOG: [flang] optionally lower scalar and explicit shape with fir.declare

Lower scalar and explicit shape arrays to fir.declare under the -hlfir option.
Update the SymMap so that it can hold fir::FortranVariableInterface.

The plan is to go towards a SymMap that only contains fir::FortranVariableInterface
once current expression lowering can be replaced. This should make the SymMap lighter
than it is today (SymBox/ExtendedValue are above 256 bytes).

Assumed shape, allocatable and pointer are left TODOs for now. Anything with a
specification expression that is not a constant expression will only be able to
be lowered when the HLFIR expression lowering skeleton is added.

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

Added: 
    flang/test/Lower/HLFIR/convert-variable.f90

Modified: 
    flang/include/flang/Lower/SymbolMap.h
    flang/include/flang/Optimizer/Builder/FIRBuilder.h
    flang/lib/Lower/ConvertVariable.cpp
    flang/lib/Lower/SymbolMap.cpp
    flang/lib/Optimizer/Builder/FIRBuilder.cpp
    flang/test/Lower/HLFIR/expr-addr.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Lower/SymbolMap.h b/flang/include/flang/Lower/SymbolMap.h
index d2dd1bb29ce7b..cd959b6e788de 100644
--- a/flang/include/flang/Lower/SymbolMap.h
+++ b/flang/include/flang/Lower/SymbolMap.h
@@ -16,6 +16,7 @@
 #include "flang/Common/reference.h"
 #include "flang/Optimizer/Builder/BoxValue.h"
 #include "flang/Optimizer/Dialect/FIRType.h"
+#include "flang/Optimizer/Dialect/FortranVariableInterface.h"
 #include "flang/Optimizer/Support/Matcher.h"
 #include "flang/Semantics/symbol.h"
 #include "mlir/IR/Value.h"
@@ -338,6 +339,15 @@ class SymMap {
   /// Dump the map. For debugging.
   LLVM_DUMP_METHOD void dump() const { llvm::errs() << *this << '\n'; }
 
+  void addVariableDefinition(semantics::SymbolRef symRef,
+                             fir::FortranVariableOpInterface definingOp,
+                             bool force = false) {
+    const auto *sym = &symRef.get().GetUltimate();
+    if (force)
+      symbolMapStack.back().erase(sym);
+    symbolMapStack.back().try_emplace(sym, definingOp);
+  }
+
 private:
   /// Add `symbol` to the current map and bind a `box`.
   void makeSym(semantics::SymbolRef symRef, const SymbolBox &box,
@@ -349,7 +359,9 @@ class SymMap {
     symbolMapStack.back().try_emplace(sym, box);
   }
 
-  llvm::SmallVector<llvm::DenseMap<const semantics::Symbol *, SymbolBox>>
+  llvm::SmallVector<
+      llvm::DenseMap<const semantics::Symbol *,
+                     std::variant<SymbolBox, fir::FortranVariableOpInterface>>>
       symbolMapStack;
 
   // Implied DO induction variables are not represented as Se::Symbol in

diff  --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
index 5cfd2ef470504..3567bc44fc095 100644
--- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
@@ -294,6 +294,7 @@ class FirOpBuilder : public mlir::OpBuilder {
   mlir::Value genShape(mlir::Location loc, llvm::ArrayRef<mlir::Value> shift,
                        llvm::ArrayRef<mlir::Value> exts);
   mlir::Value genShape(mlir::Location loc, llvm::ArrayRef<mlir::Value> exts);
+  mlir::Value genShift(mlir::Location loc, llvm::ArrayRef<mlir::Value> shift);
 
   /// Create one of the shape ops given an extended value. For a boxed value,
   /// this may create a `fir.shift` op.

diff  --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index ff8eba4458eef..d2b1e6b5c7e77 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -1293,6 +1293,42 @@ recoverShapeVector(llvm::ArrayRef<std::int64_t> shapeVec, mlir::Value initVal) {
   return result;
 }
 
+static fir::FortranVariableFlagsAttr
+translateSymbolAttributes(mlir::MLIRContext *mlirContext,
+                          const Fortran::semantics::Symbol &sym) {
+  fir::FortranVariableFlagsEnum flags = fir::FortranVariableFlagsEnum::None;
+  const auto &attrs = sym.attrs();
+  if (attrs.test(Fortran::semantics::Attr::ALLOCATABLE))
+    flags = flags | fir::FortranVariableFlagsEnum::allocatable;
+  if (attrs.test(Fortran::semantics::Attr::ASYNCHRONOUS))
+    flags = flags | fir::FortranVariableFlagsEnum::asynchronous;
+  if (attrs.test(Fortran::semantics::Attr::BIND_C))
+    flags = flags | fir::FortranVariableFlagsEnum::bind_c;
+  if (attrs.test(Fortran::semantics::Attr::CONTIGUOUS))
+    flags = flags | fir::FortranVariableFlagsEnum::contiguous;
+  if (attrs.test(Fortran::semantics::Attr::INTENT_IN))
+    flags = flags | fir::FortranVariableFlagsEnum::intent_in;
+  if (attrs.test(Fortran::semantics::Attr::INTENT_INOUT))
+    flags = flags | fir::FortranVariableFlagsEnum::intent_inout;
+  if (attrs.test(Fortran::semantics::Attr::INTENT_OUT))
+    flags = flags | fir::FortranVariableFlagsEnum::intent_out;
+  if (attrs.test(Fortran::semantics::Attr::OPTIONAL))
+    flags = flags | fir::FortranVariableFlagsEnum::optional;
+  if (attrs.test(Fortran::semantics::Attr::PARAMETER))
+    flags = flags | fir::FortranVariableFlagsEnum::parameter;
+  if (attrs.test(Fortran::semantics::Attr::POINTER))
+    flags = flags | fir::FortranVariableFlagsEnum::pointer;
+  if (attrs.test(Fortran::semantics::Attr::TARGET))
+    flags = flags | fir::FortranVariableFlagsEnum::target;
+  if (attrs.test(Fortran::semantics::Attr::VALUE))
+    flags = flags | fir::FortranVariableFlagsEnum::value;
+  if (attrs.test(Fortran::semantics::Attr::VOLATILE))
+    flags = flags | fir::FortranVariableFlagsEnum::fortran_volatile;
+  if (flags == fir::FortranVariableFlagsEnum::None)
+    return {};
+  return fir::FortranVariableFlagsAttr::get(mlirContext, flags);
+}
+
 /// Map a symbol to its FIR address and evaluated specification expressions.
 /// Not for symbols lowered to fir.box.
 /// Will optionally create fir.declare.
@@ -1303,9 +1339,29 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
                              llvm::ArrayRef<mlir::Value> shape = llvm::None,
                              llvm::ArrayRef<mlir::Value> lbounds = llvm::None,
                              bool force = false) {
-  if (converter.getLoweringOptions().getLowerToHighLevelFIR())
-    TODO(genLocation(converter, sym),
-         "generate fir.declare when lowering symbol");
+  if (converter.getLoweringOptions().getLowerToHighLevelFIR()) {
+    fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+    const mlir::Location loc = genLocation(converter, sym);
+    mlir::Value shapeOrShift;
+    if (!shape.empty() && !lbounds.empty())
+      shapeOrShift = builder.genShape(loc, shape, lbounds);
+    else if (!shape.empty())
+      shapeOrShift = builder.genShape(loc, shape);
+    else if (!lbounds.empty())
+      shapeOrShift = builder.genShift(loc, lbounds);
+    llvm::SmallVector<mlir::Value> lenParams;
+    if (len)
+      lenParams.emplace_back(len);
+    auto name = mlir::StringAttr::get(builder.getContext(),
+                                      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;
+    symMap.addVariableDefinition(sym, newBase);
+    return;
+  }
 
   if (len) {
     if (!shape.empty()) {

diff  --git a/flang/lib/Lower/SymbolMap.cpp b/flang/lib/Lower/SymbolMap.cpp
index c081c8aa1e7af..2862341ea61fc 100644
--- a/flang/lib/Lower/SymbolMap.cpp
+++ b/flang/lib/Lower/SymbolMap.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "flang/Lower/SymbolMap.h"
+#include "flang/Optimizer/Builder/Todo.h"
 #include "mlir/IR/BuiltinTypes.h"
 #include "llvm/Support/Debug.h"
 
@@ -30,6 +31,17 @@ void Fortran::lower::SymMap::addSymbol(Fortran::semantics::SymbolRef sym,
             });
 }
 
+Fortran::lower::SymbolBox toSymbolBox(
+    std::variant<Fortran::lower::SymbolBox, fir::FortranVariableOpInterface>
+        symboxOrdefiningOp) {
+  if (const Fortran::lower::SymbolBox *symBox =
+          std::get_if<Fortran::lower::SymbolBox>(&symboxOrdefiningOp))
+    return *symBox;
+  auto definingOp =
+      std::get<fir::FortranVariableOpInterface>(symboxOrdefiningOp);
+  TODO(definingOp.getLoc(), "FortranVariableOpInterface lookup as SymbolBox");
+}
+
 Fortran::lower::SymbolBox
 Fortran::lower::SymMap::lookupSymbol(Fortran::semantics::SymbolRef symRef) {
   Fortran::semantics::SymbolRef sym = symRef.get().GetUltimate();
@@ -37,7 +49,7 @@ Fortran::lower::SymMap::lookupSymbol(Fortran::semantics::SymbolRef symRef) {
        jmap != jend; ++jmap) {
     auto iter = jmap->find(&*sym);
     if (iter != jmap->end())
-      return iter->second;
+      return toSymbolBox(iter->second);
   }
   return SymbolBox::None{};
 }
@@ -47,7 +59,7 @@ Fortran::lower::SymbolBox Fortran::lower::SymMap::shallowLookupSymbol(
   auto &map = symbolMapStack.back();
   auto iter = map.find(&symRef.get().GetUltimate());
   if (iter != map.end())
-    return iter->second;
+    return toSymbolBox(iter->second);
   return SymbolBox::None{};
 }
 
@@ -65,7 +77,7 @@ Fortran::lower::SymbolBox Fortran::lower::SymMap::lookupOneLevelUpSymbol(
   for (++jmap; jmap != jend; ++jmap) {
     auto iter = jmap->find(&*sym);
     if (iter != jmap->end())
-      return iter->second;
+      return toSymbolBox(iter->second);
   }
   return SymbolBox::None{};
 }
@@ -92,15 +104,29 @@ Fortran::lower::operator<<(llvm::raw_ostream &os,
   return os;
 }
 
+static llvm::raw_ostream &
+dump(llvm::raw_ostream &os,
+     const std::variant<Fortran::lower::SymbolBox,
+                        fir::FortranVariableOpInterface> &symboxOrdefiningOp) {
+  if (const Fortran::lower::SymbolBox *symBox =
+          std::get_if<Fortran::lower::SymbolBox>(&symboxOrdefiningOp))
+    return os << *symBox;
+  auto definingOp =
+      std::get<fir::FortranVariableOpInterface>(symboxOrdefiningOp);
+  return os << definingOp << "\n";
+}
+
 llvm::raw_ostream &
 Fortran::lower::operator<<(llvm::raw_ostream &os,
                            const Fortran::lower::SymMap &symMap) {
   os << "Symbol map:\n";
   for (auto i : llvm::enumerate(symMap.symbolMapStack)) {
     os << " level " << i.index() << "<{\n";
-    for (auto iter : i.value())
+    for (auto iter : i.value()) {
       os << "  symbol @" << static_cast<const void *>(iter.first) << " ["
-         << *iter.first << "] ->\n    " << iter.second;
+         << *iter.first << "] ->\n    ";
+      dump(os, iter.second);
+    }
     os << " }>\n";
   }
   return os;

diff  --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index e4ff316316fc3..2d65d169621d8 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -392,6 +392,12 @@ mlir::Value fir::FirOpBuilder::genShape(mlir::Location loc,
   return genShape(loc, arr.getLBounds(), arr.getExtents());
 }
 
+mlir::Value fir::FirOpBuilder::genShift(mlir::Location loc,
+                                        llvm::ArrayRef<mlir::Value> shift) {
+  auto shiftType = fir::ShiftType::get(getContext(), shift.size());
+  return create<fir::ShiftOp>(loc, shiftType, shift);
+}
+
 mlir::Value fir::FirOpBuilder::createShape(mlir::Location loc,
                                            const fir::ExtendedValue &exv) {
   return exv.match(

diff  --git a/flang/test/Lower/HLFIR/convert-variable.f90 b/flang/test/Lower/HLFIR/convert-variable.f90
new file mode 100644
index 0000000000000..6c4623250341e
--- /dev/null
+++ b/flang/test/Lower/HLFIR/convert-variable.f90
@@ -0,0 +1,97 @@
+! Test lowering of variables to fir.declare
+! RUN: bbc -emit-fir -hlfir %s -o - | FileCheck %s
+
+subroutine scalar_numeric(x)
+  integer :: 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>
+
+subroutine scalar_character(c)
+  character(*) :: c
+end subroutine
+! 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,?>>
+
+subroutine scalar_character_cst_len(c)
+  character(10) :: c
+end subroutine
+! CHECK-LABEL: func.func @_QPscalar_character_cst_len(
+! 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,?>>
+
+subroutine array_numeric(x)
+  integer :: x(10, 20)
+end subroutine
+! CHECK-LABEL: func.func @_QParray_numeric(
+! CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.array<10x20xi32>>
+! 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>>
+
+
+subroutine array_numeric_lbounds(x)
+  integer :: x(-1:10, -2:20)
+end subroutine
+! CHECK-LABEL: func.func @_QParray_numeric_lbounds(
+! CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.array<12x23xi32>>
+! CHECK:  %[[VAL_1:.*]] = arith.constant -1 : index
+! 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>>
+
+subroutine array_character(c)
+  character(*) :: c(50)
+end subroutine
+! CHECK-LABEL: func.func @_QParray_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.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,?>>>
+
+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>
+
+subroutine scalar_numeric_attributes_2(x)
+  real(16), value :: x(100)
+end subroutine
+! CHECK-LABEL: func.func @_QPscalar_numeric_attributes_2(
+! 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>>
+
+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>
+
+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>>
+
+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>

diff  --git a/flang/test/Lower/HLFIR/expr-addr.f90 b/flang/test/Lower/HLFIR/expr-addr.f90
index 0ae9df50d9d8f..1af59e6cb0548 100644
--- a/flang/test/Lower/HLFIR/expr-addr.f90
+++ b/flang/test/Lower/HLFIR/expr-addr.f90
@@ -3,6 +3,6 @@
 
 subroutine foo(x)
   integer :: x
-  ! CHECK: not yet implemented: generate fir.declare when lowering symbol
+  ! CHECK: not yet implemented: lower expr to HLFIR address
   read (*,*) x
 end subroutine


        


More information about the flang-commits mailing list