[llvm] r211531 - Support: Extract ScaledNumbers::matchScale()
Duncan P. N. Exon Smith
dexonsmith at apple.com
Mon Jun 23 13:40:46 PDT 2014
Author: dexonsmith
Date: Mon Jun 23 15:40:45 2014
New Revision: 211531
URL: http://llvm.org/viewvc/llvm-project?rev=211531&view=rev
Log:
Support: Extract ScaledNumbers::matchScale()
Modified:
llvm/trunk/include/llvm/Analysis/BlockFrequencyInfoImpl.h
llvm/trunk/include/llvm/Support/ScaledNumber.h
llvm/trunk/unittests/Support/ScaledNumberTest.cpp
Modified: llvm/trunk/include/llvm/Analysis/BlockFrequencyInfoImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/BlockFrequencyInfoImpl.h?rev=211531&r1=211530&r2=211531&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/BlockFrequencyInfoImpl.h (original)
+++ llvm/trunk/include/llvm/Analysis/BlockFrequencyInfoImpl.h Mon Jun 23 15:40:45 2014
@@ -247,14 +247,10 @@ private:
///
/// The value that compares smaller will lose precision, and possibly become
/// \a isZero().
- UnsignedFloat matchExponents(UnsignedFloat X);
-
- /// \brief Increase exponent to match another float.
- ///
- /// 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
- /// isZero().
- void increaseExponentToMatch(UnsignedFloat &X, int32_t ExponentDiff);
+ UnsignedFloat matchExponents(UnsignedFloat X) {
+ ScaledNumbers::matchScales(Digits, Exponent, X.Digits, X.Exponent);
+ return X;
+ }
public:
/// \brief Scale a large number accurately.
@@ -404,44 +400,6 @@ IntT UnsignedFloat<DigitsT>::toInt() con
}
template <class DigitsT>
-UnsignedFloat<DigitsT> UnsignedFloat<DigitsT>::matchExponents(UnsignedFloat X) {
- if (isZero() || X.isZero() || Exponent == X.Exponent)
- return X;
-
- int32_t Diff = int32_t(X.Exponent) - int32_t(Exponent);
- if (Diff > 0)
- increaseExponentToMatch(X, Diff);
- else
- X.increaseExponentToMatch(*this, -Diff);
- return X;
-}
-template <class DigitsT>
-void UnsignedFloat<DigitsT>::increaseExponentToMatch(UnsignedFloat &X,
- int32_t ExponentDiff) {
- assert(ExponentDiff > 0);
- if (ExponentDiff >= 2 * Width) {
- *this = getZero();
- return;
- }
-
- // Use up any leading zeros on X, and then shift this.
- int32_t ShiftX = std::min(countLeadingZerosWidth(X.Digits), ExponentDiff);
- assert(ShiftX < Width);
-
- int32_t ShiftThis = ExponentDiff - ShiftX;
- if (ShiftThis >= Width) {
- *this = getZero();
- return;
- }
-
- X.Digits <<= ShiftX;
- X.Exponent -= ShiftX;
- Digits >>= ShiftThis;
- Exponent += ShiftThis;
- return;
-}
-
-template <class DigitsT>
UnsignedFloat<DigitsT> &UnsignedFloat<DigitsT>::
operator+=(const UnsignedFloat &X) {
if (isLargest() || X.isZero())
Modified: llvm/trunk/include/llvm/Support/ScaledNumber.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ScaledNumber.h?rev=211531&r1=211530&r2=211531&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/ScaledNumber.h (original)
+++ llvm/trunk/include/llvm/Support/ScaledNumber.h Mon Jun 23 15:40:45 2014
@@ -24,6 +24,7 @@
#include "llvm/Support/MathExtras.h"
+#include <algorithm>
#include <cstdint>
#include <limits>
#include <utility>
@@ -263,6 +264,56 @@ int compare(DigitsT LDigits, int16_t LSc
return -compareImpl(RDigits, LDigits, LScale - RScale);
}
+/// \brief Match scales of two numbers.
+///
+/// Given two scaled numbers, match up their scales. Change the digits and
+/// scales in place. Shift the digits as necessary to form equivalent numbers,
+/// losing precision only when necessary.
+///
+/// If the output value of \c LDigits (\c RDigits) is \c 0, the output value of
+/// \c LScale (\c RScale) is unspecified. If both \c LDigits and \c RDigits
+/// are \c 0, the output value is one of \c LScale and \c RScale; which is
+/// unspecified.
+template <class DigitsT>
+void matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits,
+ int16_t &RScale) {
+ static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned");
+
+ if (LScale < RScale) {
+ // Swap arguments.
+ matchScales(RDigits, RScale, LDigits, LScale);
+ return;
+ }
+ if (!LDigits || !RDigits || LScale == RScale)
+ return;
+
+ // Now LScale > RScale. Get the difference.
+ int32_t ScaleDiff = int32_t(LScale) - RScale;
+ if (ScaleDiff >= 2 * getWidth<DigitsT>()) {
+ // Don't bother shifting. RDigits will get zero-ed out anyway.
+ RDigits = 0;
+ return;
+ }
+
+ // Shift LDigits left as much as possible, then shift RDigits right.
+ int32_t ShiftL = std::min<int32_t>(countLeadingZeros(LDigits), ScaleDiff);
+ assert(ShiftL < getWidth<DigitsT>() && "can't shift more than width");
+
+ int32_t ShiftR = ScaleDiff - ShiftL;
+ if (ShiftR >= getWidth<DigitsT>()) {
+ // Don't bother shifting. RDigits will get zero-ed out anyway.
+ RDigits = 0;
+ return;
+ }
+
+ LDigits <<= ShiftL;
+ RDigits >>= ShiftR;
+
+ LScale -= ShiftL;
+ RScale += ShiftR;
+ assert(LScale == RScale && "scales should match");
+}
+
} // end namespace ScaledNumbers
} // end namespace llvm
Modified: llvm/trunk/unittests/Support/ScaledNumberTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/ScaledNumberTest.cpp?rev=211531&r1=211530&r2=211531&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/ScaledNumberTest.cpp (original)
+++ llvm/trunk/unittests/Support/ScaledNumberTest.cpp Mon Jun 23 15:40:45 2014
@@ -322,4 +322,68 @@ TEST(ScaledNumberHelpersTest, compare) {
EXPECT_EQ(-1, compare(UINT64_MAX, 0, UINT64_C(1), 64));
}
+TEST(ScaledNumberHelpersTest, matchScales) {
+ typedef std::tuple<uint32_t, int16_t, uint32_t, int16_t> Pair32;
+ typedef std::tuple<uint64_t, int16_t, uint64_t, int16_t> Pair64;
+
+#define MATCH_SCALES(T, LDIn, LSIn, RDIn, RSIn, LDOut, RDOut, SOut) \
+ do { \
+ T LDx = LDIn; \
+ T RDx = RDIn; \
+ T LDy = LDOut; \
+ T RDy = RDOut; \
+ int16_t LSx = LSIn; \
+ int16_t RSx = RSIn; \
+ int16_t Sy = SOut; \
+ \
+ matchScales(LDx, LSx, RDx, RSx); \
+ EXPECT_EQ(LDy, LDx); \
+ EXPECT_EQ(RDy, RDx); \
+ if (LDy) \
+ EXPECT_EQ(Sy, LSx); \
+ if (RDy) \
+ EXPECT_EQ(Sy, RSx); \
+ } while (false)
+
+ MATCH_SCALES(uint32_t, 0, 0, 0, 0, 0, 0, 0);
+ MATCH_SCALES(uint32_t, 0, 50, 7, 1, 0, 7, 1);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 1, 9, 0, UINT32_C(1) << 31, 4, 1);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 2, 9, 0, UINT32_C(1) << 31, 2, 2);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 3, 9, 0, UINT32_C(1) << 31, 1, 3);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 4, 9, 0, UINT32_C(1) << 31, 0, 4);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 30, 4, 9, 0, UINT32_C(1) << 31, 1, 3);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 29, 4, 9, 0, UINT32_C(1) << 31, 2, 2);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 28, 4, 9, 0, UINT32_C(1) << 31, 4, 1);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 27, 4, 9, 0, UINT32_C(1) << 31, 9, 0);
+ MATCH_SCALES(uint32_t, 7, 1, 0, 50, 7, 0, 1);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 1, 4, UINT32_C(1) << 31, 1);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 2, 2, UINT32_C(1) << 31, 2);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 3, 1, UINT32_C(1) << 31, 3);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 4, 0, UINT32_C(1) << 31, 4);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 30, 4, 1, UINT32_C(1) << 31, 3);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 29, 4, 2, UINT32_C(1) << 31, 2);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 28, 4, 4, UINT32_C(1) << 31, 1);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 27, 4, 9, UINT32_C(1) << 31, 0);
+
+ MATCH_SCALES(uint64_t, 0, 0, 0, 0, 0, 0, 0);
+ MATCH_SCALES(uint64_t, 0, 100, 7, 1, 0, 7, 1);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 1, 9, 0, UINT64_C(1) << 63, 4, 1);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 2, 9, 0, UINT64_C(1) << 63, 2, 2);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 3, 9, 0, UINT64_C(1) << 63, 1, 3);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 4, 9, 0, UINT64_C(1) << 63, 0, 4);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 62, 4, 9, 0, UINT64_C(1) << 63, 1, 3);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 61, 4, 9, 0, UINT64_C(1) << 63, 2, 2);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 60, 4, 9, 0, UINT64_C(1) << 63, 4, 1);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 59, 4, 9, 0, UINT64_C(1) << 63, 9, 0);
+ MATCH_SCALES(uint64_t, 7, 1, 0, 100, 7, 0, 1);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 1, 4, UINT64_C(1) << 63, 1);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 2, 2, UINT64_C(1) << 63, 2);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 3, 1, UINT64_C(1) << 63, 3);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 4, 0, UINT64_C(1) << 63, 4);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 62, 4, 1, UINT64_C(1) << 63, 3);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 61, 4, 2, UINT64_C(1) << 63, 2);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 60, 4, 4, UINT64_C(1) << 63, 1);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 59, 4, 9, UINT64_C(1) << 63, 0);
+}
+
} // end namespace
More information about the llvm-commits
mailing list