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