[flang-commits] [flang] 07b8927 - [flang] Lower ArrayRef to hlfir.designate
Jean Perier via flang-commits
flang-commits at lists.llvm.org
Fri Nov 18 01:10:38 PST 2022
Author: Jean Perier
Date: 2022-11-18T10:09:12+01:00
New Revision: 07b89273949a8455aa805472e779f17e051736dd
URL: https://github.com/llvm/llvm-project/commit/07b89273949a8455aa805472e779f17e051736dd
DIFF: https://github.com/llvm/llvm-project/commit/07b89273949a8455aa805472e779f17e051736dd.diff
LOG: [flang] Lower ArrayRef to hlfir.designate
Also add support for fir.boxchar in HLFIRTools so that character
designator with none constant lengths can be processed/converted to
fir::ExtendedValue.
Differential Revision: https://reviews.llvm.org/D138190
Added:
flang/test/Lower/HLFIR/designators.f90
Modified:
flang/include/flang/Optimizer/Builder/HLFIRTools.h
flang/lib/Lower/ConvertExprToHLFIR.cpp
flang/lib/Optimizer/Builder/HLFIRTools.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
index 5a693152ae623..0bc868e7863e3 100644
--- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h
+++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
@@ -88,6 +88,10 @@ class Entity : public mlir::Value {
fir::isRecordWithTypeParameters(eleTy);
}
+ bool isCharacter() const {
+ return getFortranElementType().isa<fir::CharacterType>();
+ }
+
fir::FortranVariableOpInterface getIfVariableInterface() const {
return this->getDefiningOp<fir::FortranVariableOpInterface>();
}
@@ -135,9 +139,11 @@ translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder,
Entity entity);
/// Function to translate FortranVariableOpInterface to fir::ExtendedValue.
-/// It does not generate any IR, and is a simple packaging operation.
+/// It may generates IR to unbox fir.boxchar, but has otherwise no side effects
+/// on the IR.
fir::ExtendedValue
-translateToExtendedValue(fir::FortranVariableOpInterface fortranVariable);
+translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder,
+ fir::FortranVariableOpInterface fortranVariable);
/// Generate declaration for a fir::ExtendedValue in memory.
EntityWithAttributes genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
@@ -151,6 +157,15 @@ EntityWithAttributes genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
Entity loadTrivialScalar(mlir::Location loc, fir::FirOpBuilder &builder,
Entity entity);
+/// Compute the lower and upper bounds of an entity.
+llvm::SmallVector<std::pair<mlir::Value, mlir::Value>>
+genBounds(mlir::Location loc, fir::FirOpBuilder &builder, Entity entity);
+
+/// Read length parameters into result if this entity has any.
+void genLengthParameters(mlir::Location loc, fir::FirOpBuilder &builder,
+ Entity entity,
+ llvm::SmallVectorImpl<mlir::Value> &result);
+
} // namespace hlfir
#endif // FORTRAN_OPTIMIZER_BUILDER_HLFIRTOOLS_H
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index d09cd7c87f939..3153c5ad0dbc0 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -11,11 +11,13 @@
//===----------------------------------------------------------------------===//
#include "flang/Lower/ConvertExprToHLFIR.h"
+#include "flang/Evaluate/shape.h"
#include "flang/Lower/AbstractConverter.h"
#include "flang/Lower/ConvertConstant.h"
#include "flang/Lower/StatementContext.h"
#include "flang/Lower/SymbolMap.h"
#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/HLFIR/HLFIROps.h"
namespace {
@@ -34,51 +36,199 @@ class HlfirDesignatorBuilder {
Fortran::evaluate::TypeCategory::Character, 1>>::u);
hlfir::EntityWithAttributes
gen(const CharacterDesignators &designatorVariant) {
- return std::visit([&](const auto &x) { return gen(x); }, designatorVariant);
+ return std::visit(
+ [&](const auto &x) -> hlfir::EntityWithAttributes { return gen(x); },
+ designatorVariant);
}
// Character designators variant contains complex parts
using RealDesignators =
decltype(Fortran::evaluate::Designator<Fortran::evaluate::Type<
Fortran::evaluate::TypeCategory::Real, 4>>::u);
hlfir::EntityWithAttributes gen(const RealDesignators &designatorVariant) {
- return std::visit([&](const auto &x) { return gen(x); }, designatorVariant);
+ return std::visit(
+ [&](const auto &x) -> hlfir::EntityWithAttributes { return gen(x); },
+ designatorVariant);
}
// All other designators are similar
using OtherDesignators =
decltype(Fortran::evaluate::Designator<Fortran::evaluate::Type<
Fortran::evaluate::TypeCategory::Integer, 4>>::u);
hlfir::EntityWithAttributes gen(const OtherDesignators &designatorVariant) {
- return std::visit([&](const auto &x) { return gen(x); }, designatorVariant);
+ return std::visit(
+ [&](const auto &x) -> hlfir::EntityWithAttributes { return gen(x); },
+ designatorVariant);
}
private:
- hlfir::EntityWithAttributes
+ /// Struct that is filled while visiting a part-ref (in the "visit" member
+ /// function) before the top level "gen" generates an hlfir.declare for the
+ /// part ref. It contains the lowered pieces of the part-ref that will
+ /// become the operands of an hlfir.declare.
+ struct PartInfo {
+ fir::FortranVariableOpInterface base;
+ llvm::SmallVector<hlfir::DesignateOp::Subscript, 8> subscripts;
+ mlir::Value resultShape;
+ llvm::SmallVector<mlir::Value> typeParams;
+ };
+
+ /// Generate an hlfir.declare for a part-ref given a filled PartInfo and the
+ /// FIR type for this part-ref.
+ fir::FortranVariableOpInterface genDeclare(mlir::Type resultValueType,
+ PartInfo &partInfo) {
+ // Compute hlfir.declare result type.
+ // TODO: ensure polymorphic aspect of base of component will be
+ // preserved, as well as pointer/allocatable component aspects.
+ mlir::Type resultType;
+ /// Array sections may be non contiguous, so the output must be a box even
+ /// when the extents are static. This can be refined later for cases where
+ /// the output is know to be simply contiguous and that do not have lower
+ /// bounds.
+ auto charType = resultValueType.dyn_cast<fir::CharacterType>();
+ if (charType && charType.hasDynamicLen())
+ resultType =
+ fir::BoxCharType::get(charType.getContext(), charType.getFKind());
+ else if (resultValueType.isa<fir::SequenceType>() ||
+ fir::hasDynamicSize(resultValueType))
+ resultType = fir::BoxType::get(resultValueType);
+ else
+ resultType = fir::ReferenceType::get(resultValueType);
+
+ llvm::Optional<bool> complexPart;
+ llvm::SmallVector<mlir::Value> substring;
+ auto designate = getBuilder().create<hlfir::DesignateOp>(
+ getLoc(), resultType, partInfo.base.getBase(), "",
+ /*componentShape=*/mlir::Value{}, partInfo.subscripts, substring,
+ complexPart, partInfo.resultShape, partInfo.typeParams);
+ return mlir::cast<fir::FortranVariableOpInterface>(
+ designate.getOperation());
+ }
+
+ fir::FortranVariableOpInterface
gen(const Fortran::evaluate::SymbolRef &symbolRef) {
if (llvm::Optional<fir::FortranVariableOpInterface> varDef =
getSymMap().lookupVariableDefinition(symbolRef))
return *varDef;
TODO(getLoc(), "lowering symbol to HLFIR");
}
+
hlfir::EntityWithAttributes
gen(const Fortran::evaluate::Component &component) {
TODO(getLoc(), "lowering component to HLFIR");
}
+
hlfir::EntityWithAttributes gen(const Fortran::evaluate::ArrayRef &arrayRef) {
- TODO(getLoc(), "lowering ArrayRef to HLFIR");
+ PartInfo partInfo;
+ mlir::Type resultType = visit(arrayRef, partInfo);
+ return genDeclare(resultType, partInfo);
}
+
hlfir::EntityWithAttributes
gen(const Fortran::evaluate::CoarrayRef &coarrayRef) {
TODO(getLoc(), "lowering CoarrayRef to HLFIR");
}
+
hlfir::EntityWithAttributes
gen(const Fortran::evaluate::ComplexPart &complexPart) {
TODO(getLoc(), "lowering complex part to HLFIR");
}
+
hlfir::EntityWithAttributes
gen(const Fortran::evaluate::Substring &substring) {
TODO(getLoc(), "lowering substrings to HLFIR");
}
+ mlir::Type visit(const Fortran::evaluate::SymbolRef &symbolRef,
+ PartInfo &partInfo) {
+ partInfo.base = gen(symbolRef);
+ hlfir::genLengthParameters(getLoc(), getBuilder(), partInfo.base,
+ partInfo.typeParams);
+ return partInfo.base.getElementOrSequenceType();
+ }
+
+ mlir::Type visit(const Fortran::evaluate::ArrayRef &arrayRef,
+ PartInfo &partInfo) {
+ mlir::Type baseType;
+ if (const auto *component = arrayRef.base().UnwrapComponent())
+ baseType = visit(*component, partInfo);
+ baseType = visit(arrayRef.base().GetLastSymbol(), partInfo);
+
+ fir::FirOpBuilder &builder = getBuilder();
+ mlir::Location loc = getLoc();
+ mlir::Type idxTy = builder.getIndexType();
+ llvm::SmallVector<std::pair<mlir::Value, mlir::Value>> bounds;
+ auto getBounds = [&](unsigned i) {
+ if (bounds.empty())
+ bounds = hlfir::genBounds(loc, builder, partInfo.base);
+ return bounds[i];
+ };
+ auto frontEndResultShape =
+ Fortran::evaluate::GetShape(converter.getFoldingContext(), arrayRef);
+ llvm::SmallVector<mlir::Value> resultExtents;
+ fir::SequenceType::Shape resultTypeShape;
+ for (auto subscript : llvm::enumerate(arrayRef.subscript())) {
+ if (const auto *triplet =
+ std::get_if<Fortran::evaluate::Triplet>(&subscript.value().u)) {
+ mlir::Value lb, ub;
+ if (const auto &lbExpr = triplet->lower())
+ lb = genSubscript(*lbExpr);
+ else
+ lb = getBounds(subscript.index()).first;
+ if (const auto &ubExpr = triplet->upper())
+ ub = genSubscript(*ubExpr);
+ else
+ ub = getBounds(subscript.index()).second;
+ lb = builder.createConvert(loc, idxTy, lb);
+ ub = builder.createConvert(loc, idxTy, ub);
+ mlir::Value stride = genSubscript(triplet->stride());
+ stride = builder.createConvert(loc, idxTy, stride);
+ mlir::Value extent;
+ // Use constant extent if possible. The main advantage to do this now
+ // is to get the best FIR array types as possible while lowering.
+ if (frontEndResultShape)
+ if (auto maybeI64 = Fortran::evaluate::ToInt64(
+ frontEndResultShape->at(resultExtents.size()))) {
+ resultTypeShape.push_back(*maybeI64);
+ extent = builder.createIntegerConstant(loc, idxTy, *maybeI64);
+ }
+ if (!extent) {
+ extent = builder.genExtentFromTriplet(loc, lb, ub, stride, idxTy);
+ resultTypeShape.push_back(fir::SequenceType::getUnknownExtent());
+ }
+ partInfo.subscripts.emplace_back(
+ hlfir::DesignateOp::Triplet{lb, ub, stride});
+ resultExtents.push_back(extent);
+ } else {
+ const auto &expr =
+ std::get<Fortran::evaluate::IndirectSubscriptIntegerExpr>(
+ subscript.value().u)
+ .value();
+ if (expr.Rank() > 0)
+ TODO(getLoc(), "vector subscripts in HLFIR");
+ partInfo.subscripts.push_back(genSubscript(expr));
+ }
+ }
+
+ assert(resultExtents.size() == resultTypeShape.size() &&
+ "inconsistent hlfir.designate shape");
+ mlir::Type resultType = baseType.cast<fir::SequenceType>().getEleTy();
+ if (!resultTypeShape.empty()) {
+ resultType = fir::SequenceType::get(resultTypeShape, resultType);
+ partInfo.resultShape = builder.genShape(loc, resultExtents);
+ }
+ return resultType;
+ }
+
+ mlir::Type visit(const Fortran::evaluate::Component &component,
+ PartInfo &partInfo) {
+ TODO(getLoc(), "lowering component to HLFIR");
+ }
+
+ /// Lower a subscript expression. If it is a scalar subscript that is
+ /// a variable, it is loaded into an integer value.
+ template <typename T>
+ hlfir::EntityWithAttributes
+ genSubscript(const Fortran::evaluate::Expr<T> &expr);
+
mlir::Location getLoc() const { return loc; }
Fortran::lower::AbstractConverter &getConverter() { return converter; }
fir::FirOpBuilder &getBuilder() { return converter.getFirOpBuilder(); }
@@ -220,6 +370,28 @@ class HlfirBuilder {
mlir::Location loc;
};
+template <typename T>
+hlfir::EntityWithAttributes
+HlfirDesignatorBuilder::genSubscript(const Fortran::evaluate::Expr<T> &expr) {
+ auto loweredExpr =
+ HlfirBuilder(getLoc(), getConverter(), getSymMap(), getStmtCtx())
+ .gen(expr);
+ if (!loweredExpr.isArray()) {
+ fir::FirOpBuilder &builder = getBuilder();
+ if (loweredExpr.isVariable())
+ return hlfir::EntityWithAttributes{
+ hlfir::loadTrivialScalar(loc, builder, loweredExpr).getBase()};
+ // Skip constant conversions that litters designators and makes generated
+ // IR harder to read: directly use index constants for constant subscripts.
+ mlir::Type idxTy = builder.getIndexType();
+ if (loweredExpr.getType() != idxTy)
+ if (auto cstIndex = fir::factory::getIntIfConstant(loweredExpr))
+ return hlfir::EntityWithAttributes{
+ builder.createIntegerConstant(getLoc(), idxTy, *cstIndex)};
+ }
+ return loweredExpr;
+}
+
} // namespace
hlfir::EntityWithAttributes Fortran::lower::convertExprToHLFIR(
diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index cd88118717249..026e3fd317da3 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -69,10 +69,10 @@ getExplicitTypeParams(fir::FortranVariableOpInterface var) {
}
std::pair<fir::ExtendedValue, llvm::Optional<hlfir::CleanupFunction>>
-hlfir::translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &,
+hlfir::translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder,
hlfir::Entity entity) {
if (auto variable = entity.getIfVariableInterface())
- return {hlfir::translateToExtendedValue(variable), {}};
+ return {hlfir::translateToExtendedValue(loc, builder, variable), {}};
if (entity.isVariable())
TODO(loc, "HLFIR variable to fir::ExtendedValue without a "
"FortranVariableOpInterface");
@@ -90,7 +90,8 @@ mlir::Value hlfir::Entity::getFirBase() const {
}
fir::ExtendedValue
-hlfir::translateToExtendedValue(fir::FortranVariableOpInterface variable) {
+hlfir::translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder,
+ 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();
@@ -106,6 +107,13 @@ hlfir::translateToExtendedValue(fir::FortranVariableOpInterface variable) {
return fir::CharArrayBoxValue(firBase, variable.getExplicitCharLen(),
getExplicitExtents(variable),
getExplicitLbounds(variable));
+ if (auto boxCharType = firBase.getType().dyn_cast<fir::BoxCharType>()) {
+ auto unboxed = builder.create<fir::UnboxCharOp>(
+ loc, fir::ReferenceType::get(boxCharType.getEleTy()),
+ builder.getIndexType(), firBase);
+ return fir::CharBoxValue(unboxed.getResult(0),
+ variable.getExplicitCharLen());
+ }
return fir::CharBoxValue(firBase, variable.getExplicitCharLen());
}
if (variable.isArray())
@@ -165,3 +173,55 @@ hlfir::Entity hlfir::loadTrivialScalar(mlir::Location loc,
}
return entity;
}
+
+static mlir::Value genUBound(mlir::Location loc, fir::FirOpBuilder &builder,
+ mlir::Value lb, mlir::Value extent,
+ mlir::Value one) {
+ if (auto constantLb = fir::factory::getIntIfConstant(lb))
+ if (*constantLb == 1)
+ return extent;
+ extent = builder.createConvert(loc, one.getType(), extent);
+ lb = builder.createConvert(loc, one.getType(), lb);
+ auto add = builder.create<mlir::arith::AddIOp>(loc, lb, extent);
+ return builder.create<mlir::arith::SubIOp>(loc, add, one);
+}
+
+llvm::SmallVector<std::pair<mlir::Value, mlir::Value>>
+hlfir::genBounds(mlir::Location loc, fir::FirOpBuilder &builder,
+ Entity entity) {
+ if (entity.getType().isa<hlfir::ExprType>())
+ TODO(loc, "bounds of expressions in hlfir");
+ auto [exv, cleanup] = translateToExtendedValue(loc, builder, entity);
+ assert(!cleanup && "translation of entity should not yield cleanup");
+ if (const auto *mutableBox = exv.getBoxOf<fir::MutableBoxValue>())
+ exv = fir::factory::genMutableBoxRead(builder, loc, *mutableBox);
+ mlir::Type idxTy = builder.getIndexType();
+ mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
+ llvm::SmallVector<std::pair<mlir::Value, mlir::Value>> result;
+ for (unsigned dim = 0; dim < exv.rank(); ++dim) {
+ mlir::Value extent = fir::factory::readExtent(builder, loc, exv, dim);
+ mlir::Value lb = fir::factory::readLowerBound(builder, loc, exv, dim, one);
+ mlir::Value ub = genUBound(loc, builder, lb, extent, one);
+ result.push_back({lb, ub});
+ }
+ return result;
+}
+
+void hlfir::genLengthParameters(mlir::Location loc, fir::FirOpBuilder &builder,
+ Entity entity,
+ llvm::SmallVectorImpl<mlir::Value> &result) {
+ if (!entity.hasLengthParameters())
+ return;
+ if (entity.getType().isa<hlfir::ExprType>())
+ // Going through fir::ExtendedValue would create a temp,
+ // which is not desired for an inquiry.
+ TODO(loc, "inquire type parameters of hlfir.expr");
+
+ if (entity.isCharacter()) {
+ auto [exv, cleanup] = translateToExtendedValue(loc, builder, entity);
+ assert(!cleanup && "translation of entity should not yield cleanup");
+ result.push_back(fir::factory::readCharLen(builder, loc, exv));
+ return;
+ }
+ TODO(loc, "inquire PDTs length parameters in HLFIR");
+}
diff --git a/flang/test/Lower/HLFIR/designators.f90 b/flang/test/Lower/HLFIR/designators.f90
new file mode 100644
index 0000000000000..a2aaad536e19c
--- /dev/null
+++ b/flang/test/Lower/HLFIR/designators.f90
@@ -0,0 +1,114 @@
+! Test lowering of designators to HLFIR
+! RUN: bbc -emit-fir -hlfir -o - %s 2>&1 | FileCheck %s
+
+subroutine array_ref(x, n)
+ real :: x(:)
+ integer(8) :: n
+ print *, x(n)
+end subroutine
+! CHECK-LABEL: func.func @_QParray_ref(
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFarray_refEn"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>)
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFarray_refEx"} : (!fir.box<!fir.array<?xf32>>) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
+! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i64>
+! CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_9]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
+
+subroutine char_array_ref(x, n)
+ character(*) :: x(:)
+ print *, x(10)
+end subroutine
+! CHECK-LABEL: func.func @_QPchar_array_ref(
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFchar_array_refEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFchar_array_refEx"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>)
+! CHECK: %[[VAL_9:.*]] = fir.box_elesize %[[VAL_3]]#1 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> index
+! CHECK: %[[VAL_10:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_11:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_10]]) typeparams %[[VAL_9]] : (!fir.box<!fir.array<?x!fir.char<1,?>>>, index, index) -> !fir.boxchar<1>
+
+subroutine char_array_ref_cst_len(x, n)
+ character(5) :: x(:)
+ print *, x(10)
+end subroutine
+! CHECK-LABEL: func.func @_QPchar_array_ref_cst_len(
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFchar_array_ref_cst_lenEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_3:.*]] = arith.constant 5 : index
+! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_3]] {uniq_name = "_QFchar_array_ref_cst_lenEx"} : (!fir.box<!fir.array<?x!fir.char<1,5>>>, index) -> (!fir.box<!fir.array<?x!fir.char<1,5>>>, !fir.box<!fir.array<?x!fir.char<1,5>>>)
+! CHECK: %[[VAL_10:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_11:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_10]]) typeparams %[[VAL_3]] : (!fir.box<!fir.array<?x!fir.char<1,5>>>, index, index) -> !fir.ref<!fir.char<1,5>>
+
+subroutine array_section(x)
+ real :: x(10)
+ print *, x(2:8:3)
+end subroutine
+! CHECK-LABEL: func.func @_QParray_section(
+! CHECK: %[[VAL_1:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}}(%[[VAL_2]]) {uniq_name = "_QFarray_sectionEx"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
+! CHECK: %[[VAL_9:.*]] = arith.constant 2 : index
+! CHECK: %[[VAL_10:.*]] = arith.constant 8 : index
+! CHECK: %[[VAL_11:.*]] = arith.constant 3 : index
+! CHECK: %[[VAL_12:.*]] = arith.constant 3 : index
+! CHECK: %[[VAL_13:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_9]]:%[[VAL_10]]:%[[VAL_11]]) shape %[[VAL_13]] : (!fir.ref<!fir.array<10xf32>>, index, index, index, !fir.shape<1>) -> !fir.box<!fir.array<3xf32>>
+
+subroutine array_section_2(x, n)
+ real :: x(:)
+ integer(8) :: n
+ print *, x(n::3)
+end subroutine
+! CHECK-LABEL: func.func @_QParray_section_2(
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFarray_section_2En"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>)
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFarray_section_2Ex"} : (!fir.box<!fir.array<?xf32>>) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
+! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i64>
+! CHECK: %[[VAL_10:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_11:.*]]:3 = fir.box_dims %[[VAL_3]]#1, %[[VAL_10]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_9]] : (i64) -> index
+! CHECK: %[[VAL_13:.*]] = arith.constant 3 : index
+! CHECK: %[[VAL_14:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_11]]#1, %[[VAL_12]] : index
+! CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_15]], %[[VAL_13]] : index
+! CHECK: %[[VAL_17:.*]] = arith.divsi %[[VAL_16]], %[[VAL_13]] : index
+! CHECK: %[[VAL_18:.*]] = arith.cmpi sgt, %[[VAL_17]], %[[VAL_14]] : index
+! CHECK: %[[VAL_19:.*]] = arith.select %[[VAL_18]], %[[VAL_17]], %[[VAL_14]] : index
+! CHECK: %[[VAL_20:.*]] = fir.shape %[[VAL_19]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_12]]:%[[VAL_11]]#1:%[[VAL_13]]) shape %[[VAL_20]] : (!fir.box<!fir.array<?xf32>>, index, index, index, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
+
+subroutine char_array_section(x, n)
+ character(*) :: x(:)
+ print *, x(::3)
+end subroutine
+! CHECK-LABEL: func.func @_QPchar_array_section(
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFchar_array_sectionEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFchar_array_sectionEx"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>)
+! CHECK: %[[VAL_9:.*]] = fir.box_elesize %[[VAL_3]]#1 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> index
+! CHECK: %[[VAL_10:.*]] = arith.constant 1 : index
+! CHECK: %[[VAL_11:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_12:.*]]:3 = fir.box_dims %[[VAL_3]]#1, %[[VAL_11]] : (!fir.box<!fir.array<?x!fir.char<1,?>>>, index) -> (index, index, index)
+! CHECK: %[[VAL_13:.*]] = arith.constant 3 : index
+! CHECK: %[[VAL_14:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_12]]#1, %[[VAL_10]] : index
+! CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_15]], %[[VAL_13]] : index
+! CHECK: %[[VAL_17:.*]] = arith.divsi %[[VAL_16]], %[[VAL_13]] : index
+! CHECK: %[[VAL_18:.*]] = arith.cmpi sgt, %[[VAL_17]], %[[VAL_14]] : index
+! CHECK: %[[VAL_19:.*]] = arith.select %[[VAL_18]], %[[VAL_17]], %[[VAL_14]] : index
+! CHECK: %[[VAL_20:.*]] = fir.shape %[[VAL_19]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_10]]:%[[VAL_12]]#1:%[[VAL_13]]) shape %[[VAL_20]] typeparams %[[VAL_9]] : (!fir.box<!fir.array<?x!fir.char<1,?>>>, index, index, index, !fir.shape<1>, index) -> !fir.box<!fir.array<?x!fir.char<1,?>>>
+
+subroutine char_array_section_cst_len(x, n)
+ character(5) :: x(:)
+ print *, x(::3)
+end subroutine
+! CHECK-LABEL: func.func @_QPchar_array_section_cst_len(
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFchar_array_section_cst_lenEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_3:.*]] = arith.constant 5 : index
+! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_3]] {uniq_name = "_QFchar_array_section_cst_lenEx"} : (!fir.box<!fir.array<?x!fir.char<1,5>>>, index) -> (!fir.box<!fir.array<?x!fir.char<1,5>>>, !fir.box<!fir.array<?x!fir.char<1,5>>>)
+! CHECK: %[[VAL_10:.*]] = arith.constant 1 : index
+! CHECK: %[[VAL_11:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_12:.*]]:3 = fir.box_dims %[[VAL_4]]#1, %[[VAL_11]] : (!fir.box<!fir.array<?x!fir.char<1,5>>>, index) -> (index, index, index)
+! CHECK: %[[VAL_13:.*]] = arith.constant 3 : index
+! CHECK: %[[VAL_14:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_12]]#1, %[[VAL_10]] : index
+! CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_15]], %[[VAL_13]] : index
+! CHECK: %[[VAL_17:.*]] = arith.divsi %[[VAL_16]], %[[VAL_13]] : index
+! CHECK: %[[VAL_18:.*]] = arith.cmpi sgt, %[[VAL_17]], %[[VAL_14]] : index
+! CHECK: %[[VAL_19:.*]] = arith.select %[[VAL_18]], %[[VAL_17]], %[[VAL_14]] : index
+! CHECK: %[[VAL_20:.*]] = fir.shape %[[VAL_19]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_10]]:%[[VAL_12]]#1:%[[VAL_13]]) shape %[[VAL_20]] typeparams %[[VAL_3]] : (!fir.box<!fir.array<?x!fir.char<1,5>>>, index, index, index, !fir.shape<1>, index) -> !fir.box<!fir.array<?x!fir.char<1,5>>>
More information about the flang-commits
mailing list