[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