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 { [](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 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 - + 1` case. auto diff = builder.create(loc, idxTy, ub, lb); mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); - return builder.create(loc, idxTy, diff, one); + auto rawExtent = builder.create(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 lowerBounds, - llvm::SmallVectorImpl &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 &lowerBounds, + llvm::SmallVectorImpl &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 lbounds; - llvm::SmallVector extents; + llvm::SmallVector explicitExtents; llvm::SmallVector 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(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( + loc, mlir::arith::CmpIPredicate::eq, extent, zero); + one = builder.createConvert(loc, lb.getType(), one); + return builder.create(loc, dimIsEmpty, one, lb); +} + // LBOUND fir::ExtendedValue IntrinsicLibrary::genLbound(mlir::Type resultType, llvm::ArrayRef 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()) + assert(args.size() > 0); + const fir::ExtendedValue &array = args[0]; + if (const auto *boxValue = array.getBoxOf()) 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(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(loc, lbAddrType, lbArray, index); + builder.create(loc, lb, lbAddr); + } + mlir::Value lbArrayExtent = + builder.createIntegerConstant(loc, indexType, rank); + llvm::SmallVector 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 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(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::isa_char(str.getType()); } -/// Unwrap integer constant from mlir::Value. -static llvm::Optional getIntIfConstant(mlir::Value value) { - if (auto *definingOp = value.getDefiningOp()) - if (auto cst = mlir::dyn_cast(definingOp)) - if (auto intAttr = cst.getValue().dyn_cast()) - 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 fir::factory::getIntIfConstant(mlir::Value value) { + if (auto *definingOp = value.getDefiningOp()) + if (auto cst = mlir::dyn_cast(definingOp)) + if (auto intAttr = cst.getValue().dyn_cast()) + 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>{{.*}}, %[[VAL_1:.*]]: !fir.ref>{{.*}}, %[[VAL_2:.*]]: !fir.ref{{.*}}, %[[VAL_3:.*]]: !fir.ref{{.*}}, %[[VAL_4:.*]]: !fir.ref{{.*}}) { ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_3]] : !fir.ref ! 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 ! 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>{{.*}}, %[[VAL_1:.*]]: !fir.ref>{{.*}}, %[[VAL_2:.*]]: !fir.ref{{.*}}) { ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]] : !fir.ref ! 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 ! 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.shape<1>) -> !fir.array ! 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.ref>> ! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_3]] : !fir.ref ! 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.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.ref>> ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_1]] : !fir.ref ! 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.shape<1>) -> !fir.box>> ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.box>>) -> !fir.box>> 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 ! CHECK: %[[ni:.*]] = fir.convert %[[n]] : (i32) -> index - ! CHECK: fir.alloca !fir.array>, %[[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>, %[[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 ! CHECK: %[[ni:.*]] = fir.convert %[[n]] : (i32) -> index - ! CHECK: fir.alloca !fir.array>(%[[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>(%[[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 ! 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>, %[[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 ! 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>(%[[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 ! 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 ! 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