diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 83c370eb745..baa9de02578 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -170,6 +170,7 @@ namespace llvm { APFloat(const fltSemantics &, fltCategory, bool negative); APFloat(double d); APFloat(float f); + APFloat(const APInt &); APFloat(const APFloat &); ~APFloat(); @@ -191,6 +192,7 @@ namespace llvm { opStatus convertFromInteger(const integerPart *, unsigned int, bool, roundingMode); opStatus convertFromString(const char *, roundingMode); + APInt convertToAPInt() const; double convertToDouble() const; float convertToFloat() const; @@ -256,6 +258,13 @@ namespace llvm { roundingMode); lostFraction combineLostFractions(lostFraction, lostFraction); opStatus convertFromHexadecimalString(const char *, roundingMode); + APInt convertFloatAPFloatToAPInt() const; + APInt convertDoubleAPFloatToAPInt() const; + APInt convertF80LongDoubleAPFloatToAPInt() const; + void initFromAPInt(const APInt& api); + void initFromFloatAPInt(const APInt& api); + void initFromDoubleAPInt(const APInt& api); + void initFromF80LongDoubleAPInt(const APInt& api); void assign(const APFloat &); void copySignificand(const APFloat &); diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l index 390544d8c3d..5acbbacf60f 100644 --- a/lib/AsmParser/Lexer.l +++ b/lib/AsmParser/Lexer.l @@ -91,14 +91,40 @@ static uint64_t HexIntToVal(const char *Buffer) { return Result; } - -// HexToFP - Convert the ascii string in hexidecimal format to the floating +// HexToFP - Convert the ascii string in hexadecimal format to the floating // point representation of it. // static double HexToFP(const char *Buffer) { return BitsToDouble(HexIntToVal(Buffer)); // Cast Hex constant to double } +static void HexToIntPair(const char *Buffer, uint64_t Pair[2]) { + Pair[0] = 0; + for (int i=0; i<16; i++, Buffer++) { + assert(*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; + } + Pair[1] = 0; + for (int i=0; i<16 && *Buffer; i++, Buffer++) { + 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; + } + if (*Buffer) + GenerateError("constant bigger than 128 bits detected!"); +} // UnEscapeLexed - Run through the specified buffer and change \xx codes to the // appropriate character. @@ -163,15 +189,28 @@ IntegerType i[0-9]+ PInteger [0-9]+ NInteger -[0-9]+ -/* FPConstant - A Floating point constant. +/* FPConstant - A Floating point constant. Float and double only. */ FPConstant [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)? /* HexFPConstant - Floating point constant represented in IEEE format as a * hexadecimal number for when exponential notation is not precise enough. + * Float and double only. */ HexFPConstant 0x[0-9A-Fa-f]+ +/* F80HexFPConstant - x87 long double in hexadecimal format (10 bytes) + */ +HexFP80Constant 0xK[0-9A-Fa-f]+ + +/* F128HexFPConstant - IEEE 128-bit in hexadecimal format (16 bytes) + */ +HexFP128Constant 0xL[0-9A-Fa-f]+ + +/* PPC128HexFPConstant - PowerPC 128-bit in hexadecimal format (16 bytes) + */ +HexPPC128Constant 0xM[0-9A-Fa-f]+ + /* HexIntConstant - Hexadecimal constant generated by the CFE to avoid forcing * it to deal with 64 bit numbers. */ @@ -441,6 +480,21 @@ shufflevector { RET_TOK(OtherOpVal, ShuffleVector, SHUFFLEVECTOR); } {HexFPConstant} { llvmAsmlval.FPVal = new APFloat(HexToFP(yytext)); return FPVAL; } +{HexFP80Constant} { uint64_t Pair[2]; + HexToIntPair(yytext, Pair); + llvmAsmlval.FPVal = new APFloat(APInt(80, 2, Pair)); + return FPVAL; + } +{HexFP128Constant} { uint64_t Pair[2]; + HexToIntPair(yytext, Pair); + llvmAsmlval.FPVal = new APFloat(APInt(128, 2, Pair)); + return FPVAL; + } +{HexPPC128Constant} { uint64_t Pair[2]; + HexToIntPair(yytext, Pair); + llvmAsmlval.FPVal = new APFloat(APInt(128, 2, Pair)); + return FPVAL; + } <> { /* Make sure to free the internal buffers for flex when we are diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 6364b29bcd7..c0374daf3f1 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -416,9 +416,10 @@ static Value *getExistingVal(const Type *Ty, const ValID &D) { GenerateError("FP constant invalid for type"); return 0; } - // Lexer has no type info, so builds all FP constants as double. - // Fix this here. - if (Ty==Type::FloatTy) + // Lexer has no type info, so builds all float and double FP constants + // as double. Fix this here. Long double does not need this. + if (&D.ConstPoolFP->getSemantics() == &APFloat::IEEEdouble && + Ty==Type::FloatTy) D.ConstPoolFP->convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven); return ConstantFP::get(Ty, *D.ConstPoolFP); @@ -1868,9 +1869,9 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr | FPType FPVAL { // Float & Double constants if (!ConstantFP::isValueValidForType($1, *$2)) GEN_ERROR("Floating point constant invalid for type"); - // Lexer has no type info, so builds all FP constants as double. - // Fix this here. - if ($1==Type::FloatTy) + // Lexer has no type info, so builds all float and double FP constants + // as double. Fix this here. Long double is done right. + if (&$2->getSemantics()==&APFloat::IEEEdouble && $1==Type::FloatTy) $2->convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven); $$ = ConstantFP::get($1, *$2); delete $2; diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 8715f89c257..06429931dbd 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -622,23 +622,24 @@ bool BitcodeReader::ParseConstants() { NumWords, &Words[0])); break; } - case bitc::CST_CODE_FLOAT: // FLOAT: [fpval] + case bitc::CST_CODE_FLOAT: { // FLOAT: [fpval] if (Record.empty()) return Error("Invalid FLOAT record"); if (CurTy == Type::FloatTy) - V = ConstantFP::get(CurTy, APFloat(BitsToFloat(Record[0]))); + V = ConstantFP::get(CurTy, APFloat(APInt(32, (uint32_t)Record[0]))); else if (CurTy == Type::DoubleTy) - V = ConstantFP::get(CurTy, APFloat(BitsToDouble(Record[0]))); + V = ConstantFP::get(CurTy, APFloat(APInt(64, Record[0]))); // FIXME: Make long double constants work. BitsToDouble does not make it. else if (CurTy == Type::X86_FP80Ty) - V = ConstantFP::get(CurTy, APFloat(BitsToDouble(Record[0]))); + V = ConstantFP::get(CurTy, APFloat(APInt(80, 2, &Record[0]))); else if (CurTy == Type::FP128Ty) - V = ConstantFP::get(CurTy, APFloat(BitsToDouble(Record[0]))); + V = ConstantFP::get(CurTy, APFloat(APInt(128, 2, &Record[0]))); else if (CurTy == Type::PPC_FP128Ty) assert(0 && "PowerPC long double constants not handled yet."); else V = UndefValue::get(CurTy); break; + } case bitc::CST_CODE_AGGREGATE: {// AGGREGATE: [n x value number] if (Record.empty()) diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 73f5338dcce..78a16d8f627 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -527,13 +527,20 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, Code = bitc::CST_CODE_FLOAT; const Type *Ty = CFP->getType(); if (Ty == Type::FloatTy) - Record.push_back(FloatToBits(CFP->getValueAPF().convertToFloat())); + Record.push_back((uint32_t)*CFP->getValueAPF().convertToAPInt(). + getRawData()); else if (Ty == Type::DoubleTy) { - Record.push_back(DoubleToBits(CFP->getValueAPF().convertToDouble())); - // FIXME: make long double constants work. - } else if (Ty == Type::X86_FP80Ty || - Ty == Type::FP128Ty || Ty == Type::PPC_FP128Ty) { - assert (0 && "Long double constants not handled yet."); + Record.push_back(*CFP->getValueAPF().convertToAPInt().getRawData()); + } else if (Ty == Type::X86_FP80Ty) { + const uint64_t *p = CFP->getValueAPF().convertToAPInt().getRawData(); + Record.push_back(p[0]); + Record.push_back((uint16_t)p[1]); + } else if (Ty == Type::FP128Ty) { + const uint64_t *p = CFP->getValueAPF().convertToAPInt().getRawData(); + Record.push_back(p[0]); + Record.push_back(p[1]); + } else if (Ty == Type::PPC_FP128Ty) { + assert(0 && "PowerPC long double constants not handled yet."); } else { assert (0 && "Unknown FP type!"); } diff --git a/lib/CodeGen/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter.cpp index e80afd40eed..49bcba78141 100644 --- a/lib/CodeGen/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter.cpp @@ -830,29 +830,31 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV) { // FP Constants are printed as integer constants to avoid losing // precision... if (CFP->getType() == Type::DoubleTy) { - double Val = CFP->getValueAPF().convertToDouble(); + double Val = CFP->getValueAPF().convertToDouble(); // for comment only + uint64_t i = *CFP->getValueAPF().convertToAPInt().getRawData(); if (TAI->getData64bitsDirective()) - O << TAI->getData64bitsDirective() << DoubleToBits(Val) << "\t" + O << TAI->getData64bitsDirective() << i << "\t" << TAI->getCommentString() << " double value: " << Val << "\n"; else if (TD->isBigEndian()) { - O << TAI->getData32bitsDirective() << unsigned(DoubleToBits(Val) >> 32) + O << TAI->getData32bitsDirective() << unsigned(i >> 32) << "\t" << TAI->getCommentString() << " double most significant word " << Val << "\n"; - O << TAI->getData32bitsDirective() << unsigned(DoubleToBits(Val)) + O << TAI->getData32bitsDirective() << unsigned(i) << "\t" << TAI->getCommentString() << " double least significant word " << Val << "\n"; } else { - O << TAI->getData32bitsDirective() << unsigned(DoubleToBits(Val)) + O << TAI->getData32bitsDirective() << unsigned(i) << "\t" << TAI->getCommentString() << " double least significant word " << Val << "\n"; - O << TAI->getData32bitsDirective() << unsigned(DoubleToBits(Val) >> 32) + O << TAI->getData32bitsDirective() << unsigned(i >> 32) << "\t" << TAI->getCommentString() << " double most significant word " << Val << "\n"; } return; } else { - float Val = CFP->getValueAPF().convertToFloat(); - O << TAI->getData32bitsDirective() << FloatToBits(Val) + float Val = CFP->getValueAPF().convertToFloat(); // for comment only + O << TAI->getData32bitsDirective() + << (uint32_t)*CFP->getValueAPF().convertToAPInt().getRawData() << "\t" << TAI->getCommentString() << " float " << Val << "\n"; return; } diff --git a/lib/CodeGen/MachOWriter.cpp b/lib/CodeGen/MachOWriter.cpp index af2555d3eed..1c9b0feff54 100644 --- a/lib/CodeGen/MachOWriter.cpp +++ b/lib/CodeGen/MachOWriter.cpp @@ -861,8 +861,8 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, break; } case Type::FloatTyID: { - uint64_t val = FloatToBits(cast(PC)-> - getValueAPF().convertToFloat()); + uint32_t val = (uint32_t)*cast(PC)-> + getValueAPF().convertToAPInt().getRawData(); if (TD->isBigEndian()) val = ByteSwap_32(val); ptr[0] = val; @@ -872,8 +872,8 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, break; } case Type::DoubleTyID: { - uint64_t val = DoubleToBits(cast(PC)-> - getValueAPF().convertToDouble()); + uint64_t val = *cast(PC)->getValueAPF().convertToAPInt(). + getRawData(); if (TD->isBigEndian()) val = ByteSwap_64(val); ptr[0] = val; diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 32f81d38f26..2050d23ad72 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3800,7 +3800,8 @@ SDOperand DAGCombiner::visitSTORE(SDNode *N) { default: assert(0 && "Unknown FP type"); case MVT::f32: if (!AfterLegalize || TLI.isTypeLegal(MVT::i32)) { - Tmp = DAG.getConstant(FloatToBits(CFP->getValueAPF().convertToFloat()), MVT::i32); + Tmp = DAG.getConstant((uint32_t)*CFP->getValueAPF(). + convertToAPInt().getRawData(), MVT::i32); return DAG.getStore(Chain, Tmp, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), ST->isVolatile(), ST->getAlignment()); @@ -3808,7 +3809,8 @@ SDOperand DAGCombiner::visitSTORE(SDNode *N) { break; case MVT::f64: if (!AfterLegalize || TLI.isTypeLegal(MVT::i64)) { - Tmp = DAG.getConstant(DoubleToBits(CFP->getValueAPF().convertToDouble()), MVT::i64); + Tmp = DAG.getConstant(*CFP->getValueAPF().convertToAPInt(). + getRawData(), MVT::i64); return DAG.getStore(Chain, Tmp, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), ST->isVolatile(), ST->getAlignment()); @@ -3816,7 +3818,7 @@ SDOperand DAGCombiner::visitSTORE(SDNode *N) { // Many FP stores are not make apparent until after legalize, e.g. for // argument passing. Since this is so common, custom legalize the // 64-bit integer store into two 32-bit stores. - uint64_t Val = DoubleToBits(CFP->getValueAPF().convertToDouble()); + uint64_t Val = *CFP->getValueAPF().convertToAPInt().getRawData(); SDOperand Lo = DAG.getConstant(Val & 0xFFFFFFFF, MVT::i32); SDOperand Hi = DAG.getConstant(Val >> 32, MVT::i32); if (!TLI.isLittleEndian()) std::swap(Lo, Hi); diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 31e29470e80..d7eb85bd8fb 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -491,8 +491,9 @@ static SDOperand ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP, if (!UseCP) { const APFloat& Val = LLVMC->getValueAPF(); return isDouble - ? DAG.getConstant(DoubleToBits(Val.convertToDouble()), MVT::i64) - : DAG.getConstant(FloatToBits(Val.convertToFloat()), MVT::i32); + ? DAG.getConstant(*Val.convertToAPInt().getRawData(), MVT::i64) + : DAG.getConstant((uint32_t )*Val.convertToAPInt().getRawData(), + MVT::i32); } if (isDouble && CFP->isValueValidForType(MVT::f32, CFP->getValueAPF()) && @@ -1980,12 +1981,13 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { // together. if (ConstantFPSDNode *CFP = dyn_cast(ST->getValue())) { if (CFP->getValueType(0) == MVT::f32) { - Tmp3 = DAG.getConstant(FloatToBits(CFP->getValueAPF(). - convertToFloat()), MVT::i32); + Tmp3 = DAG.getConstant((uint32_t)*CFP->getValueAPF(). + convertToAPInt().getRawData(), + MVT::i32); } else { assert(CFP->getValueType(0) == MVT::f64 && "Unknown FP type!"); - Tmp3 = DAG.getConstant(DoubleToBits(CFP->getValueAPF(). - convertToDouble()), MVT::i64); + Tmp3 = DAG.getConstant(*CFP->getValueAPF().convertToAPInt(). + getRawData(), MVT::i64); } Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(), SVOffset, isVolatile, Alignment); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 01ec5c968aa..85a76f436b1 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -109,13 +109,12 @@ bool ISD::isBuildVectorAllOnes(const SDNode *N) { } else if (isa(NotZero)) { MVT::ValueType VT = NotZero.getValueType(); if (VT== MVT::f64) { - if (DoubleToBits(cast(NotZero)-> - getValueAPF().convertToDouble()) != - (uint64_t)-1) + if (*((cast(NotZero)->getValueAPF(). + convertToAPInt().getRawData())) != (uint64_t)-1) return false; } else { - if (FloatToBits(cast(NotZero)-> - getValueAPF().convertToFloat()) != + if ((uint32_t)*cast(NotZero)-> + getValueAPF().convertToAPInt().getRawData() != (uint32_t)-1) return false; } @@ -1698,9 +1697,9 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, } case ISD::BIT_CONVERT: if (VT == MVT::i32 && C->getValueType(0) == MVT::f32) - return getConstant(FloatToBits(V.convertToFloat()), VT); + return getConstant((uint32_t)*V.convertToAPInt().getRawData(), VT); else if (VT == MVT::i64 && C->getValueType(0) == MVT::f64) - return getConstant(DoubleToBits(V.convertToDouble()), VT); + return getConstant(*V.convertToAPInt().getRawData(), VT); break; } } diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 9b8caa89ffc..96fdc42fb26 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -339,7 +339,8 @@ APFloat::~APFloat() unsigned int APFloat::partCount() const { - return partCountForBits(semantics->precision + 1); + return partCountForBits(semantics->precision + + semantics->implicitIntegerBit ? 1 : 0); } unsigned int @@ -1593,8 +1594,41 @@ APFloat::getHashValue() const { // Denormals have exponent minExponent in APFloat, but minExponent-1 in // the actual IEEE respresentation. We compensate for that here. -double -APFloat::convertToDouble() const { +APInt +APFloat::convertF80LongDoubleAPFloatToAPInt() const { + assert(semantics == (const llvm::fltSemantics* const)&x87DoubleExtended); + assert (partCount()==1); + + uint64_t myexponent, mysignificand; + + if (category==fcNormal) { + myexponent = exponent+16383; //bias + mysignificand = *significandParts(); + if (myexponent==1 && !(mysignificand & 0x8000000000000000ULL)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = 0; + } else if (category==fcInfinity) { + myexponent = 0x7fff; + mysignificand = 0x8000000000000000ULL; + } else if (category==fcNaN) { + myexponent = 0x7fff; + mysignificand = *significandParts(); + } else + assert(0); + + uint64_t words[2]; + words[0] = (((uint64_t)sign & 1) << 63) | + ((myexponent & 0x7fff) << 48) | + ((mysignificand >>16) & 0xffffffffffffLL); + words[1] = mysignificand & 0xffff; + APInt api(80, 2, words); + return api; +} + +APInt +APFloat::convertDoubleAPFloatToAPInt() const { assert(semantics == (const llvm::fltSemantics* const)&IEEEdouble); assert (partCount()==1); @@ -1617,16 +1651,17 @@ APFloat::convertToDouble() const { } else assert(0); - return BitsToDouble((((uint64_t)sign & 1) << 63) | - ((myexponent & 0x7ff) << 52) | - (mysignificand & 0xfffffffffffffLL)); + APInt api(64, (((((uint64_t)sign & 1) << 63) | + ((myexponent & 0x7ff) << 52) | + (mysignificand & 0xfffffffffffffLL)))); + return api; } -float -APFloat::convertToFloat() const { +APInt +APFloat::convertFloatAPFloatToAPInt() const { assert(semantics == (const llvm::fltSemantics* const)&IEEEsingle); assert (partCount()==1); - + uint32_t myexponent, mysignificand; if (category==fcNormal) { @@ -1646,12 +1681,78 @@ APFloat::convertToFloat() const { } else assert(0); - return BitsToFloat(((sign&1) << 31) | ((myexponent&0xff) << 23) | - (mysignificand & 0x7fffff)); + APInt api(32, (((sign&1) << 31) | ((myexponent&0xff) << 23) | + (mysignificand & 0x7fffff))); + return api; } -APFloat::APFloat(double d) { - uint64_t i = DoubleToBits(d); +APInt +APFloat::convertToAPInt() const { + if (semantics == (const llvm::fltSemantics* const)&IEEEsingle) + return convertFloatAPFloatToAPInt(); + else if (semantics == (const llvm::fltSemantics* const)&IEEEdouble) + return convertDoubleAPFloatToAPInt(); + else if (semantics == (const llvm::fltSemantics* const)&x87DoubleExtended) + return convertF80LongDoubleAPFloatToAPInt(); + else + assert(0); +} + +float +APFloat::convertToFloat() const { + assert(semantics == (const llvm::fltSemantics* const)&IEEEsingle); + APInt api = convertToAPInt(); + return api.bitsToFloat(); +} + +double +APFloat::convertToDouble() const { + assert(semantics == (const llvm::fltSemantics* const)&IEEEdouble); + APInt api = convertToAPInt(); + return api.bitsToDouble(); +} + +/// Integer bit is explicit in this format. Current Intel book does not +/// define meaning of: +/// exponent = all 1's, integer bit not set. +/// exponent = 0, integer bit set. (formerly "psuedodenormals") +/// exponent!=0 nor all 1's, integer bit not set. (formerly "unnormals") +void +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); + + initialize(&APFloat::x87DoubleExtended); + assert(partCount()==1); + + sign = i1>>63; + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0x7fff && mysignificand==0x8000000000000000ULL) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0x7fff && mysignificand!=0x8000000000000000ULL) { + // exponent meaningless + category = fcNaN; + *significandParts() = mysignificand; + } else { + category = fcNormal; + exponent = myexponent - 16383; + *significandParts() = mysignificand; + if (myexponent==0) // denormal + exponent = -16382; + } +} + +void +APFloat::initFromDoubleAPInt(const APInt &api) { + assert(api.getBitWidth()==64); + uint64_t i = *api.getRawData(); uint64_t myexponent = (i >> 52) & 0x7ff; uint64_t mysignificand = i & 0xfffffffffffffLL; @@ -1680,8 +1781,10 @@ APFloat::APFloat(double d) { } } -APFloat::APFloat(float f) { - uint32_t i = FloatToBits(f); +void +APFloat::initFromFloatAPInt(const APInt & api) { + assert(api.getBitWidth()==32); + uint32_t i = (uint32_t)*api.getRawData(); uint32_t myexponent = (i >> 23) & 0xff; uint32_t mysignificand = i & 0x7fffff; @@ -1709,3 +1812,34 @@ APFloat::APFloat(float f) { *significandParts() |= 0x800000; // integer bit } } + +/// Treat api as containing the bits of a floating point number. Currently +/// we infer the floating point type from the size of the APInt. FIXME: This +/// breaks when we get to PPC128 and IEEE128 (but both cannot exist in the +/// same compile...) +void +APFloat::initFromAPInt(const APInt& api) { + if (api.getBitWidth() == 32) + return initFromFloatAPInt(api); + else if (api.getBitWidth()==64) + return initFromDoubleAPInt(api); + else if (api.getBitWidth()==80) + return initFromF80LongDoubleAPInt(api); + else + assert(0); +} + +APFloat::APFloat(const APInt& api) { + initFromAPInt(api); +} + +APFloat::APFloat(float f) { + APInt api = APInt(32, 0); + initFromAPInt(api.floatToBits(f)); +} + +APFloat::APFloat(double d) { + APInt api = APInt(64, 0); + initFromAPInt(api.doubleToBits(d)); +} + diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 0221174e5cf..f25b1133b24 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -1715,13 +1715,16 @@ void CWriter::printFloatingPointConstants(Function &F) { if (FPC->getType() == Type::DoubleTy) { double Val = FPC->getValueAPF().convertToDouble(); + uint64_t i = *FPC->getValueAPF().convertToAPInt().getRawData(); Out << "static const ConstantDoubleTy FPConstant" << FPCounter++ - << " = 0x" << std::hex << DoubleToBits(Val) << std::dec + << " = 0x" << std::hex << i << std::dec << "ULL; /* " << Val << " */\n"; } else if (FPC->getType() == Type::FloatTy) { float Val = FPC->getValueAPF().convertToFloat(); + uint32_t i = (uint32_t)*FPC->getValueAPF().convertToAPInt(). + getRawData(); Out << "static const ConstantFloatTy FPConstant" << FPCounter++ - << " = 0x" << std::hex << FloatToBits(Val) << std::dec + << " = 0x" << std::hex << i << std::dec << "U; /* " << Val << " */\n"; } else assert(0 && "Unknown float type!"); diff --git a/lib/Target/MSIL/MSILWriter.cpp b/lib/Target/MSIL/MSILWriter.cpp index 71789703ff3..cd67df17a6f 100644 --- a/lib/Target/MSIL/MSILWriter.cpp +++ b/lib/Target/MSIL/MSILWriter.cpp @@ -428,10 +428,10 @@ void MSILWriter::printConstLoad(const Constant* C) { uint64_t X; unsigned Size; if (FP->getType()->getTypeID()==Type::FloatTyID) { - X = FloatToBits(FP->getValueAPF().convertToFloat()); + X = (uint32_t)*FP->getValueAPF().convertToAPInt().getRawData(); Size = 4; } else { - X = DoubleToBits(FP->getValueAPF().convertToDouble()); + X = *FP->getValueAPF().convertToAPInt().getRawData(); Size = 8; } Out << "\tldc.r" << Size << "\t( " << utohexstr(X) << ')'; @@ -1473,10 +1473,10 @@ void MSILWriter::printStaticConstant(const Constant* C, uint64_t& Offset) { const ConstantFP* FP = cast(C); if (Ty->getTypeID() == Type::FloatTyID) Out << "int32 (" << - FloatToBits(FP->getValueAPF().convertToFloat()) << ')'; + (uint32_t)*FP->getValueAPF().convertToAPInt().getRawData() << ')'; else Out << "int64 (" << - DoubleToBits(FP->getValueAPF().convertToDouble()) << ')'; + *FP->getValueAPF().convertToAPInt().getRawData() << ')'; break; } case Type::ArrayTyID: diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 6d3bcf7bb51..95450ac97fa 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -3410,11 +3410,11 @@ SDOperand X86TargetLowering::LowerFABS(SDOperand Op, SelectionDAG &DAG) { const Type *OpNTy = MVT::getTypeForValueType(EltVT); std::vector CV; if (EltVT == MVT::f64) { - Constant *C = ConstantFP::get(OpNTy, APFloat(BitsToDouble(~(1ULL << 63)))); + Constant *C = ConstantFP::get(OpNTy, APFloat(APInt(64, ~(1ULL << 63)))); CV.push_back(C); CV.push_back(C); } else { - Constant *C = ConstantFP::get(OpNTy, APFloat(BitsToFloat(~(1U << 31)))); + Constant *C = ConstantFP::get(OpNTy, APFloat(APInt(32, ~(1U << 31)))); CV.push_back(C); CV.push_back(C); CV.push_back(C); @@ -3438,11 +3438,11 @@ SDOperand X86TargetLowering::LowerFNEG(SDOperand Op, SelectionDAG &DAG) { const Type *OpNTy = MVT::getTypeForValueType(EltVT); std::vector CV; if (EltVT == MVT::f64) { - Constant *C = ConstantFP::get(OpNTy, APFloat(BitsToDouble(1ULL << 63))); + Constant *C = ConstantFP::get(OpNTy, APFloat(APInt(64, 1ULL << 63))); CV.push_back(C); CV.push_back(C); } else { - Constant *C = ConstantFP::get(OpNTy, APFloat(BitsToFloat(1U << 31))); + Constant *C = ConstantFP::get(OpNTy, APFloat(APInt(32, 1U << 31))); CV.push_back(C); CV.push_back(C); CV.push_back(C); @@ -3479,13 +3479,13 @@ SDOperand X86TargetLowering::LowerFCOPYSIGN(SDOperand Op, SelectionDAG &DAG) { // First get the sign bit of second operand. std::vector CV; if (SrcVT == MVT::f64) { - CV.push_back(ConstantFP::get(SrcTy, APFloat(BitsToDouble(1ULL << 63)))); - CV.push_back(ConstantFP::get(SrcTy, APFloat(0.0))); + CV.push_back(ConstantFP::get(SrcTy, APFloat(APInt(64, 1ULL << 63)))); + CV.push_back(ConstantFP::get(SrcTy, APFloat(APInt(64, 0)))); } else { - CV.push_back(ConstantFP::get(SrcTy, APFloat(BitsToFloat(1U << 31)))); - CV.push_back(ConstantFP::get(SrcTy, APFloat(0.0f))); - CV.push_back(ConstantFP::get(SrcTy, APFloat(0.0f))); - CV.push_back(ConstantFP::get(SrcTy, APFloat(0.0f))); + CV.push_back(ConstantFP::get(SrcTy, APFloat(APInt(32, 1U << 31)))); + CV.push_back(ConstantFP::get(SrcTy, APFloat(APInt(32, 0)))); + CV.push_back(ConstantFP::get(SrcTy, APFloat(APInt(32, 0)))); + CV.push_back(ConstantFP::get(SrcTy, APFloat(APInt(32, 0)))); } Constant *C = ConstantVector::get(CV); SDOperand CPIdx = DAG.getConstantPool(C, getPointerTy(), 4); @@ -3507,13 +3507,13 @@ SDOperand X86TargetLowering::LowerFCOPYSIGN(SDOperand Op, SelectionDAG &DAG) { // Clear first operand sign bit. CV.clear(); if (VT == MVT::f64) { - CV.push_back(ConstantFP::get(SrcTy, APFloat(BitsToDouble(~(1ULL << 63))))); - CV.push_back(ConstantFP::get(SrcTy, APFloat(0.0))); + CV.push_back(ConstantFP::get(SrcTy, APFloat(APInt(64, ~(1ULL << 63))))); + CV.push_back(ConstantFP::get(SrcTy, APFloat(APInt(64, 0)))); } else { - CV.push_back(ConstantFP::get(SrcTy, APFloat(BitsToFloat(~(1U << 31))))); - CV.push_back(ConstantFP::get(SrcTy, APFloat(0.0f))); - CV.push_back(ConstantFP::get(SrcTy, APFloat(0.0f))); - CV.push_back(ConstantFP::get(SrcTy, APFloat(0.0f))); + CV.push_back(ConstantFP::get(SrcTy, APFloat(APInt(32, ~(1U << 31))))); + CV.push_back(ConstantFP::get(SrcTy, APFloat(APInt(32, 0)))); + CV.push_back(ConstantFP::get(SrcTy, APFloat(APInt(32, 0)))); + CV.push_back(ConstantFP::get(SrcTy, APFloat(APInt(32, 0)))); } C = ConstantVector::get(CV); CPIdx = DAG.getConstantPool(C, getPointerTy(), 4); diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 4dc1340f908..e11b749f9be 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -87,9 +87,8 @@ static Constant *CastConstantVector(ConstantVector *CV, if (SrcEltTy->getTypeID() == Type::DoubleTyID) { for (unsigned i = 0; i != SrcNumElts; ++i) { - uint64_t V = - DoubleToBits(cast(CV->getOperand(i))-> - getValueAPF().convertToDouble()); + uint64_t V = *cast(CV->getOperand(i))-> + getValueAPF().convertToAPInt().getRawData(); Constant *C = ConstantInt::get(Type::Int64Ty, V); Result.push_back(ConstantExpr::getBitCast(C, DstEltTy )); } @@ -98,8 +97,8 @@ static Constant *CastConstantVector(ConstantVector *CV, assert(SrcEltTy->getTypeID() == Type::FloatTyID); for (unsigned i = 0; i != SrcNumElts; ++i) { - uint32_t V = FloatToBits(cast(CV->getOperand(i))-> - getValueAPF().convertToFloat()); + uint32_t V = (uint32_t)*cast(CV->getOperand(i))-> + getValueAPF().convertToAPInt().getRawData(); Constant *C = ConstantInt::get(Type::Int32Ty, V); Result.push_back(ConstantExpr::getBitCast(C, DstEltTy)); } @@ -333,9 +332,9 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, const Constant *V, if (DestTy->isFloatingPoint()) { if (DestTy == Type::FloatTy) - return ConstantFP::get(DestTy, APFloat(CI->getValue().bitsToFloat())); + return ConstantFP::get(DestTy, APFloat(CI->getValue())); assert(DestTy == Type::DoubleTy && "Unknown FP type!"); - return ConstantFP::get(DestTy, APFloat(CI->getValue().bitsToDouble())); + return ConstantFP::get(DestTy, APFloat(CI->getValue())); } // Otherwise, can't fold this (vector?) return 0; @@ -345,14 +344,10 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, const Constant *V, if (const ConstantFP *FP = dyn_cast(V)) { // FP -> Integral. if (DestTy == Type::Int32Ty) { - APInt Val(32, 0); - return ConstantInt::get(Val.floatToBits(FP-> - getValueAPF().convertToFloat())); + return ConstantInt::get(FP->getValueAPF().convertToAPInt()); } else { assert(DestTy == Type::Int64Ty && "only support f32/f64 for now!"); - APInt Val(64, 0); - return ConstantInt::get(Val.doubleToBits(FP-> - getValueAPF().convertToDouble())); + return ConstantInt::get(FP->getValueAPF().convertToAPInt()); } } return 0; diff --git a/tools/llvm2cpp/CppWriter.cpp b/tools/llvm2cpp/CppWriter.cpp index 1551dc3be78..a56c7cdd41a 100644 --- a/tools/llvm2cpp/CppWriter.cpp +++ b/tools/llvm2cpp/CppWriter.cpp @@ -250,11 +250,11 @@ CppWriter::printCFP(const ConstantFP *CFP) { } else if (CFP->getType() == Type::DoubleTy) Out << "BitsToDouble(0x" << std::hex - << DoubleToBits(CFP->getValueAPF().convertToDouble()) + << *CFP->getValueAPF().convertToAPInt().getRawData() << std::dec << "ULL) /* " << StrVal << " */"; else Out << "BitsToFloat(0x" << std::hex - << FloatToBits(CFP->getValueAPF().convertToFloat()) + << (uint32_t)*CFP->getValueAPF().convertToAPInt().getRawData() << std::dec << "U) /* " << StrVal << " */"; Out << ")"; #if HAVE_PRINTF_A