From d0018c959a30150aa923fb458c5d21cd284120d4 Mon Sep 17 00:00:00 2001 From: Jean Perier Date: Tue, 20 Dec 2022 08:46:45 +0100 Subject: [PATCH] [flang] Finish substring lowering Hlfir.designate was made to support substrings but so far substrings were not yet lowered to it. Implement support for them. Differential Revision: https://reviews.llvm.org/D140310 --- flang/include/flang/Optimizer/Builder/Character.h | 7 ++ flang/include/flang/Optimizer/Builder/HLFIRTools.h | 14 ++- flang/lib/Lower/ConvertExprToHLFIR.cpp | 136 ++++++++++++++++++++- flang/lib/Optimizer/Builder/Character.cpp | 19 ++- flang/lib/Optimizer/Builder/HLFIRTools.cpp | 10 +- .../Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp | 3 +- .../Optimizer/HLFIR/Transforms/ConvertToFIR.cpp | 58 ++++++--- flang/test/Lower/HLFIR/substrings.f90 | 114 +++++++++++++++++ .../unittests/Optimizer/Builder/HLFIRToolsTest.cpp | 3 +- 9 files changed, 327 insertions(+), 37 deletions(-) create mode 100644 flang/test/Lower/HLFIR/substrings.f90 diff --git a/flang/include/flang/Optimizer/Builder/Character.h b/flang/include/flang/Optimizer/Builder/Character.h index fca2136..820c64f 100644 --- a/flang/include/flang/Optimizer/Builder/Character.h +++ b/flang/include/flang/Optimizer/Builder/Character.h @@ -47,6 +47,13 @@ public: fir::CharBoxValue createSubstring(const fir::CharBoxValue &str, llvm::ArrayRef bounds); + /// Compute substring base address given the raw address (not fir.boxchar) of + /// a scalar string, a substring / lower bound, and the substring type. + mlir::Value genSubstringBase(mlir::Value stringRawAddr, + mlir::Value lowerBound, + mlir::Type substringAddrType, + mlir::Value one = {}); + /// Return blank character of given \p type !fir.char mlir::Value createBlankConstant(fir::CharacterType type); diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h index 0cdac83..d83766c 100644 --- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h +++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h @@ -174,10 +174,11 @@ 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, - const fir::ExtendedValue &exv, - llvm::StringRef name, - fir::FortranVariableFlagsAttr flags); +fir::FortranVariableOpInterface genDeclare(mlir::Location loc, + fir::FirOpBuilder &builder, + const fir::ExtendedValue &exv, + llvm::StringRef name, + fir::FortranVariableFlagsAttr flags); /// Generate an hlfir.associate to build a variable from an expression value. /// The type of the variable must be provided so that scalar logicals are @@ -238,6 +239,11 @@ void genLengthParameters(mlir::Location loc, fir::FirOpBuilder &builder, Entity entity, llvm::SmallVectorImpl &result); +/// Get the length of a character entity. Crashes if the entity is not +/// a character entity. +mlir::Value genCharLength(mlir::Location loc, fir::FirOpBuilder &builder, + Entity entity); + /// Return the fir base, shape, and type parameters for a variable. Note that /// type parameters are only added if the entity is not a box and the type /// parameters is not a constant in the base type. This matches the arguments diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp index 7a772a1..87c1eca 100644 --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -24,6 +24,7 @@ #include "flang/Optimizer/Builder/Runtime/Character.h" #include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" +#include "llvm/ADT/TypeSwitch.h" namespace { @@ -65,6 +66,13 @@ public: designatorVariant); } + hlfir::EntityWithAttributes + gen(const Fortran::evaluate::NamedEntity &namedEntity) { + if (namedEntity.IsSymbol()) + return gen(Fortran::evaluate::SymbolRef{namedEntity.GetLastSymbol()}); + return gen(namedEntity.GetComponent()); + } + private: /// 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 @@ -75,6 +83,7 @@ private: hlfir::DesignateOp::Subscripts subscripts; mlir::Value resultShape; llvm::SmallVector typeParams; + llvm::SmallVector substring; }; /// Generate an hlfir.declare for a part-ref given a filled PartInfo and the @@ -100,11 +109,11 @@ private: resultType = fir::ReferenceType::get(resultValueType); std::optional complexPart; - llvm::SmallVector substring; auto designate = getBuilder().create( getLoc(), resultType, partInfo.base.getBase(), "", - /*componentShape=*/mlir::Value{}, partInfo.subscripts, substring, - complexPart, partInfo.resultShape, partInfo.typeParams); + /*componentShape=*/mlir::Value{}, partInfo.subscripts, + partInfo.substring, complexPart, partInfo.resultShape, + partInfo.typeParams); return mlir::cast( designate.getOperation()); } @@ -132,6 +141,9 @@ private: gen(const Fortran::evaluate::CoarrayRef &coarrayRef) { TODO(getLoc(), "lowering CoarrayRef to HLFIR"); } + mlir::Type visit(const Fortran::evaluate::CoarrayRef &, PartInfo &) { + TODO(getLoc(), "lowering CoarrayRef to HLFIR"); + } hlfir::EntityWithAttributes gen(const Fortran::evaluate::ComplexPart &complexPart) { @@ -140,7 +152,95 @@ private: hlfir::EntityWithAttributes gen(const Fortran::evaluate::Substring &substring) { - TODO(getLoc(), "lowering substrings to HLFIR"); + PartInfo partInfo; + mlir::Type baseStringType = std::visit( + [&](const auto &x) { return visit(x, partInfo); }, substring.parent()); + assert(partInfo.typeParams.size() == 1 && "expect base string length"); + // Compute the substring lower and upper bound. + partInfo.substring.push_back(genSubscript(substring.lower())); + if (Fortran::evaluate::MaybeExtentExpr upperBound = substring.upper()) + partInfo.substring.push_back(genSubscript(*upperBound)); + else + partInfo.substring.push_back(partInfo.typeParams[0]); + fir::FirOpBuilder &builder = getBuilder(); + mlir::Location loc = getLoc(); + mlir::Type idxTy = builder.getIndexType(); + partInfo.substring[0] = + builder.createConvert(loc, idxTy, partInfo.substring[0]); + partInfo.substring[1] = + builder.createConvert(loc, idxTy, partInfo.substring[1]); + // Try using constant length if available. mlir::arith folding would + // most likely be able to fold "max(ub-lb+1,0)" too, but getting + // the constant length in the FIR types would be harder. + std::optional cstLen = + Fortran::evaluate::ToInt64(Fortran::evaluate::Fold( + getConverter().getFoldingContext(), substring.LEN())); + if (cstLen) { + partInfo.typeParams[0] = + builder.createIntegerConstant(loc, idxTy, *cstLen); + } else { + // Compute "len = max(ub-lb+1,0)" (Fortran 2018 9.4.1). + mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); + auto boundsDiff = builder.create( + loc, partInfo.substring[1], partInfo.substring[0]); + auto rawLen = builder.create(loc, boundsDiff, one); + partInfo.typeParams[0] = + fir::factory::genMaxWithZero(builder, loc, rawLen); + } + mlir::Type resultType = changeLengthInCharacterType( + loc, baseStringType, + cstLen ? *cstLen : fir::CharacterType::unknownLen()); + return genDeclare(resultType, partInfo); + } + + static mlir::Type changeLengthInCharacterType(mlir::Location loc, + mlir::Type type, + int64_t newLen) { + return llvm::TypeSwitch(type) + .Case([&](fir::CharacterType charTy) -> mlir::Type { + return fir::CharacterType::get(charTy.getContext(), charTy.getFKind(), + newLen); + }) + .Case([&](fir::SequenceType seqTy) -> mlir::Type { + return fir::SequenceType::get( + seqTy.getShape(), + changeLengthInCharacterType(loc, seqTy.getEleTy(), newLen)); + }) + .Case([&](auto t) -> mlir::Type { + using FIRT = decltype(t); + return FIRT::get( + changeLengthInCharacterType(loc, t.getEleTy(), newLen)); + }) + .Default([loc](mlir::Type t) -> mlir::Type { + fir::emitFatalError(loc, "expected character type"); + }); + } + + mlir::Type visit(const Fortran::evaluate::DataRef &dataRef, + PartInfo &partInfo) { + return std::visit([&](const auto &x) { return visit(x, partInfo); }, + dataRef.u); + } + + mlir::Type + visit(const Fortran::evaluate::StaticDataObject::Pointer &staticObject, + PartInfo &partInfo) { + fir::FirOpBuilder &builder = getBuilder(); + mlir::Location loc = getLoc(); + std::optional string = staticObject->AsString(); + // TODO: see if StaticDataObject can be replaced by something based on + // Constant to avoid dealing with endianness here for KIND>1. + // This will also avoid making string copies here. + if (!string) + TODO(loc, "StaticDataObject::Pointer substring with kind > 1"); + fir::ExtendedValue exv = + fir::factory::createStringLiteral(builder, getLoc(), *string); + auto flags = fir::FortranVariableFlagsAttr::get( + builder.getContext(), fir::FortranVariableFlagsEnum::parameter); + partInfo.base = hlfir::genDeclare(loc, builder, exv, ".stringlit", flags); + partInfo.typeParams.push_back(fir::getLen(exv)); + return partInfo.base.getElementOrSequenceType(); } mlir::Type visit(const Fortran::evaluate::SymbolRef &symbolRef, @@ -845,7 +945,33 @@ private: hlfir::EntityWithAttributes gen(const Fortran::evaluate::DescriptorInquiry &desc) { - TODO(getLoc(), "lowering descriptor inquiry to HLFIR"); + mlir::Location loc = getLoc(); + auto &builder = getBuilder(); + hlfir::EntityWithAttributes entity = + HlfirDesignatorBuilder(getLoc(), getConverter(), getSymMap(), + getStmtCtx()) + .gen(desc.base()); + using ResTy = Fortran::evaluate::DescriptorInquiry::Result; + mlir::Type resultType = + getConverter().genType(ResTy::category, ResTy::kind); + auto castResult = [&](mlir::Value v) { + return hlfir::EntityWithAttributes{ + builder.createConvert(loc, resultType, v)}; + }; + switch (desc.field()) { + case Fortran::evaluate::DescriptorInquiry::Field::Len: + return castResult(hlfir::genCharLength(loc, builder, entity)); + case Fortran::evaluate::DescriptorInquiry::Field::LowerBound: + TODO(loc, "lower bound inquiry in HLFIR"); + case Fortran::evaluate::DescriptorInquiry::Field::Extent: + TODO(loc, "extent inquiry in HLFIR"); + case Fortran::evaluate::DescriptorInquiry::Field::Rank: + TODO(loc, "rank inquiry on assumed rank"); + case Fortran::evaluate::DescriptorInquiry::Field::Stride: + // So far the front end does not generate this inquiry. + TODO(loc, "stride inquiry"); + } + llvm_unreachable("unknown descriptor inquiry"); } hlfir::EntityWithAttributes diff --git a/flang/lib/Optimizer/Builder/Character.cpp b/flang/lib/Optimizer/Builder/Character.cpp index f3bb71e..de4a557 100644 --- a/flang/lib/Optimizer/Builder/Character.cpp +++ b/flang/lib/Optimizer/Builder/Character.cpp @@ -473,6 +473,17 @@ fir::CharBoxValue fir::factory::CharacterExprHelper::createConcatenate( return temp; } +mlir::Value fir::factory::CharacterExprHelper::genSubstringBase( + mlir::Value stringRawAddr, mlir::Value lowerBound, + mlir::Type substringAddrType, mlir::Value one) { + if (!one) + one = builder.createIntegerConstant(loc, lowerBound.getType(), 1); + auto offset = + builder.create(loc, lowerBound, one).getResult(); + auto addr = createElementAddr(stringRawAddr, offset); + return builder.createConvert(loc, substringAddrType, addr); +} + fir::CharBoxValue fir::factory::CharacterExprHelper::createSubstring( const fir::CharBoxValue &box, llvm::ArrayRef bounds) { // Constant need to be materialize in memory to use fir.coordinate_of. @@ -488,14 +499,12 @@ fir::CharBoxValue fir::factory::CharacterExprHelper::createSubstring( builder.createConvert(loc, builder.getCharacterLengthType(), bound)); auto lowerBound = castBounds[0]; // FIR CoordinateOp is zero based but Fortran substring are one based. - auto one = builder.createIntegerConstant(loc, lowerBound.getType(), 1); - auto offset = - builder.create(loc, lowerBound, one).getResult(); - auto addr = createElementAddr(box.getBuffer(), offset); auto kind = getCharacterKind(box.getBuffer().getType()); auto charTy = fir::CharacterType::getUnknownLen(builder.getContext(), kind); auto resultType = builder.getRefType(charTy); - auto substringRef = builder.createConvert(loc, resultType, addr); + auto one = builder.createIntegerConstant(loc, lowerBound.getType(), 1); + auto substringRef = + genSubstringBase(box.getBuffer(), lowerBound, resultType, one); // Compute the length. mlir::Value substringLen; diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp index b090da6..ca645cf 100644 --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -139,7 +139,7 @@ hlfir::translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder, return firBase; } -hlfir::EntityWithAttributes +fir::FortranVariableOpInterface hlfir::genDeclare(mlir::Location loc, fir::FirOpBuilder &builder, const fir::ExtendedValue &exv, llvm::StringRef name, fir::FortranVariableFlagsAttr flags) { @@ -457,6 +457,14 @@ void hlfir::genLengthParameters(mlir::Location loc, fir::FirOpBuilder &builder, TODO(loc, "inquire PDTs length parameters in HLFIR"); } +mlir::Value hlfir::genCharLength(mlir::Location loc, fir::FirOpBuilder &builder, + hlfir::Entity entity) { + llvm::SmallVector lenParams; + genLengthParameters(loc, builder, entity, lenParams); + assert(lenParams.size() == 1 && "characters must have one length parameters"); + return lenParams[0]; +} + std::pair hlfir::genVariableFirBaseShapeAndParams( mlir::Location loc, fir::FirOpBuilder &builder, Entity entity, llvm::SmallVectorImpl &typeParams) { diff --git a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp index 90951f8..97b08ae 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp @@ -220,7 +220,8 @@ struct ConcatOpConversion : public mlir::OpConversionPattern { mlir::Value cast = builder.createConvert(loc, addrType, fir::getBase(res)); res = fir::substBase(res, cast); auto hlfirTempRes = hlfir::genDeclare(loc, builder, res, "tmp", - fir::FortranVariableFlagsAttr{}); + fir::FortranVariableFlagsAttr{}) + .getBase(); mlir::Value bufferizedExpr = packageBufferizedExpr(loc, builder, hlfirTempRes, false); rewriter.replaceOp(concat, bufferizedExpr); diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp index 9f64eb4..a5c31b3 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp @@ -8,6 +8,7 @@ // This file defines a pass to lower HLFIR to FIR //===----------------------------------------------------------------------===// +#include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/HLFIRTools.h" #include "flang/Optimizer/Builder/MutableBox.h" @@ -183,11 +184,8 @@ public: auto module = designate->getParentOfType(); fir::FirOpBuilder builder(rewriter, fir::getKindMapping(module)); - if (designate.getComponent() || designate.getComplexPart() || - !designate.getSubstring().empty()) { - // build path. - TODO(loc, "hlfir::designate with complex part or substring or component"); - } + if (designate.getComponent() || designate.getComplexPart()) + TODO(loc, "hlfir::designate with complex part or component"); hlfir::Entity baseEntity(designate.getMemref()); if (baseEntity.isMutableBox()) @@ -216,8 +214,20 @@ public: triples.push_back(undef); } } + llvm::SmallVector substring; + if (!designate.getSubstring().empty()) { + substring.push_back(designate.getSubstring()[0]); + mlir::Type idxTy = builder.getIndexType(); + // fir.slice op substring expects the zero based lower bound. + mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); + substring[0] = builder.createConvert(loc, idxTy, substring[0]); + substring[0] = + builder.create(loc, substring[0], one); + substring.push_back(designate.getTypeparams()[0]); + } + mlir::Value slice = builder.create( - loc, triples, /*path=*/mlir::ValueRange{}); + loc, triples, /*fields=*/mlir::ValueRange{}, substring); llvm::SmallVector resultType{designateResultType}; mlir::Value resultBox; if (base.getType().isa()) @@ -230,29 +240,37 @@ public: return mlir::success(); } - // Indexing a single element (use fir.array_coor of fir.coordinate_of). + // Otherwise, the result is the address of a scalar. The base may be an + // array, or a scalar. + mlir::Type resultAddressType = designateResultType; + if (auto boxCharType = designateResultType.dyn_cast()) + resultAddressType = fir::ReferenceType::get(boxCharType.getEleTy()); - if (designate.getIndices().empty()) { - // Scalar substring or complex part. - // generate fir.coordinate_of. - TODO(loc, "hlfir::designate to fir.coordinate_of"); + // Array element indexing. + if (!designate.getIndices().empty()) { + auto eleTy = hlfir::getFortranElementType(base.getType()); + auto arrayCoorType = fir::ReferenceType::get(eleTy); + base = builder.create(loc, arrayCoorType, base, shape, + /*slice=*/mlir::Value{}, + designate.getIndices(), + firBaseTypeParameters); } - // Generate fir.array_coor - mlir::Type resultType = designateResultType; - if (auto boxCharType = designateResultType.dyn_cast()) - resultType = fir::ReferenceType::get(boxCharType.getEleTy()); - auto arrayCoor = builder.create( - loc, resultType, base, shape, - /*slice=*/mlir::Value{}, designate.getIndices(), firBaseTypeParameters); + // Scalar substring (potentially on the previously built array element). + if (!designate.getSubstring().empty()) + base = fir::factory::CharacterExprHelper{builder, loc}.genSubstringBase( + base, designate.getSubstring()[0], resultAddressType); + + // Cast/embox the computed scalar address if needed. if (designateResultType.isa()) { assert(designate.getTypeparams().size() == 1 && "must have character length"); auto emboxChar = builder.create( - loc, designateResultType, arrayCoor, designate.getTypeparams()[0]); + loc, designateResultType, base, designate.getTypeparams()[0]); rewriter.replaceOp(designate, emboxChar.getResult()); } else { - rewriter.replaceOp(designate, arrayCoor.getResult()); + base = builder.createConvert(loc, designateResultType, base); + rewriter.replaceOp(designate, base); } return mlir::success(); } diff --git a/flang/test/Lower/HLFIR/substrings.f90 b/flang/test/Lower/HLFIR/substrings.f90 new file mode 100644 index 0000000..d97f75e --- /dev/null +++ b/flang/test/Lower/HLFIR/substrings.f90 @@ -0,0 +1,114 @@ +! Test lowering of substrings to HLFIR +! Note: cse is run to make the expected output more readable by sharing +! the boilerplate between the different susbtring cases. +! RUN: bbc -emit-fir -hlfir -o - %s | fir-opt -cse -o - | FileCheck %s + +! CHECK-LABEL: func.func @_QPcst_len( +subroutine cst_len(array, scalar) + character(10) :: array(100), scalar +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %{{.*}}(%[[VAL_6:.*]]) typeparams %[[VAL_3:[^ ]*]] {{.*}}array" +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_3]] {{.*}}scalar" + print *, array(:)(2:5) +! CHECK: %[[VAL_15:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_16:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_17:.*]] = arith.constant 5 : index +! CHECK: %[[VAL_18:.*]] = arith.constant 4 : index +! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_15]]:%[[VAL_5]]:%[[VAL_15]]) substr %[[VAL_16]], %[[VAL_17]] shape %[[VAL_6]] typeparams %[[VAL_18]] : (!fir.ref>>, index, index, index, index, index, !fir.shape<1>, index) -> !fir.box>> + + print *, array(42)(2:5) +! CHECK: %[[VAL_25:.*]] = arith.constant 42 : index +! CHECK: %[[VAL_26:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_25]]) substr %[[VAL_16]], %[[VAL_17]] typeparams %[[VAL_18]] : (!fir.ref>>, index, index, index, index) -> !fir.ref> + print *, array(:)(2:) +! CHECK: %[[VAL_33:.*]] = arith.constant 9 : index +! CHECK: %[[VAL_34:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_15]]:%[[VAL_5]]:%[[VAL_15]]) substr %[[VAL_16]], %[[VAL_3]] shape %[[VAL_6]] typeparams %[[VAL_33]] : (!fir.ref>>, index, index, index, index, index, !fir.shape<1>, index) -> !fir.box>> + + print *, scalar(2:5) +! CHECK: %[[VAL_40:.*]] = hlfir.designate %[[VAL_9]]#0 substr %[[VAL_16]], %[[VAL_17]] typeparams %[[VAL_18]] : (!fir.boxchar<1>, index, index, index) -> !fir.ref> +end subroutine + +! CHECK-LABEL: func.func @_QPdyn_len( +subroutine dyn_len(array, scalar, l, n, m, k) + integer(8) :: n,m,k +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare {{.*}}k" +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare {{.*}}m" +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare {{.*}}n" + character(l) :: array(:), scalar +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_13:[^ ]*]] {{.*}}array" +! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_18:[^ ]*]] {{.*}}scalar" + + print *, array(:)(n:m) +! CHECK: %[[VAL_25:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_26:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_27:.*]]:3 = fir.box_dims %[[VAL_14]]#1, %[[VAL_26]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[VAL_28:.*]] = arith.subi %[[VAL_27]]#1, %[[VAL_25]] : index +! CHECK: %[[VAL_29:.*]] = arith.addi %[[VAL_28]], %[[VAL_25]] : index +! CHECK: %[[VAL_30:.*]] = arith.divsi %[[VAL_29]], %[[VAL_25]] : index +! CHECK: %[[VAL_31:.*]] = arith.cmpi sgt, %[[VAL_30]], %[[VAL_26]] : index +! CHECK: %[[VAL_32:.*]] = arith.select %[[VAL_31]], %[[VAL_30]], %[[VAL_26]] : index +! CHECK: %[[VAL_33:.*]] = fir.shape %[[VAL_32]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref +! CHECK: %[[VAL_35:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref +! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (i64) -> index +! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_35]] : (i64) -> index +! CHECK: %[[VAL_38:.*]] = arith.subi %[[VAL_37]], %[[VAL_36]] : index +! CHECK: %[[VAL_39:.*]] = arith.addi %[[VAL_38]], %[[VAL_25]] : index +! CHECK: %[[VAL_40:.*]] = arith.cmpi sgt, %[[VAL_39]], %[[VAL_26]] : index +! CHECK: %[[VAL_41:.*]] = arith.select %[[VAL_40]], %[[VAL_39]], %[[VAL_26]] : index +! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_14]]#0 (%[[VAL_25]]:%[[VAL_27]]#1:%[[VAL_25]]) substr %[[VAL_36]], %[[VAL_37]] shape %[[VAL_33]] typeparams %[[VAL_41]] : (!fir.box>>, index, index, index, index, index, !fir.shape<1>, index) -> !fir.box>> + + print *, array(k)(n:m) +! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref +! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref +! CHECK: %[[VAL_50:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref +! CHECK: %[[VAL_51:.*]] = fir.convert %[[VAL_49]] : (i64) -> index +! CHECK: %[[VAL_52:.*]] = fir.convert %[[VAL_50]] : (i64) -> index +! CHECK: %[[VAL_53:.*]] = arith.subi %[[VAL_52]], %[[VAL_51]] : index +! CHECK: %[[VAL_54:.*]] = arith.addi %[[VAL_53]], %[[VAL_25]] : index +! CHECK: %[[VAL_55:.*]] = arith.cmpi sgt, %[[VAL_54]], %[[VAL_26]] : index +! CHECK: %[[VAL_56:.*]] = arith.select %[[VAL_55]], %[[VAL_54]], %[[VAL_26]] : index +! CHECK: %[[VAL_57:.*]] = hlfir.designate %[[VAL_14]]#0 (%[[VAL_48]]) substr %[[VAL_51]], %[[VAL_52]] typeparams %[[VAL_56]] : (!fir.box>>, i64, index, index, index) -> !fir.boxchar<1> + + print *, array(:)(n:) +! CHECK: %[[VAL_65:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref +! CHECK: %[[VAL_66:.*]] = fir.convert %[[VAL_13]] : (i32) -> i64 +! CHECK: %[[VAL_67:.*]] = fir.convert %[[VAL_65]] : (i64) -> index +! CHECK: %[[VAL_68:.*]] = fir.convert %[[VAL_66]] : (i64) -> index +! CHECK: %[[VAL_69:.*]] = arith.subi %[[VAL_68]], %[[VAL_67]] : index +! CHECK: %[[VAL_70:.*]] = arith.addi %[[VAL_69]], %[[VAL_25]] : index +! CHECK: %[[VAL_71:.*]] = arith.cmpi sgt, %[[VAL_70]], %[[VAL_26]] : index +! CHECK: %[[VAL_72:.*]] = arith.select %[[VAL_71]], %[[VAL_70]], %[[VAL_26]] : index +! CHECK: %[[VAL_73:.*]] = hlfir.designate %[[VAL_14]]#0 (%[[VAL_25]]:%[[VAL_27]]#1:%[[VAL_25]]) substr %[[VAL_67]], %[[VAL_68]] shape %[[VAL_33]] typeparams %[[VAL_72]] : (!fir.box>>, index, index, index, index, index, !fir.shape<1>, index) -> !fir.box>> + + print *, scalar(n:m) +! CHECK: %[[VAL_79:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref +! CHECK: %[[VAL_80:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref +! CHECK: %[[VAL_81:.*]] = fir.convert %[[VAL_79]] : (i64) -> index +! CHECK: %[[VAL_82:.*]] = fir.convert %[[VAL_80]] : (i64) -> index +! CHECK: %[[VAL_83:.*]] = arith.subi %[[VAL_82]], %[[VAL_81]] : index +! CHECK: %[[VAL_84:.*]] = arith.addi %[[VAL_83]], %[[VAL_25]] : index +! CHECK: %[[VAL_85:.*]] = arith.cmpi sgt, %[[VAL_84]], %[[VAL_26]] : index +! CHECK: %[[VAL_86:.*]] = arith.select %[[VAL_85]], %[[VAL_84]], %[[VAL_26]] : index +! CHECK: %[[VAL_87:.*]] = hlfir.designate %[[VAL_19]]#0 substr %[[VAL_81]], %[[VAL_82]] typeparams %[[VAL_86]] : (!fir.boxchar<1>, index, index, index) -> !fir.boxchar<1> +end subroutine + +subroutine test_static_substring(i, j) + integer(8) :: i, j + print *, "hello"(i:j) +end subroutine +! CHECK-LABEL: func.func @_QPtest_static_substring( +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}}i" +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}}j" +! CHECK: %[[VAL_10:.*]] = arith.constant 5 : index +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_10]] {fortran_attrs = #fir.var_attrs, uniq_name = ".stringlit"} : (!fir.ref>, index) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref +! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_12]] : (i64) -> index +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_13]] : (i64) -> index +! CHECK: %[[VAL_16:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_17:.*]] = arith.subi %[[VAL_15]], %[[VAL_14]] : index +! CHECK: %[[VAL_18:.*]] = arith.addi %[[VAL_17]], %[[VAL_16]] : index +! CHECK: %[[VAL_19:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_20:.*]] = arith.cmpi sgt, %[[VAL_18]], %[[VAL_19]] : index +! CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_20]], %[[VAL_18]], %[[VAL_19]] : index +! CHECK: %[[VAL_22:.*]] = hlfir.designate %[[VAL_11]]#0 substr %[[VAL_14]], %[[VAL_15]] typeparams %[[VAL_21]] : (!fir.ref>, index, index, index) -> !fir.boxchar<1> diff --git a/flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp b/flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp index 429f75a..75bd4b3 100644 --- a/flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp +++ b/flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp @@ -37,7 +37,8 @@ public: mlir::Value createDeclare(fir::ExtendedValue exv) { return hlfir::genDeclare(getLoc(), *firBuilder, exv, - "x" + std::to_string(varCounter++), fir::FortranVariableFlagsAttr{}); + "x" + std::to_string(varCounter++), fir::FortranVariableFlagsAttr{}) + .getBase(); } mlir::Value createConstant(std::int64_t cst) { -- 2.7.4