Skip to content

Commit 1dbc9b5

Browse files
committed
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
1 parent b4d945b commit 1dbc9b5

File tree

3 files changed

+76
-3
lines changed

3 files changed

+76
-3
lines changed

flang/runtime/reduction-templates.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ inline void PartialReduction(Descriptor &result, const Descriptor &x, int dim,
197197
result, x, dim, terminator, intrinsic, TypeCode{CAT, KIND});
198198
SubscriptValue at[maxRank];
199199
result.GetLowerBounds(at);
200-
INTERNAL_CHECK(at[0] == 1);
200+
INTERNAL_CHECK(result.rank() == 0 || at[0] == 1);
201201
using CppType = CppTypeFor<CAT, KIND>;
202202
if (mask) {
203203
CheckConformability(x, *mask, terminator, intrinsic, "ARRAY", "MASK");

flang/runtime/reduction.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ template <LogicalReduction REDUCTION> struct LogicalReduceHelper {
267267
result, x, dim, terminator, intrinsic, x.type());
268268
SubscriptValue at[maxRank];
269269
result.GetLowerBounds(at);
270-
INTERNAL_CHECK(at[0] == 1);
270+
INTERNAL_CHECK(result.rank() == 0 || at[0] == 1);
271271
using CppType = CppTypeFor<TypeCategory::Logical, KIND>;
272272
for (auto n{result.Elements()}; n-- > 0; result.IncrementSubscripts(at)) {
273273
*result.Element<CppType>(at) =
@@ -315,7 +315,7 @@ template <int KIND> struct CountDimension {
315315
TypeCode{TypeCategory::Integer, KIND});
316316
SubscriptValue at[maxRank];
317317
result.GetLowerBounds(at);
318-
INTERNAL_CHECK(at[0] == 1);
318+
INTERNAL_CHECK(result.rank() == 0 || at[0] == 1);
319319
using CppType = CppTypeFor<TypeCategory::Integer, KIND>;
320320
for (auto n{result.Elements()}; n-- > 0; result.IncrementSubscripts(at)) {
321321
*result.Element<CppType>(at) =

flang/unittests/RuntimeGTest/Reduction.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,34 @@ TEST(Reductions, DoubleMaxMinNorm2) {
146146
EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(10), 2); // 22
147147
EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(11), 2); // 22
148148
loc.Destroy();
149+
// Test scalar result for MaxlocDim, MinlocDim, MaxvalDim, MinvalDim.
150+
// A scalar result occurs when you have a rank 1 array and dim == 1.
151+
std::vector<int> shape1{24};
152+
auto array1{MakeArray<TypeCategory::Real, 8>(shape1, rawData)};
153+
StaticDescriptor<0, true> statDesc0;
154+
Descriptor &scalarResult{statDesc0.descriptor()};
155+
RTNAME(MaxlocDim)
156+
(scalarResult, *array1, /*KIND=*/2, /*DIM=*/1, __FILE__, __LINE__,
157+
/*MASK=*/nullptr, /*BACK=*/false);
158+
EXPECT_EQ(scalarResult.rank(), 0);
159+
EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int16_t>(0), 23);
160+
scalarResult.Destroy();
161+
RTNAME(MinlocDim)
162+
(scalarResult, *array1, /*KIND=*/2, /*DIM=*/1, __FILE__, __LINE__,
163+
/*MASK=*/nullptr, /*BACK=*/true);
164+
EXPECT_EQ(scalarResult.rank(), 0);
165+
EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int16_t>(0), 22);
166+
scalarResult.Destroy();
167+
RTNAME(MaxvalDim)
168+
(scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__, /*MASK=*/nullptr);
169+
EXPECT_EQ(scalarResult.rank(), 0);
170+
EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<double>(0), 22.0);
171+
scalarResult.Destroy();
172+
RTNAME(MinvalDim)
173+
(scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__, /*MASK=*/nullptr);
174+
EXPECT_EQ(scalarResult.rank(), 0);
175+
EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<double>(0), -21.0);
176+
scalarResult.Destroy();
149177
}
150178

151179
TEST(Reductions, Character) {
@@ -269,6 +297,17 @@ TEST(Reductions, Logical) {
269297
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 0);
270298
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 0);
271299
res.Destroy();
300+
// Test scalar result for AllDim.
301+
// A scalar result occurs when you have a rank 1 array.
302+
std::vector<int> shape1{4};
303+
auto array1{MakeArray<TypeCategory::Logical, 4>(
304+
shape1, std::vector<std::int32_t>{false, false, true, true})};
305+
StaticDescriptor<0, true> statDesc0;
306+
Descriptor &scalarResult{statDesc0.descriptor()};
307+
RTNAME(AllDim)(scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__);
308+
EXPECT_EQ(scalarResult.rank(), 0);
309+
EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int64_t>(0), 0);
310+
scalarResult.Destroy();
272311
RTNAME(AnyDim)(res, *array, /*DIM=*/1, __FILE__, __LINE__);
273312
EXPECT_EQ(res.rank(), 1);
274313
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
@@ -285,6 +324,12 @@ TEST(Reductions, Logical) {
285324
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
286325
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
287326
res.Destroy();
327+
// Test scalar result for AnyDim.
328+
// A scalar result occurs when you have a rank 1 array.
329+
RTNAME(AnyDim)(scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__);
330+
EXPECT_EQ(scalarResult.rank(), 0);
331+
EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int64_t>(0), 1);
332+
scalarResult.Destroy();
288333
RTNAME(ParityDim)(res, *array, /*DIM=*/1, __FILE__, __LINE__);
289334
EXPECT_EQ(res.rank(), 1);
290335
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
@@ -301,6 +346,12 @@ TEST(Reductions, Logical) {
301346
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
302347
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
303348
res.Destroy();
349+
// Test scalar result for ParityDim.
350+
// A scalar result occurs when you have a rank 1 array.
351+
RTNAME(ParityDim)(scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__);
352+
EXPECT_EQ(scalarResult.rank(), 0);
353+
EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int32_t>(0), 0);
354+
scalarResult.Destroy();
304355
RTNAME(CountDim)(res, *array, /*DIM=*/1, /*KIND=*/4, __FILE__, __LINE__);
305356
EXPECT_EQ(res.rank(), 1);
306357
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
@@ -317,6 +368,13 @@ TEST(Reductions, Logical) {
317368
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int64_t>(0), 1);
318369
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int64_t>(1), 1);
319370
res.Destroy();
371+
// Test scalar result for CountDim.
372+
// A scalar result occurs when you have a rank 1 array and dim == 1.
373+
RTNAME(CountDim)
374+
(scalarResult, *array1, /*DIM=*/1, /*KIND=*/8, __FILE__, __LINE__);
375+
EXPECT_EQ(scalarResult.rank(), 0);
376+
EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int64_t>(0), 2);
377+
scalarResult.Destroy();
320378
bool boolValue{false};
321379
Descriptor &target{statDesc[1].descriptor()};
322380
target.Establish(TypeCategory::Logical, 1, static_cast<void *>(&boolValue), 0,
@@ -436,6 +494,21 @@ TEST(Reductions, FindlocNumeric) {
436494
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 2);
437495
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 0);
438496
res.Destroy();
497+
// Test scalar result for FindlocDim.
498+
// A scalar result occurs when you have a rank 1 array, value, and dim == 1.
499+
std::vector<int> shape1{6};
500+
auto realArray1{MakeArray<TypeCategory::Real, 8>(shape1,
501+
std::vector<double>{0.0, -0.0, 1.0, 3.14,
502+
std::numeric_limits<double>::quiet_NaN(),
503+
std::numeric_limits<double>::infinity()})};
504+
StaticDescriptor<0, true> statDesc0;
505+
Descriptor &scalarResult{statDesc0.descriptor()};
506+
RTNAME(FindlocDim)
507+
(scalarResult, *realArray1, target, 8, /*DIM=*/1, __FILE__, __LINE__, nullptr,
508+
/*BACK=*/false);
509+
EXPECT_EQ(scalarResult.rank(), 0);
510+
EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<SubscriptValue>(0), 3);
511+
scalarResult.Destroy();
439512
}
440513

441514
TEST(Reductions, DotProduct) {

0 commit comments

Comments
 (0)