483 changes: 0 additions & 483 deletions llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,489 +31,6 @@

#define DEBUG_TYPE "block-freq"

//===----------------------------------------------------------------------===//
//
// ScaledNumber definition.
//
// TODO: Move to include/llvm/Support/ScaledNumber.h
//
//===----------------------------------------------------------------------===//
namespace llvm {

class ScaledNumberBase {
public:
static const int DefaultPrecision = 10;

static void dump(uint64_t D, int16_t E, int Width);
static raw_ostream &print(raw_ostream &OS, uint64_t D, int16_t E, int Width,
unsigned Precision);
static std::string toString(uint64_t D, int16_t E, int Width,
unsigned Precision);
static int countLeadingZeros32(uint32_t N) { return countLeadingZeros(N); }
static int countLeadingZeros64(uint64_t N) { return countLeadingZeros(N); }
static uint64_t getHalf(uint64_t N) { return (N >> 1) + (N & 1); }

static std::pair<uint64_t, bool> splitSigned(int64_t N) {
if (N >= 0)
return std::make_pair(N, false);
uint64_t Unsigned = N == INT64_MIN ? UINT64_C(1) << 63 : uint64_t(-N);
return std::make_pair(Unsigned, true);
}
static int64_t joinSigned(uint64_t U, bool IsNeg) {
if (U > uint64_t(INT64_MAX))
return IsNeg ? INT64_MIN : INT64_MAX;
return IsNeg ? -int64_t(U) : int64_t(U);
}
};

/// \brief Simple representation of a scaled number.
///
/// ScaledNumber is a number represented by digits and a scale. It uses simple
/// saturation arithmetic and every operation is well-defined for every value.
/// It's somewhat similar in behaviour to a soft-float, but is *not* a
/// replacement for one. If you're doing numerics, look at \a APFloat instead.
/// Nevertheless, we've found these semantics useful for modelling certain cost
/// metrics.
///
/// The number is split into a signed scale and unsigned digits. The number
/// represented is \c getDigits()*2^getScale(). In this way, the digits are
/// much like the mantissa in the x87 long double, but there is no canonical
/// form so the same number can be represented by many bit representations.
///
/// ScaledNumber is templated on the underlying integer type for digits, which
/// is expected to be unsigned.
///
/// Unlike APFloat, ScaledNumber does not model architecture floating point
/// behaviour -- while this might make it a little faster and easier to reason
/// about, it certainly makes it more dangerous for general numerics.
///
/// ScaledNumber is totally ordered. However, there is no canonical form, so
/// there are multiple representations of most scalars. E.g.:
///
/// ScaledNumber(8u, 0) == ScaledNumber(4u, 1)
/// ScaledNumber(4u, 1) == ScaledNumber(2u, 2)
/// ScaledNumber(2u, 2) == ScaledNumber(1u, 3)
///
/// ScaledNumber implements most arithmetic operations. Precision is kept
/// where possible. Uses simple saturation arithmetic, so that operations
/// 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.
/// Any other division by 0.0 is defined to be getLargest().
///
/// As a convenience for modifying the exponent, left and right shifting are
/// both implemented, and both interpret negative shifts as positive shifts in
/// the opposite direction.
///
/// Scales are limited to the range accepted by x87 long double. This makes
/// it trivial to add functionality to convert to APFloat (this is already
/// relied on for the implementation of printing).
///
/// Possible (and conflicting) future directions:
///
/// 1. Turn this into a wrapper around \a APFloat.
/// 2. Share the algorithm implementations with \a APFloat.
/// 3. Allow \a ScaledNumber to represent a signed number.
template <class DigitsT> class ScaledNumber : ScaledNumberBase {
public:
static_assert(!std::numeric_limits<DigitsT>::is_signed,
"only unsigned floats supported");

typedef DigitsT DigitsType;

private:
typedef std::numeric_limits<DigitsType> DigitsLimits;

static const int Width = sizeof(DigitsType) * 8;
static_assert(Width <= 64, "invalid integer width for digits");

private:
DigitsType Digits;
int16_t Scale;

public:
ScaledNumber() : Digits(0), Scale(0) {}

ScaledNumber(DigitsType Digits, int16_t Scale)
: Digits(Digits), Scale(Scale) {}

private:
ScaledNumber(const std::pair<uint64_t, int16_t> &X)
: Digits(X.first), Scale(X.second) {}

public:
static ScaledNumber getZero() { return ScaledNumber(0, 0); }
static ScaledNumber getOne() { return ScaledNumber(1, 0); }
static ScaledNumber getLargest() {
return ScaledNumber(DigitsLimits::max(), ScaledNumbers::MaxScale);
}
static ScaledNumber get(uint64_t N) { return adjustToWidth(N, 0); }
static ScaledNumber getInverse(uint64_t N) {
return get(N).invert();
}
static ScaledNumber getFraction(DigitsType N, DigitsType D) {
return getQuotient(N, D);
}

int16_t getScale() const { return Scale; }
DigitsType getDigits() const { return Digits; }

/// \brief Convert to the given integer type.
///
/// Convert to \c IntT using simple saturating arithmetic, truncating if
/// necessary.
template <class IntT> IntT toInt() const;

bool isZero() const { return !Digits; }
bool isLargest() const { return *this == getLargest(); }
bool isOne() const {
if (Scale > 0 || Scale <= -Width)
return false;
return Digits == DigitsType(1) << -Scale;
}

/// \brief The log base 2, rounded.
///
/// Get the lg of the scalar. lg 0 is defined to be INT32_MIN.
int32_t lg() const { return ScaledNumbers::getLg(Digits, Scale); }

/// \brief The log base 2, rounded towards INT32_MIN.
///
/// Get the lg floor. lg 0 is defined to be INT32_MIN.
int32_t lgFloor() const { return ScaledNumbers::getLgFloor(Digits, Scale); }

/// \brief The log base 2, rounded towards INT32_MAX.
///
/// Get the lg ceiling. lg 0 is defined to be INT32_MIN.
int32_t lgCeiling() const {
return ScaledNumbers::getLgCeiling(Digits, Scale);
}

bool operator==(const ScaledNumber &X) const { return compare(X) == 0; }
bool operator<(const ScaledNumber &X) const { return compare(X) < 0; }
bool operator!=(const ScaledNumber &X) const { return compare(X) != 0; }
bool operator>(const ScaledNumber &X) const { return compare(X) > 0; }
bool operator<=(const ScaledNumber &X) const { return compare(X) <= 0; }
bool operator>=(const ScaledNumber &X) const { return compare(X) >= 0; }

bool operator!() const { return isZero(); }

/// \brief Convert to a decimal representation in a string.
///
/// Convert to a string. Uses scientific notation for very large/small
/// numbers. Scientific notation is used roughly for numbers outside of the
/// range 2^-64 through 2^64.
///
/// \c Precision indicates the number of decimal digits of precision to use;
/// 0 requests the maximum available.
///
/// As a special case to make debugging easier, if the number is small enough
/// to convert without scientific notation and has more than \c Precision
/// digits before the decimal place, it's printed accurately to the first
/// digit past zero. E.g., assuming 10 digits of precision:
///
/// 98765432198.7654... => 98765432198.8
/// 8765432198.7654... => 8765432198.8
/// 765432198.7654... => 765432198.8
/// 65432198.7654... => 65432198.77
/// 5432198.7654... => 5432198.765
std::string toString(unsigned Precision = DefaultPrecision) {
return ScaledNumberBase::toString(Digits, Scale, Width, Precision);
}

/// \brief Print a decimal representation.
///
/// Print a string. See toString for documentation.
raw_ostream &print(raw_ostream &OS,
unsigned Precision = DefaultPrecision) const {
return ScaledNumberBase::print(OS, Digits, Scale, Width, Precision);
}
void dump() const { return ScaledNumberBase::dump(Digits, Scale, Width); }

ScaledNumber &operator+=(const ScaledNumber &X) {
std::tie(Digits, Scale) =
ScaledNumbers::getSum(Digits, Scale, X.Digits, X.Scale);
// Check for exponent past MaxScale.
if (Scale > ScaledNumbers::MaxScale)
*this = getLargest();
return *this;
}
ScaledNumber &operator-=(const ScaledNumber &X) {
std::tie(Digits, Scale) =
ScaledNumbers::getDifference(Digits, Scale, X.Digits, X.Scale);
return *this;
}
ScaledNumber &operator*=(const ScaledNumber &X);
ScaledNumber &operator/=(const ScaledNumber &X);
ScaledNumber &operator<<=(int16_t Shift) {
shiftLeft(Shift);
return *this;
}
ScaledNumber &operator>>=(int16_t Shift) {
shiftRight(Shift);
return *this;
}

private:
void shiftLeft(int32_t Shift);
void shiftRight(int32_t Shift);

/// \brief Adjust two floats to have matching exponents.
///
/// Adjust \c this and \c X to have matching exponents. Returns the new \c X
/// by value. Does nothing if \a isZero() for either.
///
/// The value that compares smaller will lose precision, and possibly become
/// \a isZero().
ScaledNumber matchScales(ScaledNumber X) {
ScaledNumbers::matchScales(Digits, Scale, X.Digits, X.Scale);
return X;
}

public:
/// \brief Scale a large number accurately.
///
/// Scale N (multiply it by this). Uses full precision multiplication, even
/// if Width is smaller than 64, so information is not lost.
uint64_t scale(uint64_t N) const;
uint64_t scaleByInverse(uint64_t N) const {
// TODO: implement directly, rather than relying on inverse. Inverse is
// expensive.
return inverse().scale(N);
}
int64_t scale(int64_t N) const {
std::pair<uint64_t, bool> Unsigned = splitSigned(N);
return joinSigned(scale(Unsigned.first), Unsigned.second);
}
int64_t scaleByInverse(int64_t N) const {
std::pair<uint64_t, bool> Unsigned = splitSigned(N);
return joinSigned(scaleByInverse(Unsigned.first), Unsigned.second);
}

int compare(const ScaledNumber &X) const {
return ScaledNumbers::compare(Digits, Scale, X.Digits, X.Scale);
}
int compareTo(uint64_t N) const {
ScaledNumber Scaled = get(N);
int Compare = compare(Scaled);
if (Width == 64 || Compare != 0)
return Compare;

// Check for precision loss. We know *this == RoundTrip.
uint64_t RoundTrip = Scaled.template toInt<uint64_t>();
return N == RoundTrip ? 0 : RoundTrip < N ? -1 : 1;
}
int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); }

ScaledNumber &invert() { return *this = ScaledNumber::get(1) / *this; }
ScaledNumber inverse() const { return ScaledNumber(*this).invert(); }

private:
static ScaledNumber getProduct(DigitsType LHS, DigitsType RHS) {
return ScaledNumbers::getProduct(LHS, RHS);
}
static ScaledNumber getQuotient(DigitsType Dividend, DigitsType Divisor) {
return ScaledNumbers::getQuotient(Dividend, Divisor);
}

static int countLeadingZerosWidth(DigitsType Digits) {
if (Width == 64)
return countLeadingZeros64(Digits);
if (Width == 32)
return countLeadingZeros32(Digits);
return countLeadingZeros32(Digits) + Width - 32;
}

/// \brief Adjust a number to width, rounding up if necessary.
///
/// Should only be called for \c Shift close to zero.
///
/// \pre Shift >= MinScale && Shift + 64 <= MaxScale.
static ScaledNumber adjustToWidth(uint64_t N, int32_t Shift) {
assert(Shift >= ScaledNumbers::MinScale && "Shift should be close to 0");
assert(Shift <= ScaledNumbers::MaxScale - 64 &&
"Shift should be close to 0");
auto Adjusted = ScaledNumbers::getAdjusted<DigitsT>(N, Shift);
return Adjusted;
}

static ScaledNumber getRounded(ScaledNumber P, bool Round) {
// Saturate.
if (P.isLargest())
return P;

return ScaledNumbers::getRounded(P.Digits, P.Scale, Round);
}
};

#define SCALED_NUMBER_BOP(op, base) \
template <class DigitsT> \
ScaledNumber<DigitsT> operator op(const ScaledNumber<DigitsT> &L, \
const ScaledNumber<DigitsT> &R) { \
return ScaledNumber<DigitsT>(L) base R; \
}
SCALED_NUMBER_BOP(+, += )
SCALED_NUMBER_BOP(-, -= )
SCALED_NUMBER_BOP(*, *= )
SCALED_NUMBER_BOP(/, /= )
SCALED_NUMBER_BOP(<<, <<= )
SCALED_NUMBER_BOP(>>, >>= )
#undef SCALED_NUMBER_BOP

template <class DigitsT>
raw_ostream &operator<<(raw_ostream &OS, const ScaledNumber<DigitsT> &X) {
return X.print(OS, 10);
}

#define SCALED_NUMBER_COMPARE_TO_TYPE(op, T1, T2) \
template <class DigitsT> \
bool operator op(const ScaledNumber<DigitsT> &L, T1 R) { \
return L.compareTo(T2(R)) op 0; \
} \
template <class DigitsT> \
bool operator op(T1 L, const ScaledNumber<DigitsT> &R) { \
return 0 op R.compareTo(T2(L)); \
}
#define SCALED_NUMBER_COMPARE_TO(op) \
SCALED_NUMBER_COMPARE_TO_TYPE(op, uint64_t, uint64_t) \
SCALED_NUMBER_COMPARE_TO_TYPE(op, uint32_t, uint64_t) \
SCALED_NUMBER_COMPARE_TO_TYPE(op, int64_t, int64_t) \
SCALED_NUMBER_COMPARE_TO_TYPE(op, int32_t, int64_t)
SCALED_NUMBER_COMPARE_TO(< )
SCALED_NUMBER_COMPARE_TO(> )
SCALED_NUMBER_COMPARE_TO(== )
SCALED_NUMBER_COMPARE_TO(!= )
SCALED_NUMBER_COMPARE_TO(<= )
SCALED_NUMBER_COMPARE_TO(>= )
#undef SCALED_NUMBER_COMPARE_TO
#undef SCALED_NUMBER_COMPARE_TO_TYPE

template <class DigitsT>
uint64_t ScaledNumber<DigitsT>::scale(uint64_t N) const {
if (Width == 64 || N <= DigitsLimits::max())
return (get(N) * *this).template toInt<uint64_t>();

// Defer to the 64-bit version.
return ScaledNumber<uint64_t>(Digits, Scale).scale(N);
}

template <class DigitsT>
template <class IntT>
IntT ScaledNumber<DigitsT>::toInt() const {
typedef std::numeric_limits<IntT> Limits;
if (*this < 1)
return 0;
if (*this >= Limits::max())
return Limits::max();

IntT N = Digits;
if (Scale > 0) {
assert(size_t(Scale) < sizeof(IntT) * 8);
return N << Scale;
}
if (Scale < 0) {
assert(size_t(-Scale) < sizeof(IntT) * 8);
return N >> -Scale;
}
return N;
}

template <class DigitsT>
ScaledNumber<DigitsT> &ScaledNumber<DigitsT>::
operator*=(const ScaledNumber &X) {
if (isZero())
return *this;
if (X.isZero())
return *this = X;

// Save the exponents.
int32_t Scales = int32_t(Scale) + int32_t(X.Scale);

// Get the raw product.
*this = getProduct(Digits, X.Digits);

// Combine with exponents.
return *this <<= Scales;
}
template <class DigitsT>
ScaledNumber<DigitsT> &ScaledNumber<DigitsT>::
operator/=(const ScaledNumber &X) {
if (isZero())
return *this;
if (X.isZero())
return *this = getLargest();

// Save the exponents.
int32_t Scales = int32_t(Scale) - int32_t(X.Scale);

// Get the raw quotient.
*this = getQuotient(Digits, X.Digits);

// Combine with exponents.
return *this <<= Scales;
}
template <class DigitsT> void ScaledNumber<DigitsT>::shiftLeft(int32_t Shift) {
if (!Shift || isZero())
return;
assert(Shift != INT32_MIN);
if (Shift < 0) {
shiftRight(-Shift);
return;
}

// Shift as much as we can in the exponent.
int32_t ScaleShift = std::min(Shift, ScaledNumbers::MaxScale - Scale);
Scale += ScaleShift;
if (ScaleShift == Shift)
return;

// Check this late, since it's rare.
if (isLargest())
return;

// Shift the digits themselves.
Shift -= ScaleShift;
if (Shift > countLeadingZerosWidth(Digits)) {
// Saturate.
*this = getLargest();
return;
}

Digits <<= Shift;
return;
}

template <class DigitsT> void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) {
if (!Shift || isZero())
return;
assert(Shift != INT32_MIN);
if (Shift < 0) {
shiftLeft(-Shift);
return;
}

// Shift as much as we can in the exponent.
int32_t ScaleShift = std::min(Shift, Scale - ScaledNumbers::MinScale);
Scale -= ScaleShift;
if (ScaleShift == Shift)
return;

// Shift the digits themselves.
Shift -= ScaleShift;
if (Shift >= Width) {
// Saturate.
*this = getZero();
return;
}

Digits >>= Shift;
return;
}

template <class T> struct isPodLike<ScaledNumber<T>> {
static const bool value = true;
};
}

//===----------------------------------------------------------------------===//
//
// BlockMass definition.
Expand Down
480 changes: 480 additions & 0 deletions llvm/include/llvm/Support/ScaledNumber.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <algorithm>
#include <cstdint>
#include <limits>
#include <string>
#include <utility>

namespace llvm {
Expand Down Expand Up @@ -413,4 +414,483 @@ inline std::pair<uint64_t, int16_t> getDifference64(uint64_t LDigits,
} // end namespace ScaledNumbers
} // end namespace llvm

namespace llvm {

class raw_ostream;
class ScaledNumberBase {
public:
static const int DefaultPrecision = 10;

static void dump(uint64_t D, int16_t E, int Width);
static raw_ostream &print(raw_ostream &OS, uint64_t D, int16_t E, int Width,
unsigned Precision);
static std::string toString(uint64_t D, int16_t E, int Width,
unsigned Precision);
static int countLeadingZeros32(uint32_t N) { return countLeadingZeros(N); }
static int countLeadingZeros64(uint64_t N) { return countLeadingZeros(N); }
static uint64_t getHalf(uint64_t N) { return (N >> 1) + (N & 1); }

static std::pair<uint64_t, bool> splitSigned(int64_t N) {
if (N >= 0)
return std::make_pair(N, false);
uint64_t Unsigned = N == INT64_MIN ? UINT64_C(1) << 63 : uint64_t(-N);
return std::make_pair(Unsigned, true);
}
static int64_t joinSigned(uint64_t U, bool IsNeg) {
if (U > uint64_t(INT64_MAX))
return IsNeg ? INT64_MIN : INT64_MAX;
return IsNeg ? -int64_t(U) : int64_t(U);
}
};

/// \brief Simple representation of a scaled number.
///
/// ScaledNumber is a number represented by digits and a scale. It uses simple
/// saturation arithmetic and every operation is well-defined for every value.
/// It's somewhat similar in behaviour to a soft-float, but is *not* a
/// replacement for one. If you're doing numerics, look at \a APFloat instead.
/// Nevertheless, we've found these semantics useful for modelling certain cost
/// metrics.
///
/// The number is split into a signed scale and unsigned digits. The number
/// represented is \c getDigits()*2^getScale(). In this way, the digits are
/// much like the mantissa in the x87 long double, but there is no canonical
/// form so the same number can be represented by many bit representations.
///
/// ScaledNumber is templated on the underlying integer type for digits, which
/// is expected to be unsigned.
///
/// Unlike APFloat, ScaledNumber does not model architecture floating point
/// behaviour -- while this might make it a little faster and easier to reason
/// about, it certainly makes it more dangerous for general numerics.
///
/// ScaledNumber is totally ordered. However, there is no canonical form, so
/// there are multiple representations of most scalars. E.g.:
///
/// ScaledNumber(8u, 0) == ScaledNumber(4u, 1)
/// ScaledNumber(4u, 1) == ScaledNumber(2u, 2)
/// ScaledNumber(2u, 2) == ScaledNumber(1u, 3)
///
/// ScaledNumber implements most arithmetic operations. Precision is kept
/// where possible. Uses simple saturation arithmetic, so that operations
/// 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.
/// Any other division by 0.0 is defined to be getLargest().
///
/// As a convenience for modifying the exponent, left and right shifting are
/// both implemented, and both interpret negative shifts as positive shifts in
/// the opposite direction.
///
/// Scales are limited to the range accepted by x87 long double. This makes
/// it trivial to add functionality to convert to APFloat (this is already
/// relied on for the implementation of printing).
///
/// Possible (and conflicting) future directions:
///
/// 1. Turn this into a wrapper around \a APFloat.
/// 2. Share the algorithm implementations with \a APFloat.
/// 3. Allow \a ScaledNumber to represent a signed number.
template <class DigitsT> class ScaledNumber : ScaledNumberBase {
public:
static_assert(!std::numeric_limits<DigitsT>::is_signed,
"only unsigned floats supported");

typedef DigitsT DigitsType;

private:
typedef std::numeric_limits<DigitsType> DigitsLimits;

static const int Width = sizeof(DigitsType) * 8;
static_assert(Width <= 64, "invalid integer width for digits");

private:
DigitsType Digits;
int16_t Scale;

public:
ScaledNumber() : Digits(0), Scale(0) {}

ScaledNumber(DigitsType Digits, int16_t Scale)
: Digits(Digits), Scale(Scale) {}

private:
ScaledNumber(const std::pair<uint64_t, int16_t> &X)
: Digits(X.first), Scale(X.second) {}

public:
static ScaledNumber getZero() { return ScaledNumber(0, 0); }
static ScaledNumber getOne() { return ScaledNumber(1, 0); }
static ScaledNumber getLargest() {
return ScaledNumber(DigitsLimits::max(), ScaledNumbers::MaxScale);
}
static ScaledNumber get(uint64_t N) { return adjustToWidth(N, 0); }
static ScaledNumber getInverse(uint64_t N) {
return get(N).invert();
}
static ScaledNumber getFraction(DigitsType N, DigitsType D) {
return getQuotient(N, D);
}

int16_t getScale() const { return Scale; }
DigitsType getDigits() const { return Digits; }

/// \brief Convert to the given integer type.
///
/// Convert to \c IntT using simple saturating arithmetic, truncating if
/// necessary.
template <class IntT> IntT toInt() const;

bool isZero() const { return !Digits; }
bool isLargest() const { return *this == getLargest(); }
bool isOne() const {
if (Scale > 0 || Scale <= -Width)
return false;
return Digits == DigitsType(1) << -Scale;
}

/// \brief The log base 2, rounded.
///
/// Get the lg of the scalar. lg 0 is defined to be INT32_MIN.
int32_t lg() const { return ScaledNumbers::getLg(Digits, Scale); }

/// \brief The log base 2, rounded towards INT32_MIN.
///
/// Get the lg floor. lg 0 is defined to be INT32_MIN.
int32_t lgFloor() const { return ScaledNumbers::getLgFloor(Digits, Scale); }

/// \brief The log base 2, rounded towards INT32_MAX.
///
/// Get the lg ceiling. lg 0 is defined to be INT32_MIN.
int32_t lgCeiling() const {
return ScaledNumbers::getLgCeiling(Digits, Scale);
}

bool operator==(const ScaledNumber &X) const { return compare(X) == 0; }
bool operator<(const ScaledNumber &X) const { return compare(X) < 0; }
bool operator!=(const ScaledNumber &X) const { return compare(X) != 0; }
bool operator>(const ScaledNumber &X) const { return compare(X) > 0; }
bool operator<=(const ScaledNumber &X) const { return compare(X) <= 0; }
bool operator>=(const ScaledNumber &X) const { return compare(X) >= 0; }

bool operator!() const { return isZero(); }

/// \brief Convert to a decimal representation in a string.
///
/// Convert to a string. Uses scientific notation for very large/small
/// numbers. Scientific notation is used roughly for numbers outside of the
/// range 2^-64 through 2^64.
///
/// \c Precision indicates the number of decimal digits of precision to use;
/// 0 requests the maximum available.
///
/// As a special case to make debugging easier, if the number is small enough
/// to convert without scientific notation and has more than \c Precision
/// digits before the decimal place, it's printed accurately to the first
/// digit past zero. E.g., assuming 10 digits of precision:
///
/// 98765432198.7654... => 98765432198.8
/// 8765432198.7654... => 8765432198.8
/// 765432198.7654... => 765432198.8
/// 65432198.7654... => 65432198.77
/// 5432198.7654... => 5432198.765
std::string toString(unsigned Precision = DefaultPrecision) {
return ScaledNumberBase::toString(Digits, Scale, Width, Precision);
}

/// \brief Print a decimal representation.
///
/// Print a string. See toString for documentation.
raw_ostream &print(raw_ostream &OS,
unsigned Precision = DefaultPrecision) const {
return ScaledNumberBase::print(OS, Digits, Scale, Width, Precision);
}
void dump() const { return ScaledNumberBase::dump(Digits, Scale, Width); }

ScaledNumber &operator+=(const ScaledNumber &X) {
std::tie(Digits, Scale) =
ScaledNumbers::getSum(Digits, Scale, X.Digits, X.Scale);
// Check for exponent past MaxScale.
if (Scale > ScaledNumbers::MaxScale)
*this = getLargest();
return *this;
}
ScaledNumber &operator-=(const ScaledNumber &X) {
std::tie(Digits, Scale) =
ScaledNumbers::getDifference(Digits, Scale, X.Digits, X.Scale);
return *this;
}
ScaledNumber &operator*=(const ScaledNumber &X);
ScaledNumber &operator/=(const ScaledNumber &X);
ScaledNumber &operator<<=(int16_t Shift) {
shiftLeft(Shift);
return *this;
}
ScaledNumber &operator>>=(int16_t Shift) {
shiftRight(Shift);
return *this;
}

private:
void shiftLeft(int32_t Shift);
void shiftRight(int32_t Shift);

/// \brief Adjust two floats to have matching exponents.
///
/// Adjust \c this and \c X to have matching exponents. Returns the new \c X
/// by value. Does nothing if \a isZero() for either.
///
/// The value that compares smaller will lose precision, and possibly become
/// \a isZero().
ScaledNumber matchScales(ScaledNumber X) {
ScaledNumbers::matchScales(Digits, Scale, X.Digits, X.Scale);
return X;
}

public:
/// \brief Scale a large number accurately.
///
/// Scale N (multiply it by this). Uses full precision multiplication, even
/// if Width is smaller than 64, so information is not lost.
uint64_t scale(uint64_t N) const;
uint64_t scaleByInverse(uint64_t N) const {
// TODO: implement directly, rather than relying on inverse. Inverse is
// expensive.
return inverse().scale(N);
}
int64_t scale(int64_t N) const {
std::pair<uint64_t, bool> Unsigned = splitSigned(N);
return joinSigned(scale(Unsigned.first), Unsigned.second);
}
int64_t scaleByInverse(int64_t N) const {
std::pair<uint64_t, bool> Unsigned = splitSigned(N);
return joinSigned(scaleByInverse(Unsigned.first), Unsigned.second);
}

int compare(const ScaledNumber &X) const {
return ScaledNumbers::compare(Digits, Scale, X.Digits, X.Scale);
}
int compareTo(uint64_t N) const {
ScaledNumber Scaled = get(N);
int Compare = compare(Scaled);
if (Width == 64 || Compare != 0)
return Compare;

// Check for precision loss. We know *this == RoundTrip.
uint64_t RoundTrip = Scaled.template toInt<uint64_t>();
return N == RoundTrip ? 0 : RoundTrip < N ? -1 : 1;
}
int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); }

ScaledNumber &invert() { return *this = ScaledNumber::get(1) / *this; }
ScaledNumber inverse() const { return ScaledNumber(*this).invert(); }

private:
static ScaledNumber getProduct(DigitsType LHS, DigitsType RHS) {
return ScaledNumbers::getProduct(LHS, RHS);
}
static ScaledNumber getQuotient(DigitsType Dividend, DigitsType Divisor) {
return ScaledNumbers::getQuotient(Dividend, Divisor);
}

static int countLeadingZerosWidth(DigitsType Digits) {
if (Width == 64)
return countLeadingZeros64(Digits);
if (Width == 32)
return countLeadingZeros32(Digits);
return countLeadingZeros32(Digits) + Width - 32;
}

/// \brief Adjust a number to width, rounding up if necessary.
///
/// Should only be called for \c Shift close to zero.
///
/// \pre Shift >= MinScale && Shift + 64 <= MaxScale.
static ScaledNumber adjustToWidth(uint64_t N, int32_t Shift) {
assert(Shift >= ScaledNumbers::MinScale && "Shift should be close to 0");
assert(Shift <= ScaledNumbers::MaxScale - 64 &&
"Shift should be close to 0");
auto Adjusted = ScaledNumbers::getAdjusted<DigitsT>(N, Shift);
return Adjusted;
}

static ScaledNumber getRounded(ScaledNumber P, bool Round) {
// Saturate.
if (P.isLargest())
return P;

return ScaledNumbers::getRounded(P.Digits, P.Scale, Round);
}
};

#define SCALED_NUMBER_BOP(op, base) \
template <class DigitsT> \
ScaledNumber<DigitsT> operator op(const ScaledNumber<DigitsT> &L, \
const ScaledNumber<DigitsT> &R) { \
return ScaledNumber<DigitsT>(L) base R; \
}
SCALED_NUMBER_BOP(+, += )
SCALED_NUMBER_BOP(-, -= )
SCALED_NUMBER_BOP(*, *= )
SCALED_NUMBER_BOP(/, /= )
SCALED_NUMBER_BOP(<<, <<= )
SCALED_NUMBER_BOP(>>, >>= )
#undef SCALED_NUMBER_BOP

template <class DigitsT>
raw_ostream &operator<<(raw_ostream &OS, const ScaledNumber<DigitsT> &X) {
return X.print(OS, 10);
}

#define SCALED_NUMBER_COMPARE_TO_TYPE(op, T1, T2) \
template <class DigitsT> \
bool operator op(const ScaledNumber<DigitsT> &L, T1 R) { \
return L.compareTo(T2(R)) op 0; \
} \
template <class DigitsT> \
bool operator op(T1 L, const ScaledNumber<DigitsT> &R) { \
return 0 op R.compareTo(T2(L)); \
}
#define SCALED_NUMBER_COMPARE_TO(op) \
SCALED_NUMBER_COMPARE_TO_TYPE(op, uint64_t, uint64_t) \
SCALED_NUMBER_COMPARE_TO_TYPE(op, uint32_t, uint64_t) \
SCALED_NUMBER_COMPARE_TO_TYPE(op, int64_t, int64_t) \
SCALED_NUMBER_COMPARE_TO_TYPE(op, int32_t, int64_t)
SCALED_NUMBER_COMPARE_TO(< )
SCALED_NUMBER_COMPARE_TO(> )
SCALED_NUMBER_COMPARE_TO(== )
SCALED_NUMBER_COMPARE_TO(!= )
SCALED_NUMBER_COMPARE_TO(<= )
SCALED_NUMBER_COMPARE_TO(>= )
#undef SCALED_NUMBER_COMPARE_TO
#undef SCALED_NUMBER_COMPARE_TO_TYPE

template <class DigitsT>
uint64_t ScaledNumber<DigitsT>::scale(uint64_t N) const {
if (Width == 64 || N <= DigitsLimits::max())
return (get(N) * *this).template toInt<uint64_t>();

// Defer to the 64-bit version.
return ScaledNumber<uint64_t>(Digits, Scale).scale(N);
}

template <class DigitsT>
template <class IntT>
IntT ScaledNumber<DigitsT>::toInt() const {
typedef std::numeric_limits<IntT> Limits;
if (*this < 1)
return 0;
if (*this >= Limits::max())
return Limits::max();

IntT N = Digits;
if (Scale > 0) {
assert(size_t(Scale) < sizeof(IntT) * 8);
return N << Scale;
}
if (Scale < 0) {
assert(size_t(-Scale) < sizeof(IntT) * 8);
return N >> -Scale;
}
return N;
}

template <class DigitsT>
ScaledNumber<DigitsT> &ScaledNumber<DigitsT>::
operator*=(const ScaledNumber &X) {
if (isZero())
return *this;
if (X.isZero())
return *this = X;

// Save the exponents.
int32_t Scales = int32_t(Scale) + int32_t(X.Scale);

// Get the raw product.
*this = getProduct(Digits, X.Digits);

// Combine with exponents.
return *this <<= Scales;
}
template <class DigitsT>
ScaledNumber<DigitsT> &ScaledNumber<DigitsT>::
operator/=(const ScaledNumber &X) {
if (isZero())
return *this;
if (X.isZero())
return *this = getLargest();

// Save the exponents.
int32_t Scales = int32_t(Scale) - int32_t(X.Scale);

// Get the raw quotient.
*this = getQuotient(Digits, X.Digits);

// Combine with exponents.
return *this <<= Scales;
}
template <class DigitsT> void ScaledNumber<DigitsT>::shiftLeft(int32_t Shift) {
if (!Shift || isZero())
return;
assert(Shift != INT32_MIN);
if (Shift < 0) {
shiftRight(-Shift);
return;
}

// Shift as much as we can in the exponent.
int32_t ScaleShift = std::min(Shift, ScaledNumbers::MaxScale - Scale);
Scale += ScaleShift;
if (ScaleShift == Shift)
return;

// Check this late, since it's rare.
if (isLargest())
return;

// Shift the digits themselves.
Shift -= ScaleShift;
if (Shift > countLeadingZerosWidth(Digits)) {
// Saturate.
*this = getLargest();
return;
}

Digits <<= Shift;
return;
}

template <class DigitsT> void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) {
if (!Shift || isZero())
return;
assert(Shift != INT32_MIN);
if (Shift < 0) {
shiftLeft(-Shift);
return;
}

// Shift as much as we can in the exponent.
int32_t ScaleShift = std::min(Shift, Scale - ScaledNumbers::MinScale);
Scale -= ScaleShift;
if (ScaleShift == Shift)
return;

// Shift the digits themselves.
Shift -= ScaleShift;
if (Shift >= Width) {
// Saturate.
*this = getZero();
return;
}

Digits >>= Shift;
return;
}

template <typename T> struct isPodLike;
template <typename T> struct isPodLike<ScaledNumber<T>> {
static const bool value = true;
};

} // end namespace llvm

#endif
190 changes: 0 additions & 190 deletions llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/Support/raw_ostream.h"
#include <deque>
Expand All @@ -22,195 +21,6 @@ using namespace llvm::bfi_detail;

#define DEBUG_TYPE "block-freq"

//===----------------------------------------------------------------------===//
//
// ScaledNumber implementation.
//
//===----------------------------------------------------------------------===//
static void appendDigit(std::string &Str, unsigned D) {
assert(D < 10);
Str += '0' + D % 10;
}

static void appendNumber(std::string &Str, uint64_t N) {
while (N) {
appendDigit(Str, N % 10);
N /= 10;
}
}

static bool doesRoundUp(char Digit) {
switch (Digit) {
case '5':
case '6':
case '7':
case '8':
case '9':
return true;
default:
return false;
}
}

static std::string toStringAPFloat(uint64_t D, int E, unsigned Precision) {
assert(E >= ScaledNumbers::MinScale);
assert(E <= ScaledNumbers::MaxScale);

// Find a new E, but don't let it increase past MaxScale.
int LeadingZeros = ScaledNumberBase::countLeadingZeros64(D);
int NewE = std::min(ScaledNumbers::MaxScale, E + 63 - LeadingZeros);
int Shift = 63 - (NewE - E);
assert(Shift <= LeadingZeros);
assert(Shift == LeadingZeros || NewE == ScaledNumbers::MaxScale);
D <<= Shift;
E = NewE;

// Check for a denormal.
unsigned AdjustedE = E + 16383;
if (!(D >> 63)) {
assert(E == ScaledNumbers::MaxScale);
AdjustedE = 0;
}

// Build the float and print it.
uint64_t RawBits[2] = {D, AdjustedE};
APFloat Float(APFloat::x87DoubleExtended, APInt(80, RawBits));
SmallVector<char, 24> Chars;
Float.toString(Chars, Precision, 0);
return std::string(Chars.begin(), Chars.end());
}

static std::string stripTrailingZeros(const std::string &Float) {
size_t NonZero = Float.find_last_not_of('0');
assert(NonZero != std::string::npos && "no . in floating point string");

if (Float[NonZero] == '.')
++NonZero;

return Float.substr(0, NonZero + 1);
}

std::string ScaledNumberBase::toString(uint64_t D, int16_t E, int Width,
unsigned Precision) {
if (!D)
return "0.0";

// Canonicalize exponent and digits.
uint64_t Above0 = 0;
uint64_t Below0 = 0;
uint64_t Extra = 0;
int ExtraShift = 0;
if (E == 0) {
Above0 = D;
} else if (E > 0) {
if (int Shift = std::min(int16_t(countLeadingZeros64(D)), E)) {
D <<= Shift;
E -= Shift;

if (!E)
Above0 = D;
}
} else if (E > -64) {
Above0 = D >> -E;
Below0 = D << (64 + E);
} else if (E > -120) {
Below0 = D >> (-E - 64);
Extra = D << (128 + E);
ExtraShift = -64 - E;
}

// Fall back on APFloat for very small and very large numbers.
if (!Above0 && !Below0)
return toStringAPFloat(D, E, Precision);

// Append the digits before the decimal.
std::string Str;
size_t DigitsOut = 0;
if (Above0) {
appendNumber(Str, Above0);
DigitsOut = Str.size();
} else
appendDigit(Str, 0);
std::reverse(Str.begin(), Str.end());

// Return early if there's nothing after the decimal.
if (!Below0)
return Str + ".0";

// Append the decimal and beyond.
Str += '.';
uint64_t Error = UINT64_C(1) << (64 - Width);

// We need to shift Below0 to the right to make space for calculating
// digits. Save the precision we're losing in Extra.
Extra = (Below0 & 0xf) << 56 | (Extra >> 8);
Below0 >>= 4;
size_t SinceDot = 0;
size_t AfterDot = Str.size();
do {
if (ExtraShift) {
--ExtraShift;
Error *= 5;
} else
Error *= 10;

Below0 *= 10;
Extra *= 10;
Below0 += (Extra >> 60);
Extra = Extra & (UINT64_MAX >> 4);
appendDigit(Str, Below0 >> 60);
Below0 = Below0 & (UINT64_MAX >> 4);
if (DigitsOut || Str.back() != '0')
++DigitsOut;
++SinceDot;
} while (Error && (Below0 << 4 | Extra >> 60) >= Error / 2 &&
(!Precision || DigitsOut <= Precision || SinceDot < 2));

// Return early for maximum precision.
if (!Precision || DigitsOut <= Precision)
return stripTrailingZeros(Str);

// Find where to truncate.
size_t Truncate =
std::max(Str.size() - (DigitsOut - Precision), AfterDot + 1);

// Check if there's anything to truncate.
if (Truncate >= Str.size())
return stripTrailingZeros(Str);

bool Carry = doesRoundUp(Str[Truncate]);
if (!Carry)
return stripTrailingZeros(Str.substr(0, Truncate));

// Round with the first truncated digit.
for (std::string::reverse_iterator I(Str.begin() + Truncate), E = Str.rend();
I != E; ++I) {
if (*I == '.')
continue;
if (*I == '9') {
*I = '0';
continue;
}

++*I;
Carry = false;
break;
}

// Add "1" in front if we still need to carry.
return stripTrailingZeros(std::string(Carry, '1') + Str.substr(0, Truncate));
}

raw_ostream &ScaledNumberBase::print(raw_ostream &OS, uint64_t D, int16_t E,
int Width, unsigned Precision) {
return OS << toString(D, E, Width, Precision);
}

void ScaledNumberBase::dump(uint64_t D, int16_t E, int Width) {
print(dbgs(), D, E, Width, 0) << "[" << Width << ":" << D << "*2^" << E
<< "]";
}

//===----------------------------------------------------------------------===//
//
// BlockMass implementation.
Expand Down
187 changes: 187 additions & 0 deletions llvm/lib/Support/ScaledNumber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

#include "llvm/Support/ScaledNumber.h"

#include "llvm/ADT/APFloat.h"
#include "llvm/Support/Debug.h"

using namespace llvm;
using namespace llvm::ScaledNumbers;

Expand Down Expand Up @@ -130,3 +133,187 @@ int ScaledNumbers::compareImpl(uint64_t L, uint64_t R, int ScaleDiff) {

return L > L_adjusted << ScaleDiff ? 1 : 0;
}

static void appendDigit(std::string &Str, unsigned D) {
assert(D < 10);
Str += '0' + D % 10;
}

static void appendNumber(std::string &Str, uint64_t N) {
while (N) {
appendDigit(Str, N % 10);
N /= 10;
}
}

static bool doesRoundUp(char Digit) {
switch (Digit) {
case '5':
case '6':
case '7':
case '8':
case '9':
return true;
default:
return false;
}
}

static std::string toStringAPFloat(uint64_t D, int E, unsigned Precision) {
assert(E >= ScaledNumbers::MinScale);
assert(E <= ScaledNumbers::MaxScale);

// Find a new E, but don't let it increase past MaxScale.
int LeadingZeros = ScaledNumberBase::countLeadingZeros64(D);
int NewE = std::min(ScaledNumbers::MaxScale, E + 63 - LeadingZeros);
int Shift = 63 - (NewE - E);
assert(Shift <= LeadingZeros);
assert(Shift == LeadingZeros || NewE == ScaledNumbers::MaxScale);
D <<= Shift;
E = NewE;

// Check for a denormal.
unsigned AdjustedE = E + 16383;
if (!(D >> 63)) {
assert(E == ScaledNumbers::MaxScale);
AdjustedE = 0;
}

// Build the float and print it.
uint64_t RawBits[2] = {D, AdjustedE};
APFloat Float(APFloat::x87DoubleExtended, APInt(80, RawBits));
SmallVector<char, 24> Chars;
Float.toString(Chars, Precision, 0);
return std::string(Chars.begin(), Chars.end());
}

static std::string stripTrailingZeros(const std::string &Float) {
size_t NonZero = Float.find_last_not_of('0');
assert(NonZero != std::string::npos && "no . in floating point string");

if (Float[NonZero] == '.')
++NonZero;

return Float.substr(0, NonZero + 1);
}

std::string ScaledNumberBase::toString(uint64_t D, int16_t E, int Width,
unsigned Precision) {
if (!D)
return "0.0";

// Canonicalize exponent and digits.
uint64_t Above0 = 0;
uint64_t Below0 = 0;
uint64_t Extra = 0;
int ExtraShift = 0;
if (E == 0) {
Above0 = D;
} else if (E > 0) {
if (int Shift = std::min(int16_t(countLeadingZeros64(D)), E)) {
D <<= Shift;
E -= Shift;

if (!E)
Above0 = D;
}
} else if (E > -64) {
Above0 = D >> -E;
Below0 = D << (64 + E);
} else if (E > -120) {
Below0 = D >> (-E - 64);
Extra = D << (128 + E);
ExtraShift = -64 - E;
}

// Fall back on APFloat for very small and very large numbers.
if (!Above0 && !Below0)
return toStringAPFloat(D, E, Precision);

// Append the digits before the decimal.
std::string Str;
size_t DigitsOut = 0;
if (Above0) {
appendNumber(Str, Above0);
DigitsOut = Str.size();
} else
appendDigit(Str, 0);
std::reverse(Str.begin(), Str.end());

// Return early if there's nothing after the decimal.
if (!Below0)
return Str + ".0";

// Append the decimal and beyond.
Str += '.';
uint64_t Error = UINT64_C(1) << (64 - Width);

// We need to shift Below0 to the right to make space for calculating
// digits. Save the precision we're losing in Extra.
Extra = (Below0 & 0xf) << 56 | (Extra >> 8);
Below0 >>= 4;
size_t SinceDot = 0;
size_t AfterDot = Str.size();
do {
if (ExtraShift) {
--ExtraShift;
Error *= 5;
} else
Error *= 10;

Below0 *= 10;
Extra *= 10;
Below0 += (Extra >> 60);
Extra = Extra & (UINT64_MAX >> 4);
appendDigit(Str, Below0 >> 60);
Below0 = Below0 & (UINT64_MAX >> 4);
if (DigitsOut || Str.back() != '0')
++DigitsOut;
++SinceDot;
} while (Error && (Below0 << 4 | Extra >> 60) >= Error / 2 &&
(!Precision || DigitsOut <= Precision || SinceDot < 2));

// Return early for maximum precision.
if (!Precision || DigitsOut <= Precision)
return stripTrailingZeros(Str);

// Find where to truncate.
size_t Truncate =
std::max(Str.size() - (DigitsOut - Precision), AfterDot + 1);

// Check if there's anything to truncate.
if (Truncate >= Str.size())
return stripTrailingZeros(Str);

bool Carry = doesRoundUp(Str[Truncate]);
if (!Carry)
return stripTrailingZeros(Str.substr(0, Truncate));

// Round with the first truncated digit.
for (std::string::reverse_iterator I(Str.begin() + Truncate), E = Str.rend();
I != E; ++I) {
if (*I == '.')
continue;
if (*I == '9') {
*I = '0';
continue;
}

++*I;
Carry = false;
break;
}

// Add "1" in front if we still need to carry.
return stripTrailingZeros(std::string(Carry, '1') + Str.substr(0, Truncate));
}

raw_ostream &ScaledNumberBase::print(raw_ostream &OS, uint64_t D, int16_t E,
int Width, unsigned Precision) {
return OS << toString(D, E, Width, Precision);
}

void ScaledNumberBase::dump(uint64_t D, int16_t E, int Width) {
print(dbgs(), D, E, Width, 0) << "[" << Width << ":" << D << "*2^" << E
<< "]";
}