Index: flang/include/flang/Runtime/reduction.h =================================================================== --- flang/include/flang/Runtime/reduction.h +++ flang/include/flang/Runtime/reduction.h @@ -211,13 +211,67 @@ void RTNAME(FindlocDim)(Descriptor &, const Descriptor &x, const Descriptor &target, int kind, int dim, const char *source, int line, const Descriptor *mask = nullptr, bool back = false); -void RTNAME(Maxloc)(Descriptor &, const Descriptor &x, int kind, +void RTNAME(MaxlocCharacter)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MaxlocInteger1)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MaxlocInteger2)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MaxlocInteger4)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MaxlocInteger8)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MaxlocInteger16)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MaxlocReal4)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MaxlocReal8)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MaxlocReal10)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MaxlocReal16)(Descriptor &, const Descriptor &, int kind, const char *source, int line, const Descriptor *mask = nullptr, bool back = false); void RTNAME(MaxlocDim)(Descriptor &, const Descriptor &x, int kind, int dim, const char *source, int line, const Descriptor *mask = nullptr, bool back = false); -void RTNAME(Minloc)(Descriptor &, const Descriptor &x, int kind, +void RTNAME(MinlocCharacter)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MinlocInteger1)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MinlocInteger2)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MinlocInteger4)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MinlocInteger8)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MinlocInteger16)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MinlocReal4)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MinlocReal8)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MinlocReal10)(Descriptor &, const Descriptor &, int kind, + const char *source, int line, const Descriptor *mask = nullptr, + bool back = false); +void RTNAME(MinlocReal16)(Descriptor &, const Descriptor &, int kind, const char *source, int line, const Descriptor *mask = nullptr, bool back = false); void RTNAME(MinlocDim)(Descriptor &, const Descriptor &x, int kind, int dim, Index: flang/lib/Optimizer/Builder/Runtime/Reduction.cpp =================================================================== --- flang/lib/Optimizer/Builder/Runtime/Reduction.cpp +++ flang/lib/Optimizer/Builder/Runtime/Reduction.cpp @@ -582,7 +582,35 @@ mlir::Value resultBox, mlir::Value arrayBox, mlir::Value maskBox, mlir::Value kind, mlir::Value back) { - auto func = fir::runtime::getRuntimeFunc(loc, builder); + mlir::func::FuncOp func; + auto ty = arrayBox.getType(); + auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); + auto eleTy = arrTy.cast().getEleTy(); + fir::factory::CharacterExprHelper charHelper{builder, loc}; + if (eleTy.isF16() || eleTy.isBF16()) + TODO(loc, "half-precision MAXLOC"); + else if (eleTy.isF32()) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isF64()) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isF80()) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isF128()) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (charHelper.isCharacterScalar(eleTy)) + func = fir::runtime::getRuntimeFunc(loc, builder); + else + fir::emitFatalError(loc, "invalid type in MAXLOC"); genReduction4Args(func, builder, loc, resultBox, arrayBox, maskBox, kind, back); } @@ -673,7 +701,35 @@ mlir::Value resultBox, mlir::Value arrayBox, mlir::Value maskBox, mlir::Value kind, mlir::Value back) { - auto func = fir::runtime::getRuntimeFunc(loc, builder); + mlir::func::FuncOp func; + auto ty = arrayBox.getType(); + auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); + auto eleTy = arrTy.cast().getEleTy(); + fir::factory::CharacterExprHelper charHelper{builder, loc}; + if (eleTy.isF16() || eleTy.isBF16()) + TODO(loc, "half-precision MINLOC"); + else if (eleTy.isF32()) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isF64()) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isF80()) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isF128()) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (charHelper.isCharacterScalar(eleTy)) + func = fir::runtime::getRuntimeFunc(loc, builder); + else + fir::emitFatalError(loc, "invalid type in MINLOC"); genReduction4Args(func, builder, loc, resultBox, arrayBox, maskBox, kind, back); } Index: flang/runtime/extrema.cpp =================================================================== --- flang/runtime/extrema.cpp +++ flang/runtime/extrema.cpp @@ -128,19 +128,19 @@ } } -template struct TypedMaxOrMinLocHelper { +template struct CharacterMaxOrMinLocHelper { template struct Functor { void operator()(const char *intrinsic, Descriptor &result, const Descriptor &x, int kind, const char *source, int line, const Descriptor *mask, bool back) const { - DoMaxOrMinLoc( + DoMaxOrMinLoc( intrinsic, result, x, kind, source, line, mask, back); } }; }; template -inline void TypedMaxOrMinLoc(const char *intrinsic, Descriptor &result, +inline void CharacterMaxOrMinLoc(const char *intrinsic, Descriptor &result, const Descriptor &x, int kind, const char *source, int line, const Descriptor *mask, bool back) { int rank{x.rank()}; @@ -157,21 +157,8 @@ auto catKind{x.type().GetCategoryAndKind()}; RUNTIME_CHECK(terminator, catKind.has_value()); switch (catKind->first) { - case TypeCategory::Integer: - ApplyIntegerKind< - TypedMaxOrMinLocHelper::template Functor, - void>(catKind->second, terminator, intrinsic, result, x, kind, source, - line, mask, back); - break; - case TypeCategory::Real: - ApplyFloatingPointKind< - TypedMaxOrMinLocHelper::template Functor, - void>(catKind->second, terminator, intrinsic, result, x, kind, source, - line, mask, back); - break; case TypeCategory::Character: - ApplyCharacterKind::template Functor, + ApplyCharacterKind::template Functor, void>(catKind->second, terminator, intrinsic, result, x, kind, source, line, mask, back); break; @@ -181,15 +168,135 @@ } } +template +inline void TotalNumericMaxOrMinLoc(const char *intrinsic, Descriptor &result, + const Descriptor &x, int kind, const char *source, int line, + const Descriptor *mask, bool back) { + int rank{x.rank()}; + SubscriptValue extent[1]{rank}; + result.Establish(TypeCategory::Integer, kind, nullptr, 1, extent, + CFI_attribute_allocatable); + result.GetDimension(0).SetBounds(1, extent[0]); + Terminator terminator{source, line}; + if (int stat{result.Allocate()}) { + terminator.Crash( + "%s: could not allocate memory for result; STAT=%d", intrinsic, stat); + } + CheckIntegerKind(terminator, kind, intrinsic); + RUNTIME_CHECK(terminator, TypeCode(CAT, KIND) == x.type()); + DoMaxOrMinLoc( + intrinsic, result, x, kind, source, line, mask, back); +} + extern "C" { -void RTNAME(Maxloc)(Descriptor &result, const Descriptor &x, int kind, +void RTNAME(MaxlocCharacter)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + CharacterMaxOrMinLoc( + "MAXLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MaxlocInteger1)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MAXLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MaxlocInteger2)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MAXLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MaxlocInteger4)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MAXLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MaxlocInteger8)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MAXLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MaxlocInteger16)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MAXLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MaxlocReal4)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MAXLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MaxlocReal8)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MAXLOC", result, x, kind, source, line, mask, back); +} +#if LDBL_MANT_DIG == 64 +void RTNAME(MaxlocReal10)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MAXLOC", result, x, kind, source, line, mask, back); +} +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +void RTNAME(MaxlocReal16)(Descriptor &result, const Descriptor &x, int kind, const char *source, int line, const Descriptor *mask, bool back) { - TypedMaxOrMinLoc("MAXLOC", result, x, kind, source, line, mask, back); + TotalNumericMaxOrMinLoc( + "MAXLOC", result, x, kind, source, line, mask, back); } -void RTNAME(Minloc)(Descriptor &result, const Descriptor &x, int kind, +#endif +void RTNAME(MinlocCharacter)(Descriptor &result, const Descriptor &x, int kind, const char *source, int line, const Descriptor *mask, bool back) { - TypedMaxOrMinLoc("MINLOC", result, x, kind, source, line, mask, back); + CharacterMaxOrMinLoc( + "MINLOC", result, x, kind, source, line, mask, back); } +void RTNAME(MinlocInteger1)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MINLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MinlocInteger2)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MINLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MinlocInteger4)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MINLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MinlocInteger8)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MINLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MinlocInteger16)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MINLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MinlocReal4)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MINLOC", result, x, kind, source, line, mask, back); +} +void RTNAME(MinlocReal8)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MINLOC", result, x, kind, source, line, mask, back); +} +#if LDBL_MANT_DIG == 64 +void RTNAME(MinlocReal10)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MINLOC", result, x, kind, source, line, mask, back); +} +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +void RTNAME(MinlocReal16)(Descriptor &result, const Descriptor &x, int kind, + const char *source, int line, const Descriptor *mask, bool back) { + TotalNumericMaxOrMinLoc( + "MINLOC", result, x, kind, source, line, mask, back); +} +#endif } // extern "C" // MAXLOC/MINLOC with DIM= Index: flang/test/Lower/Intrinsics/maxloc.f90 =================================================================== --- flang/test/Lower/Intrinsics/maxloc.f90 +++ flang/test/Lower/Intrinsics/maxloc.f90 @@ -13,7 +13,7 @@ ! CHECK-DAG: %[[a8:.*]] = fir.convert %[[c4]] : (index) -> i32 ! CHECK-DAG: %[[a10:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box res = maxloc(arr) - ! CHECK: %{{.*}} = fir.call @_FortranAMaxloc(%[[a6]], %[[a7]], %[[a8]], %{{.*}}, %{{.*}}, %[[a10]], %false) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %{{.*}} = fir.call @_FortranAMaxlocInteger4(%[[a6]], %[[a7]], %[[a8]], %{{.*}}, %{{.*}}, %[[a10]], %false) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none ! CHECK-DAG: %[[a12:.*]] = fir.load %[[a0]] : !fir.ref>>> ! CHECK-DAG: %[[a14:.*]] = fir.box_addr %[[a12]] : (!fir.box>>) -> !fir.heap> ! CHECK-DAG: fir.freemem %[[a14]] @@ -63,7 +63,7 @@ ! CHECK: } ! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_12]] : (!fir.box>) -> !fir.box ! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_14]] : (!fir.logical<4>) -> i1 - ! CHECK: fir.call @_FortranAMaxloc(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_29]], %[[VAL_30]]) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: fir.call @_FortranAMaxlocInteger4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_29]], %[[VAL_30]]) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none end subroutine ! CHECK-LABEL: func @_QPtest_maxloc_optional_array_mask( @@ -85,5 +85,5 @@ ! CHECK: } ! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_0]] : (!fir.box>>) -> !fir.box ! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_10]] : (!fir.logical<4>) -> i1 - ! CHECK: fir.call @_FortranAMaxloc(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_25]], %[[VAL_26]]) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: fir.call @_FortranAMaxlocInteger4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_25]], %[[VAL_26]]) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none end subroutine Index: flang/test/Lower/Intrinsics/minloc.f90 =================================================================== --- flang/test/Lower/Intrinsics/minloc.f90 +++ flang/test/Lower/Intrinsics/minloc.f90 @@ -13,7 +13,7 @@ ! CHECK-DAG: %[[a8:.*]] = fir.convert %[[c4]] : (index) -> i32 ! CHECK-DAG: %[[a10:.*]] = fir.convert %[[a1]] : (!fir.box) -> !fir.box res = minloc(arr) - ! CHECK: %{{.*}} = fir.call @_FortranAMinloc(%[[a6]], %[[a7]], %[[a8]], %{{.*}}, %{{.*}}, %[[a10]], %false) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: %{{.*}} = fir.call @_FortranAMinlocInteger4(%[[a6]], %[[a7]], %[[a8]], %{{.*}}, %{{.*}}, %[[a10]], %false) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none ! CHECK-DAG: %[[a12:.*]] = fir.load %[[a0]] : !fir.ref>>> ! CHECK-DAG: %[[a14:.*]] = fir.box_addr %[[a12]] : (!fir.box>>) -> !fir.heap> ! CHECK-DAG: fir.freemem %[[a14]] @@ -63,7 +63,7 @@ ! CHECK: } ! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_12]] : (!fir.box>) -> !fir.box ! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_14]] : (!fir.logical<4>) -> i1 - ! CHECK: fir.call @_FortranAMinloc(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_29]], %[[VAL_30]]) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: fir.call @_FortranAMinlocInteger4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_29]], %[[VAL_30]]) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none end subroutine ! CHECK-LABEL: func @_QPtest_minloc_optional_array_mask( @@ -85,5 +85,5 @@ ! CHECK: } ! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_0]] : (!fir.box>>) -> !fir.box ! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_10]] : (!fir.logical<4>) -> i1 - ! CHECK: fir.call @_FortranAMinloc(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_25]], %[[VAL_26]]) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none + ! CHECK: fir.call @_FortranAMinlocInteger4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_25]], %[[VAL_26]]) : (!fir.ref>, !fir.box, i32, !fir.ref, i32, !fir.box, i1) -> none end subroutine Index: flang/unittests/Optimizer/Builder/Runtime/ReductionTest.cpp =================================================================== --- flang/unittests/Optimizer/Builder/Runtime/ReductionTest.cpp +++ flang/unittests/Optimizer/Builder/Runtime/ReductionTest.cpp @@ -227,14 +227,14 @@ testGenDotProduct(*firBuilder, c16Ty, "_FortranACppDotProductComplex16"); } -void checkGenMxxloc(fir::FirOpBuilder &builder, +void checkGenMxxloc(fir::FirOpBuilder &builder, mlir::Type eleTy, void (*genFct)(fir::FirOpBuilder &, mlir::Location, mlir::Value, mlir::Value, mlir::Value, mlir::Value, mlir::Value), llvm::StringRef fctName, unsigned nbArgs) { mlir::Location loc = builder.getUnknownLoc(); mlir::Type i32Ty = builder.getI32Type(); mlir::Type seqTy = - fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); + fir::SequenceType::get(fir::SequenceType::Shape(1, 10), eleTy); mlir::Type refSeqTy = fir::ReferenceType::get(seqTy); mlir::Value a = builder.create(loc, refSeqTy); mlir::Value result = builder.create(loc, seqTy); @@ -246,11 +246,57 @@ } TEST_F(RuntimeCallTest, genMaxlocTest) { - checkGenMxxloc(*firBuilder, fir::runtime::genMaxloc, "_FortranAMaxloc", 5); + checkGenMxxloc(*firBuilder, char1Ty, fir::runtime::genMaxloc, + "_FortranAMaxlocCharacter", 5); + checkGenMxxloc(*firBuilder, char2Ty, fir::runtime::genMaxloc, + "_FortranAMaxlocCharacter", 5); + checkGenMxxloc(*firBuilder, char4Ty, fir::runtime::genMaxloc, + "_FortranAMaxlocCharacter", 5); + checkGenMxxloc( + *firBuilder, i8Ty, fir::runtime::genMaxloc, "_FortranAMaxlocInteger1", 5); + checkGenMxxloc(*firBuilder, i16Ty, fir::runtime::genMaxloc, + "_FortranAMaxlocInteger2", 5); + checkGenMxxloc(*firBuilder, i32Ty, fir::runtime::genMaxloc, + "_FortranAMaxlocInteger4", 5); + checkGenMxxloc(*firBuilder, i64Ty, fir::runtime::genMaxloc, + "_FortranAMaxlocInteger8", 5); + checkGenMxxloc(*firBuilder, i128Ty, fir::runtime::genMaxloc, + "_FortranAMaxlocInteger16", 5); + checkGenMxxloc( + *firBuilder, f32Ty, fir::runtime::genMaxloc, "_FortranAMaxlocReal4", 5); + checkGenMxxloc( + *firBuilder, f64Ty, fir::runtime::genMaxloc, "_FortranAMaxlocReal8", 5); + checkGenMxxloc( + *firBuilder, f80Ty, fir::runtime::genMaxloc, "_FortranAMaxlocReal10", 5); + checkGenMxxloc( + *firBuilder, f128Ty, fir::runtime::genMaxloc, "_FortranAMaxlocReal16", 5); } TEST_F(RuntimeCallTest, genMinlocTest) { - checkGenMxxloc(*firBuilder, fir::runtime::genMinloc, "_FortranAMinloc", 5); + checkGenMxxloc(*firBuilder, char1Ty, fir::runtime::genMinloc, + "_FortranAMinlocCharacter", 5); + checkGenMxxloc(*firBuilder, char2Ty, fir::runtime::genMinloc, + "_FortranAMinlocCharacter", 5); + checkGenMxxloc(*firBuilder, char4Ty, fir::runtime::genMinloc, + "_FortranAMinlocCharacter", 5); + checkGenMxxloc( + *firBuilder, i8Ty, fir::runtime::genMinloc, "_FortranAMinlocInteger1", 5); + checkGenMxxloc(*firBuilder, i16Ty, fir::runtime::genMinloc, + "_FortranAMinlocInteger2", 5); + checkGenMxxloc(*firBuilder, i32Ty, fir::runtime::genMinloc, + "_FortranAMinlocInteger4", 5); + checkGenMxxloc(*firBuilder, i64Ty, fir::runtime::genMinloc, + "_FortranAMinlocInteger8", 5); + checkGenMxxloc(*firBuilder, i128Ty, fir::runtime::genMinloc, + "_FortranAMinlocInteger16", 5); + checkGenMxxloc( + *firBuilder, f32Ty, fir::runtime::genMinloc, "_FortranAMinlocReal4", 5); + checkGenMxxloc( + *firBuilder, f64Ty, fir::runtime::genMinloc, "_FortranAMinlocReal8", 5); + checkGenMxxloc( + *firBuilder, f80Ty, fir::runtime::genMinloc, "_FortranAMinlocReal10", 5); + checkGenMxxloc( + *firBuilder, f128Ty, fir::runtime::genMinloc, "_FortranAMinlocReal16", 5); } void checkGenMxxlocDim(fir::FirOpBuilder &builder, Index: flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h =================================================================== --- flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h +++ flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h @@ -54,6 +54,10 @@ seqTy10 = fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); boxTy = fir::BoxType::get(mlir::NoneType::get(firBuilder->getContext())); + + char1Ty = fir::CharacterType::getSingleton(builder.getContext(), 1); + char2Ty = fir::CharacterType::getSingleton(builder.getContext(), 2); + char4Ty = fir::CharacterType::getSingleton(builder.getContext(), 4); } mlir::MLIRContext context; @@ -77,6 +81,9 @@ mlir::Type c16Ty; mlir::Type seqTy10; mlir::Type boxTy; + mlir::Type char1Ty; + mlir::Type char2Ty; + mlir::Type char4Ty; }; /// Check that the \p op is a `fir::CallOp` operation and its name matches Index: flang/unittests/Runtime/Reduction.cpp =================================================================== --- flang/unittests/Runtime/Reduction.cpp +++ flang/unittests/Runtime/Reduction.cpp @@ -74,7 +74,7 @@ EXPECT_LE(norm2Error, 0.000001 * naiveNorm2); StaticDescriptor<2, true> statDesc; Descriptor &loc{statDesc.descriptor()}; - RTNAME(Maxloc) + RTNAME(MaxlocReal8) (loc, *array, /*KIND=*/8, __FILE__, __LINE__, /*MASK=*/nullptr, /*BACK=*/false); EXPECT_EQ(loc.rank(), 1); @@ -88,7 +88,7 @@ EXPECT_EQ(*loc.ZeroBasedIndexedElement(1), 4); EXPECT_EQ(*loc.ZeroBasedIndexedElement(2), 2); loc.Destroy(); - RTNAME(Maxloc) + RTNAME(MaxlocReal8) (loc, *array, /*KIND=*/8, __FILE__, __LINE__, /*MASK=*/nullptr, /*BACK=*/true); EXPECT_EQ(loc.rank(), 1); @@ -264,7 +264,7 @@ EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Character, 1}.raw())); EXPECT_EQ(std::memcmp(res.OffsetElement(), "abc", 3), 0); res.Destroy(); - RTNAME(Maxloc) + RTNAME(MaxlocCharacter) (res, *array, /*KIND=*/4, __FILE__, __LINE__, /*MASK=*/nullptr, /*BACK=*/false); EXPECT_EQ(res.rank(), 1); @@ -276,7 +276,7 @@ res.Destroy(); auto mask{MakeArray( shape, std::vector{false, true, false, true, false, true})}; - RTNAME(Maxloc) + RTNAME(MaxlocCharacter) (res, *array, /*KIND=*/4, __FILE__, __LINE__, /*MASK=*/&*mask, /*BACK=*/false); EXPECT_EQ(res.rank(), 1); @@ -286,7 +286,7 @@ EXPECT_EQ(*res.ZeroBasedIndexedElement(0), 2); EXPECT_EQ(*res.ZeroBasedIndexedElement(1), 2); res.Destroy(); - RTNAME(Minloc) + RTNAME(MinlocCharacter) (res, *array, /*KIND=*/4, __FILE__, __LINE__, /*MASK=*/nullptr, /*BACK=*/false); EXPECT_EQ(res.rank(), 1); @@ -296,7 +296,7 @@ EXPECT_EQ(*res.ZeroBasedIndexedElement(0), 1); EXPECT_EQ(*res.ZeroBasedIndexedElement(1), 1); res.Destroy(); - RTNAME(Minloc) + RTNAME(MinlocCharacter) (res, *array, /*KIND=*/4, __FILE__, __LINE__, /*MASK=*/nullptr, /*BACK=*/true); EXPECT_EQ(res.rank(), 1); @@ -306,7 +306,7 @@ EXPECT_EQ(*res.ZeroBasedIndexedElement(0), 2); EXPECT_EQ(*res.ZeroBasedIndexedElement(1), 3); res.Destroy(); - RTNAME(Minloc) + RTNAME(MinlocCharacter) (res, *array, /*KIND=*/4, __FILE__, __LINE__, /*MASK=*/&*mask, /*BACK=*/true); EXPECT_EQ(res.rank(), 1);