summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorEli Friedman <efriedma@quicinc.com>2019-03-19 21:55:58 +0000
committerEli Friedman <efriedma@quicinc.com>2019-03-19 21:55:58 +0000
commitef821f937fff68b0fe9cd71c116ad2cb387b8e5b (patch)
tree3255ee4cdc5a7208bd6a955507a4e2a034c782e9 /lib
parent9342558f6da1f6c5644040e3cecfc42be66b181a (diff)
downloadcompiler-rt-ef821f937fff68b0fe9cd71c116ad2cb387b8e5b.tar.gz
[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
Diffstat (limited to 'lib')
-rw-r--r--lib/builtins/divdf3.c12
-rw-r--r--lib/builtins/divsf3.c12
-rw-r--r--lib/builtins/divtf3.c12
3 files changed, 36 insertions, 0 deletions
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);