[flang-commits] [flang] 1e1cf25 - [flang] Fix IEEE_NEAREST_AFTER folding edge cases (#104846)
via flang-commits
flang-commits at lists.llvm.org
Tue Aug 20 12:05:00 PDT 2024
Author: Peter Klausler
Date: 2024-08-20T12:04:57-07:00
New Revision: 1e1cf258c718bdce8c50c2b1923f1a522163fbc9
URL: https://github.com/llvm/llvm-project/commit/1e1cf258c718bdce8c50c2b1923f1a522163fbc9
DIFF: https://github.com/llvm/llvm-project/commit/1e1cf258c718bdce8c50c2b1923f1a522163fbc9.diff
LOG: [flang] Fix IEEE_NEAREST_AFTER folding edge cases (#104846)
Conversions of infinities from other kinds to real(10) were incorrect,
and comparisons of real(2) vs real(3) are dicey as conversions in one
direction can overflow and conversions in the other can lose precision.
Use real(16) as the common type for comparisons in IEEE_NEAREST_AFTER.
Added:
Modified:
flang/include/flang/Evaluate/real.h
flang/lib/Evaluate/fold-real.cpp
flang/test/Evaluate/fold-nearest.f90
Removed:
################################################################################
diff --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h
index cb3c0036e0cfae..11cc8f776b0e95 100644
--- a/flang/include/flang/Evaluate/real.h
+++ b/flang/include/flang/Evaluate/real.h
@@ -281,7 +281,7 @@ template <typename WORD, int PREC> class Real {
}
if constexpr (bits == 80) { // x87
// 7FFF8000000000000000 is Infinity, not NaN, on 80387 & later.
- infinity.IBSET(63);
+ infinity = infinity.IBSET(63);
}
return {infinity};
}
diff --git a/flang/lib/Evaluate/fold-real.cpp b/flang/lib/Evaluate/fold-real.cpp
index 15a9bcf6dbd854..fd8eca28a679c1 100644
--- a/flang/lib/Evaluate/fold-real.cpp
+++ b/flang/lib/Evaluate/fold-real.cpp
@@ -468,11 +468,9 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
return FoldElementalIntrinsic<T, T, TY>(context, std::move(funcRef),
ScalarFunc<T, T, TY>([&](const Scalar<T> &x,
const Scalar<TY> &y) -> Scalar<T> {
- bool reverseCompare{
- Scalar<T>::binaryPrecision < Scalar<TY>::binaryPrecision};
- switch (reverseCompare
- ? y.Compare(Scalar<TY>::Convert(x).value)
- : x.Compare(Scalar<T>::Convert(y).value)) {
+ auto xBig{Scalar<LargestReal>::Convert(x).value};
+ auto yBig{Scalar<LargestReal>::Convert(y).value};
+ switch (xBig.Compare(yBig)) {
case Relation::Unordered:
if (context.languageFeatures().ShouldWarn(
common::UsageWarning::FoldingValueChecks)) {
@@ -483,9 +481,9 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
case Relation::Equal:
break;
case Relation::Less:
- return x.NEAREST(!reverseCompare).value;
+ return x.NEAREST(true).value;
case Relation::Greater:
- return x.NEAREST(reverseCompare).value;
+ return x.NEAREST(false).value;
}
return x; // dodge bogus "missing return" GCC warning
}));
diff --git a/flang/test/Evaluate/fold-nearest.f90 b/flang/test/Evaluate/fold-nearest.f90
index 7ca7757f79664e..bb53db928443cc 100644
--- a/flang/test/Evaluate/fold-nearest.f90
+++ b/flang/test/Evaluate/fold-nearest.f90
@@ -91,3 +91,18 @@ module m3
real(kind(0.d0)), parameter :: x14 = ieee_next_down(nan)
logical, parameter :: test_14 = .not. (x14 == x14)
end module
+
+module m4
+ use ieee_arithmetic
+ real(8), parameter :: neg_inf_8 = real(z'fff0000000000000',8)
+ real(8), parameter :: neg_huge_8 = real(z'ffefffffffffffff',8)
+ real(10), parameter :: neg_one_10 = real(z'bfff8000000000000000',10)
+ real(10), parameter :: neg_inf_10 = real(z'ffff8000000000000000',10)
+ real(2), parameter :: neg_inf_2 = real(z'fc00',2)
+ real(2), parameter :: neg_huge_2 = real(z'fbff',2)
+ real(3), parameter :: neg_huge_3 = real(z'ff7f',3)
+ logical, parameter :: test_1 = ieee_next_after(neg_inf_8,neg_one_10) == neg_huge_8
+ logical, parameter :: test_2 = ieee_next_after(neg_inf_2, neg_huge_3) == neg_huge_2
+ logical, parameter :: test_3 = ieee_next_after(neg_one_10, neg_inf_10) == &
+ real(z'bfff8000000000000001', 10)
+end module
More information about the flang-commits
mailing list