[flang-commits] [flang] 07f1e1f - [flang] Correct shape analysis for transformational intrinsic functions
peter klausler via flang-commits
flang-commits at lists.llvm.org
Fri Jan 22 10:49:08 PST 2021
Author: peter klausler
Date: 2021-01-22T10:48:58-08:00
New Revision: 07f1e1f44c87d1ee84caf13d6e5aa64eb7e1b068
URL: https://github.com/llvm/llvm-project/commit/07f1e1f44c87d1ee84caf13d6e5aa64eb7e1b068
DIFF: https://github.com/llvm/llvm-project/commit/07f1e1f44c87d1ee84caf13d6e5aa64eb7e1b068.diff
LOG: [flang] Correct shape analysis for transformational intrinsic functions
Correct the analysis of references to transformational intrinsic
functions that have different semantics based on the presence or
absence of a DIM= argument; add shape analysis for UNPACK().
Differential Revision: https://reviews.llvm.org/D94716
Added:
Modified:
flang/lib/Evaluate/intrinsics.cpp
flang/lib/Evaluate/shape.cpp
Removed:
################################################################################
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index 3de43fd88d7e..98fbe92e2815 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -181,12 +181,13 @@ ENUM_CLASS(Rank,
conformable, // scalar, or array of same rank & shape as "array" argument
reduceOperation, // a pure function with constraints for REDUCE
dimReduced, // scalar if no DIM= argument, else rank(array)-1
- dimRemoved, // scalar, or rank(array)-1
+ dimRemovedOrScalar, // rank(array)-1 (less DIM) or scalar
+ locReduced, // vector(1:rank) if no DIM= argument, else rank(array)-1
rankPlus1, // rank(known)+1
shaped, // rank is length of SHAPE vector
)
-ENUM_CLASS(Optionality, required, optional,
+ENUM_CLASS(Optionality, required, optional, missing,
defaultsToSameKind, // for MatchingDefaultKIND
defaultsToDefaultForResult, // for DefaultingKIND
defaultsToSizeKind, // for SizeDefaultKIND
@@ -227,6 +228,9 @@ static constexpr IntrinsicDummyArgument RequiredDIM{"dim",
static constexpr IntrinsicDummyArgument OptionalDIM{"dim",
{IntType, KindCode::dimArg}, Rank::scalar, Optionality::optional,
common::Intent::In};
+static constexpr IntrinsicDummyArgument MissingDIM{"dim",
+ {IntType, KindCode::dimArg}, Rank::scalar, Optionality::missing,
+ common::Intent::In};
static constexpr IntrinsicDummyArgument OptionalMASK{"mask", AnyLogical,
Rank::conformable, Optionality::optional, common::Intent::In};
@@ -346,8 +350,8 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"count", {{"mask", AnyLogical, Rank::array}, OptionalDIM, DefaultingKIND},
KINDInt, Rank::dimReduced, IntrinsicClass::transformationalFunction},
{"cshift",
- {{"array", SameType, Rank::array}, {"shift", AnyInt, Rank::dimRemoved},
- OptionalDIM},
+ {{"array", SameType, Rank::array},
+ {"shift", AnyInt, Rank::dimRemovedOrScalar}, OptionalDIM},
SameType, Rank::conformable, IntrinsicClass::transformationalFunction},
{"dble", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, DoublePrecision},
{"digits", {{"x", AnyIntOrReal, Rank::anyOrAssumedRank}}, DefaultInt,
@@ -380,16 +384,16 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
{"eoshift",
{{"array", SameIntrinsic, Rank::array},
- {"shift", AnyInt, Rank::dimRemoved},
- {"boundary", SameIntrinsic, Rank::dimRemoved,
+ {"shift", AnyInt, Rank::dimRemovedOrScalar},
+ {"boundary", SameIntrinsic, Rank::dimReduced,
Optionality::optional},
OptionalDIM},
SameIntrinsic, Rank::conformable,
IntrinsicClass::transformationalFunction},
{"eoshift",
{{"array", SameDerivedType, Rank::array},
- {"shift", AnyInt, Rank::dimRemoved},
- {"boundary", SameDerivedType, Rank::dimRemoved}, OptionalDIM},
+ {"shift", AnyInt, Rank::dimReduced},
+ {"boundary", SameDerivedType, Rank::dimReduced}, OptionalDIM},
SameDerivedType, Rank::conformable,
IntrinsicClass::transformationalFunction},
{"epsilon", {{"x", SameReal, Rank::anyOrAssumedRank}}, SameReal,
@@ -410,20 +414,21 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"value", AnyNumeric, Rank::scalar}, RequiredDIM, OptionalMASK,
SizeDefaultKIND,
{"back", AnyLogical, Rank::scalar, Optionality::optional}},
- KINDInt, Rank::dimRemoved, IntrinsicClass::transformationalFunction},
+ KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction},
{"findloc",
{{"array", AnyNumeric, Rank::array},
- {"value", AnyNumeric, Rank::scalar}, OptionalMASK, SizeDefaultKIND,
+ {"value", AnyNumeric, Rank::scalar}, MissingDIM, OptionalMASK,
+ SizeDefaultKIND,
{"back", AnyLogical, Rank::scalar, Optionality::optional}},
KINDInt, Rank::vector, IntrinsicClass::transformationalFunction},
{"findloc",
{{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar},
RequiredDIM, OptionalMASK, SizeDefaultKIND,
{"back", AnyLogical, Rank::scalar, Optionality::optional}},
- KINDInt, Rank::dimRemoved, IntrinsicClass::transformationalFunction},
+ KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction},
{"findloc",
{{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar},
- OptionalMASK, SizeDefaultKIND,
+ MissingDIM, OptionalMASK, SizeDefaultKIND,
{"back", AnyLogical, Rank::scalar, Optionality::optional}},
KINDInt, Rank::vector, IntrinsicClass::transformationalFunction},
{"findloc",
@@ -431,10 +436,11 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"value", AnyLogical, Rank::scalar}, RequiredDIM, OptionalMASK,
SizeDefaultKIND,
{"back", AnyLogical, Rank::scalar, Optionality::optional}},
- KINDInt, Rank::dimRemoved, IntrinsicClass::transformationalFunction},
+ KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction},
{"findloc",
{{"array", AnyLogical, Rank::array},
- {"value", AnyLogical, Rank::scalar}, OptionalMASK, SizeDefaultKIND,
+ {"value", AnyLogical, Rank::scalar}, MissingDIM, OptionalMASK,
+ SizeDefaultKIND,
{"back", AnyLogical, Rank::scalar, Optionality::optional}},
KINDInt, Rank::vector, IntrinsicClass::transformationalFunction},
{"floor", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
@@ -444,12 +450,18 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
Rank::scalar, IntrinsicClass::inquiryFunction},
{"hypot", {{"x", OperandReal}, {"y", OperandReal}}, OperandReal},
{"iachar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
- {"iall", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
+ {"iall", {{"array", SameInt, Rank::array}, RequiredDIM, OptionalMASK},
SameInt, Rank::dimReduced, IntrinsicClass::transformationalFunction},
- {"iany", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
+ {"iall", {{"array", SameInt, Rank::array}, MissingDIM, OptionalMASK},
+ SameInt, Rank::scalar, IntrinsicClass::transformationalFunction},
+ {"iany", {{"array", SameInt, Rank::array}, RequiredDIM, OptionalMASK},
SameInt, Rank::dimReduced, IntrinsicClass::transformationalFunction},
- {"iparity", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK},
+ {"iany", {{"array", SameInt, Rank::array}, MissingDIM, OptionalMASK},
+ SameInt, Rank::scalar, IntrinsicClass::transformationalFunction},
+ {"iparity", {{"array", SameInt, Rank::array}, RequiredDIM, OptionalMASK},
SameInt, Rank::dimReduced, IntrinsicClass::transformationalFunction},
+ {"iparity", {{"array", SameInt, Rank::array}, MissingDIM, OptionalMASK},
+ SameInt, Rank::scalar, IntrinsicClass::transformationalFunction},
{"iand", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt},
{"iand", {{"i", BOZ}, {"j", SameInt}}, SameInt},
{"ibclr", {{"i", SameInt}, {"pos", AnyInt}}, SameInt},
@@ -540,14 +552,22 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"maxexponent", {{"x", AnyReal, Rank::anyOrAssumedRank}}, DefaultInt,
Rank::scalar, IntrinsicClass::inquiryFunction},
{"maxloc",
- {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
+ {{"array", AnyRelatable, Rank::array}, RequiredDIM, OptionalMASK,
SizeDefaultKIND,
{"back", AnyLogical, Rank::scalar, Optionality::optional}},
- KINDInt, Rank::dimReduced, IntrinsicClass::transformationalFunction},
+ KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction},
+ {"maxloc",
+ {{"array", AnyRelatable, Rank::array}, MissingDIM, OptionalMASK,
+ SizeDefaultKIND,
+ {"back", AnyLogical, Rank::scalar, Optionality::optional}},
+ KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction},
{"maxval",
- {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
+ {{"array", SameRelatable, Rank::array}, RequiredDIM, OptionalMASK},
SameRelatable, Rank::dimReduced,
IntrinsicClass::transformationalFunction},
+ {"maxval",
+ {{"array", SameRelatable, Rank::array}, MissingDIM, OptionalMASK},
+ SameRelatable, Rank::scalar, IntrinsicClass::transformationalFunction},
{"merge",
{{"tsource", SameType}, {"fsource", SameType}, {"mask", AnyLogical}},
SameType},
@@ -569,14 +589,22 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"minexponent", {{"x", AnyReal, Rank::anyOrAssumedRank}}, DefaultInt,
Rank::scalar, IntrinsicClass::inquiryFunction},
{"minloc",
- {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK,
+ {{"array", AnyRelatable, Rank::array}, RequiredDIM, OptionalMASK,
SizeDefaultKIND,
{"back", AnyLogical, Rank::scalar, Optionality::optional}},
- KINDInt, Rank::dimReduced, IntrinsicClass::transformationalFunction},
+ KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction},
+ {"minloc",
+ {{"array", AnyRelatable, Rank::array}, MissingDIM, OptionalMASK,
+ SizeDefaultKIND,
+ {"back", AnyLogical, Rank::scalar, Optionality::optional}},
+ KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction},
{"minval",
- {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK},
+ {{"array", SameRelatable, Rank::array}, RequiredDIM, OptionalMASK},
SameRelatable, Rank::dimReduced,
IntrinsicClass::transformationalFunction},
+ {"minval",
+ {{"array", SameRelatable, Rank::array}, MissingDIM, OptionalMASK},
+ SameRelatable, Rank::scalar, IntrinsicClass::transformationalFunction},
{"mod", {{"a", OperandIntOrReal}, {"p", OperandIntOrReal}},
OperandIntOrReal},
{"modulo", {{"a", OperandIntOrReal}, {"p", OperandIntOrReal}},
@@ -611,9 +639,11 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"popcnt", {{"i", AnyInt}}, DefaultInt},
{"poppar", {{"i", AnyInt}}, DefaultInt},
{"product",
- {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
+ {{"array", SameNumeric, Rank::array}, RequiredDIM, OptionalMASK},
SameNumeric, Rank::dimReduced,
IntrinsicClass::transformationalFunction},
+ {"product", {{"array", SameNumeric, Rank::array}, MissingDIM, OptionalMASK},
+ SameNumeric, Rank::scalar, IntrinsicClass::transformationalFunction},
{"precision", {{"x", AnyFloating, Rank::anyOrAssumedRank}}, DefaultInt,
Rank::scalar, IntrinsicClass::inquiryFunction},
{"present", {{"a", Addressable, Rank::anyOrAssumedRank}}, DefaultLogical,
@@ -630,10 +660,16 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
KINDReal},
{"reduce",
{{"array", SameType, Rank::array},
- {"operation", SameType, Rank::reduceOperation}, OptionalDIM,
+ {"operation", SameType, Rank::reduceOperation}, RequiredDIM,
OptionalMASK, {"identity", SameType, Rank::scalar},
{"ordered", AnyLogical, Rank::scalar, Optionality::optional}},
SameType, Rank::dimReduced, IntrinsicClass::transformationalFunction},
+ {"reduce",
+ {{"array", SameType, Rank::array},
+ {"operation", SameType, Rank::reduceOperation}, MissingDIM,
+ OptionalMASK, {"identity", SameType, Rank::scalar},
+ {"ordered", AnyLogical, Rank::scalar, Optionality::optional}},
+ SameType, Rank::scalar, IntrinsicClass::transformationalFunction},
{"repeat", {{"string", SameChar, Rank::scalar}, {"ncopies", AnyInt}},
SameChar, Rank::scalar, IntrinsicClass::transformationalFunction},
{"reshape",
@@ -695,9 +731,11 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"sqrt", {{"x", SameFloating}}, SameFloating},
{"storage_size", {{"a", AnyData, Rank::anyOrAssumedRank}, SizeDefaultKIND},
KINDInt, Rank::scalar, IntrinsicClass::inquiryFunction},
- {"sum", {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK},
+ {"sum", {{"array", SameNumeric, Rank::array}, RequiredDIM, OptionalMASK},
SameNumeric, Rank::dimReduced,
IntrinsicClass::transformationalFunction},
+ {"sum", {{"array", SameNumeric, Rank::array}, MissingDIM, OptionalMASK},
+ SameNumeric, Rank::scalar, IntrinsicClass::transformationalFunction},
{"tan", {{"x", SameFloating}}, SameFloating},
{"tand", {{"x", SameFloating}}, SameFloating},
{"tanh", {{"x", SameFloating}}, SameFloating},
@@ -1083,6 +1121,9 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
bool found{false};
int slot{missingActualArguments};
for (std::size_t j{0}; j < nonRepeatedDummies && !found; ++j) {
+ if (dummy[j].optionality == Optionality::missing) {
+ continue;
+ }
if (arg->keyword()) {
found = *arg->keyword() == dummy[j].keyword;
if (found) {
@@ -1150,6 +1191,9 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
} else {
continue;
}
+ } else if (d.optionality == Optionality::missing) {
+ messages.Say("unexpected '%s=' argument"_err_en_US, d.keyword);
+ return std::nullopt;
}
if (arg->GetAssumedTypeDummy()) {
// TYPE(*) assumed-type dummy argument forwarded to intrinsic
@@ -1350,7 +1394,8 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
CHECK(arrayArg);
argOk = rank == 0 || rank == arrayArg->Rank();
break;
- case Rank::dimRemoved:
+ case Rank::dimReduced:
+ case Rank::dimRemovedOrScalar:
CHECK(arrayArg);
argOk = rank == 0 || rank + 1 == arrayArg->Rank();
break;
@@ -1360,7 +1405,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
CHECK(arrayArg);
argOk = rank == 0;
break;
- case Rank::dimReduced:
+ case Rank::locReduced:
case Rank::rankPlus1:
case Rank::shaped:
common::die("INTERNAL: result-only rank code appears on argument '%s' "
@@ -1518,9 +1563,9 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
CHECK(arrayArg);
resultRank = hasDimArg ? arrayArg->Rank() - 1 : 0;
break;
- case Rank::dimRemoved:
+ case Rank::locReduced:
CHECK(arrayArg);
- resultRank = arrayArg->Rank() - 1;
+ resultRank = hasDimArg ? arrayArg->Rank() - 1 : 1;
break;
case Rank::rankPlus1:
CHECK(knownArg);
@@ -1536,6 +1581,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
case Rank::known:
case Rank::anyOrAssumedRank:
case Rank::reduceOperation:
+ case Rank::dimRemovedOrScalar:
common::die("INTERNAL: bad Rank code on intrinsic '%s' result", name);
break;
}
diff --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp
index d1bf64cd0fad..eb94139635ef 100644
--- a/flang/lib/Evaluate/shape.cpp
+++ b/flang/lib/Evaluate/shape.cpp
@@ -575,8 +575,7 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
} else if (intrinsic->name == "all" || intrinsic->name == "any" ||
intrinsic->name == "count" || intrinsic->name == "iall" ||
intrinsic->name == "iany" || intrinsic->name == "iparity" ||
- intrinsic->name == "maxloc" || intrinsic->name == "maxval" ||
- intrinsic->name == "minloc" || intrinsic->name == "minval" ||
+ intrinsic->name == "maxval" || intrinsic->name == "minval" ||
intrinsic->name == "norm2" || intrinsic->name == "parity" ||
intrinsic->name == "product" || intrinsic->name == "sum") {
// Reduction with DIM=
@@ -594,6 +593,25 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
}
}
}
+ } else if (intrinsic->name == "maxloc" || intrinsic->name == "minloc") {
+ // TODO: FINDLOC
+ if (call.arguments().size() >= 2) {
+ if (auto arrayShape{
+ (*this)(UnwrapExpr<Expr<SomeType>>(call.arguments().at(0)))}) {
+ auto rank{static_cast<int>(arrayShape->size())};
+ if (const auto *dimArg{
+ UnwrapExpr<Expr<SomeType>>(call.arguments()[1])}) {
+ auto dim{ToInt64(*dimArg)};
+ if (dim && *dim >= 1 && *dim <= rank) {
+ arrayShape->erase(arrayShape->begin() + (*dim - 1));
+ return std::move(*arrayShape);
+ }
+ } else {
+ // xxxLOC(no DIM=) result is vector(1:RANK(ARRAY=))
+ return Shape{ExtentExpr{rank}};
+ }
+ }
+ }
} else if (intrinsic->name == "cshift" || intrinsic->name == "eoshift") {
if (!call.arguments().empty()) {
return (*this)(call.arguments()[0]);
@@ -723,6 +741,10 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
}
}
}
+ } else if (intrinsic->name == "unpack") {
+ if (call.arguments().size() >= 2) {
+ return (*this)(call.arguments()[1]); // MASK=
+ }
} else if (intrinsic->characteristics.value().attrs.test(characteristics::
Procedure::Attr::NullPointer)) { // NULL(MOLD=)
return (*this)(call.arguments());
More information about the flang-commits
mailing list