From ef821f937fff68b0fe9cd71c116ad2cb387b8e5b Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Tue, 19 Mar 2019 21:55:58 +0000 Subject: [builtins] Divide shouldn't underflow if rounded result would be normal. We were treating certain edge cases that are actually normal as denormal results, and flushing them to zero; we shouldn't do that. Not sure this is the cleanest way to implement this edge case, but I wanted to avoid adding any code on the common path. Differential Revision: https://reviews.llvm.org/D59070 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@356529 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/builtins/divdf3.c | 12 ++++++++++++ lib/builtins/divsf3.c | 12 ++++++++++++ lib/builtins/divtf3.c | 12 ++++++++++++ 3 files changed, 36 insertions(+) (limited to 'lib') diff --git a/lib/builtins/divdf3.c b/lib/builtins/divdf3.c index 3993507a0..9132f8381 100644 --- a/lib/builtins/divdf3.c +++ b/lib/builtins/divdf3.c @@ -162,6 +162,18 @@ __divdf3(fp_t a, fp_t b) { } else if (writtenExponent < 1) { + if (writtenExponent == 0) { + // Check whether the rounded result is normal. + const bool round = (residual << 1) > bSignificand; + // Clear the implicit bit. + rep_t absResult = quotient & significandMask; + // Round. + absResult += round; + if (absResult & ~significandMask) { + // The rounded result is normal; return it. + return fromRep(absResult | quotientSign); + } + } // Flush denormals to zero. In the future, it would be nice to add // code to round them correctly. return fromRep(quotientSign); diff --git a/lib/builtins/divsf3.c b/lib/builtins/divsf3.c index 97cbcc196..944524749 100644 --- a/lib/builtins/divsf3.c +++ b/lib/builtins/divsf3.c @@ -147,6 +147,18 @@ __divsf3(fp_t a, fp_t b) { } else if (writtenExponent < 1) { + if (writtenExponent == 0) { + // Check whether the rounded result is normal. + const bool round = (residual << 1) > bSignificand; + // Clear the implicit bit. + rep_t absResult = quotient & significandMask; + // Round. + absResult += round; + if (absResult & ~significandMask) { + // The rounded result is normal; return it. + return fromRep(absResult | quotientSign); + } + } // Flush denormals to zero. In the future, it would be nice to add // code to round them correctly. return fromRep(quotientSign); diff --git a/lib/builtins/divtf3.c b/lib/builtins/divtf3.c index 17273749b..ba5de99f9 100644 --- a/lib/builtins/divtf3.c +++ b/lib/builtins/divtf3.c @@ -181,6 +181,18 @@ COMPILER_RT_ABI fp_t __divtf3(fp_t a, fp_t b) { return fromRep(infRep | quotientSign); } else if (writtenExponent < 1) { + if (writtenExponent == 0) { + // Check whether the rounded result is normal. + const bool round = (residual << 1) > bSignificand; + // Clear the implicit bit. + rep_t absResult = quotient & significandMask; + // Round. + absResult += round; + if (absResult & ~significandMask) { + // The rounded result is normal; return it. + return fromRep(absResult | quotientSign); + } + } // Flush denormals to zero. In the future, it would be nice to add // code to round them correctly. return fromRep(quotientSign); -- cgit v1.2.1