Skip to content

Commit d43a2f0

Browse files
committed
[flang] Lower F08 FINDLOC intrinsic
The implementation follows the patterns established by the lowering of other similar intrinsics. In addition to the code for lowering, the DoTotalReduction template had to be fixed to correctly break when signaled to do so by the accumulator function. Differential Revision: https://reviews.llvm.org/D138140
1 parent 6841c43 commit d43a2f0

File tree

5 files changed

+417
-1
lines changed

5 files changed

+417
-1
lines changed

flang/include/flang/Optimizer/Builder/Runtime/Reduction.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,19 @@ mlir::Value genDotProduct(fir::FirOpBuilder &builder, mlir::Location loc,
7575
mlir::Value vectorABox, mlir::Value vectorBBox,
7676
mlir::Value resultBox);
7777

78+
/// Generate call to `Findloc` intrinsic runtime routine. This is the version
79+
/// that does not take a dim argument.
80+
void genFindloc(fir::FirOpBuilder &builder, mlir::Location loc,
81+
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value val,
82+
mlir::Value maskBox, mlir::Value kind, mlir::Value back);
83+
84+
/// Generate call to `FindlocDim` intrinsic runtime routine. This is the version
85+
/// that takes a dim argument.
86+
void genFindlocDim(fir::FirOpBuilder &builder, mlir::Location loc,
87+
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value val,
88+
mlir::Value dim, mlir::Value maskBox, mlir::Value kind,
89+
mlir::Value back);
90+
7891
/// Generate call to `Maxloc` intrinsic runtime routine. This is the version
7992
/// that does not take a dim argument.
8093
void genMaxloc(fir::FirOpBuilder &builder, mlir::Location loc,

flang/lib/Lower/IntrinsicCall.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ struct IntrinsicLibrary {
516516
mlir::Value genIbits(mlir::Type, llvm::ArrayRef<mlir::Value>);
517517
mlir::Value genIbset(mlir::Type, llvm::ArrayRef<mlir::Value>);
518518
fir::ExtendedValue genIchar(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
519+
fir::ExtendedValue genFindloc(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
519520
mlir::Value genIeeeIsFinite(mlir::Type, llvm::ArrayRef<mlir::Value>);
520521
template <mlir::arith::CmpIPredicate pred>
521522
fir::ExtendedValue genIeeeTypeCompare(mlir::Type,
@@ -801,6 +802,15 @@ static constexpr IntrinsicHandler handlers[]{
801802
{{{"status", asValue, handleDynamicOptional}}},
802803
/*isElemental=*/false},
803804
{"exponent", &I::genExponent},
805+
{"findloc",
806+
&I::genFindloc,
807+
{{{"array", asBox},
808+
{"value", asAddr},
809+
{"dim", asValue},
810+
{"mask", asBox, handleDynamicOptional},
811+
{"kind", asValue},
812+
{"back", asValue, handleDynamicOptional}}},
813+
/*isElemental=*/false},
804814
{"floor", &I::genFloor},
805815
{"fraction", &I::genFraction},
806816
{"get_command",
@@ -3181,6 +3191,98 @@ mlir::Value IntrinsicLibrary::genExponent(mlir::Type resultType,
31813191
fir::getBase(args[0])));
31823192
}
31833193

3194+
// FINDLOC
3195+
fir::ExtendedValue
3196+
IntrinsicLibrary::genFindloc(mlir::Type resultType,
3197+
llvm::ArrayRef<fir::ExtendedValue> args) {
3198+
assert(args.size() == 6);
3199+
3200+
llvm::StringRef errMsg = "unexpected result for Findloc";
3201+
3202+
// Handle required array argument
3203+
mlir::Value array = builder.createBox(loc, args[0]);
3204+
unsigned rank = fir::BoxValue(array).rank();
3205+
assert(rank >= 1);
3206+
3207+
// Handle required value argument
3208+
mlir::Value val = builder.createBox(loc, args[1]);
3209+
3210+
// Check if dim argument is present
3211+
bool absentDim = isStaticallyAbsent(args[2]);
3212+
3213+
// Handle optional mask argument
3214+
auto mask = isStaticallyAbsent(args[3])
3215+
? builder.create<fir::AbsentOp>(
3216+
loc, fir::BoxType::get(builder.getI1Type()))
3217+
: builder.createBox(loc, args[3]);
3218+
3219+
// Handle optional kind argument
3220+
auto kind = isStaticallyAbsent(args[4])
3221+
? builder.createIntegerConstant(
3222+
loc, builder.getIndexType(),
3223+
builder.getKindMap().defaultIntegerKind())
3224+
: fir::getBase(args[4]);
3225+
3226+
// Handle optional back argument
3227+
auto back = isStaticallyAbsent(args[5]) ? builder.createBool(loc, false)
3228+
: fir::getBase(args[5]);
3229+
3230+
if (!absentDim && rank == 1) {
3231+
// If dim argument is present and the array is rank 1, then the result is
3232+
// a scalar (since the the result is rank-1 or 0).
3233+
// Therefore, we use a scalar result descriptor with FindlocDim().
3234+
// Create mutable fir.box to be passed to the runtime for the result.
3235+
fir::MutableBoxValue resultMutableBox =
3236+
fir::factory::createTempMutableBox(builder, loc, resultType);
3237+
mlir::Value resultIrBox =
3238+
fir::factory::getMutableIRBox(builder, loc, resultMutableBox);
3239+
mlir::Value dim = fir::getBase(args[2]);
3240+
3241+
fir::runtime::genFindlocDim(builder, loc, resultIrBox, array, val, dim,
3242+
mask, kind, back);
3243+
3244+
// Handle cleanup of allocatable result descriptor and return
3245+
fir::ExtendedValue res =
3246+
fir::factory::genMutableBoxRead(builder, loc, resultMutableBox);
3247+
return res.match(
3248+
[&](const mlir::Value &addr) -> fir::ExtendedValue {
3249+
addCleanUpForTemp(loc, addr);
3250+
return builder.create<fir::LoadOp>(loc, resultType, addr);
3251+
},
3252+
[&](const auto &) -> fir::ExtendedValue {
3253+
fir::emitFatalError(loc, errMsg);
3254+
});
3255+
}
3256+
3257+
// The result will be an array. Create mutable fir.box to be passed to the
3258+
// runtime for the result.
3259+
mlir::Type resultArrayType =
3260+
builder.getVarLenSeqTy(resultType, absentDim ? 1 : rank - 1);
3261+
fir::MutableBoxValue resultMutableBox =
3262+
fir::factory::createTempMutableBox(builder, loc, resultArrayType);
3263+
mlir::Value resultIrBox =
3264+
fir::factory::getMutableIRBox(builder, loc, resultMutableBox);
3265+
3266+
if (absentDim) {
3267+
fir::runtime::genFindloc(builder, loc, resultIrBox, array, val, mask, kind,
3268+
back);
3269+
} else {
3270+
mlir::Value dim = fir::getBase(args[2]);
3271+
fir::runtime::genFindlocDim(builder, loc, resultIrBox, array, val, dim,
3272+
mask, kind, back);
3273+
}
3274+
3275+
return fir::factory::genMutableBoxRead(builder, loc, resultMutableBox)
3276+
.match(
3277+
[&](const fir::ArrayBoxValue &box) -> fir::ExtendedValue {
3278+
addCleanUpForTemp(loc, box.getAddr());
3279+
return box;
3280+
},
3281+
[&](const auto &) -> fir::ExtendedValue {
3282+
fir::emitFatalError(loc, errMsg);
3283+
});
3284+
}
3285+
31843286
// FLOOR
31853287
mlir::Value IntrinsicLibrary::genFloor(mlir::Type resultType,
31863288
llvm::ArrayRef<mlir::Value> args) {

flang/lib/Optimizer/Builder/Runtime/Reduction.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,41 @@ void fir::runtime::genCountDim(fir::FirOpBuilder &builder, mlir::Location loc,
576576
builder.create<fir::CallOp>(loc, func, args);
577577
}
578578

579+
/// Generate call to `Findloc` intrinsic runtime routine. This is the version
580+
/// that does not take a dim argument.
581+
void fir::runtime::genFindloc(fir::FirOpBuilder &builder, mlir::Location loc,
582+
mlir::Value resultBox, mlir::Value arrayBox,
583+
mlir::Value valBox, mlir::Value maskBox,
584+
mlir::Value kind, mlir::Value back) {
585+
auto func = fir::runtime::getRuntimeFunc<mkRTKey(Findloc)>(loc, builder);
586+
auto fTy = func.getFunctionType();
587+
auto sourceFile = fir::factory::locationToFilename(builder, loc);
588+
auto sourceLine =
589+
fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
590+
auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
591+
arrayBox, valBox, kind, sourceFile,
592+
sourceLine, maskBox, back);
593+
builder.create<fir::CallOp>(loc, func, args);
594+
}
595+
596+
/// Generate call to `FindlocDim` intrinsic runtime routine. This is the version
597+
/// that takes a dim argument.
598+
void fir::runtime::genFindlocDim(fir::FirOpBuilder &builder, mlir::Location loc,
599+
mlir::Value resultBox, mlir::Value arrayBox,
600+
mlir::Value valBox, mlir::Value dim,
601+
mlir::Value maskBox, mlir::Value kind,
602+
mlir::Value back) {
603+
auto func = fir::runtime::getRuntimeFunc<mkRTKey(FindlocDim)>(loc, builder);
604+
auto fTy = func.getFunctionType();
605+
auto sourceFile = fir::factory::locationToFilename(builder, loc);
606+
auto sourceLine =
607+
fir::factory::locationToLineNo(builder, loc, fTy.getInput(6));
608+
auto args = fir::runtime::createArguments(
609+
builder, loc, fTy, resultBox, arrayBox, valBox, kind, dim, sourceFile,
610+
sourceLine, maskBox, back);
611+
builder.create<fir::CallOp>(loc, func, args);
612+
}
613+
579614
/// Generate call to `Maxloc` intrinsic runtime routine. This is the version
580615
/// that does not take a dim argument.
581616
void fir::runtime::genMaxloc(fir::FirOpBuilder &builder, mlir::Location loc,

flang/runtime/reduction-templates.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ inline void DoTotalReduction(const Descriptor &x, int dim,
5757
for (auto elements{x.Elements()}; elements--;
5858
x.IncrementSubscripts(xAt), mask->IncrementSubscripts(maskAt)) {
5959
if (IsLogicalElementTrue(*mask, maskAt)) {
60-
accumulator.template AccumulateAt<TYPE>(xAt);
60+
if (!accumulator.template AccumulateAt<TYPE>(xAt))
61+
break;
6162
}
6263
}
6364
return;

0 commit comments

Comments
 (0)