From 68efe6356551237e967c23c1bf5fd01dc4a2fc90 Mon Sep 17 00:00:00 2001 From: Mike Kashkarov Date: Tue, 5 Apr 2022 17:09:54 +0300 Subject: [PATCH] [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 --- flang/include/flang/Evaluate/real.h | 4 ++++ flang/lib/Evaluate/real.cpp | 8 +++++--- flang/test/Evaluate/folding28.f90 | 5 +++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h index 14f26dfb52ff..2f4f7b2c4775 100644 --- a/flang/include/flang/Evaluate/real.h +++ b/flang/include/flang/Evaluate/real.h @@ -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); diff --git a/flang/lib/Evaluate/real.cpp b/flang/lib/Evaluate/real.cpp index d273e76d70e1..eb6bd148e341 100644 --- a/flang/lib/Evaluate/real.cpp +++ b/flang/lib/Evaluate/real.cpp @@ -98,7 +98,7 @@ ValueWithRealFlags> Real::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::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::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) { diff --git a/flang/test/Evaluate/folding28.f90 b/flang/test/Evaluate/folding28.f90 index 95db37abe832..004c661692fe 100644 --- a/flang/test/Evaluate/folding28.f90 +++ b/flang/test/Evaluate/folding28.f90 @@ -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