Chris,

Here is round two. This is a slightly larger patch that also includes
the following changes:

      * APInt::getValue() -> getSExtValue() and getZExtValue()
      * const APInt& ConstantInt::getValue() const { return Val; }
      * ConstantInt::get(const Type*, const APInt&)
      * APInt constructor for ConstantInt::get to use
      * APInt::getHashValue()  -- used for the DenseMap of ConstantInt
        values.
      * Changes in Constants.cpp to use getHashValue() for the key in
        the map of ConstantInt values.
Reid.

On Mon, 2007-02-26 at 10:46 -0800, Reid Spencer wrote:
> Hi,
> 
> I would like to commit this small patch but thought I should send it out
> first. This changes ConstantInt to use an APInt object as its value
> instead of a uint64_t. The interface to ConstantInt still uses uint64_t
> so the APInt is just being used as a glorified uint64_t as all bit
> widths are <= 64. This change passes DejaGnu, the MultiSource/Benchmarks
> test suite, and a few of the SPEC benchmarks that I tried (444.namd,
> 176.gcc, 473.astar).
> 
> Okay to commit?
> 
> Reid.
> _______________________________________________
> llvm-commits mailing list
> llvm-commits@cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
Index: include/llvm/Constants.h
===================================================================
RCS file: /var/cvs/llvm/llvm/include/llvm/Constants.h,v
retrieving revision 1.132
diff -t -d -u -p -5 -r1.132 Constants.h
--- include/llvm/Constants.h	20 Feb 2007 07:18:01 -0000	1.132
+++ include/llvm/Constants.h	26 Feb 2007 20:22:10 -0000
@@ -20,10 +20,11 @@
 #ifndef LLVM_CONSTANTS_H
 #define LLVM_CONSTANTS_H
 
 #include "llvm/Constant.h"
 #include "llvm/Type.h"
+#include "llvm/ADT/APInt.h"
 
 namespace llvm {
 
 class ArrayType;
 class StructType;
@@ -41,33 +42,43 @@ struct ConvertConstantType;
 /// @brief Class for constant integers.
 class ConstantInt : public Constant {
   static ConstantInt *TheTrueVal, *TheFalseVal;
   ConstantInt(const ConstantInt &);      // DO NOT IMPLEMENT
   ConstantInt(const IntegerType *Ty, uint64_t V);
-  uint64_t Val;
+  ConstantInt(const IntegerType *Ty, const APInt& V);
+  APInt Val;
 public:
+  /// Return the constant as an APInt value reference. This allows clients to
+  /// obtain a copy of the value, with all its precision in tact.
+  /// @brief Return the constant's value.
+  inline const APInt& getValue() const {
+    return Val;
+  }
+
   /// Return the constant as a 64-bit unsigned integer value after it
-  /// has been zero extended as appropriate for the type of this constant.
+  /// has been zero extended as appropriate for the type of this constant. Note
+  /// that this method can assert if the value does not fit in 64 bits.
+  /// @deprecated
   /// @brief Return the zero extended value.
   inline uint64_t getZExtValue() const {
-    return Val;
+    return Val.getZExtValue();
   }
 
   /// Return the constant as a 64-bit integer value after it has been sign
-  /// sign extended as appropriate for the type of this constant.
+  /// sign extended as appropriate for the type of this constant. Note that
+  /// this method can assert if the value does not fit in 64 bits.
+  /// @deprecated
   /// @brief Return the sign extended value.
   inline int64_t getSExtValue() const {
-    unsigned Size = Value::getType()->getPrimitiveSizeInBits();
-    return (int64_t(Val) << (64-Size)) >> (64-Size);
+    return Val.getSExtValue();
   }
+
   /// A helper method that can be used to determine if the constant contained 
   /// within is equal to a constant.  This only works for very small values, 
   /// because this is all that can be represented with all types.
   /// @brief Determine if this constant's value is same as an unsigned char.
-  bool equalsInt(unsigned char V) const {
-    assert(V <= 127 &&
-           "equalsInt: Can only be used with very small positive constants!");
+  bool equalsInt(uint64_t V) const {
     return Val == V;
   }
 
   /// getTrue/getFalse - Return the singleton true/false values.
   static inline ConstantInt *getTrue() {
@@ -83,10 +94,11 @@ public:
   /// value V will be canonicalized to a uint64_t but accessing it with either
   /// getSExtValue() or getZExtValue() (ConstantInt) will yield the correct
   /// sized/signed value for the type Ty.
   /// @brief Get a ConstantInt for a specific value.
   static ConstantInt *get(const Type *Ty, int64_t V);
+  static ConstantInt *get(const Type *Ty, const APInt& V);
 
   /// getType - Specialize the getType() method to always return an IntegerType,
   /// which reduces the amount of casting needed in parts of the compiler.
   ///
   inline const IntegerType *getType() const {
@@ -116,41 +128,35 @@ public:
   /// This function will return true iff every bit in this constant is set
   /// to true.
   /// @returns true iff this constant's bits are all set to true.
   /// @brief Determine if the value is all ones.
   bool isAllOnesValue() const { 
-    return getSExtValue() == -1; 
+    return Val.isAllOnesValue();
   }
 
   /// This function will return true iff this constant represents the largest
   /// value that may be represented by the constant's type.
   /// @returns true iff this is the largest value that may be represented 
   /// by this type.
   /// @brief Determine if the value is maximal.
   bool isMaxValue(bool isSigned) const {
-    if (isSigned) {
-      int64_t V = getSExtValue();
-      if (V < 0) return false;    // Be careful about wrap-around on 'long's
-      ++V;
-      return !isValueValidForType(Value::getType(), V) || V < 0;
-    }
-    return isAllOnesValue();
+    if (isSigned) 
+      return Val.isMaxSignedValue();
+    else
+      return Val.isMaxValue();
   }
 
   /// This function will return true iff this constant represents the smallest
   /// value that may be represented by this constant's type.
   /// @returns true if this is the smallest value that may be represented by 
   /// this type.
   /// @brief Determine if the value is minimal.
   bool isMinValue(bool isSigned) const {
-    if (isSigned) {
-      int64_t V = getSExtValue();
-      if (V > 0) return false;    // Be careful about wrap-around on 'long's
-      --V;
-      return !isValueValidForType(Value::getType(), V) || V > 0;
-    }
-    return getZExtValue() == 0;
+    if (isSigned) 
+      return Val.isMinSignedValue();
+    else
+      return Val.isMinValue();
   }
 
   /// @returns the value for an integer constant of the given type that has all
   /// its bits set to true.
   /// @brief Get the all ones value
Index: include/llvm/ADT/APInt.h
===================================================================
RCS file: /var/cvs/llvm/llvm/include/llvm/ADT/APInt.h,v
retrieving revision 1.22
diff -t -d -u -p -5 -r1.22 APInt.h
--- include/llvm/ADT/APInt.h	26 Feb 2007 17:50:32 -0000	1.22
+++ include/llvm/ADT/APInt.h	26 Feb 2007 20:22:10 -0000
@@ -445,20 +445,31 @@ public:
   /// @brief Compute the number of active bits in the value
   inline uint32_t getActiveBits() const {
     return BitWidth - countLeadingZeros();
   }
 
-  /// @returns a uint64_t value from this APInt. If this APInt contains a single
-  /// word, just returns VAL, otherwise pVal[0].
-  inline uint64_t getValue(bool isSigned = false) const {
+  /// This method attempts to return the value of this APInt as a zero extended
+  /// uint64_t. The bitwidth must be <= 64 or the value must fit within a
+  /// uint64_t. Otherwise an assertion will result.
+  /// @brief Get zero extended value
+  inline uint64_t getZExtValue() const {
     if (isSingleWord())
-      return isSigned ? int64_t(VAL << (64 - BitWidth)) >> 
-                                       (64 - BitWidth) : VAL;
-    uint32_t n = getActiveBits();
-    if (n <= 64)
-      return pVal[0];
-    assert(0 && "This APInt's bitwidth > 64");
+      return VAL;
+    assert(getActiveBits() <= 64 && "Too many bits for uint64_t");
+    return pVal[0];
+  }
+
+  /// This method attempts to return the value of this APInt as a sign extended
+  /// int64_t. The bit width must be <= 64 or the value must fit within an
+  /// int64_t. Otherwise an assertion will result.
+  /// @brief Get sign extended value
+  inline int64_t getSExtValue() const {
+    if (isSingleWord())
+      return int64_t(VAL << (APINT_BITS_PER_WORD - BitWidth)) >> 
+                     (APINT_BITS_PER_WORD - BitWidth);
+    assert(getActiveBits() <= 64 && "Too many bits for int64_t");
+      return int64_t(pVal[0]);
   }
 
   /// @returns the largest value for an APInt of the specified bit-width and 
   /// if isSign == true, it should be largest signed value, otherwise largest
   /// unsigned value.
@@ -476,10 +487,15 @@ public:
 
   /// @returns the '0' value for an APInt of the specified bit-width.
   /// @brief Get the '0' value.
   static APInt getNullValue(uint32_t numBits);
 
+  /// The hash value is computed as the sum of the words and the bit width.
+  /// @returns A hash value computed from the sum of the APInt words.
+  /// @brief Get a hash value based on this APInt
+  uint64_t getHashValue() const;
+
   /// This converts the APInt to a boolean valy as a test against zero.
   /// @brief Boolean conversion function. 
   inline bool getBoolValue() const {
     return countLeadingZeros() != BitWidth;
   }
Index: lib/Support/APInt.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/Support/APInt.cpp,v
retrieving revision 1.48
diff -t -d -u -p -5 -r1.48 APInt.cpp
--- lib/Support/APInt.cpp	26 Feb 2007 08:10:54 -0000	1.48
+++ lib/Support/APInt.cpp	26 Feb 2007 20:22:11 -0000
@@ -659,10 +659,20 @@ APInt APInt::getAllOnesValue(uint32_t nu
 /// APInt of the specified bit-width.
 APInt APInt::getNullValue(uint32_t numBits) {
   return getMinValue(numBits, false);
 }
 
+uint64_t APInt::getHashValue() const {
+  uint64_t hash = BitWidth;
+  if (isSingleWord())
+    hash += VAL;
+  else
+    for (uint32_t i = 0; i < getNumWords(); ++i)
+      hash += pVal[i];
+  return hash;
+}
+
 /// HiBits - This function returns the high "numBits" bits of this APInt.
 APInt APInt::getHiBits(uint32_t numBits) const {
   return APIntOps::lshr(*this, BitWidth - numBits);
 }
 
@@ -1658,11 +1668,11 @@ std::string APInt::toString(uint8_t radi
   else while (tmp.ne(zero)) {
     APInt APdigit(1,0);
     APInt tmp2(tmp.getBitWidth(), 0);
     divide(tmp, tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, 
            &APdigit);
-    uint32_t digit = APdigit.getValue();
+    uint32_t digit = APdigit.getZExtValue();
     assert(digit < radix && "divide failed");
     result.insert(insert_at,digits[digit]);
     tmp = tmp2;
   }
 
Index: lib/VMCore/Constants.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/VMCore/Constants.cpp,v
retrieving revision 1.220
diff -t -d -u -p -5 -r1.220 Constants.cpp
--- lib/VMCore/Constants.cpp	20 Feb 2007 21:30:56 -0000	1.220
+++ lib/VMCore/Constants.cpp	26 Feb 2007 20:22:12 -0000
@@ -137,11 +137,16 @@ ConstantVector *ConstantVector::getAllOn
 //===----------------------------------------------------------------------===//
 //                                ConstantInt
 //===----------------------------------------------------------------------===//
 
 ConstantInt::ConstantInt(const IntegerType *Ty, uint64_t V)
+  : Constant(Ty, ConstantIntVal, 0, 0), Val(Ty->getBitWidth(), V) {
+}
+
+ConstantInt::ConstantInt(const IntegerType *Ty, const APInt& V)
   : Constant(Ty, ConstantIntVal, 0, 0), Val(V) {
+  assert(V.getBitWidth() == Ty->getBitWidth() && "Invalid constant for type");
 }
 
 ConstantInt *ConstantInt::TheTrueVal = 0;
 ConstantInt *ConstantInt::TheFalseVal = 0;
 
@@ -187,13 +192,22 @@ static ManagedStatic<IntMapTy> IntConsta
 // integer type of the ConstantInt. This allows the getZExtValue method to 
 // just return the stored value while getSExtValue has to convert back to sign
 // extended. getZExtValue is more common in LLVM than getSExtValue().
 ConstantInt *ConstantInt::get(const Type *Ty, int64_t V) {
   const IntegerType *ITy = cast<IntegerType>(Ty);
-  V &= ITy->getBitMask();
-  ConstantInt *&Slot = (*IntConstants)[std::make_pair(uint64_t(V), Ty)];
-  if (Slot) return Slot;
+  APInt Tmp(ITy->getBitWidth(), V);
+  ConstantInt *&Slot = (*IntConstants)[std::make_pair(Tmp.getHashValue(), Ty)];
+  if (Slot) 
+    return Slot;
+  return Slot = new ConstantInt(ITy, V);
+}
+
+ConstantInt *ConstantInt::get(const Type *Ty, const APInt& V) {
+  const IntegerType *ITy = cast<IntegerType>(Ty);
+  ConstantInt *&Slot = (*IntConstants)[std::make_pair(V.getHashValue(), Ty)];
+  if (Slot)
+    return Slot;
   return Slot = new ConstantInt(ITy, V);
 }
 
 //===----------------------------------------------------------------------===//
 //                                ConstantFP
_______________________________________________
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

Reply via email to