Index: llvm/trunk/include/llvm/ADT/APFloat.h =================================================================== --- llvm/trunk/include/llvm/ADT/APFloat.h +++ llvm/trunk/include/llvm/ADT/APFloat.h @@ -42,7 +42,7 @@ lfMoreThanHalf // 1xxxxx x's not all zero }; -/// \brief A self-contained host- and target-independent arbitrary-precision +/// A self-contained host- and target-independent arbitrary-precision /// floating-point software implementation. /// /// APFloat uses bignum integer arithmetic as provided by static functions in @@ -191,7 +191,7 @@ uninitialized }; - /// \brief Enumeration of \c ilogb error results. + /// Enumeration of \c ilogb error results. enum IlogbErrorKinds { IEK_Zero = INT_MIN + 1, IEK_NaN = INT_MIN, @@ -227,7 +227,7 @@ /// @} - /// \brief Returns whether this instance allocated memory. + /// Returns whether this instance allocated memory. bool needsCleanup() const { return partCount() > 1; } /// \name Convenience "constructors" @@ -361,7 +361,7 @@ IEEEFloat &operator=(const IEEEFloat &); IEEEFloat &operator=(IEEEFloat &&); - /// \brief Overload to compute a hash code for an APFloat value. + /// Overload to compute a hash code for an APFloat value. /// /// Note that the use of hash codes for floating point values is in general /// frought with peril. Equality is hard to define for these values. For @@ -399,7 +399,7 @@ /// return true. bool getExactInverse(APFloat *inv) const; - /// \brief Returns the exponent of the internal representation of the APFloat. + /// Returns the exponent of the internal representation of the APFloat. /// /// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)). /// For special APFloat values, this returns special error codes: @@ -410,7 +410,7 @@ /// friend int ilogb(const IEEEFloat &Arg); - /// \brief Returns: X * 2^Exp for integral exponents. + /// Returns: X * 2^Exp for integral exponents. friend IEEEFloat scalbn(IEEEFloat X, int Exp, roundingMode); friend IEEEFloat frexp(const IEEEFloat &X, int &Exp, roundingMode); @@ -1051,6 +1051,8 @@ llvm_unreachable("Unexpected semantics"); } + // TODO: bool parameters are not readable and a source of bugs. + // Do something. opStatus next(bool nextDown) { if (usesLayout(getSemantics())) return U.IEEE.next(nextDown); @@ -1059,32 +1061,32 @@ llvm_unreachable("Unexpected semantics"); } - /// \brief Operator+ overload which provides the default - /// \c rmNearestTiesToEven rounding mode and *no* error checking. + /// Add two APFloats, rounding ties to the nearest even. + /// No error checking. APFloat operator+(const APFloat &RHS) const { APFloat Result(*this); (void)Result.add(RHS, rmNearestTiesToEven); return Result; } - /// \brief Operator- overload which provides the default - /// \c rmNearestTiesToEven rounding mode and *no* error checking. + /// Subtract two APFloats, rounding ties to the nearest even. + /// No error checking. APFloat operator-(const APFloat &RHS) const { APFloat Result(*this); (void)Result.subtract(RHS, rmNearestTiesToEven); return Result; } - /// \brief Operator* overload which provides the default - /// \c rmNearestTiesToEven rounding mode and *no* error checking. + /// Multiply two APFloats, rounding ties to the nearest even. + /// No error checking. APFloat operator*(const APFloat &RHS) const { APFloat Result(*this); (void)Result.multiply(RHS, rmNearestTiesToEven); return Result; } - /// \brief Operator/ overload which provides the default - /// \c rmNearestTiesToEven rounding mode and *no* error checking. + /// Divide the first APFloat by the second, rounding ties to the nearest even. + /// No error checking. APFloat operator/(const APFloat &RHS) const { APFloat Result(*this); (void)Result.divide(RHS, rmNearestTiesToEven); @@ -1111,7 +1113,7 @@ changeSign(); } - /// \brief A static helper to produce a copy of an APFloat value with its sign + /// A static helper to produce a copy of an APFloat value with its sign /// copied from some other APFloat. static APFloat copySign(APFloat Value, const APFloat &Sign) { Value.copySign(Sign); @@ -1296,7 +1298,7 @@ llvm_unreachable("Unexpected semantics"); } -/// \brief Equivalent of C standard library function. +/// Equivalent of C standard library function. /// /// While the C standard says Exp is an unspecified value for infinity and nan, /// this returns INT_MAX for infinities, and INT_MIN for NaNs. @@ -1307,7 +1309,7 @@ return APFloat(frexp(X.U.Double, Exp, RM), X.getSemantics()); llvm_unreachable("Unexpected semantics"); } -/// \brief Returns the absolute value of the argument. +/// Returns the absolute value of the argument. inline APFloat abs(APFloat X) { X.clearSign(); return X; Index: llvm/trunk/lib/Support/APFloat.cpp =================================================================== --- llvm/trunk/lib/Support/APFloat.cpp +++ llvm/trunk/lib/Support/APFloat.cpp @@ -66,17 +66,11 @@ static const fltSemantics semX87DoubleExtended = {16383, -16382, 64, 80}; static const fltSemantics semBogus = {0, 0, 0, 0}; - /* The PowerPC format consists of two doubles. It does not map cleanly - onto the usual format above. It is approximated using twice the - mantissa bits. Note that for exponents near the double minimum, - we no longer can represent the full 106 mantissa bits, so those - will be treated as denormal numbers. - - FIXME: While this approximation is equivalent to what GCC uses for - compile-time arithmetic on PPC double-double numbers, it is not able - to represent all possible values held by a PPC double-double number, - for example: (long double) 1.0 + (long double) 0x1p-106 - Should this be replaced by a full emulation of PPC double-double? + /* The IBM double-double semantics. Such a number consists of a pair of IEEE + 64-bit doubles (Hi, Lo), where |Hi| > |Lo|, and if normal, + (double)(Hi + Lo) == Hi. The numeric value it's modeling is Hi + Lo. + Therefore it has two 53-bit mantissa parts that aren't necessarily adjacent + to each other, and two 11-bit exponents. Note: we need to make the value different from semBogus as otherwise an unsafe optimization may collapse both values to a single address, @@ -85,15 +79,21 @@ /* These are legacy semantics for the fallback, inaccrurate implementation of IBM double-double, if the accurate semPPCDoubleDouble doesn't handle the - case. It's equivalent to have an IEEE number with consecutive 106 bits of - mantissa, and 11 bits of exponent. It's not accurate, becuase the two - 53-bit mantissa parts don't actually have to be consecutive, - e.g. 1 + epsilon. + operation. It's equivalent to having an IEEE number with consecutive 106 + bits of mantissa and 11 bits of exponent. + + It's not equivalent to IBM double-double. For example, a legit IBM + double-double, 1 + epsilon: + + 1 + epsilon = 1 + (1 >> 1076) + + is not representable by a consecutive 106 bits of mantissa. Currently, these semantics are used in the following way: - (IEEEdouble, IEEEdouble) -> (64-bit APInt, 64-bit APInt) -> - (128-bit APInt) -> semPPCDoubleDoubleLegacy -> IEEE operations + semPPCDoubleDouble -> (IEEEdouble, IEEEdouble) -> + (64-bit APInt, 64-bit APInt) -> (128-bit APInt) -> + semPPCDoubleDoubleLegacy -> IEEE operations We use bitcastToAPInt() to get the bit representation (in APInt) of the underlying IEEEdouble, then use the APInt constructor to construct the @@ -3907,7 +3907,7 @@ if (!z.isFinite()) { if (!z.isInfinity()) { Floats[0] = std::move(z); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); return (opStatus)Status; } Status = opOK; @@ -3925,7 +3925,7 @@ } if (!z.isFinite()) { Floats[0] = std::move(z); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); return (opStatus)Status; } Floats[0] = z; @@ -3961,13 +3961,13 @@ Status |= zz.add(cc, RM); if (zz.isZero() && !zz.isNegative()) { Floats[0] = std::move(z); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); return opOK; } Floats[0] = z; Status |= Floats[0].add(zz, RM); if (!Floats[0].isFinite()) { - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); return (opStatus)Status; } Floats[1] = std::move(z); @@ -4086,7 +4086,7 @@ Status |= T.multiply(C, RM); if (!T.isFiniteNonZero()) { Floats[0] = T; - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); return (opStatus)Status; } @@ -4112,7 +4112,7 @@ Floats[0] = U; if (!U.isFinite()) { - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); } else { // Floats[1] = (t - u) + tau Status |= T.subtract(U, RM); @@ -4204,12 +4204,12 @@ void DoubleAPFloat::makeInf(bool Neg) { Floats[0].makeInf(Neg); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); } void DoubleAPFloat::makeZero(bool Neg) { Floats[0].makeZero(Neg); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); } void DoubleAPFloat::makeLargest(bool Neg) { @@ -4223,7 +4223,7 @@ void DoubleAPFloat::makeSmallest(bool Neg) { assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); Floats[0].makeSmallest(Neg); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); } void DoubleAPFloat::makeSmallestNormalized(bool Neg) { @@ -4231,16 +4231,17 @@ Floats[0] = APFloat(semIEEEdouble, APInt(64, 0x0360000000000000ull)); if (Neg) Floats[0].changeSign(); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); } void DoubleAPFloat::makeNaN(bool SNaN, bool Neg, const APInt *fill) { Floats[0].makeNaN(SNaN, Neg, fill); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); } APFloat::cmpResult DoubleAPFloat::compare(const DoubleAPFloat &RHS) const { auto Result = Floats[0].compare(RHS.Floats[0]); + // |Float[0]| > |Float[1]| if (Result == APFloat::cmpEqual) return Floats[1].compare(RHS.Floats[1]); return Result; @@ -4337,6 +4338,7 @@ bool DoubleAPFloat::isDenormal() const { return getCategory() == fcNormal && (Floats[0].isDenormal() || Floats[1].isDenormal() || + // (double)(Hi + Lo) == Hi defines a normal number. Floats[0].compare(Floats[0] + Floats[1]) != cmpEqual); }