Skip to content

Commit 4169187

Browse files
committed
add an utility for char length analysis to avoid premature new ops generation
1 parent 0c4f8e9 commit 4169187

File tree

1 file changed

+56
-7
lines changed

1 file changed

+56
-7
lines changed

flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
23012352
class IndexOpConversion : public mlir::OpRewritePattern<hlfir::IndexOp> {
23022353
public:
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

Comments
 (0)