[flang-commits] [flang] 9f6aae4 - [flang] Add type-specific runtime entries for Minloc/Maxloc.

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Mon Oct 10 17:00:21 PDT 2022


Author: Slava Zakharin
Date: 2022-10-10T16:58:33-07:00
New Revision: 9f6aae46062e4f4e560cb3ae7a0110260a3c75da

URL: https://github.com/llvm/llvm-project/commit/9f6aae46062e4f4e560cb3ae7a0110260a3c75da
DIFF: https://github.com/llvm/llvm-project/commit/9f6aae46062e4f4e560cb3ae7a0110260a3c75da.diff

LOG: [flang] Add type-specific runtime entries for Minloc/Maxloc.

We used to have a big switch statement over the type categories and kinds
inside Minloc/Maxloc. After D133051 the switch grew bigger, and this
changed inlining decisions made by GCC (the build compiler). Some of the
simple methods stopped being inlined, and this caused slight performance
regression in Polyhedron/gas_dyn2. This change adds separate entries
for real/integer data types to let them be optimized separately.

Differential Revision: https://reviews.llvm.org/D135610

Added: 
    

Modified: 
    flang/include/flang/Runtime/reduction.h
    flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
    flang/runtime/extrema.cpp
    flang/test/Lower/Intrinsics/maxloc.f90
    flang/test/Lower/Intrinsics/minloc.f90
    flang/unittests/Optimizer/Builder/Runtime/ReductionTest.cpp
    flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h
    flang/unittests/Runtime/Reduction.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Runtime/reduction.h b/flang/include/flang/Runtime/reduction.h
index 411b90432a1c0..43da1d36c763b 100644
--- a/flang/include/flang/Runtime/reduction.h
+++ b/flang/include/flang/Runtime/reduction.h
@@ -211,13 +211,67 @@ void RTNAME(Findloc)(Descriptor &, const Descriptor &x,
 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,

diff  --git a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
index dd19b6589c06a..bd90741114249 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
@@ -582,7 +582,35 @@ void fir::runtime::genMaxloc(fir::FirOpBuilder &builder, mlir::Location loc,
                              mlir::Value resultBox, mlir::Value arrayBox,
                              mlir::Value maskBox, mlir::Value kind,
                              mlir::Value back) {
-  auto func = fir::runtime::getRuntimeFunc<mkRTKey(Maxloc)>(loc, builder);
+  mlir::func::FuncOp func;
+  auto ty = arrayBox.getType();
+  auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
+  auto eleTy = arrTy.cast<fir::SequenceType>().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<mkRTKey(MaxlocReal4)>(loc, builder);
+  else if (eleTy.isF64())
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocReal8)>(loc, builder);
+  else if (eleTy.isF80())
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocReal10)>(loc, builder);
+  else if (eleTy.isF128())
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocReal16)>(loc, builder);
+  else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1)))
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocInteger1)>(loc, builder);
+  else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2)))
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocInteger2)>(loc, builder);
+  else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4)))
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocInteger4)>(loc, builder);
+  else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8)))
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocInteger8)>(loc, builder);
+  else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16)))
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocInteger16)>(loc, builder);
+  else if (charHelper.isCharacterScalar(eleTy))
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocCharacter)>(loc, builder);
+  else
+    fir::emitFatalError(loc, "invalid type in MAXLOC");
   genReduction4Args(func, builder, loc, resultBox, arrayBox, maskBox, kind,
                     back);
 }
@@ -673,7 +701,35 @@ void fir::runtime::genMinloc(fir::FirOpBuilder &builder, mlir::Location loc,
                              mlir::Value resultBox, mlir::Value arrayBox,
                              mlir::Value maskBox, mlir::Value kind,
                              mlir::Value back) {
-  auto func = fir::runtime::getRuntimeFunc<mkRTKey(Minloc)>(loc, builder);
+  mlir::func::FuncOp func;
+  auto ty = arrayBox.getType();
+  auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
+  auto eleTy = arrTy.cast<fir::SequenceType>().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<mkRTKey(MinlocReal4)>(loc, builder);
+  else if (eleTy.isF64())
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocReal8)>(loc, builder);
+  else if (eleTy.isF80())
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocReal10)>(loc, builder);
+  else if (eleTy.isF128())
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocReal16)>(loc, builder);
+  else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1)))
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocInteger1)>(loc, builder);
+  else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2)))
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocInteger2)>(loc, builder);
+  else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4)))
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocInteger4)>(loc, builder);
+  else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8)))
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocInteger8)>(loc, builder);
+  else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16)))
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocInteger16)>(loc, builder);
+  else if (charHelper.isCharacterScalar(eleTy))
+    func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocCharacter)>(loc, builder);
+  else
+    fir::emitFatalError(loc, "invalid type in MINLOC");
   genReduction4Args(func, builder, loc, resultBox, arrayBox, maskBox, kind,
                     back);
 }

diff  --git a/flang/runtime/extrema.cpp b/flang/runtime/extrema.cpp
index a1413b4734446..6e7e07c1fdf51 100644
--- a/flang/runtime/extrema.cpp
+++ b/flang/runtime/extrema.cpp
@@ -128,19 +128,19 @@ inline void DoMaxOrMinLoc(const char *intrinsic, Descriptor &result,
   }
 }
 
-template <TypeCategory CAT, bool IS_MAX> struct TypedMaxOrMinLocHelper {
+template <bool IS_MAX> struct CharacterMaxOrMinLocHelper {
   template <int KIND> 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<CAT, KIND, IS_MAX, NumericCompare>(
+      DoMaxOrMinLoc<TypeCategory::Character, KIND, IS_MAX, NumericCompare>(
           intrinsic, result, x, kind, source, line, mask, back);
     }
   };
 };
 
 template <bool IS_MAX>
-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 @@ inline void TypedMaxOrMinLoc(const char *intrinsic, Descriptor &result,
   auto catKind{x.type().GetCategoryAndKind()};
   RUNTIME_CHECK(terminator, catKind.has_value());
   switch (catKind->first) {
-  case TypeCategory::Integer:
-    ApplyIntegerKind<
-        TypedMaxOrMinLocHelper<TypeCategory::Integer, IS_MAX>::template Functor,
-        void>(catKind->second, terminator, intrinsic, result, x, kind, source,
-        line, mask, back);
-    break;
-  case TypeCategory::Real:
-    ApplyFloatingPointKind<
-        TypedMaxOrMinLocHelper<TypeCategory::Real, IS_MAX>::template Functor,
-        void>(catKind->second, terminator, intrinsic, result, x, kind, source,
-        line, mask, back);
-    break;
   case TypeCategory::Character:
-    ApplyCharacterKind<TypedMaxOrMinLocHelper<TypeCategory::Character,
-                           IS_MAX>::template Functor,
+    ApplyCharacterKind<CharacterMaxOrMinLocHelper<IS_MAX>::template Functor,
         void>(catKind->second, terminator, intrinsic, result, x, kind, source,
         line, mask, back);
     break;
@@ -181,15 +168,135 @@ inline void TypedMaxOrMinLoc(const char *intrinsic, Descriptor &result,
   }
 }
 
+template <TypeCategory CAT, int KIND, bool IS_MAXVAL>
+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<CAT, KIND, IS_MAXVAL, NumericCompare>(
+      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<true>(
+      "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<TypeCategory::Integer, 1, true>(
+      "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<TypeCategory::Integer, 2, true>(
+      "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<TypeCategory::Integer, 4, true>(
+      "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<TypeCategory::Integer, 8, true>(
+      "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<TypeCategory::Integer, 16, true>(
+      "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<TypeCategory::Real, 4, true>(
+      "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<TypeCategory::Real, 8, true>(
+      "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<TypeCategory::Real, 10, true>(
+      "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<true>("MAXLOC", result, x, kind, source, line, mask, back);
+  TotalNumericMaxOrMinLoc<TypeCategory::Real, 16, true>(
+      "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<false>("MINLOC", result, x, kind, source, line, mask, back);
+  CharacterMaxOrMinLoc<false>(
+      "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<TypeCategory::Integer, 1, false>(
+      "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<TypeCategory::Integer, 2, false>(
+      "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<TypeCategory::Integer, 4, false>(
+      "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<TypeCategory::Integer, 8, false>(
+      "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<TypeCategory::Integer, 16, false>(
+      "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<TypeCategory::Real, 4, false>(
+      "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<TypeCategory::Real, 8, false>(
+      "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<TypeCategory::Real, 10, false>(
+      "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<TypeCategory::Real, 16, false>(
+      "MINLOC", result, x, kind, source, line, mask, back);
+}
+#endif
 } // extern "C"
 
 // MAXLOC/MINLOC with DIM=

diff  --git a/flang/test/Lower/Intrinsics/maxloc.f90 b/flang/test/Lower/Intrinsics/maxloc.f90
index 9fe28f2d86b34..a36c2d2b7a847 100644
--- a/flang/test/Lower/Intrinsics/maxloc.f90
+++ b/flang/test/Lower/Intrinsics/maxloc.f90
@@ -13,7 +13,7 @@ subroutine maxloc_test(arr,res)
   ! CHECK-DAG: %[[a8:.*]] = fir.convert %[[c4]] : (index) -> i32
   ! CHECK-DAG: %[[a10:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
     res = maxloc(arr)
-  ! CHECK: %{{.*}} = fir.call @_FortranAMaxloc(%[[a6]], %[[a7]], %[[a8]], %{{.*}}, %{{.*}}, %[[a10]], %false) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %{{.*}} = fir.call @_FortranAMaxlocInteger4(%[[a6]], %[[a7]], %[[a8]], %{{.*}}, %{{.*}}, %[[a10]], %false) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
   ! CHECK-DAG: %[[a12:.*]] = fir.load %[[a0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
   ! CHECK-DAG: %[[a14:.*]] = fir.box_addr %[[a12]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
   ! CHECK-DAG: fir.freemem %[[a14]]
@@ -63,7 +63,7 @@ subroutine test_maxloc_optional_scalar_mask(mask, back, array)
   ! CHECK:  }
   ! CHECK:  %[[VAL_29:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.logical<4>>) -> !fir.box<none>
   ! CHECK:  %[[VAL_30:.*]] = fir.convert %[[VAL_14]] : (!fir.logical<4>) -> i1
-  ! CHECK:  fir.call @_FortranAMaxloc(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_29]], %[[VAL_30]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK:  fir.call @_FortranAMaxlocInteger4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_29]], %[[VAL_30]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
   end subroutine
   
   ! CHECK-LABEL: func @_QPtest_maxloc_optional_array_mask(
@@ -85,5 +85,5 @@ subroutine test_maxloc_optional_array_mask(mask, back, array)
   ! CHECK:  }
   ! CHECK:  %[[VAL_25:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
   ! CHECK:  %[[VAL_26:.*]] = fir.convert %[[VAL_10]] : (!fir.logical<4>) -> i1
-  ! CHECK:  fir.call @_FortranAMaxloc(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_25]], %[[VAL_26]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK:  fir.call @_FortranAMaxlocInteger4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_25]], %[[VAL_26]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
   end subroutine

diff  --git a/flang/test/Lower/Intrinsics/minloc.f90 b/flang/test/Lower/Intrinsics/minloc.f90
index b16edcea4762c..62e17ec1733f6 100644
--- a/flang/test/Lower/Intrinsics/minloc.f90
+++ b/flang/test/Lower/Intrinsics/minloc.f90
@@ -13,7 +13,7 @@ subroutine minloc_test(arr,res)
   ! CHECK-DAG: %[[a8:.*]] = fir.convert %[[c4]] : (index) -> i32
   ! CHECK-DAG: %[[a10:.*]] = fir.convert %[[a1]] : (!fir.box<i1>) -> !fir.box<none>
     res = minloc(arr)
-  ! CHECK: %{{.*}} = fir.call @_FortranAMinloc(%[[a6]], %[[a7]], %[[a8]], %{{.*}}, %{{.*}}, %[[a10]], %false) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK: %{{.*}} = fir.call @_FortranAMinlocInteger4(%[[a6]], %[[a7]], %[[a8]], %{{.*}}, %{{.*}}, %[[a10]], %false) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
   ! CHECK-DAG: %[[a12:.*]] = fir.load %[[a0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
   ! CHECK-DAG: %[[a14:.*]] = fir.box_addr %[[a12]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
   ! CHECK-DAG: fir.freemem %[[a14]]
@@ -63,7 +63,7 @@ subroutine test_minloc_optional_scalar_mask(mask, back, array)
   ! CHECK:  }
   ! CHECK:  %[[VAL_29:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.logical<4>>) -> !fir.box<none>
   ! CHECK:  %[[VAL_30:.*]] = fir.convert %[[VAL_14]] : (!fir.logical<4>) -> i1
-  ! CHECK:  fir.call @_FortranAMinloc(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_29]], %[[VAL_30]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK:  fir.call @_FortranAMinlocInteger4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_29]], %[[VAL_30]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
   end subroutine
   
   ! CHECK-LABEL: func @_QPtest_minloc_optional_array_mask(
@@ -85,5 +85,5 @@ subroutine test_minloc_optional_array_mask(mask, back, array)
   ! CHECK:  }
   ! CHECK:  %[[VAL_25:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
   ! CHECK:  %[[VAL_26:.*]] = fir.convert %[[VAL_10]] : (!fir.logical<4>) -> i1
-  ! CHECK:  fir.call @_FortranAMinloc(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_25]], %[[VAL_26]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
+  ! CHECK:  fir.call @_FortranAMinlocInteger4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_25]], %[[VAL_26]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> none
   end subroutine

diff  --git a/flang/unittests/Optimizer/Builder/Runtime/ReductionTest.cpp b/flang/unittests/Optimizer/Builder/Runtime/ReductionTest.cpp
index fea28d0c7e663..a4006c6b59c12 100644
--- a/flang/unittests/Optimizer/Builder/Runtime/ReductionTest.cpp
+++ b/flang/unittests/Optimizer/Builder/Runtime/ReductionTest.cpp
@@ -227,14 +227,14 @@ TEST_F(RuntimeCallTest, genDotProduct) {
   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<fir::UndefOp>(loc, refSeqTy);
   mlir::Value result = builder.create<fir::UndefOp>(loc, seqTy);
@@ -246,11 +246,57 @@ void checkGenMxxloc(fir::FirOpBuilder &builder,
 }
 
 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,

diff  --git a/flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h b/flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h
index 4b7c9f18543a8..6b387eca9b988 100644
--- a/flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h
+++ b/flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h
@@ -54,6 +54,10 @@ struct RuntimeCallTest : public testing::Test {
 
     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 @@ struct RuntimeCallTest : public testing::Test {
   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

diff  --git a/flang/unittests/Runtime/Reduction.cpp b/flang/unittests/Runtime/Reduction.cpp
index 6f499b7203438..064edd4ce3db7 100644
--- a/flang/unittests/Runtime/Reduction.cpp
+++ b/flang/unittests/Runtime/Reduction.cpp
@@ -74,7 +74,7 @@ TEST(Reductions, DoubleMaxMinNorm2) {
   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 @@ TEST(Reductions, DoubleMaxMinNorm2) {
   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int64_t>(1), 4);
   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int64_t>(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 @@ TEST(Reductions, Character) {
   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Character, 1}.raw()));
   EXPECT_EQ(std::memcmp(res.OffsetElement<char>(), "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 @@ TEST(Reductions, Character) {
   res.Destroy();
   auto mask{MakeArray<TypeCategory::Logical, 1>(
       shape, std::vector<bool>{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 @@ TEST(Reductions, Character) {
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 2);
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(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 @@ TEST(Reductions, Character) {
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(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 @@ TEST(Reductions, Character) {
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 2);
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 3);
   res.Destroy();
-  RTNAME(Minloc)
+  RTNAME(MinlocCharacter)
   (res, *array, /*KIND=*/4, __FILE__, __LINE__, /*MASK=*/&*mask,
       /*BACK=*/true);
   EXPECT_EQ(res.rank(), 1);


        


More information about the flang-commits mailing list