diff options
author | Serge Pavlov <sepavloff@gmail.com> | 2021-05-07 02:17:42 +0700 |
---|---|---|
committer | Serge Pavlov <sepavloff@gmail.com> | 2021-05-21 11:02:51 +0700 |
commit | c162f086ba632ffaedfe92d63bf21571bc8ae4da (patch) | |
tree | 6798043c54cf97d5db4d936c36fe7b689aaace48 /llvm/lib/Support/APFloat.cpp | |
parent | 49028858637946ce8c00f12e41138b5ed7783276 (diff) | |
download | llvm-c162f086ba632ffaedfe92d63bf21571bc8ae4da.zip llvm-c162f086ba632ffaedfe92d63bf21571bc8ae4da.tar.gz llvm-c162f086ba632ffaedfe92d63bf21571bc8ae4da.tar.bz2 |
[APFloat] convertToDouble/Float can work on shorter types
Previously APFloat::convertToDouble may be called only for APFloats that
were built using double semantics. Other semantics like single precision
were not allowed although corresponding numbers could be converted to
double without loss of precision. The similar restriction applied to
APFloat::convertToFloat.
With this change any APFloat that can be precisely represented by double
can be handled with convertToDouble. Behavior of convertToFloat was
updated similarly. It make the conversion operations more convenient and
adds support for formats like half and bfloat.
Differential Revision: https://reviews.llvm.org/D102671
Diffstat (limited to 'llvm/lib/Support/APFloat.cpp')
-rw-r--r-- | llvm/lib/Support/APFloat.cpp | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 1069d1f..7abca83 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -66,6 +66,13 @@ namespace llvm { /* Number of bits actually used in the semantics. */ unsigned int sizeInBits; + + // Returns true if any number described by this semantics can be precisely + // represented by the specified semantics. + bool isRepresentableBy(const fltSemantics &S) const { + return maxExponent <= S.maxExponent && minExponent >= S.minExponent && + precision <= S.precision; + } }; static const fltSemantics semIEEEhalf = {15, -14, 11, 16}; @@ -4875,6 +4882,32 @@ APFloat::opStatus APFloat::convertToInteger(APSInt &result, return status; } +double APFloat::convertToDouble() const { + if (&getSemantics() == (const llvm::fltSemantics *)&semIEEEdouble) + return getIEEE().convertToDouble(); + assert(getSemantics().isRepresentableBy(semIEEEdouble) && + "Float semantics is not representable by IEEEdouble"); + APFloat Temp = *this; + bool LosesInfo; + opStatus St = Temp.convert(semIEEEdouble, rmNearestTiesToEven, &LosesInfo); + assert(!(St & opInexact) && !LosesInfo && "Unexpected imprecision"); + (void)St; + return Temp.getIEEE().convertToDouble(); +} + +float APFloat::convertToFloat() const { + if (&getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle) + return getIEEE().convertToFloat(); + assert(getSemantics().isRepresentableBy(semIEEEsingle) && + "Float semantics is not representable by IEEEsingle"); + APFloat Temp = *this; + bool LosesInfo; + opStatus St = Temp.convert(semIEEEsingle, rmNearestTiesToEven, &LosesInfo); + assert(!(St & opInexact) && !LosesInfo && "Unexpected imprecision"); + (void)St; + return Temp.getIEEE().convertToFloat(); +} + } // namespace llvm #undef APFLOAT_DISPATCH_ON_SEMANTICS |