aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDale Johannesen <dalej@apple.com>2007-08-24 00:56:33 +0000
committerDale Johannesen <dalej@apple.com>2007-08-24 00:56:33 +0000
commit96ec39d5ec31d28be092d2e343773eee1fa30e14 (patch)
tree7a47d5e48fde4a3990a915df06776a2122625610 /lib
parent8c556616241ed32e39ffe1b91850483d69d43346 (diff)
downloadexternal_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.cpp188
-rw-r--r--lib/VMCore/Constants.cpp66
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.");