[flang-commits] [flang] 1dbc9b5 - Fix runtime internal error with certain intrinsics that can take a scalar

Mark Leair via flang-commits flang-commits at lists.llvm.org
Thu Jul 29 13:10:02 PDT 2021


Author: Mark Leair
Date: 2021-07-29T13:08:41-07:00
New Revision: 1dbc9b534b2a4903af0f98bde72b8f6da797bc19

URL: https://github.com/llvm/llvm-project/commit/1dbc9b534b2a4903af0f98bde72b8f6da797bc19
DIFF: https://github.com/llvm/llvm-project/commit/1dbc9b534b2a4903af0f98bde72b8f6da797bc19.diff

LOG: Fix runtime internal error with certain intrinsics that can take a scalar
result descriptor (e.g., maxloc, minloc, maxval, minval, all, any, count,
parity, findloc, etc.)

Also add a scalar case for these intrinsic unit tests.

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

Added: 
    

Modified: 
    flang/runtime/reduction-templates.h
    flang/runtime/reduction.cpp
    flang/unittests/RuntimeGTest/Reduction.cpp

Removed: 
    


################################################################################
diff  --git a/flang/runtime/reduction-templates.h b/flang/runtime/reduction-templates.h
index 3f77ac0dfb300..ff9841a9e4756 100644
--- a/flang/runtime/reduction-templates.h
+++ b/flang/runtime/reduction-templates.h
@@ -197,7 +197,7 @@ inline void PartialReduction(Descriptor &result, const Descriptor &x, int dim,
       result, x, dim, terminator, intrinsic, TypeCode{CAT, KIND});
   SubscriptValue at[maxRank];
   result.GetLowerBounds(at);
-  INTERNAL_CHECK(at[0] == 1);
+  INTERNAL_CHECK(result.rank() == 0 || at[0] == 1);
   using CppType = CppTypeFor<CAT, KIND>;
   if (mask) {
     CheckConformability(x, *mask, terminator, intrinsic, "ARRAY", "MASK");

diff  --git a/flang/runtime/reduction.cpp b/flang/runtime/reduction.cpp
index f5f6abff9b28e..66fe9efa56222 100644
--- a/flang/runtime/reduction.cpp
+++ b/flang/runtime/reduction.cpp
@@ -267,7 +267,7 @@ template <LogicalReduction REDUCTION> struct LogicalReduceHelper {
           result, x, dim, terminator, intrinsic, x.type());
       SubscriptValue at[maxRank];
       result.GetLowerBounds(at);
-      INTERNAL_CHECK(at[0] == 1);
+      INTERNAL_CHECK(result.rank() == 0 || at[0] == 1);
       using CppType = CppTypeFor<TypeCategory::Logical, KIND>;
       for (auto n{result.Elements()}; n-- > 0; result.IncrementSubscripts(at)) {
         *result.Element<CppType>(at) =
@@ -315,7 +315,7 @@ template <int KIND> struct CountDimension {
         TypeCode{TypeCategory::Integer, KIND});
     SubscriptValue at[maxRank];
     result.GetLowerBounds(at);
-    INTERNAL_CHECK(at[0] == 1);
+    INTERNAL_CHECK(result.rank() == 0 || at[0] == 1);
     using CppType = CppTypeFor<TypeCategory::Integer, KIND>;
     for (auto n{result.Elements()}; n-- > 0; result.IncrementSubscripts(at)) {
       *result.Element<CppType>(at) =

diff  --git a/flang/unittests/RuntimeGTest/Reduction.cpp b/flang/unittests/RuntimeGTest/Reduction.cpp
index 617131c6f2273..1750b914f0f88 100644
--- a/flang/unittests/RuntimeGTest/Reduction.cpp
+++ b/flang/unittests/RuntimeGTest/Reduction.cpp
@@ -146,6 +146,34 @@ TEST(Reductions, DoubleMaxMinNorm2) {
   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(10), 2); // 22
   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(11), 2); // 22
   loc.Destroy();
+  // Test scalar result for MaxlocDim, MinlocDim, MaxvalDim, MinvalDim.
+  // A scalar result occurs when you have a rank 1 array and dim == 1.
+  std::vector<int> shape1{24};
+  auto array1{MakeArray<TypeCategory::Real, 8>(shape1, rawData)};
+  StaticDescriptor<0, true> statDesc0;
+  Descriptor &scalarResult{statDesc0.descriptor()};
+  RTNAME(MaxlocDim)
+  (scalarResult, *array1, /*KIND=*/2, /*DIM=*/1, __FILE__, __LINE__,
+      /*MASK=*/nullptr, /*BACK=*/false);
+  EXPECT_EQ(scalarResult.rank(), 0);
+  EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int16_t>(0), 23);
+  scalarResult.Destroy();
+  RTNAME(MinlocDim)
+  (scalarResult, *array1, /*KIND=*/2, /*DIM=*/1, __FILE__, __LINE__,
+      /*MASK=*/nullptr, /*BACK=*/true);
+  EXPECT_EQ(scalarResult.rank(), 0);
+  EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int16_t>(0), 22);
+  scalarResult.Destroy();
+  RTNAME(MaxvalDim)
+  (scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__, /*MASK=*/nullptr);
+  EXPECT_EQ(scalarResult.rank(), 0);
+  EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<double>(0), 22.0);
+  scalarResult.Destroy();
+  RTNAME(MinvalDim)
+  (scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__, /*MASK=*/nullptr);
+  EXPECT_EQ(scalarResult.rank(), 0);
+  EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<double>(0), -21.0);
+  scalarResult.Destroy();
 }
 
 TEST(Reductions, Character) {
@@ -269,6 +297,17 @@ TEST(Reductions, Logical) {
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 0);
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 0);
   res.Destroy();
+  // Test scalar result for AllDim.
+  // A scalar result occurs when you have a rank 1 array.
+  std::vector<int> shape1{4};
+  auto array1{MakeArray<TypeCategory::Logical, 4>(
+      shape1, std::vector<std::int32_t>{false, false, true, true})};
+  StaticDescriptor<0, true> statDesc0;
+  Descriptor &scalarResult{statDesc0.descriptor()};
+  RTNAME(AllDim)(scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__);
+  EXPECT_EQ(scalarResult.rank(), 0);
+  EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int64_t>(0), 0);
+  scalarResult.Destroy();
   RTNAME(AnyDim)(res, *array, /*DIM=*/1, __FILE__, __LINE__);
   EXPECT_EQ(res.rank(), 1);
   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
@@ -285,6 +324,12 @@ TEST(Reductions, Logical) {
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
   res.Destroy();
+  // Test scalar result for AnyDim.
+  // A scalar result occurs when you have a rank 1 array.
+  RTNAME(AnyDim)(scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__);
+  EXPECT_EQ(scalarResult.rank(), 0);
+  EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int64_t>(0), 1);
+  scalarResult.Destroy();
   RTNAME(ParityDim)(res, *array, /*DIM=*/1, __FILE__, __LINE__);
   EXPECT_EQ(res.rank(), 1);
   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
@@ -301,6 +346,12 @@ TEST(Reductions, Logical) {
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
   res.Destroy();
+  // Test scalar result for ParityDim.
+  // A scalar result occurs when you have a rank 1 array.
+  RTNAME(ParityDim)(scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__);
+  EXPECT_EQ(scalarResult.rank(), 0);
+  EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int32_t>(0), 0);
+  scalarResult.Destroy();
   RTNAME(CountDim)(res, *array, /*DIM=*/1, /*KIND=*/4, __FILE__, __LINE__);
   EXPECT_EQ(res.rank(), 1);
   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
@@ -317,6 +368,13 @@ TEST(Reductions, Logical) {
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int64_t>(0), 1);
   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int64_t>(1), 1);
   res.Destroy();
+  // Test scalar result for CountDim.
+  // A scalar result occurs when you have a rank 1 array and dim == 1.
+  RTNAME(CountDim)
+  (scalarResult, *array1, /*DIM=*/1, /*KIND=*/8, __FILE__, __LINE__);
+  EXPECT_EQ(scalarResult.rank(), 0);
+  EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int64_t>(0), 2);
+  scalarResult.Destroy();
   bool boolValue{false};
   Descriptor &target{statDesc[1].descriptor()};
   target.Establish(TypeCategory::Logical, 1, static_cast<void *>(&boolValue), 0,
@@ -436,6 +494,21 @@ TEST(Reductions, FindlocNumeric) {
   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 2);
   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 0);
   res.Destroy();
+  // Test scalar result for FindlocDim.
+  // A scalar result occurs when you have a rank 1 array, value, and dim == 1.
+  std::vector<int> shape1{6};
+  auto realArray1{MakeArray<TypeCategory::Real, 8>(shape1,
+      std::vector<double>{0.0, -0.0, 1.0, 3.14,
+          std::numeric_limits<double>::quiet_NaN(),
+          std::numeric_limits<double>::infinity()})};
+  StaticDescriptor<0, true> statDesc0;
+  Descriptor &scalarResult{statDesc0.descriptor()};
+  RTNAME(FindlocDim)
+  (scalarResult, *realArray1, target, 8, /*DIM=*/1, __FILE__, __LINE__, nullptr,
+      /*BACK=*/false);
+  EXPECT_EQ(scalarResult.rank(), 0);
+  EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<SubscriptValue>(0), 3);
+  scalarResult.Destroy();
 }
 
 TEST(Reductions, DotProduct) {


        


More information about the flang-commits mailing list