Fix internal representation of fp80 to be the

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.

llvm-svn: 67562
This commit is contained in:
Dale Johannesen 2009-03-23 21:16:53 +00:00
parent 2441a7df96
commit 93eefa0043
9 changed files with 97 additions and 27 deletions

View 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;
}

View 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

View 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])));

View 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();

View 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";
}

View 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;

View 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();

View 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';

View File

@ -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
}