[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:
Mike Kashkarov 2022-04-05 17:09:54 +03:00
parent ba038a3080
commit 68efe63565
3 changed files with 14 additions and 3 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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