[llvm-commits] CVS: llvm/lib/Support/APInt.cpp

Zhou Sheng zhousheng00 at gmail.com
Mon Feb 12 12:03:11 PST 2007



Changes in directory llvm/lib/Support:

APInt.cpp updated: 1.7 -> 1.8
---
Log message:

1. Make APInt::shl work correctly and more efficiently.
2. Add functions to support the numberical conversion between APInt and
   double/float.


---
Diffs of the changes:  (+78 -10)

 APInt.cpp |   88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 78 insertions(+), 10 deletions(-)


Index: llvm/lib/Support/APInt.cpp
diff -u llvm/lib/Support/APInt.cpp:1.7 llvm/lib/Support/APInt.cpp:1.8
--- llvm/lib/Support/APInt.cpp:1.7	Fri Feb  9 01:48:24 2007
+++ llvm/lib/Support/APInt.cpp	Mon Feb 12 14:02:55 2007
@@ -955,6 +955,69 @@
   return A;
 }
 
+/// DoubleRoundToAPInt - This function convert a double value to
+/// a APInt value.
+APInt llvm::APIntOps::DoubleRoundToAPInt(double Double) {
+  union {
+    double D;
+    uint64_t I;
+  } T;
+  T.D = Double;
+  bool isNeg = T.I >> 63;
+  int64_t exp = ((T.I >> 52) & 0x7ff) - 1023;
+  if (exp < 0)
+    return APInt(0);
+  uint64_t mantissa = ((T.I << 12) >> 12) | (1ULL << 52);
+  if (exp < 52)
+    return isNeg ? -APInt(mantissa >> (52 - exp)) : 
+                    APInt(mantissa >> (52 - exp));
+  APInt Tmp(mantissa, exp + 1);
+  Tmp = Tmp.shl(exp - 52);
+  return isNeg ? -Tmp : Tmp;
+}
+
+/// APIntRoundToDouble - This function convert this APInt to a double.
+/// The layout for double is as following (IEEE Standard 754):
+///  --------------------------------------
+/// |  Sign    Exponent    Fraction    Bias |
+/// |-------------------------------------- |
+/// |  1[63]   11[62-52]   52[51-00]   1023 |
+///  -------------------------------------- 
+double APInt::APIntRoundToDouble(bool isSigned) const {
+  bool isNeg = isSigned ? (*this)[BitsNum-1] : false;
+  APInt Tmp(isNeg ? -(*this) : (*this));
+  if (Tmp.isSingleWord())
+    return isSigned ? double(int64_t(Tmp.VAL)) : double(Tmp.VAL);
+  unsigned n = Tmp.getNumWords() * 64 - Tmp.CountLeadingZeros();
+  if (n <= 64) 
+    return isSigned ? double(int64_t(Tmp.pVal[0])) : double(Tmp.pVal[0]);
+  // Exponent when normalized to have decimal point directly after
+  // leading one. This is stored excess 1023 in the exponent bit field.
+  uint64_t exp = n - 1;
+
+  // Gross overflow.
+  assert(exp <= 1023 && "Infinity value!");
+
+  // Number of bits in mantissa including the leading one
+  // equals to 53.
+  uint64_t mantissa;
+  if (n % 64 >= 53)
+    mantissa = Tmp.pVal[whichWord(n - 1)] >> (n % 64 - 53);
+  else
+    mantissa = (Tmp.pVal[whichWord(n - 1)] << (53 - n % 64)) | 
+               (Tmp.pVal[whichWord(n - 1) - 1] >> (11 + n % 64));
+  // The leading bit of mantissa is implicit, so get rid of it.
+  mantissa &= ~(1ULL << 52);
+  uint64_t sign = isNeg ? (1ULL << 63) : 0;
+  exp += 1023;
+  union {
+    double D;
+    uint64_t I;
+  } T;
+  T.I = sign | (exp << 52) | mantissa;
+  return T.D;
+}
+
 /// Arithmetic right-shift this APInt by shiftAmt.
 /// @brief Arithmetic right-shift function.
 APInt APInt::ashr(unsigned shiftAmt) const {
@@ -1004,17 +1067,22 @@
 /// @brief Left-shift function.
 APInt APInt::shl(unsigned shiftAmt) const {
   APInt API(*this);
-  if (shiftAmt >= API.BitsNum) {
-    if (API.isSingleWord()) 
-      API.VAL = 0;
-    else 
-      memset(API.pVal, 0, API.getNumWords() * 8);
-  } else {
-    for (unsigned i = 0; i < shiftAmt; ++i) API.clear(i);
-    for (unsigned i = shiftAmt; i < API.BitsNum; ++i) {
-      if (API[i-shiftAmt]) API.set(i);
-      else API.clear(i);
+  if (API.isSingleWord())
+    API.VAL <<= shiftAmt;
+  else if (shiftAmt >= API.BitsNum)
+    memset(API.pVal, 0, API.getNumWords() * 8);
+  else {
+    if (unsigned offset = shiftAmt / 64) {
+      for (unsigned i = API.getNumWords() - 1; i > offset - 1; --i)
+        API.pVal[i] = API.pVal[i-offset];
+      memset(API.pVal, 0, offset * 8);
     }
+    shiftAmt %= 64;
+    unsigned i;
+    for (i = API.getNumWords() - 1; i > 0; --i)
+      API.pVal[i] = (API.pVal[i] << shiftAmt) | 
+                    (API.pVal[i-1] >> (64-shiftAmt));
+    API.pVal[i] <<= shiftAmt;
   }
   return API;
 }






More information about the llvm-commits mailing list