[llvm-commits] [llvm] r41348 - in /llvm/trunk: include/llvm/ADT/APFloat.h include/llvm/Constants.h lib/Support/APFloat.cpp lib/VMCore/Constants.cpp

Dale Johannesen dalej at apple.com
Thu Aug 23 17:56:33 PDT 2007


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.");





More information about the llvm-commits mailing list