mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-27 14:34:58 +00:00
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
This commit is contained in:
parent
57e4785123
commit
343e770983
@ -118,6 +118,9 @@ namespace llvm {
|
||||
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 @@ namespace llvm {
|
||||
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 @@ namespace llvm {
|
||||
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 @@ namespace llvm {
|
||||
|
||||
APFloat& operator=(const APFloat &);
|
||||
|
||||
/* Return an arbitrary integer value usable for hashing. */
|
||||
uint32_t getHashValue() const;
|
||||
|
||||
private:
|
||||
|
||||
/* Trivial queries. */
|
||||
|
@ -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 @@ private:
|
||||
/// 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 @@ public:
|
||||
|
||||
/// 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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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 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;
|
||||
static inline KeyTy getTombstoneKey() {
|
||||
return KeyTy(APFloat(APFloat::Bogus,2));
|
||||
}
|
||||
static bool isPod() { return true; }
|
||||
static unsigned getHashValue(const KeyTy &Key) {
|
||||
return Key.val.getHashValue();
|
||||
}
|
||||
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.");
|
||||
|
Loading…
x
Reference in New Issue
Block a user