summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorMatt Arsenault <Matthew.Arsenault@amd.com>2016-03-13 05:11:51 +0000
committerMatt Arsenault <Matthew.Arsenault@amd.com>2016-03-13 05:11:51 +0000
commitafa31cf4ccbb733b18df34a79bb2db710931ea82 (patch)
tree10f90750a92934e1a9b3ab5d17c1515ce6e23cc5 /llvm/lib
parentfc467e77b8c07b0cdef8b0193d4e99640c4eb84d (diff)
downloadbcm5719-llvm-afa31cf4ccbb733b18df34a79bb2db710931ea82.tar.gz
bcm5719-llvm-afa31cf4ccbb733b18df34a79bb2db710931ea82.zip
APFloat: Fix scalbn handling of denormals
This was incorrect for denormals, and also failed on longer exponent ranges. llvm-svn: 263369
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Support/APFloat.cpp26
1 files changed, 14 insertions, 12 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 744506ccfa8..95953b6d071 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -3945,19 +3945,21 @@ APFloat::makeZero(bool Negative) {
APInt::tcSet(significandParts(), 0, partCount());
}
-APFloat llvm::scalbn(APFloat X, int Exp) {
- if (X.isInfinity() || X.isZero() || X.isNaN())
- return X;
-
+APFloat llvm::scalbn(APFloat X, int Exp, APFloat::roundingMode RoundingMode) {
auto MaxExp = X.getSemantics().maxExponent;
auto MinExp = X.getSemantics().minExponent;
- if (Exp > (MaxExp - X.exponent))
- // Overflow saturates to infinity.
- return APFloat::getInf(X.getSemantics(), X.isNegative());
- if (Exp < (MinExp - X.exponent))
- // Underflow saturates to zero.
- return APFloat::getZero(X.getSemantics(), X.isNegative());
-
- X.exponent += Exp;
+
+ // If Exp is wildly out-of-scale, simply adding it to X.exponent will
+ // overflow; clamp it to a safe range before adding, but ensure that the range
+ // is large enough that the clamp does not change the result. The range we
+ // need to support is the difference between the largest possible exponent and
+ // the normalized exponent of half the smallest denormal.
+
+ int SignificandBits = X.getSemantics().precision - 1;
+ int MaxIncrement = MaxExp - (MinExp - SignificandBits) + 1;
+
+ // Clamp to one past the range ends to let normalize handle overlflow.
+ X.exponent += std::min(std::max(Exp, -MaxIncrement - 1), MaxIncrement);
+ X.normalize(RoundingMode, lfExactlyZero);
return X;
}
OpenPOWER on IntegriCloud