diff options
| author | Eli Friedman <efriedma@quicinc.com> | 2019-03-19 21:55:58 +0000 |
|---|---|---|
| committer | Eli Friedman <efriedma@quicinc.com> | 2019-03-19 21:55:58 +0000 |
| commit | d674d96bc56c0f377879d01c9d8dfdaaa7859cdb (patch) | |
| tree | 869005e7206fd8c7489d59822fddf38f6e0d319f /compiler-rt/lib/builtins | |
| parent | 4d03bbbb3aa8d7d12941f9743b87f430e1f3d92d (diff) | |
| download | bcm5719-llvm-d674d96bc56c0f377879d01c9d8dfdaaa7859cdb.tar.gz bcm5719-llvm-d674d96bc56c0f377879d01c9d8dfdaaa7859cdb.zip | |
[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
llvm-svn: 356529
Diffstat (limited to 'compiler-rt/lib/builtins')
| -rw-r--r-- | compiler-rt/lib/builtins/divdf3.c | 12 | ||||
| -rw-r--r-- | compiler-rt/lib/builtins/divsf3.c | 12 | ||||
| -rw-r--r-- | compiler-rt/lib/builtins/divtf3.c | 12 |
3 files changed, 36 insertions, 0 deletions
diff --git a/compiler-rt/lib/builtins/divdf3.c b/compiler-rt/lib/builtins/divdf3.c index 3993507a0f7..9132f83813b 100644 --- a/compiler-rt/lib/builtins/divdf3.c +++ b/compiler-rt/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/compiler-rt/lib/builtins/divsf3.c b/compiler-rt/lib/builtins/divsf3.c index 97cbcc1960b..944524749e9 100644 --- a/compiler-rt/lib/builtins/divsf3.c +++ b/compiler-rt/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/compiler-rt/lib/builtins/divtf3.c b/compiler-rt/lib/builtins/divtf3.c index 17273749b5b..ba5de99f995 100644 --- a/compiler-rt/lib/builtins/divtf3.c +++ b/compiler-rt/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); |

