From 8d672c0b3e70b060e215cbd13536a10b50f6fab2 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Tue, 20 Apr 2021 09:19:21 -0700 Subject: [PATCH] [flang] Implement IPARITY, PARITY, and FINDLOC reductions Define APIs for, and implement, these three more recently-introduced standard reduction transformational intrinsic functions to the runtime. Differential Revision: https://reviews.llvm.org/D100863 --- flang/runtime/reduction.cpp | 1123 +++++++++++++++++----------- flang/runtime/reduction.h | 42 +- flang/runtime/terminator.h | 4 + flang/runtime/tools.h | 79 ++ flang/unittests/RuntimeGTest/Reduction.cpp | 168 ++++- 5 files changed, 956 insertions(+), 460 deletions(-) diff --git a/flang/runtime/reduction.cpp b/flang/runtime/reduction.cpp index 1f4ed50..50fbc5b 100644 --- a/flang/runtime/reduction.cpp +++ b/flang/runtime/reduction.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// -// Implements ALL, ANY, COUNT, MAXLOC, MAXVAL, MINLOC, MINVAL, PRODUCT, and SUM -// for all required operand types and shapes and (for MAXLOC & MINLOC) kinds of -// results. +// Implements ALL, ANY, COUNT, FINDLOC, IPARITY, MAXLOC, MAXVAL, MINLOC, MINVAL, +// PARITY, PRODUCT, and SUM for all required operand types and shapes and, +// for FINDLOC, MAXLOC, & MINLOC, kinds of results. // // * Real and complex SUM reductions attempt to reduce floating-point // cancellation on intermediate results by adding up partial sums @@ -16,7 +16,7 @@ // * Partial reductions (i.e., those with DIM= arguments that are not // required to be 1 by the rank of the argument) return arrays that // are dynamically allocated in a caller-supplied descriptor. -// * Total reductions (i.e., no DIM= argument) with MAXLOC & MINLOC +// * Total reductions (i.e., no DIM= argument) with FINDLOC, MAXLOC, & MINLOC // return integer vectors of some kind, not scalars; a caller-supplied // descriptor is used // * Character-valued reductions (MAXVAL & MINVAL) return arbitrary @@ -46,8 +46,8 @@ namespace Fortran::runtime { // member function that copies a final result into its destination. // Total reduction of the array argument to a scalar (or to a vector in the -// cases of MAXLOC & MINLOC). These are the cases without DIM= or cases -// where the argument has rank 1 and DIM=, if present, must be 1. +// cases of FINDLOC, MAXLOC, & MINLOC). These are the cases without DIM= or +// cases where the argument has rank 1 and DIM=, if present, must be 1. template inline void DoTotalReduction(const Descriptor &x, int dim, const Descriptor *mask, ACCUMULATOR &accumulator, const char *intrinsic, @@ -122,8 +122,7 @@ inline void GetExpandedSubscripts(SubscriptValue at[], template inline void ReduceDimToScalar(const Descriptor &x, int zeroBasedDim, - SubscriptValue subscripts[], TYPE *result) { - ACCUMULATOR accumulator{x}; + SubscriptValue subscripts[], TYPE *result, ACCUMULATOR &accumulator) { SubscriptValue xAt[maxRank]; GetExpandedSubscripts(xAt, x, zeroBasedDim, subscripts); const auto &dim{x.GetDimension(zeroBasedDim)}; @@ -143,8 +142,8 @@ inline void ReduceDimToScalar(const Descriptor &x, int zeroBasedDim, template inline void ReduceDimMaskToScalar(const Descriptor &x, int zeroBasedDim, - SubscriptValue subscripts[], const Descriptor &mask, TYPE *result) { - ACCUMULATOR accumulator{x}; + SubscriptValue subscripts[], const Descriptor &mask, TYPE *result, + ACCUMULATOR &accumulator) { SubscriptValue xAt[maxRank], maskAt[maxRank]; GetExpandedSubscripts(xAt, x, zeroBasedDim, subscripts); GetExpandedSubscripts(maskAt, mask, zeroBasedDim, subscripts); @@ -201,7 +200,8 @@ static void CreatePartialReductionResult(Descriptor &result, template inline void PartialReduction(Descriptor &result, const Descriptor &x, int dim, - const Descriptor *mask, Terminator &terminator, const char *intrinsic) { + const Descriptor *mask, Terminator &terminator, const char *intrinsic, + ACCUMULATOR &accumulator) { CreatePartialReductionResult( result, x, dim, terminator, intrinsic, TypeCode{CAT, KIND}); SubscriptValue at[maxRank]; @@ -213,13 +213,14 @@ inline void PartialReduction(Descriptor &result, const Descriptor &x, int dim, SubscriptValue maskAt[maxRank]; // contents unused if (mask->rank() > 0) { for (auto n{result.Elements()}; n-- > 0; result.IncrementSubscripts(at)) { + accumulator.Reinitialize(); ReduceDimMaskToScalar( - x, dim - 1, at, *mask, result.Element(at)); + x, dim - 1, at, *mask, result.Element(at), accumulator); } return; } else if (!IsLogicalElementTrue(*mask, maskAt)) { // scalar MASK=.FALSE. - ACCUMULATOR accumulator{x}; + accumulator.Reinitialize(); for (auto n{result.Elements()}; n-- > 0; result.IncrementSubscripts(at)) { accumulator.GetResult(result.Element(at)); } @@ -228,11 +229,54 @@ inline void PartialReduction(Descriptor &result, const Descriptor &x, int dim, } // No MASK= or scalar MASK=.TRUE. for (auto n{result.Elements()}; n-- > 0; result.IncrementSubscripts(at)) { + accumulator.Reinitialize(); ReduceDimToScalar( - x, dim - 1, at, result.Element(at)); + x, dim - 1, at, result.Element(at), accumulator); } } +template