[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