blockfreq: Some cleanup of UnsignedFloat

Change `PositiveFloat` to `UnsignedFloat`, and fix some of the comments
to indicate that it's disappearing eventually.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206771 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan P. N. Exon Smith 2014-04-21 18:31:58 +00:00
parent 72eedb3c1d
commit 9c3ac928df
2 changed files with 133 additions and 138 deletions

View File

@ -26,14 +26,14 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// PositiveFloat definition. // UnsignedFloat definition.
// //
// TODO: Make this private to BlockFrequencyInfoImpl or delete. // TODO: Make this private to BlockFrequencyInfoImpl or delete.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
namespace llvm { namespace llvm {
class PositiveFloatBase { class UnsignedFloatBase {
public: public:
static const int32_t MaxExponent = 16383; static const int32_t MaxExponent = 16383;
static const int32_t MinExponent = -16382; static const int32_t MinExponent = -16382;
@ -87,9 +87,9 @@ public:
} }
}; };
/// \brief Simple representation of a positive floating point. /// \brief Simple representation of an unsigned floating point.
/// ///
/// PositiveFloat is a positive floating point number. It uses simple /// UnsignedFloat is a unsigned floating point number. It uses simple
/// saturation arithmetic, and every operation is well-defined for every value. /// saturation arithmetic, and every operation is well-defined for every value.
/// ///
/// The number is split into a signed exponent and unsigned digits. The number /// The number is split into a signed exponent and unsigned digits. The number
@ -98,23 +98,23 @@ public:
/// form, so the same number can be represented by many bit representations /// form, so the same number can be represented by many bit representations
/// (it's always in "denormal" mode). /// (it's always in "denormal" mode).
/// ///
/// PositiveFloat is templated on the underlying integer type for digits, which /// UnsignedFloat is templated on the underlying integer type for digits, which
/// is expected to be one of uint64_t, uint32_t, uint16_t or uint8_t. /// is expected to be one of uint64_t, uint32_t, uint16_t or uint8_t.
/// ///
/// Unlike builtin floating point types, PositiveFloat is portable. /// Unlike builtin floating point types, UnsignedFloat is portable.
/// ///
/// Unlike APFloat, PositiveFloat does not model architecture floating point /// Unlike APFloat, UnsignedFloat does not model architecture floating point
/// behaviour (this should make it a little faster), and implements most /// behaviour (this should make it a little faster), and implements most
/// operators (this makes it usable). /// operators (this makes it usable).
/// ///
/// PositiveFloat is totally ordered. However, there is no canonical form, so /// UnsignedFloat is totally ordered. However, there is no canonical form, so
/// there are multiple representations of most scalars. E.g.: /// there are multiple representations of most scalars. E.g.:
/// ///
/// PositiveFloat(8u, 0) == PositiveFloat(4u, 1) /// UnsignedFloat(8u, 0) == UnsignedFloat(4u, 1)
/// PositiveFloat(4u, 1) == PositiveFloat(2u, 2) /// UnsignedFloat(4u, 1) == UnsignedFloat(2u, 2)
/// PositiveFloat(2u, 2) == PositiveFloat(1u, 3) /// UnsignedFloat(2u, 2) == UnsignedFloat(1u, 3)
/// ///
/// PositiveFloat implements most arithmetic operations. Precision is kept /// UnsignedFloat implements most arithmetic operations. Precision is kept
/// where possible. Uses simple saturation arithmetic, so that operations /// where possible. Uses simple saturation arithmetic, so that operations
/// saturate to 0.0 or getLargest() rather than under or overflowing. It has /// saturate to 0.0 or getLargest() rather than under or overflowing. It has
/// some extra arithmetic for unit inversion. 0.0/0.0 is defined to be 0.0. /// some extra arithmetic for unit inversion. 0.0/0.0 is defined to be 0.0.
@ -124,15 +124,13 @@ public:
/// both implemented, and both interpret negative shifts as positive shifts in /// both implemented, and both interpret negative shifts as positive shifts in
/// the opposite direction. /// the opposite direction.
/// ///
/// Future work might extract most of the implementation into a base class
/// (e.g., \c Float) that has an \c IsSigned template parameter. The initial
/// use case for this only needed positive semantics, but it wouldn't take much
/// work to extend.
///
/// Exponents are limited to the range accepted by x87 long double. This makes /// Exponents are limited to the range accepted by x87 long double. This makes
/// it trivial to add functionality to convert to APFloat (this is already /// it trivial to add functionality to convert to APFloat (this is already
/// relied on for the implementation of printing). /// relied on for the implementation of printing).
template <class DigitsT> class PositiveFloat : PositiveFloatBase { ///
/// The current plan is to gut this and make the necessary parts of it (even
/// more) private to BlockFrequencyInfo.
template <class DigitsT> class UnsignedFloat : UnsignedFloatBase {
public: public:
static_assert(!std::numeric_limits<DigitsT>::is_signed, static_assert(!std::numeric_limits<DigitsT>::is_signed,
"only unsigned floats supported"); "only unsigned floats supported");
@ -150,26 +148,26 @@ private:
int16_t Exponent; int16_t Exponent;
public: public:
PositiveFloat() : Digits(0), Exponent(0) {} UnsignedFloat() : Digits(0), Exponent(0) {}
PositiveFloat(DigitsType Digits, int16_t Exponent) UnsignedFloat(DigitsType Digits, int16_t Exponent)
: Digits(Digits), Exponent(Exponent) {} : Digits(Digits), Exponent(Exponent) {}
private: private:
PositiveFloat(const std::pair<uint64_t, int16_t> &X) UnsignedFloat(const std::pair<uint64_t, int16_t> &X)
: Digits(X.first), Exponent(X.second) {} : Digits(X.first), Exponent(X.second) {}
public: public:
static PositiveFloat getZero() { return PositiveFloat(0, 0); } static UnsignedFloat getZero() { return UnsignedFloat(0, 0); }
static PositiveFloat getOne() { return PositiveFloat(1, 0); } static UnsignedFloat getOne() { return UnsignedFloat(1, 0); }
static PositiveFloat getLargest() { static UnsignedFloat getLargest() {
return PositiveFloat(DigitsLimits::max(), MaxExponent); return UnsignedFloat(DigitsLimits::max(), MaxExponent);
} }
static PositiveFloat getFloat(uint64_t N) { return adjustToWidth(N, 0); } static UnsignedFloat getFloat(uint64_t N) { return adjustToWidth(N, 0); }
static PositiveFloat getInverseFloat(uint64_t N) { static UnsignedFloat getInverseFloat(uint64_t N) {
return getFloat(N).invert(); return getFloat(N).invert();
} }
static PositiveFloat getFraction(DigitsType N, DigitsType D) { static UnsignedFloat getFraction(DigitsType N, DigitsType D) {
return getQuotient(N, D); return getQuotient(N, D);
} }
@ -205,12 +203,12 @@ public:
/// Get the lg ceiling. lg 0 is defined to be INT32_MIN. /// Get the lg ceiling. lg 0 is defined to be INT32_MIN.
int32_t lgCeiling() const { return extractLgCeiling(lgImpl()); } int32_t lgCeiling() const { return extractLgCeiling(lgImpl()); }
bool operator==(const PositiveFloat &X) const { return compare(X) == 0; } bool operator==(const UnsignedFloat &X) const { return compare(X) == 0; }
bool operator<(const PositiveFloat &X) const { return compare(X) < 0; } bool operator<(const UnsignedFloat &X) const { return compare(X) < 0; }
bool operator!=(const PositiveFloat &X) const { return compare(X) != 0; } bool operator!=(const UnsignedFloat &X) const { return compare(X) != 0; }
bool operator>(const PositiveFloat &X) const { return compare(X) > 0; } bool operator>(const UnsignedFloat &X) const { return compare(X) > 0; }
bool operator<=(const PositiveFloat &X) const { return compare(X) <= 0; } bool operator<=(const UnsignedFloat &X) const { return compare(X) <= 0; }
bool operator>=(const PositiveFloat &X) const { return compare(X) >= 0; } bool operator>=(const UnsignedFloat &X) const { return compare(X) >= 0; }
bool operator!() const { return isZero(); } bool operator!() const { return isZero(); }
@ -234,7 +232,7 @@ public:
/// 65432198.7654... => 65432198.77 /// 65432198.7654... => 65432198.77
/// 5432198.7654... => 5432198.765 /// 5432198.7654... => 5432198.765
std::string toString(unsigned Precision = DefaultPrecision) { std::string toString(unsigned Precision = DefaultPrecision) {
return PositiveFloatBase::toString(Digits, Exponent, Width, Precision); return UnsignedFloatBase::toString(Digits, Exponent, Width, Precision);
} }
/// \brief Print a decimal representation. /// \brief Print a decimal representation.
@ -242,16 +240,16 @@ public:
/// Print a string. See toString for documentation. /// Print a string. See toString for documentation.
raw_ostream &print(raw_ostream &OS, raw_ostream &print(raw_ostream &OS,
unsigned Precision = DefaultPrecision) const { unsigned Precision = DefaultPrecision) const {
return PositiveFloatBase::print(OS, Digits, Exponent, Width, Precision); return UnsignedFloatBase::print(OS, Digits, Exponent, Width, Precision);
} }
void dump() const { return PositiveFloatBase::dump(Digits, Exponent, Width); } void dump() const { return UnsignedFloatBase::dump(Digits, Exponent, Width); }
PositiveFloat &operator+=(const PositiveFloat &X); UnsignedFloat &operator+=(const UnsignedFloat &X);
PositiveFloat &operator-=(const PositiveFloat &X); UnsignedFloat &operator-=(const UnsignedFloat &X);
PositiveFloat &operator*=(const PositiveFloat &X); UnsignedFloat &operator*=(const UnsignedFloat &X);
PositiveFloat &operator/=(const PositiveFloat &X); UnsignedFloat &operator/=(const UnsignedFloat &X);
PositiveFloat &operator<<=(int16_t Shift) { shiftLeft(Shift); return *this; } UnsignedFloat &operator<<=(int16_t Shift) { shiftLeft(Shift); return *this; }
PositiveFloat &operator>>=(int16_t Shift) { shiftRight(Shift); return *this; } UnsignedFloat &operator>>=(int16_t Shift) { shiftRight(Shift); return *this; }
private: private:
void shiftLeft(int32_t Shift); void shiftLeft(int32_t Shift);
@ -264,14 +262,14 @@ private:
/// ///
/// The value that compares smaller will lose precision, and possibly become /// The value that compares smaller will lose precision, and possibly become
/// \a isZero(). /// \a isZero().
PositiveFloat matchExponents(PositiveFloat X); UnsignedFloat matchExponents(UnsignedFloat X);
/// \brief Increase exponent to match another float. /// \brief Increase exponent to match another float.
/// ///
/// Increases \c this to have an exponent matching \c X. May decrease the /// Increases \c this to have an exponent matching \c X. May decrease the
/// exponent of \c X in the process, and \c this may possibly become \a /// exponent of \c X in the process, and \c this may possibly become \a
/// isZero(). /// isZero().
void increaseExponentToMatch(PositiveFloat &X, int32_t ExponentDiff); void increaseExponentToMatch(UnsignedFloat &X, int32_t ExponentDiff);
public: public:
/// \brief Scale a large number accurately. /// \brief Scale a large number accurately.
@ -293,9 +291,9 @@ public:
return joinSigned(scaleByInverse(Unsigned.first), Unsigned.second); return joinSigned(scaleByInverse(Unsigned.first), Unsigned.second);
} }
int compare(const PositiveFloat &X) const; int compare(const UnsignedFloat &X) const;
int compareTo(uint64_t N) const { int compareTo(uint64_t N) const {
PositiveFloat Float = getFloat(N); UnsignedFloat Float = getFloat(N);
int Compare = compare(Float); int Compare = compare(Float);
if (Width == 64 || Compare != 0) if (Width == 64 || Compare != 0)
return Compare; return Compare;
@ -306,12 +304,12 @@ public:
} }
int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); } int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); }
PositiveFloat &invert() { return *this = PositiveFloat::getFloat(1) / *this; } UnsignedFloat &invert() { return *this = UnsignedFloat::getFloat(1) / *this; }
PositiveFloat inverse() const { return PositiveFloat(*this).invert(); } UnsignedFloat inverse() const { return UnsignedFloat(*this).invert(); }
private: private:
static PositiveFloat getProduct(DigitsType L, DigitsType R); static UnsignedFloat getProduct(DigitsType L, DigitsType R);
static PositiveFloat getQuotient(DigitsType Dividend, DigitsType Divisor); static UnsignedFloat getQuotient(DigitsType Dividend, DigitsType Divisor);
std::pair<int32_t, int> lgImpl() const; std::pair<int32_t, int> lgImpl() const;
static int countLeadingZerosWidth(DigitsType Digits) { static int countLeadingZerosWidth(DigitsType Digits) {
@ -322,11 +320,11 @@ private:
return countLeadingZeros32(Digits) + Width - 32; return countLeadingZeros32(Digits) + Width - 32;
} }
static PositiveFloat adjustToWidth(uint64_t N, int32_t S) { static UnsignedFloat adjustToWidth(uint64_t N, int32_t S) {
assert(S >= MinExponent); assert(S >= MinExponent);
assert(S <= MaxExponent); assert(S <= MaxExponent);
if (Width == 64 || N <= DigitsLimits::max()) if (Width == 64 || N <= DigitsLimits::max())
return PositiveFloat(N, S); return UnsignedFloat(N, S);
// Shift right. // Shift right.
int Shift = 64 - Width - countLeadingZeros64(N); int Shift = 64 - Width - countLeadingZeros64(N);
@ -334,73 +332,73 @@ private:
// Round. // Round.
assert(S + Shift <= MaxExponent); assert(S + Shift <= MaxExponent);
return getRounded(PositiveFloat(Shifted, S + Shift), return getRounded(UnsignedFloat(Shifted, S + Shift),
N & UINT64_C(1) << (Shift - 1)); N & UINT64_C(1) << (Shift - 1));
} }
static PositiveFloat getRounded(PositiveFloat P, bool Round) { static UnsignedFloat getRounded(UnsignedFloat P, bool Round) {
if (!Round) if (!Round)
return P; return P;
if (P.Digits == DigitsLimits::max()) if (P.Digits == DigitsLimits::max())
// Careful of overflow in the exponent. // Careful of overflow in the exponent.
return PositiveFloat(1, P.Exponent) <<= Width; return UnsignedFloat(1, P.Exponent) <<= Width;
return PositiveFloat(P.Digits + 1, P.Exponent); return UnsignedFloat(P.Digits + 1, P.Exponent);
} }
}; };
#define POSITIVE_FLOAT_BOP(op, base) \ #define UNSIGNED_FLOAT_BOP(op, base) \
template <class DigitsT> \ template <class DigitsT> \
PositiveFloat<DigitsT> operator op(const PositiveFloat<DigitsT> &L, \ UnsignedFloat<DigitsT> operator op(const UnsignedFloat<DigitsT> &L, \
const PositiveFloat<DigitsT> &R) { \ const UnsignedFloat<DigitsT> &R) { \
return PositiveFloat<DigitsT>(L) base R; \ return UnsignedFloat<DigitsT>(L) base R; \
} }
POSITIVE_FLOAT_BOP(+, += ) UNSIGNED_FLOAT_BOP(+, += )
POSITIVE_FLOAT_BOP(-, -= ) UNSIGNED_FLOAT_BOP(-, -= )
POSITIVE_FLOAT_BOP(*, *= ) UNSIGNED_FLOAT_BOP(*, *= )
POSITIVE_FLOAT_BOP(/, /= ) UNSIGNED_FLOAT_BOP(/, /= )
POSITIVE_FLOAT_BOP(<<, <<= ) UNSIGNED_FLOAT_BOP(<<, <<= )
POSITIVE_FLOAT_BOP(>>, >>= ) UNSIGNED_FLOAT_BOP(>>, >>= )
#undef POSITIVE_FLOAT_BOP #undef UNSIGNED_FLOAT_BOP
template <class DigitsT> template <class DigitsT>
raw_ostream &operator<<(raw_ostream &OS, const PositiveFloat<DigitsT> &X) { raw_ostream &operator<<(raw_ostream &OS, const UnsignedFloat<DigitsT> &X) {
return X.print(OS, 10); return X.print(OS, 10);
} }
#define POSITIVE_FLOAT_COMPARE_TO_TYPE(op, T1, T2) \ #define UNSIGNED_FLOAT_COMPARE_TO_TYPE(op, T1, T2) \
template <class DigitsT> \ template <class DigitsT> \
bool operator op(const PositiveFloat<DigitsT> &L, T1 R) { \ bool operator op(const UnsignedFloat<DigitsT> &L, T1 R) { \
return L.compareTo(T2(R)) op 0; \ return L.compareTo(T2(R)) op 0; \
} \ } \
template <class DigitsT> \ template <class DigitsT> \
bool operator op(T1 L, const PositiveFloat<DigitsT> &R) { \ bool operator op(T1 L, const UnsignedFloat<DigitsT> &R) { \
return 0 op R.compareTo(T2(L)); \ return 0 op R.compareTo(T2(L)); \
} }
#define POSITIVE_FLOAT_COMPARE_TO(op) \ #define UNSIGNED_FLOAT_COMPARE_TO(op) \
POSITIVE_FLOAT_COMPARE_TO_TYPE(op, uint64_t, uint64_t) \ UNSIGNED_FLOAT_COMPARE_TO_TYPE(op, uint64_t, uint64_t) \
POSITIVE_FLOAT_COMPARE_TO_TYPE(op, uint32_t, uint64_t) \ UNSIGNED_FLOAT_COMPARE_TO_TYPE(op, uint32_t, uint64_t) \
POSITIVE_FLOAT_COMPARE_TO_TYPE(op, int64_t, int64_t) \ UNSIGNED_FLOAT_COMPARE_TO_TYPE(op, int64_t, int64_t) \
POSITIVE_FLOAT_COMPARE_TO_TYPE(op, int32_t, int64_t) UNSIGNED_FLOAT_COMPARE_TO_TYPE(op, int32_t, int64_t)
POSITIVE_FLOAT_COMPARE_TO(< ) UNSIGNED_FLOAT_COMPARE_TO(< )
POSITIVE_FLOAT_COMPARE_TO(> ) UNSIGNED_FLOAT_COMPARE_TO(> )
POSITIVE_FLOAT_COMPARE_TO(== ) UNSIGNED_FLOAT_COMPARE_TO(== )
POSITIVE_FLOAT_COMPARE_TO(!= ) UNSIGNED_FLOAT_COMPARE_TO(!= )
POSITIVE_FLOAT_COMPARE_TO(<= ) UNSIGNED_FLOAT_COMPARE_TO(<= )
POSITIVE_FLOAT_COMPARE_TO(>= ) UNSIGNED_FLOAT_COMPARE_TO(>= )
#undef POSITIVE_FLOAT_COMPARE_TO #undef UNSIGNED_FLOAT_COMPARE_TO
#undef POSITIVE_FLOAT_COMPARE_TO_TYPE #undef UNSIGNED_FLOAT_COMPARE_TO_TYPE
template <class DigitsT> template <class DigitsT>
uint64_t PositiveFloat<DigitsT>::scale(uint64_t N) const { uint64_t UnsignedFloat<DigitsT>::scale(uint64_t N) const {
if (Width == 64 || N <= DigitsLimits::max()) if (Width == 64 || N <= DigitsLimits::max())
return (getFloat(N) * *this).template toInt<uint64_t>(); return (getFloat(N) * *this).template toInt<uint64_t>();
// Defer to the 64-bit version. // Defer to the 64-bit version.
return PositiveFloat<uint64_t>(Digits, Exponent).scale(N); return UnsignedFloat<uint64_t>(Digits, Exponent).scale(N);
} }
template <class DigitsT> template <class DigitsT>
PositiveFloat<DigitsT> PositiveFloat<DigitsT>::getProduct(DigitsType L, UnsignedFloat<DigitsT> UnsignedFloat<DigitsT>::getProduct(DigitsType L,
DigitsType R) { DigitsType R) {
// Check for zero. // Check for zero.
if (!L || !R) if (!L || !R)
@ -411,10 +409,10 @@ PositiveFloat<DigitsT> PositiveFloat<DigitsT>::getProduct(DigitsType L,
return adjustToWidth(uint64_t(L) * uint64_t(R), 0); return adjustToWidth(uint64_t(L) * uint64_t(R), 0);
// Do the full thing. // Do the full thing.
return PositiveFloat(multiply64(L, R)); return UnsignedFloat(multiply64(L, R));
} }
template <class DigitsT> template <class DigitsT>
PositiveFloat<DigitsT> PositiveFloat<DigitsT>::getQuotient(DigitsType Dividend, UnsignedFloat<DigitsT> UnsignedFloat<DigitsT>::getQuotient(DigitsType Dividend,
DigitsType Divisor) { DigitsType Divisor) {
// Check for zero. // Check for zero.
if (!Dividend) if (!Dividend)
@ -423,7 +421,7 @@ PositiveFloat<DigitsT> PositiveFloat<DigitsT>::getQuotient(DigitsType Dividend,
return getLargest(); return getLargest();
if (Width == 64) if (Width == 64)
return PositiveFloat(divide64(Dividend, Divisor)); return UnsignedFloat(divide64(Dividend, Divisor));
// We can compute this with 64-bit math. // We can compute this with 64-bit math.
int Shift = countLeadingZeros64(Dividend); int Shift = countLeadingZeros64(Dividend);
@ -435,13 +433,13 @@ PositiveFloat<DigitsT> PositiveFloat<DigitsT>::getQuotient(DigitsType Dividend,
return adjustToWidth(Quotient, -Shift); return adjustToWidth(Quotient, -Shift);
// Round based on the value of the next bit. // Round based on the value of the next bit.
return getRounded(PositiveFloat(Quotient, -Shift), return getRounded(UnsignedFloat(Quotient, -Shift),
Shifted % Divisor >= getHalf(Divisor)); Shifted % Divisor >= getHalf(Divisor));
} }
template <class DigitsT> template <class DigitsT>
template <class IntT> template <class IntT>
IntT PositiveFloat<DigitsT>::toInt() const { IntT UnsignedFloat<DigitsT>::toInt() const {
typedef std::numeric_limits<IntT> Limits; typedef std::numeric_limits<IntT> Limits;
if (*this < 1) if (*this < 1)
return 0; return 0;
@ -461,7 +459,7 @@ IntT PositiveFloat<DigitsT>::toInt() const {
} }
template <class DigitsT> template <class DigitsT>
std::pair<int32_t, int> PositiveFloat<DigitsT>::lgImpl() const { std::pair<int32_t, int> UnsignedFloat<DigitsT>::lgImpl() const {
if (isZero()) if (isZero())
return std::make_pair(INT32_MIN, 0); return std::make_pair(INT32_MIN, 0);
@ -480,7 +478,7 @@ std::pair<int32_t, int> PositiveFloat<DigitsT>::lgImpl() const {
} }
template <class DigitsT> template <class DigitsT>
PositiveFloat<DigitsT> PositiveFloat<DigitsT>::matchExponents(PositiveFloat X) { UnsignedFloat<DigitsT> UnsignedFloat<DigitsT>::matchExponents(UnsignedFloat X) {
if (isZero() || X.isZero() || Exponent == X.Exponent) if (isZero() || X.isZero() || Exponent == X.Exponent)
return X; return X;
@ -492,7 +490,7 @@ PositiveFloat<DigitsT> PositiveFloat<DigitsT>::matchExponents(PositiveFloat X) {
return X; return X;
} }
template <class DigitsT> template <class DigitsT>
void PositiveFloat<DigitsT>::increaseExponentToMatch(PositiveFloat &X, void UnsignedFloat<DigitsT>::increaseExponentToMatch(UnsignedFloat &X,
int32_t ExponentDiff) { int32_t ExponentDiff) {
assert(ExponentDiff > 0); assert(ExponentDiff > 0);
if (ExponentDiff >= 2 * Width) { if (ExponentDiff >= 2 * Width) {
@ -518,15 +516,15 @@ void PositiveFloat<DigitsT>::increaseExponentToMatch(PositiveFloat &X,
} }
template <class DigitsT> template <class DigitsT>
PositiveFloat<DigitsT> &PositiveFloat<DigitsT>:: UnsignedFloat<DigitsT> &UnsignedFloat<DigitsT>::
operator+=(const PositiveFloat &X) { operator+=(const UnsignedFloat &X) {
if (isLargest() || X.isZero()) if (isLargest() || X.isZero())
return *this; return *this;
if (isZero() || X.isLargest()) if (isZero() || X.isLargest())
return *this = X; return *this = X;
// Normalize exponents. // Normalize exponents.
PositiveFloat Scaled = matchExponents(X); UnsignedFloat Scaled = matchExponents(X);
// Check for zero again. // Check for zero again.
if (isZero()) if (isZero())
@ -550,15 +548,15 @@ operator+=(const PositiveFloat &X) {
return *this; return *this;
} }
template <class DigitsT> template <class DigitsT>
PositiveFloat<DigitsT> &PositiveFloat<DigitsT>:: UnsignedFloat<DigitsT> &UnsignedFloat<DigitsT>::
operator-=(const PositiveFloat &X) { operator-=(const UnsignedFloat &X) {
if (X.isZero()) if (X.isZero())
return *this; return *this;
if (*this <= X) if (*this <= X)
return *this = getZero(); return *this = getZero();
// Normalize exponents. // Normalize exponents.
PositiveFloat Scaled = matchExponents(X); UnsignedFloat Scaled = matchExponents(X);
assert(Digits >= Scaled.Digits); assert(Digits >= Scaled.Digits);
// Compute difference. // Compute difference.
@ -570,15 +568,15 @@ operator-=(const PositiveFloat &X) {
// Check if X just barely lost its last bit. E.g., for 32-bit: // Check if X just barely lost its last bit. E.g., for 32-bit:
// //
// 1*2^32 - 1*2^0 == 0xffffffff != 1*2^32 // 1*2^32 - 1*2^0 == 0xffffffff != 1*2^32
if (*this == PositiveFloat(1, X.lgFloor() + Width)) { if (*this == UnsignedFloat(1, X.lgFloor() + Width)) {
Digits = DigitsType(0) - 1; Digits = DigitsType(0) - 1;
--Exponent; --Exponent;
} }
return *this; return *this;
} }
template <class DigitsT> template <class DigitsT>
PositiveFloat<DigitsT> &PositiveFloat<DigitsT>:: UnsignedFloat<DigitsT> &UnsignedFloat<DigitsT>::
operator*=(const PositiveFloat &X) { operator*=(const UnsignedFloat &X) {
if (isZero()) if (isZero())
return *this; return *this;
if (X.isZero()) if (X.isZero())
@ -594,8 +592,8 @@ operator*=(const PositiveFloat &X) {
return *this <<= Exponents; return *this <<= Exponents;
} }
template <class DigitsT> template <class DigitsT>
PositiveFloat<DigitsT> &PositiveFloat<DigitsT>:: UnsignedFloat<DigitsT> &UnsignedFloat<DigitsT>::
operator/=(const PositiveFloat &X) { operator/=(const UnsignedFloat &X) {
if (isZero()) if (isZero())
return *this; return *this;
if (X.isZero()) if (X.isZero())
@ -611,7 +609,7 @@ operator/=(const PositiveFloat &X) {
return *this <<= Exponents; return *this <<= Exponents;
} }
template <class DigitsT> template <class DigitsT>
void PositiveFloat<DigitsT>::shiftLeft(int32_t Shift) { void UnsignedFloat<DigitsT>::shiftLeft(int32_t Shift) {
if (!Shift || isZero()) if (!Shift || isZero())
return; return;
assert(Shift != INT32_MIN); assert(Shift != INT32_MIN);
@ -643,7 +641,7 @@ void PositiveFloat<DigitsT>::shiftLeft(int32_t Shift) {
} }
template <class DigitsT> template <class DigitsT>
void PositiveFloat<DigitsT>::shiftRight(int32_t Shift) { void UnsignedFloat<DigitsT>::shiftRight(int32_t Shift) {
if (!Shift || isZero()) if (!Shift || isZero())
return; return;
assert(Shift != INT32_MIN); assert(Shift != INT32_MIN);
@ -671,7 +669,7 @@ void PositiveFloat<DigitsT>::shiftRight(int32_t Shift) {
} }
template <class DigitsT> template <class DigitsT>
int PositiveFloat<DigitsT>::compare(const PositiveFloat &X) const { int UnsignedFloat<DigitsT>::compare(const UnsignedFloat &X) const {
// Check for zero. // Check for zero.
if (isZero()) if (isZero())
return X.isZero() ? 0 : -1; return X.isZero() ? 0 : -1;
@ -686,12 +684,12 @@ int PositiveFloat<DigitsT>::compare(const PositiveFloat &X) const {
// Compare digits. // Compare digits.
if (Exponent < X.Exponent) if (Exponent < X.Exponent)
return PositiveFloatBase::compare(Digits, X.Digits, X.Exponent - Exponent); return UnsignedFloatBase::compare(Digits, X.Digits, X.Exponent - Exponent);
return -PositiveFloatBase::compare(X.Digits, Digits, Exponent - X.Exponent); return -UnsignedFloatBase::compare(X.Digits, Digits, Exponent - X.Exponent);
} }
template <class T> struct isPodLike<PositiveFloat<T>> { template <class T> struct isPodLike<UnsignedFloat<T>> {
static const bool value = true; static const bool value = true;
}; };
} }
@ -845,7 +843,7 @@ public:
/// ///
/// Convert to a float. \a isFull() gives 1.0, while \a isEmpty() gives /// Convert to a float. \a isFull() gives 1.0, while \a isEmpty() gives
/// slightly above 0.0. /// slightly above 0.0.
PositiveFloat<uint64_t> toFloat() const; UnsignedFloat<uint64_t> toFloat() const;
void dump() const; void dump() const;
raw_ostream &print(raw_ostream &OS) const; raw_ostream &print(raw_ostream &OS) const;
@ -904,7 +902,7 @@ class MachineLoopInfo;
/// BlockFrequencyInfoImpl. See there for details. /// BlockFrequencyInfoImpl. See there for details.
class BlockFrequencyInfoImplBase { class BlockFrequencyInfoImplBase {
public: public:
typedef PositiveFloat<uint64_t> Float; typedef UnsignedFloat<uint64_t> Float;
/// \brief Representative of a block. /// \brief Representative of a block.
/// ///
@ -1183,7 +1181,7 @@ template <> inline std::string getBlockName(const BasicBlock *BB) {
/// MachineBlockFrequencyInfo, and calculates the relative frequencies of /// MachineBlockFrequencyInfo, and calculates the relative frequencies of
/// blocks. /// blocks.
/// ///
/// This algorithm leverages BlockMass and PositiveFloat to maintain precision, /// This algorithm leverages BlockMass and UnsignedFloat to maintain precision,
/// separates mass distribution from loop scaling, and dithers to eliminate /// separates mass distribution from loop scaling, and dithers to eliminate
/// probability mass loss. /// probability mass loss.
/// ///

View File

@ -21,12 +21,12 @@ using namespace llvm;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// PositiveFloat implementation. // UnsignedFloat implementation.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef _MSC_VER #ifndef _MSC_VER
const int32_t PositiveFloatBase::MaxExponent; const int32_t UnsignedFloatBase::MaxExponent;
const int32_t PositiveFloatBase::MinExponent; const int32_t UnsignedFloatBase::MinExponent;
#endif #endif
static void appendDigit(std::string &Str, unsigned D) { static void appendDigit(std::string &Str, unsigned D) {
@ -55,22 +55,22 @@ static bool doesRoundUp(char Digit) {
} }
static std::string toStringAPFloat(uint64_t D, int E, unsigned Precision) { static std::string toStringAPFloat(uint64_t D, int E, unsigned Precision) {
assert(E >= PositiveFloatBase::MinExponent); assert(E >= UnsignedFloatBase::MinExponent);
assert(E <= PositiveFloatBase::MaxExponent); assert(E <= UnsignedFloatBase::MaxExponent);
// Find a new E, but don't let it increase past MaxExponent. // Find a new E, but don't let it increase past MaxExponent.
int LeadingZeros = PositiveFloatBase::countLeadingZeros64(D); int LeadingZeros = UnsignedFloatBase::countLeadingZeros64(D);
int NewE = std::min(PositiveFloatBase::MaxExponent, E + 63 - LeadingZeros); int NewE = std::min(UnsignedFloatBase::MaxExponent, E + 63 - LeadingZeros);
int Shift = 63 - (NewE - E); int Shift = 63 - (NewE - E);
assert(Shift <= LeadingZeros); assert(Shift <= LeadingZeros);
assert(Shift == LeadingZeros || NewE == PositiveFloatBase::MaxExponent); assert(Shift == LeadingZeros || NewE == UnsignedFloatBase::MaxExponent);
D <<= Shift; D <<= Shift;
E = NewE; E = NewE;
// Check for a denormal. // Check for a denormal.
unsigned AdjustedE = E + 16383; unsigned AdjustedE = E + 16383;
if (!(D >> 63)) { if (!(D >> 63)) {
assert(E == PositiveFloatBase::MaxExponent); assert(E == UnsignedFloatBase::MaxExponent);
AdjustedE = 0; AdjustedE = 0;
} }
@ -92,7 +92,7 @@ static std::string stripTrailingZeros(const std::string &Float) {
return Float.substr(0, NonZero + 1); return Float.substr(0, NonZero + 1);
} }
std::string PositiveFloatBase::toString(uint64_t D, int16_t E, int Width, std::string UnsignedFloatBase::toString(uint64_t D, int16_t E, int Width,
unsigned Precision) { unsigned Precision) {
if (!D) if (!D)
return "0.0"; return "0.0";
@ -203,12 +203,12 @@ std::string PositiveFloatBase::toString(uint64_t D, int16_t E, int Width,
return stripTrailingZeros(std::string(Carry, '1') + Str.substr(0, Truncate)); return stripTrailingZeros(std::string(Carry, '1') + Str.substr(0, Truncate));
} }
raw_ostream &PositiveFloatBase::print(raw_ostream &OS, uint64_t D, int16_t E, raw_ostream &UnsignedFloatBase::print(raw_ostream &OS, uint64_t D, int16_t E,
int Width, unsigned Precision) { int Width, unsigned Precision) {
return OS << toString(D, E, Width, Precision); return OS << toString(D, E, Width, Precision);
} }
void PositiveFloatBase::dump(uint64_t D, int16_t E, int Width) { void UnsignedFloatBase::dump(uint64_t D, int16_t E, int Width) {
print(dbgs(), D, E, Width, 0) << "[" << Width << ":" << D << "*2^" << E print(dbgs(), D, E, Width, 0) << "[" << Width << ":" << D << "*2^" << E
<< "]"; << "]";
} }
@ -222,7 +222,7 @@ getRoundedFloat(uint64_t N, bool ShouldRound, int64_t Shift) {
return std::make_pair(N, Shift); return std::make_pair(N, Shift);
} }
std::pair<uint64_t, int16_t> PositiveFloatBase::divide64(uint64_t Dividend, std::pair<uint64_t, int16_t> UnsignedFloatBase::divide64(uint64_t Dividend,
uint64_t Divisor) { uint64_t Divisor) {
// Input should be sanitized. // Input should be sanitized.
assert(Divisor); assert(Divisor);
@ -273,7 +273,7 @@ std::pair<uint64_t, int16_t> PositiveFloatBase::divide64(uint64_t Dividend,
return getRoundedFloat(Quotient, Dividend >= getHalf(Divisor), Shift); return getRoundedFloat(Quotient, Dividend >= getHalf(Divisor), Shift);
} }
std::pair<uint64_t, int16_t> PositiveFloatBase::multiply64(uint64_t L, std::pair<uint64_t, int16_t> UnsignedFloatBase::multiply64(uint64_t L,
uint64_t R) { uint64_t R) {
// Separate into two 32-bit digits (U.L). // Separate into two 32-bit digits (U.L).
uint64_t UL = L >> 32, LL = L & UINT32_MAX, UR = R >> 32, LR = R & UINT32_MAX; uint64_t UL = L >> 32, LL = L & UINT32_MAX, UR = R >> 32, LR = R & UINT32_MAX;
@ -335,10 +335,10 @@ BlockMass &BlockMass::operator*=(const BranchProbability &P) {
return *this; return *this;
} }
PositiveFloat<uint64_t> BlockMass::toFloat() const { UnsignedFloat<uint64_t> BlockMass::toFloat() const {
if (isFull()) if (isFull())
return PositiveFloat<uint64_t>(1, 0); return UnsignedFloat<uint64_t>(1, 0);
return PositiveFloat<uint64_t>(getMass() + 1, -64); return UnsignedFloat<uint64_t>(getMass() + 1, -64);
} }
void BlockMass::dump() const { print(dbgs()); } void BlockMass::dump() const { print(dbgs()); }
@ -709,11 +709,8 @@ void BlockFrequencyInfoImplBase::addLoopSuccessorsToDist(
/// \brief Get the maximum allowed loop scale. /// \brief Get the maximum allowed loop scale.
/// ///
/// Gives the maximum number of estimated iterations allowed for a loop. /// Gives the maximum number of estimated iterations allowed for a loop. Very
/// Downstream users have trouble with very large numbers (even within /// large numbers cause problems downstream (even within 64-bits).
/// 64-bits). Perhaps they can be changed to use PositiveFloat.
///
/// TODO: change downstream users so that this can be increased or removed.
static Float getMaxLoopScale() { return Float(1, 12); } static Float getMaxLoopScale() { return Float(1, 12); }
/// \brief Compute the loop scale for a loop. /// \brief Compute the loop scale for a loop.