[flang-commits] [flang] [flang] Guard absent optional operands in elemental character MIN/MAX (PR #191244)
Sairudra More via flang-commits
flang-commits at lists.llvm.org
Fri Apr 10 22:31:50 PDT 2026
================
@@ -465,7 +465,55 @@ mlir::Value HlfirCharExtremumLowering::lowerImpl(
const Fortran::lower::PreparedActualArguments &loweredActuals,
const fir::IntrinsicArgumentLoweringRules *argLowering,
mlir::Type stmtResultType) {
- auto operands = getOperandVector(loweredActuals, argLowering);
+ // Check whether any argument is dynamically optional. When an optional
+ // character argument is absent, calling getActual() to read the character
+ // length from the descriptor is unsafe. Guard each optional argument's
+ // element access inside a fir.if.
+ bool hasDynamicOptional = llvm::any_of(loweredActuals, [](const auto &arg) {
+ return arg.has_value() && arg->handleDynamicOptional();
+ });
+ if (!hasDynamicOptional) {
+ auto operands = getOperandVector(loweredActuals, argLowering);
+ assert(operands.size() >= 2);
+ return createOp<hlfir::CharExtremumOp>(pred, mlir::ValueRange{operands});
+ }
+
+ // For absent optional arguments, use the first required argument's element
+ // as a neutral dummy so that min/max semantics are preserved:
+ // min(a, b, a) == min(a, b) and max(a, b, a) == max(a, b).
+ // Scan ahead to find the first non-optional argument so it can be used as
+ // the neutral element for any optional arguments that appear earlier.
+ mlir::Value firstRequired;
+ for (const auto &opt_arg : loweredActuals) {
+ if (opt_arg && !opt_arg->handleDynamicOptional()) {
+ firstRequired = loadTrivialScalar(*opt_arg);
+ break;
+ }
+ }
+ assert(firstRequired &&
+ "MIN/MAX must have at least one non-optional argument");
+ llvm::SmallVector<mlir::Value> operands;
+ for (const auto &opt_arg : loweredActuals) {
+ if (!opt_arg)
+ continue;
+ if (!opt_arg->handleDynamicOptional()) {
+ mlir::Value elem = loadTrivialScalar(*opt_arg);
+ operands.push_back(elem);
+ } else {
+ mlir::Value isPresent = opt_arg->getIsPresent();
+ mlir::Type elemType = firstRequired.getType();
+ const Fortran::lower::PreparedActualArgument &argRef = *opt_arg;
+ mlir::Value elem =
+ builder.genIfOp(loc, {elemType}, isPresent, /*withElseRegion=*/true)
+ .genThen([&]() {
+ fir::ResultOp::create(builder, loc, loadTrivialScalar(argRef));
+ })
+ .genElse(
+ [&]() { fir::ResultOp::create(builder, loc, firstRequired); })
+ .getResults()[0];
----------------
Saieiei wrote:
Yes, dropped this workaround in the https://github.com/llvm/llvm-project/commit/b23993eb475f81e6c315364b8972bce41218007e update.
https://github.com/llvm/llvm-project/pull/191244
More information about the flang-commits
mailing list