Skip to content

Commit 437a48b

Browse files
authored
[flang] Handle absent optional in LOC (llvm#73530)
LOC is a GNU extension, so gfortran is the reference for it, and it accepts absent OPTIONAL and returns zero. Support this use case in flang too. Update the LOC test to use HLFIR while touching it. Fixes llvm#72823.
1 parent af65379 commit 437a48b

File tree

2 files changed

+150
-148
lines changed

2 files changed

+150
-148
lines changed

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4138,17 +4138,46 @@ IntrinsicLibrary::genCharacterCompare(mlir::Type resultType,
41384138
fir::getBase(args[1]), fir::getLen(args[1]));
41394139
}
41404140

4141+
static bool isOptional(mlir::Value value) {
4142+
auto varIface = mlir::dyn_cast_or_null<fir::FortranVariableOpInterface>(
4143+
value.getDefiningOp());
4144+
return varIface && varIface.isOptional();
4145+
}
4146+
41414147
// LOC
41424148
fir::ExtendedValue
41434149
IntrinsicLibrary::genLoc(mlir::Type resultType,
41444150
llvm::ArrayRef<fir::ExtendedValue> args) {
41454151
assert(args.size() == 1);
4146-
mlir::Value argValue = fir::getBase(args[0]);
4147-
assert(fir::isa_box_type(argValue.getType()) &&
4152+
mlir::Value box = fir::getBase(args[0]);
4153+
assert(fir::isa_box_type(box.getType()) &&
41484154
"argument must have been lowered to box type");
4149-
bool isFunc = argValue.getType().isa<fir::BoxProcType>();
4150-
mlir::Value argAddr = getAddrFromBox(builder, loc, args[0], isFunc);
4151-
return builder.createConvert(loc, fir::unwrapRefType(resultType), argAddr);
4155+
bool isFunc = box.getType().isa<fir::BoxProcType>();
4156+
if (!isOptional(box)) {
4157+
mlir::Value argAddr = getAddrFromBox(builder, loc, args[0], isFunc);
4158+
return builder.createConvert(loc, resultType, argAddr);
4159+
}
4160+
// Optional assumed shape case. Although this is not specified in this GNU
4161+
// intrinsic extension, LOC accepts absent optional and returns zero in that
4162+
// case.
4163+
// Note that the other OPTIONAL cases do not fall here since `box` was
4164+
// created when preparing the argument cases, but the box can be safely be
4165+
// used for all those cases and the address will be null if absent.
4166+
mlir::Value isPresent =
4167+
builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), box);
4168+
return builder
4169+
.genIfOp(loc, {resultType}, isPresent,
4170+
/*withElseRegion=*/true)
4171+
.genThen([&]() {
4172+
mlir::Value argAddr = getAddrFromBox(builder, loc, args[0], isFunc);
4173+
mlir::Value cast = builder.createConvert(loc, resultType, argAddr);
4174+
builder.create<fir::ResultOp>(loc, cast);
4175+
})
4176+
.genElse([&]() {
4177+
mlir::Value zero = builder.createIntegerConstant(loc, resultType, 0);
4178+
builder.create<fir::ResultOp>(loc, zero);
4179+
})
4180+
.getResults()[0];
41524181
}
41534182

41544183
// MASKL, MASKR

0 commit comments

Comments
 (0)