Do not use host floating point types when emitting
authorDale Johannesen <dalej@apple.com>
Wed, 21 Jan 2009 20:32:55 +0000 (20:32 +0000)
committerDale Johannesen <dalej@apple.com>
Wed, 21 Jan 2009 20:32:55 +0000 (20:32 +0000)
ASCII IR; loading and storing these can change the
bits of NaNs on some hosts.  Remove or add warnings
at a few other places using host floating point;
this is a bad thing to do in general.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62712 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/FoldingSet.h
include/llvm/Support/MathExtras.h
lib/Support/APFloat.cpp
lib/Support/FoldingSet.cpp
lib/VMCore/AsmWriter.cpp
test/Transforms/InstCombine/2009-01-19-fmod-constant-float-specials.ll

index a69197f337718064755ad42c9191118e2f0b4464..d6010adfb9f7dda5fc672089d8d699f06effce00 100644 (file)
@@ -225,8 +225,6 @@ public:
   void AddInteger(unsigned long I);
   void AddInteger(long long I);
   void AddInteger(unsigned long long I);
-  void AddFloat(float F);
-  void AddDouble(double D);
   void AddString(const std::string &String);
   void AddString(const char* String);
 
index 8a89d85cd58fa019b10ee9de7ba5b895c5c338a7..d55fb80268adf398f8805631ed45f2797e51a5d2 100644 (file)
@@ -361,7 +361,9 @@ inline float BitsToFloat(uint32_t Bits) {
 }
 
 /// DoubleToBits - This function takes a double and returns the bit
-/// equivalent 64-bit integer.
+/// equivalent 64-bit integer.  Note that copying doubles around
+/// changes the bits of NaNs on some hosts, notably x86, so this
+/// routine cannot be used if these bits are needed.
 inline uint64_t DoubleToBits(double Double) {
   union {
     uint64_t L;
@@ -372,7 +374,9 @@ inline uint64_t DoubleToBits(double Double) {
 }
 
 /// FloatToBits - This function takes a float and returns the bit
-/// equivalent 32-bit integer.
+/// equivalent 32-bit integer.  Note that copying floats around
+/// changes the bits of NaNs on some hosts, notably x86, so this
+/// routine cannot be used if these bits are needed.
 inline uint32_t FloatToBits(float Float) {
   union {
     uint32_t I;
index c296770385f9f71cbb3f114774d2add3ea8eea20..d8d414d7ea5a166fd15dc343ba6d4539f32e59cc 100644 (file)
@@ -599,7 +599,8 @@ APFloat::copySignificand(const APFloat &rhs)
 }
 
 /* Make this number a NaN, with an arbitrary but deterministic value
-   for the significand.  */
+   for the significand.  If double or longer, this is a signalling NaN,
+   which may not be ideal. */
 void
 APFloat::makeNaN(void)
 {
index d2b02f240c9c3efbc9947dff6e75c89b72dd6782..3a1a0cd842e050f1fc0c04122e0ac3e8d9c20e2d 100644 (file)
@@ -61,12 +61,6 @@ void FoldingSetNodeID::AddInteger(unsigned long long I) {
   if ((uint64_t)(int)I != I)
     Bits.push_back(unsigned(I >> 32));
 }
-void FoldingSetNodeID::AddFloat(float F) {
-  Bits.push_back(FloatToBits(F));
-}
-void FoldingSetNodeID::AddDouble(double D) {
- AddInteger(DoubleToBits(D));
-}
 
 void FoldingSetNodeID::AddString(const char *String) {
   unsigned Size = static_cast<unsigned>(strlen(String));
index b59ec0863b352e480906b6d4653ad8fc9896eb09..6a17516be26d71126d28a14ffae39ecd9a067dce 100644 (file)
@@ -640,6 +640,7 @@ static void WriteConstantInt(raw_ostream &Out, const Constant *CV,
       // make sure that we only output it in exponential format if we can parse
       // the value back and get the same value.
       //
+      bool ignored;
       bool isDouble = &CFP->getValueAPF().getSemantics()==&APFloat::IEEEdouble;
       double Val = isDouble ? CFP->getValueAPF().convertToDouble() :
                               CFP->getValueAPF().convertToFloat();
@@ -659,11 +660,20 @@ static void WriteConstantInt(raw_ostream &Out, const Constant *CV,
         }
       }
       // Otherwise we could not reparse it to exactly the same value, so we must
-      // output the string in hexadecimal format!
+      // output the string in hexadecimal format!  Note that loading and storing
+      // floating point types changes the bits of NaNs on some hosts, notably
+      // x86, so we must not use these types.
       assert(sizeof(double) == sizeof(uint64_t) &&
              "assuming that double is 64 bits!");
       char Buffer[40];
-      Out << "0x" << utohex_buffer(uint64_t(DoubleToBits(Val)), Buffer+40);
+      APFloat apf = CFP->getValueAPF();
+      // Floats are represented in ASCII IR as double, convert.
+      if (!isDouble)
+        apf.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, 
+                          &ignored);
+      Out << "0x" << 
+              utohex_buffer(uint64_t(apf.bitcastToAPInt().getZExtValue()), 
+                            Buffer+40);
       return;
     }
     
index 47f2573a180cd8e147aa79f93496b9599a1461f6..cc001f0334c34d250bff714da1423e03ab7789c0 100644 (file)
@@ -1,8 +1,8 @@
 ; RUN: llvm-as < %s | opt -simplifycfg -instcombine | llvm-dis | grep 0x7FF8000000000000 | count 7
-; RUN: llvm-as < %s | opt -simplifycfg -instcombine | llvm-dis | grep 0x7FF80000FFFFFFFF | count 5
+; RUN: llvm-as < %s | opt -simplifycfg -instcombine | llvm-dis | grep 0x7FF00000FFFFFFFF | count 5
 ; RUN: llvm-as < %s | opt -simplifycfg -instcombine | llvm-dis | grep {0\\.0} | count 3
 ; RUN: llvm-as < %s | opt -simplifycfg -instcombine | llvm-dis | grep {3\\.5} | count 1
-; XFAIL: x86_64
+;
 
 ; ModuleID = 'apf.c'
 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"