[flang-commits] [flang] 5bc9ee1 - [flang][lowering] Handle zero extent case in LBOUND

Jean Perier via flang-commits flang-commits at lists.llvm.org
Fri Mar 25 10:07:15 PDT 2022


Author: Jean Perier
Date: 2022-03-25T18:05:54+01:00
New Revision: 5bc9ee1b780656c6d7f27c4ca657c5a7815311c1

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

LOG: [flang][lowering] Handle zero extent case in LBOUND

Follow up of https://reviews.llvm.org/D121488. Ensure lower bounds
are `1` when the related dimension extent is zero. Note that lower
bounds from descriptors are now guaranteed to fulfill this property
after the runtime/codegen patches.

Also fixes explicit shape array extent lowering when instantiating
variables to deal with negative extent cases (issue found while testing
LBOUND edge case). This notably caused allocation crashes when dealing
with automatic arrays with reversed bounds or negative size
specification expression. The standard specifies that the extent of such
arrays is zero. This change has some ripple effect in the current lit
tests.

Add move two helpers as part of this change:
- Add a helper to tell if a fir::ExtendedValue describes an assumed size
  array (last dimension extent is unknown to the compiler, both at compile
  time and runtime).

- Move and share getIntIfConstant from Character.cpp so that it can be
  used elsewhere (NFC).

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

Added: 
    

Modified: 
    flang/include/flang/Optimizer/Builder/BoxValue.h
    flang/include/flang/Optimizer/Builder/FIRBuilder.h
    flang/lib/Lower/ConvertVariable.cpp
    flang/lib/Lower/IntrinsicCall.cpp
    flang/lib/Optimizer/Builder/BoxValue.cpp
    flang/lib/Optimizer/Builder/Character.cpp
    flang/lib/Optimizer/Builder/FIRBuilder.cpp
    flang/test/Lower/array-expression.f90
    flang/test/Lower/call-parenthesized-arg.f90
    flang/test/Lower/character-local-variables.f90
    flang/test/Lower/forall/test9.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Builder/BoxValue.h b/flang/include/flang/Optimizer/Builder/BoxValue.h
index c81b7e61aadb4..55aaa6da69ff3 100644
--- a/flang/include/flang/Optimizer/Builder/BoxValue.h
+++ b/flang/include/flang/Optimizer/Builder/BoxValue.h
@@ -468,6 +468,9 @@ class ExtendedValue : public details::matcher<ExtendedValue> {
                  [](const auto &box) -> unsigned { return box.rank(); });
   }
 
+  /// Is this an assumed size array ?
+  bool isAssumedSize() const;
+
   /// LLVM style debugging of extended values
   LLVM_DUMP_METHOD void dump() const { llvm::errs() << *this << '\n'; }
 

diff  --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
index c2d42547f5eb6..fae5cfa7c52ec 100644
--- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
@@ -539,6 +539,9 @@ mlir::Value genLenOfCharacter(fir::FirOpBuilder &builder, mlir::Location loc,
 mlir::Value createZeroValue(fir::FirOpBuilder &builder, mlir::Location loc,
                             mlir::Type type);
 
+/// Unwrap integer constant from an mlir::Value.
+llvm::Optional<std::int64_t> getIntIfConstant(mlir::Value value);
+
 } // namespace fir::factory
 
 #endif // FORTRAN_OPTIMIZER_BUILDER_FIRBUILDER_H

diff  --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 361f23bd8d0b8..87ed2286f7630 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -1035,7 +1035,8 @@ static mlir::Value computeExtent(fir::FirOpBuilder &builder, mlir::Location loc,
   // Let the folder deal with the common `ub - <const> + 1` case.
   auto 
diff  = builder.create<mlir::arith::SubIOp>(loc, idxTy, ub, lb);
   mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
-  return builder.create<mlir::arith::AddIOp>(loc, idxTy, 
diff , one);
+  auto rawExtent = builder.create<mlir::arith::AddIOp>(loc, idxTy, 
diff , one);
+  return Fortran::lower::genMaxWithZero(builder, loc, rawExtent);
 }
 
 /// Lower explicit lower bounds into \p result. Does nothing if this is not an
@@ -1068,13 +1069,13 @@ static void lowerExplicitLowerBounds(
 /// Lower explicit extents into \p result if this is an explicit-shape or
 /// assumed-size array. Does nothing if this is not an explicit-shape or
 /// assumed-size array.
-static void lowerExplicitExtents(Fortran::lower::AbstractConverter &converter,
-                                 mlir::Location loc,
-                                 const Fortran::lower::BoxAnalyzer &box,
-                                 llvm::ArrayRef<mlir::Value> lowerBounds,
-                                 llvm::SmallVectorImpl<mlir::Value> &result,
-                                 Fortran::lower::SymMap &symMap,
-                                 Fortran::lower::StatementContext &stmtCtx) {
+static void
+lowerExplicitExtents(Fortran::lower::AbstractConverter &converter,
+                     mlir::Location loc, const Fortran::lower::BoxAnalyzer &box,
+                     llvm::SmallVectorImpl<mlir::Value> &lowerBounds,
+                     llvm::SmallVectorImpl<mlir::Value> &result,
+                     Fortran::lower::SymMap &symMap,
+                     Fortran::lower::StatementContext &stmtCtx) {
   if (!box.isArray())
     return;
   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
@@ -1090,7 +1091,7 @@ static void lowerExplicitExtents(Fortran::lower::AbstractConverter &converter,
       mlir::Value ub = builder.createConvert(
           loc, idxTy, genScalarValue(converter, loc, expr, symMap, stmtCtx));
       if (lowerBounds.empty())
-        result.emplace_back(ub);
+        result.emplace_back(Fortran::lower::genMaxWithZero(builder, loc, ub));
       else
         result.emplace_back(
             computeExtent(builder, loc, lowerBounds[spec.index()], ub));
@@ -1194,7 +1195,7 @@ void Fortran::lower::mapSymbolAttributes(
     mlir::Value dummyArg = symMap.lookupSymbol(sym).getAddr();
     if (lowerToBoxValue(sym, dummyArg)) {
       llvm::SmallVector<mlir::Value> lbounds;
-      llvm::SmallVector<mlir::Value> extents;
+      llvm::SmallVector<mlir::Value> explicitExtents;
       llvm::SmallVector<mlir::Value> explicitParams;
       // Lower lower bounds, explicit type parameters and explicit
       // extents if any.
@@ -1204,10 +1205,10 @@ void Fortran::lower::mapSymbolAttributes(
           explicitParams.push_back(len);
       // TODO: derived type length parameters.
       lowerExplicitLowerBounds(converter, loc, ba, lbounds, symMap, stmtCtx);
-      lowerExplicitExtents(converter, loc, ba, lbounds, extents, symMap,
+      lowerExplicitExtents(converter, loc, ba, lbounds, explicitExtents, symMap,
                            stmtCtx);
-      symMap.addBoxSymbol(sym, dummyArg, lbounds, explicitParams, extents,
-                          replace);
+      symMap.addBoxSymbol(sym, dummyArg, lbounds, explicitParams,
+                          explicitExtents, replace);
       return;
     }
   }
@@ -1229,7 +1230,8 @@ void Fortran::lower::mapSymbolAttributes(
       if (auto high = spec->ubound().GetExplicit()) {
         Fortran::lower::SomeExpr highEx{*high};
         mlir::Value ub = genValue(highEx);
-        shapes.emplace_back(builder.createConvert(loc, idxTy, ub));
+        ub = builder.createConvert(loc, idxTy, ub);
+        shapes.emplace_back(genMaxWithZero(builder, loc, ub));
       } else if (spec->ubound().isColon()) {
         assert(box && "assumed bounds require a descriptor");
         mlir::Value dim =
@@ -1276,16 +1278,15 @@ void Fortran::lower::mapSymbolAttributes(
         } else {
           TODO(loc, "assumed rank lowering");
         }
+        lbounds.emplace_back(lb);
 
         if (auto high = spec->ubound().GetExplicit()) {
           auto expr = Fortran::lower::SomeExpr{*high};
           ub = builder.createConvert(loc, idxTy, genValue(expr));
-          lbounds.emplace_back(lb);
           extents.emplace_back(computeExtent(builder, loc, lb, ub));
         } else {
           // An assumed size array. The extent is not computed.
           assert(spec->ubound().isStar() && "expected assumed size");
-          lbounds.emplace_back(lb);
           extents.emplace_back(builder.create<fir::UndefOp>(loc, idxTy));
         }
       }

diff  --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp
index 2b92e52841ea6..4685ac45837bc 100644
--- a/flang/lib/Lower/IntrinsicCall.cpp
+++ b/flang/lib/Lower/IntrinsicCall.cpp
@@ -3267,21 +3267,82 @@ IntrinsicLibrary::genSize(mlir::Type resultType,
       .getResults()[0];
 }
 
+static bool hasDefaultLowerBound(const fir::ExtendedValue &exv) {
+  return exv.match(
+      [](const fir::ArrayBoxValue &arr) { return arr.getLBounds().empty(); },
+      [](const fir::CharArrayBoxValue &arr) {
+        return arr.getLBounds().empty();
+      },
+      [](const fir::BoxValue &arr) { return arr.getLBounds().empty(); },
+      [](const auto &) { return false; });
+}
+
+/// Compute the lower bound in dimension \p dim (zero based) of \p array
+/// taking care of returning one when the related extent is zero.
+static mlir::Value computeLBOUND(fir::FirOpBuilder &builder, mlir::Location loc,
+                                 const fir::ExtendedValue &array, unsigned dim,
+                                 mlir::Value zero, mlir::Value one) {
+  assert(dim < array.rank() && "invalid dimension");
+  if (hasDefaultLowerBound(array))
+    return one;
+  mlir::Value lb = fir::factory::readLowerBound(builder, loc, array, dim, one);
+  if (dim + 1 == array.rank() && array.isAssumedSize())
+    return lb;
+  mlir::Value extent = fir::factory::readExtent(builder, loc, array, dim);
+  zero = builder.createConvert(loc, extent.getType(), zero);
+  auto dimIsEmpty = builder.create<mlir::arith::CmpIOp>(
+      loc, mlir::arith::CmpIPredicate::eq, extent, zero);
+  one = builder.createConvert(loc, lb.getType(), one);
+  return builder.create<mlir::arith::SelectOp>(loc, dimIsEmpty, one, lb);
+}
+
 // LBOUND
 fir::ExtendedValue
 IntrinsicLibrary::genLbound(mlir::Type resultType,
                             llvm::ArrayRef<fir::ExtendedValue> args) {
-  // Calls to LBOUND that don't have the DIM argument, or for which
-  // the DIM is a compile time constant, are folded to descriptor inquiries by
-  // semantics.  This function covers the situations where a call to the
-  // runtime is required.
-  assert(args.size() == 3);
-  assert(!isAbsent(args[1]));
-  if (const auto *boxValue = args[0].getBoxOf<fir::BoxValue>())
+  assert(args.size() > 0);
+  const fir::ExtendedValue &array = args[0];
+  if (const auto *boxValue = array.getBoxOf<fir::BoxValue>())
     if (boxValue->hasAssumedRank())
       TODO(loc, "LBOUND intrinsic with assumed rank argument");
 
-  const fir::ExtendedValue &array = args[0];
+  //===----------------------------------------------------------------------===//
+  mlir::Type indexType = builder.getIndexType();
+
+  if (isAbsent(args, 1)) {
+    mlir::Type lbType = fir::unwrapSequenceType(resultType);
+    unsigned rank = array.rank();
+    mlir::Type lbArrayType = fir::SequenceType::get(
+        {static_cast<fir::SequenceType::Extent>(array.rank())}, lbType);
+    mlir::Value lbArray = builder.createTemporary(loc, lbArrayType);
+    mlir::Type lbAddrType = builder.getRefType(lbType);
+    mlir::Value one = builder.createIntegerConstant(loc, lbType, 1);
+    mlir::Value zero = builder.createIntegerConstant(loc, indexType, 0);
+    for (unsigned dim = 0; dim < rank; ++dim) {
+      mlir::Value lb = computeLBOUND(builder, loc, array, dim, zero, one);
+      lb = builder.createConvert(loc, lbType, lb);
+      auto index = builder.createIntegerConstant(loc, indexType, dim);
+      auto lbAddr =
+          builder.create<fir::CoordinateOp>(loc, lbAddrType, lbArray, index);
+      builder.create<fir::StoreOp>(loc, lb, lbAddr);
+    }
+    mlir::Value lbArrayExtent =
+        builder.createIntegerConstant(loc, indexType, rank);
+    llvm::SmallVector<mlir::Value> extents{lbArrayExtent};
+    return fir::ArrayBoxValue{lbArray, extents};
+  }
+  // DIM is present.
+  mlir::Value dim = fir::getBase(args[1]);
+
+  // If it is a compile time constant, skip the runtime call.
+  if (llvm::Optional<std::int64_t> cstDim =
+          fir::factory::getIntIfConstant(dim)) {
+    mlir::Value one = builder.createIntegerConstant(loc, resultType, 1);
+    mlir::Value zero = builder.createIntegerConstant(loc, indexType, 0);
+    mlir::Value lb = computeLBOUND(builder, loc, array, *cstDim - 1, zero, one);
+    return builder.createConvert(loc, resultType, lb);
+  }
+
   mlir::Value box = array.match(
       [&](const fir::BoxValue &boxValue) -> mlir::Value {
         // This entity is mapped to a fir.box that may not contain the local
@@ -3301,7 +3362,6 @@ IntrinsicLibrary::genLbound(mlir::Type resultType,
         return builder.createBox(loc, array);
       });
 
-  mlir::Value dim = fir::getBase(args[1]);
   return builder.createConvert(
       loc, resultType,
       fir::runtime::genLboundDim(builder, loc, fir::getBase(box), dim));

diff  --git a/flang/lib/Optimizer/Builder/BoxValue.cpp b/flang/lib/Optimizer/Builder/BoxValue.cpp
index dc64276621b8e..951bc3e18bc49 100644
--- a/flang/lib/Optimizer/Builder/BoxValue.cpp
+++ b/flang/lib/Optimizer/Builder/BoxValue.cpp
@@ -230,3 +230,19 @@ mlir::Value fir::getExtentAtDimension(const fir::ExtendedValue &exv,
     return extents[dim];
   return {};
 }
+
+static inline bool isUndefOp(mlir::Value v) {
+  return mlir::isa_and_nonnull<fir::UndefOp>(v.getDefiningOp());
+}
+
+bool fir::ExtendedValue::isAssumedSize() const {
+  return match(
+      [](const fir::ArrayBoxValue &box) -> bool {
+        return !box.getExtents().empty() && isUndefOp(box.getExtents().back());
+        ;
+      },
+      [](const fir::CharArrayBoxValue &box) -> bool {
+        return !box.getExtents().empty() && isUndefOp(box.getExtents().back());
+      },
+      [](const auto &box) -> bool { return false; });
+}

diff  --git a/flang/lib/Optimizer/Builder/Character.cpp b/flang/lib/Optimizer/Builder/Character.cpp
index 97ccea0bb2850..4a90a697aca51 100644
--- a/flang/lib/Optimizer/Builder/Character.cpp
+++ b/flang/lib/Optimizer/Builder/Character.cpp
@@ -94,15 +94,6 @@ LLVM_ATTRIBUTE_UNUSED static bool needToMaterialize(mlir::Value str) {
   return str.getType().isa<fir::SequenceType>() || fir::isa_char(str.getType());
 }
 
-/// Unwrap integer constant from mlir::Value.
-static llvm::Optional<std::int64_t> getIntIfConstant(mlir::Value value) {
-  if (auto *definingOp = value.getDefiningOp())
-    if (auto cst = mlir::dyn_cast<mlir::arith::ConstantOp>(definingOp))
-      if (auto intAttr = cst.getValue().dyn_cast<mlir::IntegerAttr>())
-        return intAttr.getInt();
-  return {};
-}
-
 /// This is called only if `str` does not reside in memory. Such a bare string
 /// value will be converted into a memory-based temporary and an extended
 /// boxchar value returned.

diff  --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index d30eadf47a9d1..b53d79e61f897 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -1135,3 +1135,11 @@ mlir::Value fir::factory::createZeroValue(fir::FirOpBuilder &builder,
   fir::emitFatalError(loc, "internal: trying to generate zero value of non "
                            "numeric or logical type");
 }
+
+llvm::Optional<std::int64_t> fir::factory::getIntIfConstant(mlir::Value value) {
+  if (auto *definingOp = value.getDefiningOp())
+    if (auto cst = mlir::dyn_cast<mlir::arith::ConstantOp>(definingOp))
+      if (auto intAttr = cst.getValue().dyn_cast<mlir::IntegerAttr>())
+        return intAttr.getInt();
+  return {};
+}

diff  --git a/flang/test/Lower/array-expression.f90 b/flang/test/Lower/array-expression.f90
index d268301b09648..8bc5a5d1b88cf 100644
--- a/flang/test/Lower/array-expression.f90
+++ b/flang/test/Lower/array-expression.f90
@@ -115,10 +115,16 @@ end subroutine test5
 ! CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.array<?xf32>>{{.*}}, %[[VAL_1:.*]]: !fir.ref<!fir.array<?xf32>>{{.*}}, %[[VAL_2:.*]]: !fir.ref<f32>{{.*}}, %[[VAL_3:.*]]: !fir.ref<i32>{{.*}}, %[[VAL_4:.*]]: !fir.ref<i32>{{.*}}) {
 ! CHECK:         %[[VAL_5:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32>
 ! CHECK:         %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i32) -> i64
-! CHECK:         %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i64) -> index
+! CHECK:         %[[VAL_7A:.*]] = fir.convert %[[VAL_6]] : (i64) -> index
+! CHECK:         %[[C0:.*]] = arith.constant 0 : index 
+! CHECK:         %[[CMP:.*]] = arith.cmpi sgt, %[[VAL_7A]], %[[C0]] : index 
+! CHECK:         %[[VAL_7:.*]] = arith.select %[[CMP]], %[[VAL_7A]], %[[C0]] : index 
 ! CHECK:         %[[VAL_8:.*]] = fir.load %[[VAL_4]] : !fir.ref<i32>
 ! CHECK:         %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i32) -> i64
-! CHECK:         %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i64) -> index
+! CHECK:         %[[VAL_10A:.*]] = fir.convert %[[VAL_9]] : (i64) -> index
+! CHECK:         %[[C0_2:.*]] = arith.constant 0 : index 
+! CHECK:         %[[CMP_2:.*]] = arith.cmpi sgt, %[[VAL_10A]], %[[C0_2]] : index 
+! CHECK:         %[[VAL_10:.*]] = arith.select %[[CMP_2]], %[[VAL_10A]], %[[C0_2]] : index 
 ! CHECK:         %[[VAL_11:.*]] = arith.constant 3 : i64
 ! CHECK:         %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (i64) -> index
 ! CHECK:         %[[VAL_13:.*]] = arith.constant 4 : i64
@@ -248,10 +254,16 @@ end subroutine test6b
 ! CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.array<?xf32>>{{.*}}, %[[VAL_1:.*]]: !fir.ref<!fir.array<?xf32>>{{.*}}, %[[VAL_2:.*]]: !fir.ref<i32>{{.*}}) {
 ! CHECK:         %[[VAL_3:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>
 ! CHECK:         %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i32) -> i64
-! CHECK:         %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i64) -> index
+! CHECK:         %[[VAL_5A:.*]] = fir.convert %[[VAL_4]] : (i64) -> index
+! CHECK:         %[[C0:.*]] = arith.constant 0 : index 
+! CHECK:         %[[CMP:.*]] = arith.cmpi sgt, %[[VAL_5A]], %[[C0]] : index 
+! CHECK:         %[[VAL_5:.*]] = arith.select %[[CMP]], %[[VAL_5A]], %[[C0]] : index 
 ! CHECK:         %[[VAL_6:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>
 ! CHECK:         %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i32) -> i64
-! CHECK:         %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i64) -> index
+! CHECK:         %[[VAL_8A:.*]] = fir.convert %[[VAL_7]] : (i64) -> index
+! CHECK:         %[[C0_2:.*]] = arith.constant 0 : index 
+! CHECK:         %[[CMP_2:.*]] = arith.cmpi sgt, %[[VAL_8A]], %[[C0_2]] : index 
+! CHECK:         %[[VAL_8:.*]] = arith.select %[[CMP_2]], %[[VAL_8A]], %[[C0_2]] : index 
 ! CHECK:         %[[VAL_9:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1>
 ! CHECK:         %[[VAL_10:.*]] = fir.array_load %[[VAL_0]](%[[VAL_9]]) : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.array<?xf32>
 ! CHECK:         %[[VAL_11:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1>
@@ -1052,7 +1064,10 @@ end subroutine test19g
 ! CHECK:         %[[VAL_12:.*]] = fir.convert %[[VAL_11]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<?x!fir.char<1,?>>>
 ! CHECK:         %[[VAL_13:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32>
 ! CHECK:         %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (i32) -> i64
-! CHECK:         %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i64) -> index
+! CHECK:         %[[VAL_15A:.*]] = fir.convert %[[VAL_14]] : (i64) -> index
+! CHECK:         %[[C0:.*]] = arith.constant 0 : index 
+! CHECK:         %[[CMP:.*]] = arith.cmpi sgt, %[[VAL_15A]], %[[C0]] : index 
+! CHECK:         %[[VAL_15:.*]] = arith.select %[[CMP]], %[[VAL_15A]], %[[C0]] : index 
 ! CHECK:         %[[VAL_16:.*]] = fir.shape %[[VAL_10]] : (index) -> !fir.shape<1>
 ! CHECK:         %[[VAL_17:.*]] = fir.array_load %[[VAL_9]](%[[VAL_16]]) typeparams %[[VAL_8]] : (!fir.ref<!fir.array<70x!fir.char<1,?>>>, !fir.shape<1>, i32) -> !fir.array<70x!fir.char<1,?>>
 ! CHECK:         %[[VAL_18:.*]] = arith.constant 1 : i64

diff  --git a/flang/test/Lower/call-parenthesized-arg.f90 b/flang/test/Lower/call-parenthesized-arg.f90
index 3454b8b8541dd..92b6706f5ea49 100644
--- a/flang/test/Lower/call-parenthesized-arg.f90
+++ b/flang/test/Lower/call-parenthesized-arg.f90
@@ -172,7 +172,10 @@ subroutine foo_char_array_box(x, n)
   ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<?x!fir.char<1,10>>>
   ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32>
   ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> i64
-  ! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i64) -> index
+  ! CHECK: %[[VAL_6A:.*]] = fir.convert %[[VAL_5]] : (i64) -> index
+  ! CHECK: %[[C0:.*]] = arith.constant 0 : index 
+  ! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[VAL_6A]], %[[C0]] : index 
+  ! CHECK: %[[VAL_6:.*]] = arith.select %[[CMP]], %[[VAL_6A]], %[[C0]] : index 
   ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
   ! CHECK: %[[VAL_8:.*]] = fir.embox %[[VAL_3]](%[[VAL_7]]) : (!fir.ref<!fir.array<?x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.box<!fir.array<?x!fir.char<1,10>>>
   ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<!fir.array<?x!fir.char<1,?>>>

diff  --git a/flang/test/Lower/character-local-variables.f90 b/flang/test/Lower/character-local-variables.f90
index 555f11edd0b03..c281d8284ef97 100644
--- a/flang/test/Lower/character-local-variables.f90
+++ b/flang/test/Lower/character-local-variables.f90
@@ -43,7 +43,9 @@ subroutine dyn_array_cst_len(n)
   character(10) :: c(n)
   ! CHECK: %[[n:.*]] = fir.load %[[arg0]] : !fir.ref<i32>
   ! CHECK: %[[ni:.*]] = fir.convert %[[n]] : (i32) -> index
-  ! CHECK: fir.alloca !fir.array<?x!fir.char<1,10>>, %[[ni]] {{{.*}}uniq_name = "_QFdyn_array_cst_lenEc"}
+  ! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[ni]], %c0{{.*}} : index
+  ! CHECK: %[[extent:.*]] = arith.select %[[is_positive]], %[[ni]], %c0{{.*}} : index
+  ! CHECK: fir.alloca !fir.array<?x!fir.char<1,10>>, %[[extent]] {{{.*}}uniq_name = "_QFdyn_array_cst_lenEc"}
 end subroutine
 
 ! CHECK: func @_QPdyn_array_dyn_len
@@ -56,7 +58,9 @@ subroutine dyn_array_dyn_len(l, n)
   ! CHECK-DAG: %[[l:.*]] = arith.select %[[is_positive]], %[[lexpr]], %c0{{.*}} : i32
   ! CHECK-DAG: %[[n:.*]] = fir.load %[[arg1]] : !fir.ref<i32>
   ! CHECK: %[[ni:.*]] = fir.convert %[[n]] : (i32) -> index
-  ! CHECK: fir.alloca !fir.array<?x!fir.char<1,?>>(%[[l]] : i32), %[[ni]] {{{.*}}uniq_name = "_QFdyn_array_dyn_lenEc"}
+  ! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[ni]], %c0{{.*}} : index
+  ! CHECK: %[[extent:.*]] = arith.select %[[is_positive]], %[[ni]], %c0{{.*}} : index
+  ! CHECK: fir.alloca !fir.array<?x!fir.char<1,?>>(%[[l]] : i32), %[[extent]] {{{.*}}uniq_name = "_QFdyn_array_dyn_lenEc"}
 end subroutine
 
 ! CHECK-LABEL: func @_QPcst_array_cst_len_lb
@@ -84,7 +88,9 @@ subroutine dyn_array_cst_len_lb(n)
   ! CHECK-DAG: %[[cm10:.*]] = arith.constant -10 : index
   ! CHECK-DAG: %[[n:.*]] = fir.load %[[arg0]] : !fir.ref<i64>
   ! CHECK-DAG: %[[ni:.*]] = fir.convert %[[n]] : (i64) -> index
-  ! CHECK: %[[extent:.*]] = arith.addi %[[ni]], %[[cm10]] : index
+  ! CHECK: %[[raw_extent:.*]] = arith.addi %[[ni]], %[[cm10]] : index
+  ! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[raw_extent]], %c0{{.*}} : index
+  ! CHECK: %[[extent:.*]] = arith.select %[[is_positive]], %[[raw_extent]], %c0{{.*}} : index
   ! CHECK: fir.alloca !fir.array<?x!fir.char<1,10>>, %[[extent]] {{{.*}}uniq_name = "_QFdyn_array_cst_len_lbEc"}
 end subroutine
 
@@ -99,7 +105,9 @@ subroutine dyn_array_dyn_len_lb(l, n)
   ! CHECK-DAG: %[[l:.*]] = arith.select %[[is_positive]], %[[lexpr]], %c0{{.*}} : i64
   ! CHECK-DAG: %[[n:.*]] = fir.load %[[arg1]] : !fir.ref<i64>
   ! CHECK-DAG: %[[ni:.*]] = fir.convert %[[n]] : (i64) -> index
-  ! CHECK: %[[extent:.*]] = arith.addi %[[ni]], %[[cm10]] : index
+  ! CHECK: %[[raw_extent:.*]] = arith.addi %[[ni]], %[[cm10]] : index
+  ! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[raw_extent]], %c0{{.*}} : index
+  ! CHECK: %[[extent:.*]] = arith.select %[[is_positive]], %[[raw_extent]], %c0{{.*}} : index
   ! CHECK: fir.alloca !fir.array<?x!fir.char<1,?>>(%[[l]] : i64), %[[extent]] {{{.*}}uniq_name = "_QFdyn_array_dyn_len_lbEc"}
 end subroutine
 

diff  --git a/flang/test/Lower/forall/test9.f90 b/flang/test/Lower/forall/test9.f90
index 1d20cad06feed..6ac862b5cb39d 100644
--- a/flang/test/Lower/forall/test9.f90
+++ b/flang/test/Lower/forall/test9.f90
@@ -20,10 +20,16 @@ end subroutine test9
 ! CHECK:         %[[VAL_3:.*]] = fir.alloca i32 {adapt.valuebyref, bindc_name = "i"}
 ! CHECK:         %[[VAL_4:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>
 ! CHECK:         %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> i64
-! CHECK:         %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i64) -> index
+! CHECK:         %[[VAL_6A:.*]] = fir.convert %[[VAL_5]] : (i64) -> index
+! CHECK:         %[[C0:.*]] = arith.constant 0 : index
+! CHECK:         %[[CMP:.*]] = arith.cmpi sgt, %[[VAL_6A]], %[[C0]] : index
+! CHECK:         %[[VAL_6:.*]] = arith.select %[[CMP]], %[[VAL_6A]], %[[C0]] : index
 ! CHECK:         %[[VAL_7:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>
 ! CHECK:         %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i32) -> i64
-! CHECK:         %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i64) -> index
+! CHECK:         %[[VAL_9A:.*]] = fir.convert %[[VAL_8]] : (i64) -> index
+! CHECK:         %[[C0_2:.*]] = arith.constant 0 : index
+! CHECK:         %[[CMP_2:.*]] = arith.cmpi sgt, %[[VAL_9A]], %[[C0_2]] : index
+! CHECK:         %[[VAL_9:.*]] = arith.select %[[CMP_2]], %[[VAL_9A]], %[[C0_2]] : index
 ! CHECK:         %[[VAL_10:.*]] = arith.constant 1 : i32
 ! CHECK:         %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (i32) -> index
 ! CHECK:         %[[VAL_12:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>


        


More information about the flang-commits mailing list