[flang-commits] [flang] e0daa2e - [flang] Fix ISHFTC argument value check
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Thu Mar 2 09:21:44 PST 2023
Author: Peter Klausler
Date: 2023-03-02T09:17:09-08:00
New Revision: e0daa2ebd39c5ce542a6af87e1e3ce68e91604d8
URL: https://github.com/llvm/llvm-project/commit/e0daa2ebd39c5ce542a6af87e1e3ce68e91604d8
DIFF: https://github.com/llvm/llvm-project/commit/e0daa2ebd39c5ce542a6af87e1e3ce68e91604d8.diff
LOG: [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
Added:
Modified:
flang/lib/Evaluate/fold-integer.cpp
flang/test/Semantics/ishftc.f90
Removed:
################################################################################
diff --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp
index 4a66d437f06c1..601fa729980e6 100644
--- a/flang/lib/Evaluate/fold-integer.cpp
+++ b/flang/lib/Evaluate/fold-integer.cpp
@@ -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) {
diff --git a/flang/test/Semantics/ishftc.f90 b/flang/test/Semantics/ishftc.f90
index 15d1213999cc9..c6908026e89ff 100644
--- a/flang/test/Semantics/ishftc.f90
+++ b/flang/test/Semantics/ishftc.f90
@@ -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
More information about the flang-commits
mailing list