Fix internal representation of fp80 to be the
authorDale Johannesen <dalej@apple.com>
Mon, 23 Mar 2009 21:16:53 +0000 (21:16 +0000)
committerDale Johannesen <dalej@apple.com>
Mon, 23 Mar 2009 21:16:53 +0000 (21:16 +0000)
same as a normal i80 {low64, high16} rather
than its own {high64, low16}.  A depressing number
of places know about this; I think I got them all.
Bitcode readers and writers convert back to the old
form to avoid breaking compatibility.

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

lib/AsmParser/LLLexer.cpp
lib/AsmParser/LLLexer.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/Support/APFloat.cpp
lib/Target/CBackend/CBackend.cpp
lib/VMCore/AsmWriter.cpp
test/CodeGen/X86/2009-03-23-i80-fp80.ll [new file with mode: 0644]

index 5a38e6090f7410b64e8e79a99897d72bcb8de1ca..95e6c90a59c27d5c2d7981e9cc1ad69219f8d01a 100644 (file)
@@ -115,6 +115,37 @@ void LLLexer::HexToIntPair(const char *Buffer, const char *End,
     Error("constant bigger than 128 bits detected!");
 }
 
+/// FP80HexToIntPair - translate an 80 bit FP80 number (20 hexits) into
+/// { low64, high16 } as usual for an APInt.
+void LLLexer::FP80HexToIntPair(const char *Buffer, const char *End,
+                           uint64_t Pair[2]) {
+  Pair[1] = 0;
+  for (int i=0; i<4 && Buffer != End; i++, Buffer++) {
+    assert(Buffer != End);
+    Pair[1] *= 16;
+    char C = *Buffer;
+    if (C >= '0' && C <= '9')
+      Pair[1] += C-'0';
+    else if (C >= 'A' && C <= 'F')
+      Pair[1] += C-'A'+10;
+    else if (C >= 'a' && C <= 'f')
+      Pair[1] += C-'a'+10;
+  }
+  Pair[0] = 0;
+  for (int i=0; i<16; i++, Buffer++) {
+    Pair[0] *= 16;
+    char C = *Buffer;
+    if (C >= '0' && C <= '9')
+      Pair[0] += C-'0';
+    else if (C >= 'A' && C <= 'F')
+      Pair[0] += C-'A'+10;
+    else if (C >= 'a' && C <= 'f')
+      Pair[0] += C-'a'+10;
+  }
+  if (Buffer != End)
+    Error("constant bigger than 128 bits detected!");
+}
+
 // UnEscapeLexed - Run through the specified buffer and change \xx codes to the
 // appropriate character.
 static void UnEscapeLexed(std::string &Str) {
@@ -670,19 +701,21 @@ lltok::Kind LLLexer::Lex0x() {
   }
 
   uint64_t Pair[2];
-  HexToIntPair(TokStart+3, CurPtr, Pair);
   switch (Kind) {
   default: assert(0 && "Unknown kind!");
   case 'K':
     // F80HexFPConstant - x87 long double in hexadecimal format (10 bytes)
+    FP80HexToIntPair(TokStart+3, CurPtr, Pair);
     APFloatVal = APFloat(APInt(80, 2, Pair));
     return lltok::APFloat;
   case 'L':
     // F128HexFPConstant - IEEE 128-bit in hexadecimal format (16 bytes)
+    HexToIntPair(TokStart+3, CurPtr, Pair);
     APFloatVal = APFloat(APInt(128, 2, Pair), true);
     return lltok::APFloat;
   case 'M':
     // PPC128HexFPConstant - PowerPC 128-bit in hexadecimal format (16 bytes)
+    HexToIntPair(TokStart+3, CurPtr, Pair);
     APFloatVal = APFloat(APInt(128, 2, Pair));
     return lltok::APFloat;
   }
index adf053cf9b0c8a4ad3facddd88a6790b0a08bf77..995aa4eb0794e1c5417828a0126bcd8a8d0df879 100644 (file)
@@ -77,6 +77,7 @@ namespace llvm {
     uint64_t atoull(const char *Buffer, const char *End);
     uint64_t HexIntToVal(const char *Buffer, const char *End);
     void HexToIntPair(const char *Buffer, const char *End, uint64_t Pair[2]);
+    void FP80HexToIntPair(const char *Buff, const char *End, uint64_t Pair[2]);
   };
 } // end namespace llvm
 
index 299ce0b94a4a03a3e5de73515baed97bf5bd5610..69eadd9ee41fb0248c3bd6030c17564780931d6b 100644 (file)
@@ -801,9 +801,13 @@ bool BitcodeReader::ParseConstants() {
         V = ConstantFP::get(APFloat(APInt(32, (uint32_t)Record[0])));
       else if (CurTy == Type::DoubleTy)
         V = ConstantFP::get(APFloat(APInt(64, Record[0])));
-      else if (CurTy == Type::X86_FP80Ty)
-        V = ConstantFP::get(APFloat(APInt(80, 2, &Record[0])));
-      else if (CurTy == Type::FP128Ty)
+      else if (CurTy == Type::X86_FP80Ty) {
+        // Bits are not stored the same way as a normal i80 APInt, compensate.
+        uint64_t Rearrange[2];
+        Rearrange[0] = (Record[1] & 0xffffLL) | (Record[0] << 16);
+        Rearrange[1] = Record[0] >> 48;
+        V = ConstantFP::get(APFloat(APInt(80, 2, Rearrange)));
+      } else if (CurTy == Type::FP128Ty)
         V = ConstantFP::get(APFloat(APInt(128, 2, &Record[0]), true));
       else if (CurTy == Type::PPC_FP128Ty)
         V = ConstantFP::get(APFloat(APInt(128, 2, &Record[0])));
index 1055564be2167e4c861997c4cf170a99ac52ff6b..d4d3443ee05cba1b2f612ffc996f3228b2c0402c 100644 (file)
@@ -559,10 +559,11 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
         Record.push_back(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
       } else if (Ty == Type::X86_FP80Ty) {
         // api needed to prevent premature destruction
+        // bits are not in the same order as a normal i80 APInt, compensate.
         APInt api = CFP->getValueAPF().bitcastToAPInt();
         const uint64_t *p = api.getRawData();
-        Record.push_back(p[0]);
-        Record.push_back((uint16_t)p[1]);
+        Record.push_back((p[1] << 48) | (p[0] >> 16));
+        Record.push_back(p[0] & 0xffffLL);
       } else if (Ty == Type::FP128Ty || Ty == Type::PPC_FP128Ty) {
         APInt api = CFP->getValueAPF().bitcastToAPInt();
         const uint64_t *p = api.getRawData();
index 2a64524860e1a32769d8cd90441fdb5a5254b256..79d14f7aeb65660b82907007bbb279a9cea2cc7a 100644 (file)
@@ -1046,10 +1046,13 @@ void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP,
     DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
                       &ignored);
     if (TD->isBigEndian()) {
-      O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48)
+      O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1])
         << '\t' << TAI->getCommentString()
         << " long double most significant halfword of ~"
         << DoubleVal.convertToDouble() << '\n';
+      O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48)
+        << '\t' << TAI->getCommentString()
+        << " long double next halfword\n";
       O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32)
         << '\t' << TAI->getCommentString()
         << " long double next halfword\n";
@@ -1057,19 +1060,13 @@ void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP,
         << '\t' << TAI->getCommentString()
         << " long double next halfword\n";
       O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0])
-        << '\t' << TAI->getCommentString()
-        << " long double next halfword\n";
-      O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1])
         << '\t' << TAI->getCommentString()
         << " long double least significant halfword\n";
      } else {
-      O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1])
+      O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0])
         << '\t' << TAI->getCommentString()
         << " long double least significant halfword of ~"
         << DoubleVal.convertToDouble() << '\n';
-      O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0])
-        << '\t' << TAI->getCommentString()
-        << " long double next halfword\n";
       O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16)
         << '\t' << TAI->getCommentString()
         << " long double next halfword\n";
@@ -1077,6 +1074,9 @@ void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP,
         << '\t' << TAI->getCommentString()
         << " long double next halfword\n";
       O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48)
+        << '\t' << TAI->getCommentString()
+        << " long double next halfword\n";
+      O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1])
         << '\t' << TAI->getCommentString()
         << " long double most significant halfword\n";
     }
index d7f0d8215987c0a2720eac4cd6ac697747004b00..2ee6a276fdf8b3ae29d6cc51200d81cd5b2aa12b 100644 (file)
@@ -2603,10 +2603,9 @@ APFloat::convertF80LongDoubleAPFloatToAPInt() const
   }
 
   uint64_t words[2];
-  words[0] =  ((uint64_t)(sign & 1) << 63) |
-              ((myexponent & 0x7fffLL) <<  48) |
-              ((mysignificand >>16) & 0xffffffffffffLL);
-  words[1] = mysignificand & 0xffff;
+  words[0] = mysignificand;
+  words[1] =  ((uint64_t)(sign & 1) << 15) |
+              (myexponent & 0x7fffLL);
   return APInt(80, 2, words);
 }
 
@@ -2764,14 +2763,13 @@ APFloat::initFromF80LongDoubleAPInt(const APInt &api)
   assert(api.getBitWidth()==80);
   uint64_t i1 = api.getRawData()[0];
   uint64_t i2 = api.getRawData()[1];
-  uint64_t myexponent = (i1 >> 48) & 0x7fff;
-  uint64_t mysignificand = ((i1 << 16) &  0xffffffffffff0000ULL) |
-                          (i2 & 0xffff);
+  uint64_t myexponent = (i2 & 0x7fff);
+  uint64_t mysignificand = i1;
 
   initialize(&APFloat::x87DoubleExtended);
   assert(partCount()==2);
 
-  sign = static_cast<unsigned int>(i1>>63);
+  sign = static_cast<unsigned int>(i2>>15);
   if (myexponent==0 && mysignificand==0) {
     // exponent, significand meaningless
     category = fcZero;
index 53c986409687ca6745b57d0b51cce8a6708a6e62..fc99f503f1d0e04291099fbefdccfc8a3fccc974 100644 (file)
@@ -2087,9 +2087,8 @@ void CWriter::printFloatingPointConstants(const Constant *C) {
     APInt api = FPC->getValueAPF().bitcastToAPInt();
     const uint64_t *p = api.getRawData();
     Out << "static const ConstantFP80Ty FPConstant" << FPCounter++
-    << " = { 0x"
-    << utohexstr((uint16_t)p[1] | (p[0] & 0xffffffffffffLL)<<16)
-    << "ULL, 0x" << utohexstr((uint16_t)(p[0] >> 48)) << ",{0,0,0}"
+    << " = { 0x" << utohexstr(p[0]) 
+    << "ULL, 0x" << utohexstr((uint16_t)p[1]) << ",{0,0,0}"
     << "}; /* Long double constant */\n";
   } else if (FPC->getType() == Type::PPC_FP128Ty) {
     APInt api = FPC->getValueAPF().bitcastToAPInt();
index 1d52d63957777542cf5c8ac1ad375180f0109640..3f8be4781f341244e60dd5a1ccd6890ddc8de0de 100644 (file)
@@ -797,9 +797,29 @@ static void WriteConstantInt(raw_ostream &Out, const Constant *CV,
     // Some form of long double.  These appear as a magic letter identifying
     // the type, then a fixed number of hex digits.
     Out << "0x";
-    if (&CFP->getValueAPF().getSemantics() == &APFloat::x87DoubleExtended)
+    if (&CFP->getValueAPF().getSemantics() == &APFloat::x87DoubleExtended) {
       Out << 'K';
-    else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad)
+      // api needed to prevent premature destruction
+      APInt api = CFP->getValueAPF().bitcastToAPInt();
+      const uint64_t* p = api.getRawData();
+      uint64_t word = p[1];
+      int shiftcount=12;
+      int width = api.getBitWidth();
+      for (int j=0; j<width; j+=4, shiftcount-=4) {
+        unsigned int nibble = (word>>shiftcount) & 15;
+        if (nibble < 10)
+          Out << (unsigned char)(nibble + '0');
+        else
+          Out << (unsigned char)(nibble - 10 + 'A');
+        if (shiftcount == 0 && j+4 < width) {
+          word = *p;
+          shiftcount = 64;
+          if (width-j-4 < 64)
+            shiftcount = width-j-4;
+        }
+      }
+      return;
+    } else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad)
       Out << 'L';
     else if (&CFP->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble)
       Out << 'M';
diff --git a/test/CodeGen/X86/2009-03-23-i80-fp80.ll b/test/CodeGen/X86/2009-03-23-i80-fp80.ll
new file mode 100644 (file)
index 0000000..0619e12
--- /dev/null
@@ -0,0 +1,14 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep 302245289961712575840256
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep K40018000000000000000
+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"
+target triple = "i686-apple-darwin9"
+
+define i80 @from() {
+  %tmp = bitcast x86_fp80 0xK4000C000000000000000 to i80
+  ret i80 %tmp
+}
+
+define x86_fp80 @to() {
+  %tmp = bitcast i80 302259125019767858003968 to x86_fp80
+  ret x86_fp80 %tmp
+}