Author: johannes Date: Thu Aug 23 19:56:33 2007 New Revision: 41348 URL: http://llvm.org/viewvc/llvm-project?rev=41348&view=rev Log: Change internal representation of ConstantFP to use APFloat. Interface to rest of the compiler unchanged, as yet.
Modified: llvm/trunk/include/llvm/ADT/APFloat.h llvm/trunk/include/llvm/Constants.h llvm/trunk/lib/Support/APFloat.cpp llvm/trunk/lib/VMCore/Constants.cpp Modified: llvm/trunk/include/llvm/ADT/APFloat.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APFloat.h?rev=41348&r1=41347&r2=41348&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/APFloat.h (original) +++ llvm/trunk/include/llvm/ADT/APFloat.h Thu Aug 23 19:56:33 2007 @@ -118,6 +118,9 @@ static const fltSemantics IEEEdouble; static const fltSemantics IEEEquad; static const fltSemantics x87DoubleExtended; + /* And this psuedo, used to construct APFloats that cannot + conflict with anything real. */ + static const fltSemantics Bogus; static unsigned int semanticsPrecision(const fltSemantics &); @@ -161,6 +164,8 @@ APFloat(const fltSemantics &, const char *); APFloat(const fltSemantics &, integerPart); APFloat(const fltSemantics &, fltCategory, bool negative); + APFloat(double d); + APFloat(float f); APFloat(const APFloat &); ~APFloat(); @@ -179,10 +184,16 @@ opStatus convertFromInteger(const integerPart *, unsigned int, bool, roundingMode); opStatus convertFromString(const char *, roundingMode); + double convertToDouble() const; + float convertToFloat() const; - /* Comparison with another floating point number. */ + /* IEEE comparison with another floating point number (QNaNs + compare unordered, 0==-0). */ cmpResult compare(const APFloat &) const; + /* Bitwise comparison for equality (QNaNs compare equal, 0!=-0). */ + bool operator==(const APFloat &) const; + /* Simple queries. */ fltCategory getCategory() const { return category; } const fltSemantics &getSemantics() const { return *semantics; } @@ -192,6 +203,9 @@ APFloat& operator=(const APFloat &); + /* Return an arbitrary integer value usable for hashing. */ + uint32_t getHashValue() const; + private: /* Trivial queries. */ Modified: llvm/trunk/include/llvm/Constants.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constants.h?rev=41348&r1=41347&r2=41348&view=diff ============================================================================== --- llvm/trunk/include/llvm/Constants.h (original) +++ llvm/trunk/include/llvm/Constants.h Thu Aug 23 19:56:33 2007 @@ -23,6 +23,7 @@ #include "llvm/Constant.h" #include "llvm/Type.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/APFloat.h" namespace llvm { @@ -213,7 +214,7 @@ /// ConstantFP - Floating Point Values [float, double] /// class ConstantFP : public Constant { - double Val; + APFloat Val; ConstantFP(const ConstantFP &); // DO NOT IMPLEMENT protected: ConstantFP(const Type *Ty, double V); @@ -223,7 +224,14 @@ /// isValueValidForType - return true if Ty is big enough to represent V. static bool isValueValidForType(const Type *Ty, double V); - inline double getValue() const { return Val; } + inline double getValue() const { + if (&Val.getSemantics() == &APFloat::IEEEdouble) + return Val.convertToDouble(); + else if (&Val.getSemantics() == &APFloat::IEEEsingle) + return (double)Val.convertToFloat(); + else + assert(0); + } /// isNullValue - Return true if this is the value that would be returned by /// getNullValue. Don't depend on == for doubles to tell us it's zero, it Modified: llvm/trunk/lib/Support/APFloat.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APFloat.cpp?rev=41348&r1=41347&r2=41348&view=diff ============================================================================== --- llvm/trunk/lib/Support/APFloat.cpp (original) +++ llvm/trunk/lib/Support/APFloat.cpp Thu Aug 23 19:56:33 2007 @@ -46,6 +46,7 @@ const fltSemantics APFloat::IEEEdouble = { 1023, -1022, 53, true }; const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113, true }; const fltSemantics APFloat::x87DoubleExtended = { 16383, -16382, 64, false }; + const fltSemantics APFloat::Bogus = { 0, 0, 0, false }; } /* Put a bunch of private, handy routines in an anonymous namespace. */ @@ -273,6 +274,31 @@ return *this; } +bool +APFloat::operator==(const APFloat &rhs) const { + if (this == &rhs) + return true; + if (semantics != rhs.semantics || + category != rhs.category) + return false; + if (category==fcQNaN) + return true; + else if (category==fcZero || category==fcInfinity) + return sign==rhs.sign; + else { + if (sign!=rhs.sign || exponent!=rhs.exponent) + return false; + int i= partCount(); + const integerPart* p=significandParts(); + const integerPart* q=rhs.significandParts(); + for (; i>0; i--, p++, q++) { + if (*p != *q) + return false; + } + return true; + } +} + APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value) { initialize(&ourSemantics); @@ -1482,7 +1508,167 @@ return convertFromHexadecimalString(p + 2, rounding_mode); else { - assert(0 && "Decimal to binary conversions not yet imlemented"); + assert(0 && "Decimal to binary conversions not yet implemented"); abort(); } } + +// For good performance it is desirable for different APFloats +// to produce different integers. +uint32_t +APFloat::getHashValue() const { + if (category==fcZero) return sign<<8 | semantics->precision ; + else if (category==fcInfinity) return sign<<9 | semantics->precision; + else if (category==fcQNaN) return 1<<10 | semantics->precision; + else { + uint32_t hash = sign<<11 | semantics->precision | exponent<<12; + const integerPart* p = significandParts(); + for (int i=partCount(); i>0; i--, p++) + hash ^= ((uint32_t)*p) ^ (*p)>>32; + return hash; + } +} + +// Conversion from APFloat to/from host float/double. It may eventually be +// possible to eliminate these and have everybody deal with APFloats, but that +// will take a while. This approach will not easily extend to long double. +// Current implementation requires partCount()==1, which is correct at the +// moment but could be made more general. + +double +APFloat::convertToDouble() const { + union { + double d; + uint64_t i; + } u; + assert(semantics == (const llvm::fltSemantics* const)&IEEEdouble); + assert (partCount()==1); + + uint64_t myexponent, mysign, mysignificand; + + if (category==fcNormal) { + mysign = sign; + mysignificand = *significandParts(); + myexponent = exponent+1023; //bias + } else if (category==fcZero) { + mysign = sign; + myexponent = 0; + mysignificand = 0; + } else if (category==fcInfinity) { + mysign = sign; + myexponent = 0x7ff; + mysignificand = 0; + } else if (category==fcQNaN) { + mysign = 0; + myexponent = 0x7ff; + mysignificand = 0xfffffffffffffLL; + } else + assert(0); + + u.i = ((mysign & 1) << 63) | ((myexponent & 0x7ff) << 52) | + (mysignificand & 0xfffffffffffffLL); + return u.d; +} + +float +APFloat::convertToFloat() const { + union { + float f; + int32_t i; + } u; + assert(semantics == (const llvm::fltSemantics* const)&IEEEsingle); + assert (partCount()==1); + + uint32_t mysign, myexponent, mysignificand; + + if (category==fcNormal) { + mysign = sign; + myexponent = exponent+127; //bias + mysignificand = *significandParts(); + } else if (category==fcZero) { + mysign = sign; + myexponent = 0; + mysignificand = 0; + } else if (category==fcInfinity) { + mysign = sign; + myexponent = 0xff; + mysignificand = 0; + } else if (category==fcQNaN) { + mysign = sign; + myexponent = 0x7ff; + mysignificand = 0x7fffff; + } else + assert(0); + + u.i = ((mysign&1) << 31) | ((myexponent&0xff) << 23) | + ((mysignificand & 0x7fffff)); + return u.f; +} + +APFloat::APFloat(double d) { + initialize(&APFloat::IEEEdouble); + union { + double d; + uint64_t i; + } u; + u.d = d; + assert(partCount()==1); + + uint64_t mysign, myexponent, mysignificand; + + mysign = u.i >> 63; + myexponent = (u.i >> 52) & 0x7ff; + mysignificand = u.i & 0xfffffffffffffLL; + + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + category = fcZero; + sign = mysign; + } else if (myexponent==0x7ff && mysignificand==0) { + // exponent, significand meaningless + category = fcInfinity; + sign = mysign; + } else if (myexponent==0x7ff && (mysignificand & 0x8000000000000LL)) { + // sign, exponent, significand meaningless + category = fcQNaN; + } else { + sign = mysign; + category = fcNormal; + exponent = myexponent - 1023; + *significandParts() = mysignificand | 0x100000000000000LL; + } +} + +APFloat::APFloat(float f) { + initialize(&APFloat::IEEEsingle); + union { + float f; + uint32_t i; + } u; + u.f = f; + assert(partCount()==1); + + uint32_t mysign, myexponent, mysignificand; + + mysign = u.i >> 31; + myexponent = (u.i >> 23) & 0xff; + mysignificand = u.i & 0x7fffff; + + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + category = fcZero; + sign = mysign; + } else if (myexponent==0xff && mysignificand==0) { + // exponent, significand meaningless + category = fcInfinity; + sign = mysign; + } else if (myexponent==0xff && (mysignificand & 0x400000)) { + // sign, exponent, significand meaningless + category = fcQNaN; + } else { + category = fcNormal; + sign = mysign; + exponent = myexponent - 127; //bias + *significandParts() = mysignificand | 0x800000; // integer bit + } +} Modified: llvm/trunk/lib/VMCore/Constants.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Constants.cpp?rev=41348&r1=41347&r2=41348&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Constants.cpp (original) +++ llvm/trunk/lib/VMCore/Constants.cpp Thu Aug 23 19:56:33 2007 @@ -202,7 +202,7 @@ return DenseMapKeyInfo<void*>::getHashValue(Key.type) ^ Key.val.getHashValue(); } - static bool isPod() { return true; } + static bool isPod() { return false; } }; } @@ -240,63 +240,63 @@ ConstantFP::ConstantFP(const Type *Ty, double V) - : Constant(Ty, ConstantFPVal, 0, 0) { - Val = V; + : Constant(Ty, ConstantFPVal, 0, 0), Val(APFloat(V)) { } bool ConstantFP::isNullValue() const { - return DoubleToBits(Val) == 0; + return Val.isZero() && !Val.isNegative(); } bool ConstantFP::isExactlyValue(double V) const { - return DoubleToBits(V) == DoubleToBits(Val); + return Val == APFloat(V); } - namespace { - struct DenseMapInt64KeyInfo { - typedef std::pair<uint64_t, const Type*> KeyTy; - static inline KeyTy getEmptyKey() { return KeyTy(0, 0); } - static inline KeyTy getTombstoneKey() { return KeyTy(1, 0); } - static unsigned getHashValue(const KeyTy &Key) { - return DenseMapKeyInfo<void*>::getHashValue(Key.second) ^ Key.first; + struct DenseMapAPFloatKeyInfo { + struct KeyTy { + APFloat val; + KeyTy(const APFloat& V) : val(V){} + KeyTy(const KeyTy& that) : val(that.val) {} + bool operator==(const KeyTy& that) const { + return this->val == that.val; + } + bool operator!=(const KeyTy& that) const { + return !this->operator==(that); + } + }; + static inline KeyTy getEmptyKey() { + return KeyTy(APFloat(APFloat::Bogus,1)); + } + static inline KeyTy getTombstoneKey() { + return KeyTy(APFloat(APFloat::Bogus,2)); } - static bool isPod() { return true; } - }; - struct DenseMapInt32KeyInfo { - typedef std::pair<uint32_t, const Type*> KeyTy; - static inline KeyTy getEmptyKey() { return KeyTy(0, 0); } - static inline KeyTy getTombstoneKey() { return KeyTy(1, 0); } static unsigned getHashValue(const KeyTy &Key) { - return DenseMapKeyInfo<void*>::getHashValue(Key.second) ^ Key.first; + return Key.val.getHashValue(); } - static bool isPod() { return true; } + static bool isPod() { return false; } }; } //---- ConstantFP::get() implementation... // -typedef DenseMap<DenseMapInt32KeyInfo::KeyTy, ConstantFP*, - DenseMapInt32KeyInfo> FloatMapTy; -typedef DenseMap<DenseMapInt64KeyInfo::KeyTy, ConstantFP*, - DenseMapInt64KeyInfo> DoubleMapTy; +typedef DenseMap<DenseMapAPFloatKeyInfo::KeyTy, ConstantFP*, + DenseMapAPFloatKeyInfo> FPMapTy; -static ManagedStatic<FloatMapTy> FloatConstants; -static ManagedStatic<DoubleMapTy> DoubleConstants; +static ManagedStatic<FPMapTy> FPConstants; ConstantFP *ConstantFP::get(const Type *Ty, double V) { if (Ty == Type::FloatTy) { - uint32_t IntVal = FloatToBits((float)V); - - ConstantFP *&Slot = (*FloatConstants)[std::make_pair(IntVal, Ty)]; + DenseMapAPFloatKeyInfo::KeyTy Key(APFloat((float)V)); + ConstantFP *&Slot = (*FPConstants)[Key]; if (Slot) return Slot; return Slot = new ConstantFP(Ty, (float)V); - } else if (Ty == Type::DoubleTy) { - uint64_t IntVal = DoubleToBits(V); - ConstantFP *&Slot = (*DoubleConstants)[std::make_pair(IntVal, Ty)]; + } else if (Ty == Type::DoubleTy) { + // Without the redundant cast, the following is taken to be + // a function declaration. What a language. + DenseMapAPFloatKeyInfo::KeyTy Key(APFloat((double)V)); + ConstantFP *&Slot = (*FPConstants)[Key]; if (Slot) return Slot; return Slot = new ConstantFP(Ty, V); - // FIXME: Make long double constants work. } else if (Ty == Type::X86_FP80Ty || Ty == Type::PPC_FP128Ty || Ty == Type::FP128Ty) { assert(0 && "Long double constants not handled yet."); _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits