diff options
author | Dale Johannesen <dalej@apple.com> | 2007-08-24 00:56:33 +0000 |
---|---|---|
committer | Dale Johannesen <dalej@apple.com> | 2007-08-24 00:56:33 +0000 |
commit | 96ec39d5ec31d28be092d2e343773eee1fa30e14 (patch) | |
tree | 7a47d5e48fde4a3990a915df06776a2122625610 /lib | |
parent | 8c556616241ed32e39ffe1b91850483d69d43346 (diff) | |
download | external_llvm-96ec39d5ec31d28be092d2e343773eee1fa30e14.tar.gz external_llvm-96ec39d5ec31d28be092d2e343773eee1fa30e14.tar.bz2 external_llvm-96ec39d5ec31d28be092d2e343773eee1fa30e14.zip |
Change internal representation of ConstantFP to use APFloat.
Interface to rest of the compiler unchanged, as yet.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41348 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Support/APFloat.cpp | 188 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 66 |
2 files changed, 220 insertions, 34 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 8ac92475db..ae435d116c 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -46,6 +46,7 @@ namespace llvm { 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 @@ APFloat::operator=(const APFloat &rhs) 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 @@ APFloat::convertFromString(const char *p, roundingMode rounding_mode) 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 + } +} diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 87306fedb0..fc3f5c92b6 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -202,7 +202,7 @@ namespace { return DenseMapKeyInfo<void*>::getHashValue(Key.type) ^ Key.val.getHashValue(); } - static bool isPod() { return true; } + static bool isPod() { return false; } }; } @@ -240,63 +240,63 @@ ConstantInt *ConstantInt::get(const APInt& V) { 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."); |