[flang] Fix ISHFTC argument value check

The code that visits all pairs of constant SHIFT= and SIZE= arguments
in an array-valued call to the ISHFTC intrinsic function had a bad loop
test that affected the case where one of these arguments was scalar and
the other was not.  Fix it, and add tests.

Differential Revision: https://reviews.llvm.org/D145092
This commit is contained in:
Peter Klausler 2023-02-14 16:07:24 -08:00
parent fee3f0bd4a
commit e0daa2ebd3
2 changed files with 37 additions and 28 deletions

View File

@ -596,7 +596,9 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
name == "dshiftl" ? &Scalar<T>::DSHIFTL : &Scalar<T>::DSHIFTR};
// Third argument can be of any kind. However, it must be smaller or equal
// than BIT_SIZE. It can be converted to Int4 to simplify.
if (const auto *shiftCon{Folder<Int4>(context).Folding(args[2])}) {
if (const auto *argCon{Folder<T>(context).Folding(args[0])};
argCon && argCon->empty()) {
} else if (const auto *shiftCon{Folder<Int4>(context).Folding(args[2])}) {
for (const auto &scalar : shiftCon->values()) {
std::int64_t shiftVal{scalar.ToInt64()};
if (shiftVal < 0) {
@ -696,7 +698,9 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
} else {
common::die("missing case to fold intrinsic function %s", name.c_str());
}
if (const auto *posCon{Folder<Int4>(context).Folding(args[1])}) {
if (const auto *argCon{Folder<T>(context).Folding(args[0])};
argCon && argCon->empty()) {
} else if (const auto *posCon{Folder<Int4>(context).Folding(args[1])}) {
for (const auto &scalar : posCon->values()) {
std::int64_t posVal{scalar.ToInt64()};
if (posVal < 0) {
@ -720,7 +724,9 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
} else if (name == "ibits") {
const auto *posCon{Folder<Int4>(context).Folding(args[1])};
const auto *lenCon{Folder<Int4>(context).Folding(args[2])};
if (posCon && lenCon &&
if (const auto *argCon{Folder<T>(context).Folding(args[0])};
argCon && argCon->empty()) {
} else if (posCon && lenCon &&
(posCon->size() == 1 || lenCon->size() == 1 ||
posCon->size() == lenCon->size())) {
auto posIter{posCon->values().begin()};
@ -823,9 +829,17 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
return FoldBitReduction(
context, std::move(funcRef), &Scalar<T>::IEOR, Scalar<T>{});
} else if (name == "ishft" || name == "ishftc") {
const auto *argCon{Folder<T>(context).Folding(args[0])};
const auto *shiftCon{Folder<Int4>(context).Folding(args[1])};
if (shiftCon) {
for (const auto &scalar : shiftCon->values()) {
const auto *shiftVals{shiftCon ? &shiftCon->values() : nullptr};
const auto *sizeCon{
args.size() == 3 ? Folder<Int4>(context).Folding(args[2]) : nullptr};
const auto *sizeVals{sizeCon ? &sizeCon->values() : nullptr};
if ((argCon && argCon->empty()) || !shiftVals || shiftVals->empty() ||
(sizeVals && sizeVals->empty())) {
// size= and shift= values don't need to be checked
} else {
for (const auto &scalar : *shiftVals) {
std::int64_t shiftVal{scalar.ToInt64()};
if (shiftVal < -T::Scalar::bits) {
context.messages().Say(
@ -839,10 +853,8 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
break;
}
}
}
if (args.size() == 3) { // ISHFTC
if (const auto *sizeCon{Folder<Int4>(context).Folding(args[2])}) {
for (const auto &scalar : sizeCon->values()) {
if (sizeVals) {
for (const auto &scalar : *sizeVals) {
std::int64_t sizeVal{scalar.ToInt64()};
if (sizeVal <= 0) {
context.messages().Say(
@ -856,22 +868,14 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
break;
}
}
if (shiftCon &&
(shiftCon->size() == 1 || sizeCon->size() == 1 ||
shiftCon->size() == sizeCon->size())) {
auto shiftIter{shiftCon->values().begin()};
auto sizeIter{sizeCon->values().begin()};
for (; shiftIter != shiftCon->values().end() &&
sizeIter != sizeCon->values().end();
++shiftIter, ++sizeIter) {
shiftIter = shiftIter == shiftCon->values().end()
? shiftCon->values().begin()
: shiftIter;
sizeIter = sizeIter == sizeCon->values().end()
? sizeCon->values().begin()
: sizeIter;
auto shiftVal{static_cast<int>(shiftIter->ToInt64())};
auto sizeVal{static_cast<int>(sizeIter->ToInt64())};
if (shiftVals->size() == 1 || sizeVals->size() == 1 ||
shiftVals->size() == sizeVals->size()) {
auto iters{std::max(shiftVals->size(), sizeVals->size())};
for (std::size_t j{0}; j < iters; ++j) {
auto shiftVal{static_cast<int>(
(*shiftVals)[j % shiftVals->size()].ToInt64())};
auto sizeVal{
static_cast<int>((*sizeVals)[j % sizeVals->size()].ToInt64())};
if (sizeVal > 0 && std::abs(shiftVal) > sizeVal) {
context.messages().Say(
"SHIFT=%jd count for ishftc is greater in magnitude than SIZE=%jd"_err_en_US,
@ -900,7 +904,6 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
ScalarFunc<T, T, Int4, Int4>(
[&](const Scalar<T> &i, const Scalar<Int4> &shift,
const Scalar<Int4> &size) -> Scalar<T> {
// Errors are caught in intrinsics.cpp
auto shiftVal{static_cast<int>(shift.ToInt64())};
auto sizeVal{static_cast<int>(size.ToInt64())};
return i.ISHFTC(shiftVal, sizeVal);
@ -1154,7 +1157,9 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
} else {
common::die("missing case to fold intrinsic function %s", name.c_str());
}
if (const auto *shiftCon{Folder<Int4>(context).Folding(args[1])}) {
if (const auto *argCon{Folder<T>(context).Folding(args[0])};
argCon && argCon->empty()) {
} else if (const auto *shiftCon{Folder<Int4>(context).Folding(args[1])}) {
for (const auto &scalar : shiftCon->values()) {
std::int64_t shiftVal{scalar.ToInt64()};
if (shiftVal < 0) {

View File

@ -26,6 +26,10 @@ program test_ishftc
n = ishftc(3, 2, 1)
!ERROR: SHIFT=-2 count for ishftc is greater in magnitude than SIZE=1
n = ishftc(3, -2, 1)
!ERROR: SHIFT=4 count for ishftc is greater in magnitude than SIZE=3
array_result = ishftc(666, [(j,integer::j=1,5)], 3)
!ERROR: SHIFT=4 count for ishftc is greater in magnitude than SIZE=3
array_result = ishftc(666, 4, [(j,integer::j=10,3,-1)])
!ERROR: SIZE=-3 count for ishftc is not positive
array_result = ishftc([3,3], [2,2], [-3,3])
!ERROR: SIZE=-3 count for ishftc is not positive
@ -44,5 +48,5 @@ program test_ishftc
array_result = ishftc([3,3], [-2,-2], const_arr6)
!ERROR: SIZE=0 count for ishftc is not positive
array_result = ishftc([3,3], [-2,-2], const_arr7)
array_result = ishftc([(j,integer::j=1,0)], 10, 9) ! ok because empty
end program test_ishftc