@@ -2298,6 +2298,57 @@ getVariable(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value val) {
22982298 return {associate.getBase (), associate};
22992299}
23002300
2301+ // Return character length if known at compile time. Unlike genCharLength
2302+ // it does not create any new op as specifically is intended for analysis.
2303+ // It is inspired by genLengthParameters that does the job for genCharLength.
2304+ static std::optional<std::int64_t > getCharLengthIfConst (hlfir::Entity entity) {
2305+ if (!entity.isCharacter ()) {
2306+ return std::nullopt ;
2307+ }
2308+
2309+ if (mlir::isa<hlfir::ExprType>(entity.getType ())) {
2310+ mlir::Value expr = entity;
2311+ if (auto reassoc = expr.getDefiningOp <hlfir::NoReassocOp>())
2312+ expr = reassoc.getVal ();
2313+ // Going through fir::ExtendedValue would create a temp,
2314+ // which is not desired for an inquiry.
2315+ // TODO: make this an interface when adding further character producing ops.
2316+ if (auto concat = expr.getDefiningOp <hlfir::ConcatOp>()) {
2317+ return fir::getIntIfConstant (concat.getLength ());
2318+ } else if (auto setLength = expr.getDefiningOp <hlfir::SetLengthOp>()) {
2319+ return fir::getIntIfConstant (setLength.getLength ());
2320+ } else if (auto asExpr = expr.getDefiningOp <hlfir::AsExprOp>()) {
2321+ return getCharLengthIfConst (hlfir::Entity{asExpr.getVar ()});
2322+ } else {
2323+ llvm::SmallVector<mlir::Value> param;
2324+ if (auto elemental = expr.getDefiningOp <hlfir::ElementalOp>()) {
2325+ param.append (elemental.getTypeparams ().begin (),
2326+ elemental.getTypeparams ().end ());
2327+ } else if (auto evalInMem =
2328+ expr.getDefiningOp <hlfir::EvaluateInMemoryOp>()) {
2329+ param.append (evalInMem.getTypeparams ().begin (),
2330+ evalInMem.getTypeparams ().end ());
2331+ } else if (auto apply = expr.getDefiningOp <hlfir::ApplyOp>()) {
2332+ param.append (apply.getTypeparams ().begin (),
2333+ apply.getTypeparams ().end ());
2334+ } else {
2335+ return std::nullopt ;
2336+ }
2337+ assert (param.size () == 1 && " characters must have one length parameters" );
2338+ return fir::getIntIfConstant (param.pop_back_val ());
2339+ }
2340+ }
2341+
2342+ if (auto varIface = entity.getMaybeDereferencedVariableInterface ())
2343+ if (!varIface.getExplicitTypeParams ().empty ())
2344+ return fir::getIntIfConstant (varIface.getExplicitTypeParams ()[0 ]);
2345+ auto charType =
2346+ mlir::cast<fir::CharacterType>(entity.getFortranElementType ());
2347+ if (charType.hasConstantLen ())
2348+ return charType.getLen ();
2349+ return std::nullopt ;
2350+ }
2351+
23012352class IndexOpConversion : public mlir ::OpRewritePattern<hlfir::IndexOp> {
23022353public:
23032354 using mlir::OpRewritePattern<hlfir::IndexOp>::OpRewritePattern;
@@ -2321,22 +2372,19 @@ class IndexOpConversion : public mlir::OpRewritePattern<hlfir::IndexOp> {
23212372
23222373 auto resultTy = op.getType ();
23232374 mlir::Value back = op.getBack ();
2324- mlir::Value substrLen =
2325- hlfir::genCharLength (loc, builder, hlfir::Entity{op.getSubstr ()});
2326-
2327- auto substrLenCst = fir::getIntIfConstant (substrLen);
2375+ auto substrLenCst = getCharLengthIfConst (hlfir::Entity{op.getSubstr ()});
23282376 if (!substrLenCst) {
23292377 return rewriter.notifyMatchFailure (
23302378 op, " substring length unknown at compile time" );
23312379 }
2332- mlir::Value strLen =
2333- hlfir::genCharLength (loc, builder, hlfir::Entity{op.getStr ()});
2380+ hlfir::Entity strEntity{op.getStr ()};
23342381 auto i1Ty = builder.getI1Type ();
23352382 auto idxTy = builder.getIndexType ();
23362383 if (*substrLenCst == 0 ) {
23372384 mlir::Value oneIdx = builder.createIntegerConstant (loc, idxTy, 1 );
23382385 // zero length substring. For back search replace with
23392386 // strLen+1, or otherwise with 1.
2387+ mlir::Value strLen = hlfir::genCharLength (loc, builder, strEntity);
23402388 mlir::Value strEnd = mlir::arith::AddIOp::create (
23412389 builder, loc, builder.createConvert (loc, idxTy, strLen), oneIdx);
23422390 if (back)
@@ -2350,7 +2398,7 @@ class IndexOpConversion : public mlir::OpRewritePattern<hlfir::IndexOp> {
23502398 return mlir::success ();
23512399 }
23522400
2353- if (auto strLenCst = fir::getIntIfConstant (strLen )) {
2401+ if (auto strLenCst = getCharLengthIfConst (strEntity )) {
23542402 if (*strLenCst < *substrLenCst) {
23552403 rewriter.replaceOp (op, builder.createIntegerConstant (loc, resultTy, 0 ));
23562404 return mlir::success ();
@@ -2430,6 +2478,7 @@ class IndexOpConversion : public mlir::OpRewritePattern<hlfir::IndexOp> {
24302478 // result = str[at-1] == want ? at : result;
24312479 // }
24322480 // }
2481+ mlir::Value strLen = hlfir::genCharLength (loc, builder, strEntity);
24332482 if (!back)
24342483 back = builder.createIntegerConstant (loc, i1Ty, 0 );
24352484 else
0 commit comments