forked from OSchip/llvm-project
[flang] Fix ICE for sqrt(0.0) evaluation
During real range reduction to [0.5, 4) with SQRT(2**(2a) * x) = SQRT(2**(2a)) * SQRT(x) = 2**a * SQRT(x) we fall into inf. recursion if IsZero() == true. Explicitly handle SQRT(0.0) instead of additional checks during folding. Also add helpers for +0.0/-0.0 generation to clean up a bit. Reviewed By: klausler Differential Revision: https://reviews.llvm.org/D123131
This commit is contained in:
parent
ba038a3080
commit
68efe63565
|
@ -196,6 +196,10 @@ public:
|
|||
.IBSET(significandBits - 2)};
|
||||
}
|
||||
|
||||
static constexpr Real PositiveZero() { return Real{}; }
|
||||
|
||||
static constexpr Real NegativeZero() { return {Word{}.MASKL(1)}; }
|
||||
|
||||
static constexpr Real Infinity(bool negative) {
|
||||
Word infinity{maxExponent};
|
||||
infinity = infinity.SHIFTL(significandBits);
|
||||
|
|
|
@ -98,7 +98,7 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::Add(
|
|||
if (order == Ordering::Equal) {
|
||||
// x + (-x) -> +0.0 unless rounding is directed downwards
|
||||
if (rounding.mode == common::RoundingMode::Down) {
|
||||
result.value.word_ = result.value.word_.IBSET(bits - 1); // -0.0
|
||||
result.value = NegativeZero();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::Divide(
|
|||
}
|
||||
} else if (IsZero() || y.IsInfinite()) { // 0/x, x/Inf -> 0
|
||||
if (isNegative) {
|
||||
result.value.word_ = result.value.word_.IBSET(bits - 1);
|
||||
result.value = NegativeZero();
|
||||
}
|
||||
} else {
|
||||
// dividend and divisor are both finite and nonzero numbers
|
||||
|
@ -272,13 +272,15 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::SQRT(Rounding rounding) const {
|
|||
} else if (IsNegative()) {
|
||||
if (IsZero()) {
|
||||
// SQRT(-0) == -0 in IEEE-754.
|
||||
result.value.word_ = result.value.word_.IBSET(bits - 1);
|
||||
result.value = NegativeZero();
|
||||
} else {
|
||||
result.value = NotANumber();
|
||||
}
|
||||
} else if (IsInfinite()) {
|
||||
// SQRT(+Inf) == +Inf
|
||||
result.value = Infinity(false);
|
||||
} else if (IsZero()) {
|
||||
result.value = PositiveZero();
|
||||
} else {
|
||||
int expo{UnbiasedExponent()};
|
||||
if (expo < -1 || expo > 1) {
|
||||
|
|
|
@ -44,4 +44,9 @@ module m
|
|||
logical, parameter :: test_before_1 = sqrt_before_1 == before_1
|
||||
real(4), parameter :: sq_sqrt_before_1 = sqrt_before_1 * sqrt_before_1
|
||||
logical, parameter :: test_sq_before_1 = sq_sqrt_before_1 < before_1
|
||||
! ICE at 0.0
|
||||
real(4), parameter :: sqrt_zero_4 = sqrt(0.0)
|
||||
logical, parameter :: test_sqrt_zero_4 = sqrt_zero_4 == 0.0
|
||||
real(8), parameter :: sqrt_zero_8 = sqrt(0.0)
|
||||
logical, parameter :: test_sqrt_zero_8 = sqrt_zero_8 == 0.0
|
||||
end module
|
||||
|
|
Loading…
Reference in New Issue