Add a "loses information" return value to APFloat::convert

and APFloat::convertToInteger.  Restore return value to
IEEE754.  Adjust all users accordingly.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57329 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dale Johannesen 2008-10-09 23:00:39 +00:00
parent 7111b02c73
commit 23a98551ab
15 changed files with 115 additions and 55 deletions

View File

@ -216,9 +216,9 @@ namespace llvm {
void copySign(const APFloat &); void copySign(const APFloat &);
/* Conversions. */ /* Conversions. */
opStatus convert(const fltSemantics &, roundingMode); opStatus convert(const fltSemantics &, roundingMode, bool *);
opStatus convertToInteger(integerPart *, unsigned int, bool, opStatus convertToInteger(integerPart *, unsigned int, bool,
roundingMode) const; roundingMode, bool *) const;
opStatus convertFromAPInt(const APInt &, opStatus convertFromAPInt(const APInt &,
bool, roundingMode); bool, roundingMode);
opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int, opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int,
@ -299,7 +299,7 @@ namespace llvm {
opStatus handleOverflow(roundingMode); opStatus handleOverflow(roundingMode);
bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const; bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const;
opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool, opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool,
roundingMode) const; roundingMode, bool *) const;
opStatus convertFromUnsignedParts(const integerPart *, unsigned int, opStatus convertFromUnsignedParts(const integerPart *, unsigned int,
roundingMode); roundingMode);
opStatus convertFromHexadecimalString(const char *, roundingMode); opStatus convertFromHexadecimalString(const char *, roundingMode);

View File

@ -1756,12 +1756,13 @@ public:
/// convenient to write "2.0" and the like. Without this function we'd /// convenient to write "2.0" and the like. Without this function we'd
/// have to duplicate its logic everywhere it's called. /// have to duplicate its logic everywhere it's called.
bool isExactlyValue(double V) const { bool isExactlyValue(double V) const {
bool ignored;
// convert is not supported on this type // convert is not supported on this type
if (&Value->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble) if (&Value->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble)
return false; return false;
APFloat Tmp(V); APFloat Tmp(V);
Tmp.convert(Value->getValueAPF().getSemantics(), Tmp.convert(Value->getValueAPF().getSemantics(),
APFloat::rmNearestTiesToEven); APFloat::rmNearestTiesToEven, &ignored);
return isExactlyValue(Tmp); return isExactlyValue(Tmp);
} }
bool isExactlyValue(const APFloat& V) const; bool isExactlyValue(const APFloat& V) const;

View File

@ -428,8 +428,11 @@ static Value *getExistingVal(const Type *Ty, const ValID &D) {
// Lexer has no type info, so builds all float and double FP constants // Lexer has no type info, so builds all float and double FP constants
// as double. Fix this here. Long double does not need this. // as double. Fix this here. Long double does not need this.
if (&D.ConstPoolFP->getSemantics() == &APFloat::IEEEdouble && if (&D.ConstPoolFP->getSemantics() == &APFloat::IEEEdouble &&
Ty==Type::FloatTy) Ty==Type::FloatTy) {
D.ConstPoolFP->convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven); bool ignored;
D.ConstPoolFP->convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven,
&ignored);
}
return ConstantFP::get(*D.ConstPoolFP); return ConstantFP::get(*D.ConstPoolFP);
case ValID::ConstNullVal: // Is it a null value? case ValID::ConstNullVal: // Is it a null value?
@ -1929,8 +1932,11 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
GEN_ERROR("Floating point constant invalid for type"); GEN_ERROR("Floating point constant invalid for type");
// Lexer has no type info, so builds all float and double FP constants // Lexer has no type info, so builds all float and double FP constants
// as double. Fix this here. Long double is done right. // as double. Fix this here. Long double is done right.
if (&$2->getSemantics()==&APFloat::IEEEdouble && $1==Type::FloatTy) if (&$2->getSemantics()==&APFloat::IEEEdouble && $1==Type::FloatTy) {
$2->convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven); bool ignored;
$2->convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven,
&ignored);
}
$$ = ConstantFP::get(*$2); $$ = ConstantFP::get(*$2);
delete $2; delete $2;
CHECK_FOR_ERROR CHECK_FOR_ERROR

View File

@ -1000,8 +1000,11 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
// api needed to prevent premature destruction // api needed to prevent premature destruction
APInt api = CFP->getValueAPF().bitcastToAPInt(); APInt api = CFP->getValueAPF().bitcastToAPInt();
const uint64_t *p = api.getRawData(); const uint64_t *p = api.getRawData();
// Convert to double so we can print the approximate val as a comment.
APFloat DoubleVal = CFP->getValueAPF(); APFloat DoubleVal = CFP->getValueAPF();
DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven); bool ignored;
DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
&ignored);
if (TD->isBigEndian()) { if (TD->isBigEndian()) {
O << TAI->getData16bitsDirective() << uint16_t(p[0] >> 48) O << TAI->getData16bitsDirective() << uint16_t(p[0] >> 48)
<< '\t' << TAI->getCommentString() << '\t' << TAI->getCommentString()

View File

@ -93,8 +93,10 @@ unsigned FastISel::getRegForValue(Value *V) {
uint64_t x[2]; uint64_t x[2];
uint32_t IntBitWidth = IntVT.getSizeInBits(); uint32_t IntBitWidth = IntVT.getSizeInBits();
if (!Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true, bool isExact;
APFloat::rmTowardZero) != APFloat::opOK) { (void) Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true,
APFloat::rmTowardZero, &isExact);
if (isExact) {
APInt IntVal(IntBitWidth, 2, x); APInt IntVal(IntBitWidth, 2, x);
unsigned IntegerReg = getRegForValue(ConstantInt::get(IntVal)); unsigned IntegerReg = getRegForValue(ConstantInt::get(IntVal));
@ -711,8 +713,10 @@ unsigned FastISel::FastEmit_rf_(MVT::SimpleValueType VT, ISD::NodeType Opcode,
uint64_t x[2]; uint64_t x[2];
uint32_t IntBitWidth = IntVT.getSizeInBits(); uint32_t IntBitWidth = IntVT.getSizeInBits();
if (Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true, bool isExact;
APFloat::rmTowardZero) != APFloat::opOK) (void) Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true,
APFloat::rmTowardZero, &isExact);
if (!isExact)
return 0; return 0;
APInt IntVal(IntBitWidth, 2, x); APInt IntVal(IntBitWidth, 2, x);

View File

@ -84,8 +84,10 @@ bool ConstantFPSDNode::isValueValidForType(MVT VT,
// convert modifies in place, so make a copy. // convert modifies in place, so make a copy.
APFloat Val2 = APFloat(Val); APFloat Val2 = APFloat(Val);
return Val2.convert(*MVTToAPFloatSemantics(VT), bool losesInfo;
APFloat::rmNearestTiesToEven) == APFloat::opOK; (void) Val2.convert(*MVTToAPFloatSemantics(VT), APFloat::rmNearestTiesToEven,
&losesInfo);
return !losesInfo;
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -118,7 +120,7 @@ bool ISD::isBuildVectorAllOnes(const SDNode *N) {
return false; return false;
} else if (isa<ConstantFPSDNode>(NotZero)) { } else if (isa<ConstantFPSDNode>(NotZero)) {
if (!cast<ConstantFPSDNode>(NotZero)->getValueAPF(). if (!cast<ConstantFPSDNode>(NotZero)->getValueAPF().
convertToAPInt().isAllOnesValue()) bitcastToAPInt().isAllOnesValue())
return false; return false;
} else } else
return false; return false;
@ -2124,29 +2126,32 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) {
V.clearSign(); V.clearSign();
return getConstantFP(V, VT); return getConstantFP(V, VT);
case ISD::FP_ROUND: case ISD::FP_ROUND:
case ISD::FP_EXTEND: case ISD::FP_EXTEND: {
bool ignored;
// This can return overflow, underflow, or inexact; we don't care. // This can return overflow, underflow, or inexact; we don't care.
// FIXME need to be more flexible about rounding mode. // FIXME need to be more flexible about rounding mode.
(void)V.convert(*MVTToAPFloatSemantics(VT), (void)V.convert(*MVTToAPFloatSemantics(VT),
APFloat::rmNearestTiesToEven); APFloat::rmNearestTiesToEven, &ignored);
return getConstantFP(V, VT); return getConstantFP(V, VT);
}
case ISD::FP_TO_SINT: case ISD::FP_TO_SINT:
case ISD::FP_TO_UINT: { case ISD::FP_TO_UINT: {
integerPart x; integerPart x;
bool ignored;
assert(integerPartWidth >= 64); assert(integerPartWidth >= 64);
// FIXME need to be more flexible about rounding mode. // FIXME need to be more flexible about rounding mode.
APFloat::opStatus s = V.convertToInteger(&x, 64U, APFloat::opStatus s = V.convertToInteger(&x, 64U,
Opcode==ISD::FP_TO_SINT, Opcode==ISD::FP_TO_SINT,
APFloat::rmTowardZero); APFloat::rmTowardZero, &ignored);
if (s==APFloat::opInvalidOp) // inexact is OK, in fact usual if (s==APFloat::opInvalidOp) // inexact is OK, in fact usual
break; break;
return getConstant(x, VT); return getConstant(x, VT);
} }
case ISD::BIT_CONVERT: case ISD::BIT_CONVERT:
if (VT == MVT::i32 && C->getValueType(0) == MVT::f32) if (VT == MVT::i32 && C->getValueType(0) == MVT::f32)
return getConstant((uint32_t)V.convertToAPInt().getZExtValue(), VT); return getConstant((uint32_t)V.bitcastToAPInt().getZExtValue(), VT);
else if (VT == MVT::i64 && C->getValueType(0) == MVT::f64) else if (VT == MVT::i64 && C->getValueType(0) == MVT::f64)
return getConstant(V.convertToAPInt().getZExtValue(), VT); return getConstant(V.bitcastToAPInt().getZExtValue(), VT);
break; break;
} }
} }
@ -5245,7 +5250,7 @@ void SDNode::print(raw_ostream &OS, const SelectionDAG *G) const {
OS << '<' << CSDN->getValueAPF().convertToDouble() << '>'; OS << '<' << CSDN->getValueAPF().convertToDouble() << '>';
else { else {
OS << "<APFloat("; OS << "<APFloat(";
CSDN->getValueAPF().convertToAPInt().dump(); CSDN->getValueAPF().bitcastToAPInt().dump();
OS << ")>"; OS << ")>";
} }
} else if (const GlobalAddressSDNode *GADN = } else if (const GlobalAddressSDNode *GADN =

View File

@ -498,9 +498,10 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
else if (Op0->getType() == Type::X86_FP80Ty) { else if (Op0->getType() == Type::X86_FP80Ty) {
APFloat apf = APFloat(GV.IntVal); APFloat apf = APFloat(GV.IntVal);
uint64_t v; uint64_t v;
bool ignored;
(void)apf.convertToInteger(&v, BitWidth, (void)apf.convertToInteger(&v, BitWidth,
CE->getOpcode()==Instruction::FPToSI, CE->getOpcode()==Instruction::FPToSI,
APFloat::rmTowardZero); APFloat::rmTowardZero, &ignored);
GV.IntVal = v; // endian? GV.IntVal = v; // endian?
} }
return GV; return GV;

View File

@ -788,6 +788,7 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)
integerPart scratch[4]; integerPart scratch[4];
integerPart *fullSignificand; integerPart *fullSignificand;
lostFraction lost_fraction; lostFraction lost_fraction;
bool ignored;
assert(semantics == rhs.semantics); assert(semantics == rhs.semantics);
@ -836,7 +837,7 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)
semantics = &extendedSemantics; semantics = &extendedSemantics;
APFloat extendedAddend(*addend); APFloat extendedAddend(*addend);
status = extendedAddend.convert(extendedSemantics, rmTowardZero); status = extendedAddend.convert(extendedSemantics, rmTowardZero, &ignored);
assert(status == opOK); assert(status == opOK);
lost_fraction = addOrSubtractSignificand(extendedAddend, false); lost_fraction = addOrSubtractSignificand(extendedAddend, false);
@ -1528,8 +1529,9 @@ APFloat::mod(const APFloat &rhs, roundingMode rounding_mode)
int parts = partCount(); int parts = partCount();
integerPart *x = new integerPart[parts]; integerPart *x = new integerPart[parts];
bool ignored;
fs = V.convertToInteger(x, parts * integerPartWidth, true, fs = V.convertToInteger(x, parts * integerPartWidth, true,
rmNearestTiesToEven); rmNearestTiesToEven, &ignored);
if (fs==opInvalidOp) if (fs==opInvalidOp)
return fs; return fs;
@ -1670,9 +1672,16 @@ APFloat::compare(const APFloat &rhs) const
return result; return result;
} }
/// APFloat::convert - convert a value of one floating point type to another.
/// The return value corresponds to the IEEE754 exceptions. *losesInfo
/// records whether the transformation lost information, i.e. whether
/// converting the result back to the original type will produce the
/// original value (this is almost the same as return value==fsOK, but there
/// are edge cases where this is not so).
APFloat::opStatus APFloat::opStatus
APFloat::convert(const fltSemantics &toSemantics, APFloat::convert(const fltSemantics &toSemantics,
roundingMode rounding_mode) roundingMode rounding_mode, bool *losesInfo)
{ {
lostFraction lostFraction; lostFraction lostFraction;
unsigned int newPartCount, oldPartCount; unsigned int newPartCount, oldPartCount;
@ -1718,38 +1727,41 @@ APFloat::convert(const fltSemantics &toSemantics,
exponent += toSemantics.precision - semantics->precision; exponent += toSemantics.precision - semantics->precision;
semantics = &toSemantics; semantics = &toSemantics;
fs = normalize(rounding_mode, lostFraction); fs = normalize(rounding_mode, lostFraction);
*losesInfo = (fs != opOK);
} else if (category == fcNaN) { } else if (category == fcNaN) {
int shift = toSemantics.precision - semantics->precision; int shift = toSemantics.precision - semantics->precision;
// Do this now so significandParts gets the right answer // Do this now so significandParts gets the right answer
const fltSemantics *oldSemantics = semantics; const fltSemantics *oldSemantics = semantics;
semantics = &toSemantics; semantics = &toSemantics;
fs = opOK; *losesInfo = false;
// No normalization here, just truncate // No normalization here, just truncate
if (shift>0) if (shift>0)
APInt::tcShiftLeft(significandParts(), newPartCount, shift); APInt::tcShiftLeft(significandParts(), newPartCount, shift);
else if (shift < 0) { else if (shift < 0) {
unsigned ushift = -shift; unsigned ushift = -shift;
// We mark this as Inexact if we are losing information. This happens // Figure out if we are losing information. This happens
// if are shifting out something other than 0s, or if the x87 long // if are shifting out something other than 0s, or if the x87 long
// double input did not have its integer bit set (pseudo-NaN), or if the // double input did not have its integer bit set (pseudo-NaN), or if the
// x87 long double input did not have its QNan bit set (because the x87 // x87 long double input did not have its QNan bit set (because the x87
// hardware sets this bit when converting a lower-precision NaN to // hardware sets this bit when converting a lower-precision NaN to
// x87 long double). // x87 long double).
if (APInt::tcLSB(significandParts(), newPartCount) < ushift) if (APInt::tcLSB(significandParts(), newPartCount) < ushift)
fs = opInexact; *losesInfo = true;
if (oldSemantics == &APFloat::x87DoubleExtended && if (oldSemantics == &APFloat::x87DoubleExtended &&
(!(*significandParts() & 0x8000000000000000ULL) || (!(*significandParts() & 0x8000000000000000ULL) ||
!(*significandParts() & 0x4000000000000000ULL))) !(*significandParts() & 0x4000000000000000ULL)))
fs = opInexact; *losesInfo = true;
APInt::tcShiftRight(significandParts(), newPartCount, ushift); APInt::tcShiftRight(significandParts(), newPartCount, ushift);
} }
// gcc forces the Quiet bit on, which means (float)(double)(float_sNan) // gcc forces the Quiet bit on, which means (float)(double)(float_sNan)
// does not give you back the same bits. This is dubious, and we // does not give you back the same bits. This is dubious, and we
// don't currently do it. You're really supposed to get // don't currently do it. You're really supposed to get
// an invalid operation signal at runtime, but nobody does that. // an invalid operation signal at runtime, but nobody does that.
fs = opOK;
} else { } else {
semantics = &toSemantics; semantics = &toSemantics;
fs = opOK; fs = opOK;
*losesInfo = false;
} }
return fs; return fs;
@ -1768,7 +1780,8 @@ APFloat::convert(const fltSemantics &toSemantics,
APFloat::opStatus APFloat::opStatus
APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width, APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width,
bool isSigned, bool isSigned,
roundingMode rounding_mode) const roundingMode rounding_mode,
bool *isExact) const
{ {
lostFraction lost_fraction; lostFraction lost_fraction;
const integerPart *src; const integerPart *src;
@ -1776,6 +1789,8 @@ APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width,
assertArithmeticOK(*semantics); assertArithmeticOK(*semantics);
*isExact = false;
/* Handle the three special cases first. */ /* Handle the three special cases first. */
if(category == fcInfinity || category == fcNaN) if(category == fcInfinity || category == fcNaN)
return opInvalidOp; return opInvalidOp;
@ -1785,7 +1800,8 @@ APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width,
if(category == fcZero) { if(category == fcZero) {
APInt::tcSet(parts, 0, dstPartsCount); APInt::tcSet(parts, 0, dstPartsCount);
// Negative zero can't be represented as an int. // Negative zero can't be represented as an int.
return sign ? opInexact : opOK; *isExact = !sign;
return opOK;
} }
src = significandParts(); src = significandParts();
@ -1857,24 +1873,31 @@ APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width,
return opInvalidOp; return opInvalidOp;
} }
if (lost_fraction == lfExactlyZero) if (lost_fraction == lfExactlyZero) {
*isExact = true;
return opOK; return opOK;
else } else
return opInexact; return opInexact;
} }
/* Same as convertToSignExtendedInteger, except we provide /* Same as convertToSignExtendedInteger, except we provide
deterministic values in case of an invalid operation exception, deterministic values in case of an invalid operation exception,
namely zero for NaNs and the minimal or maximal value respectively namely zero for NaNs and the minimal or maximal value respectively
for underflow or overflow. */ for underflow or overflow.
The *isExact output tells whether the result is exact, in the sense
that converting it back to the original floating point type produces
the original value. This is almost equivalent to result==opOK,
except for negative zeroes.
*/
APFloat::opStatus APFloat::opStatus
APFloat::convertToInteger(integerPart *parts, unsigned int width, APFloat::convertToInteger(integerPart *parts, unsigned int width,
bool isSigned, bool isSigned,
roundingMode rounding_mode) const roundingMode rounding_mode, bool *isExact) const
{ {
opStatus fs; opStatus fs;
fs = convertToSignExtendedInteger(parts, width, isSigned, rounding_mode); fs = convertToSignExtendedInteger(parts, width, isSigned, rounding_mode,
isExact);
if (fs == opInvalidOp) { if (fs == opInvalidOp) {
unsigned int bits, dstPartsCount; unsigned int bits, dstPartsCount;

View File

@ -832,12 +832,13 @@ void CWriter::printConstantVector(ConstantVector *CP, bool Static) {
// only deal in IEEE FP). // only deal in IEEE FP).
// //
static bool isFPCSafeToPrint(const ConstantFP *CFP) { static bool isFPCSafeToPrint(const ConstantFP *CFP) {
bool ignored;
// Do long doubles in hex for now. // Do long doubles in hex for now.
if (CFP->getType()!=Type::FloatTy && CFP->getType()!=Type::DoubleTy) if (CFP->getType()!=Type::FloatTy && CFP->getType()!=Type::DoubleTy)
return false; return false;
APFloat APF = APFloat(CFP->getValueAPF()); // copy APFloat APF = APFloat(CFP->getValueAPF()); // copy
if (CFP->getType()==Type::FloatTy) if (CFP->getType()==Type::FloatTy)
APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven); APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored);
#if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A #if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A
char Buffer[100]; char Buffer[100];
sprintf(Buffer, "%a", APF.convertToDouble()); sprintf(Buffer, "%a", APF.convertToDouble());

View File

@ -218,9 +218,10 @@ namespace {
// This makes sure that conversion to/from floating yields the same binary // This makes sure that conversion to/from floating yields the same binary
// result so that we don't lose precision. // result so that we don't lose precision.
void CppWriter::printCFP(const ConstantFP *CFP) { void CppWriter::printCFP(const ConstantFP *CFP) {
bool ignored;
APFloat APF = APFloat(CFP->getValueAPF()); // copy APFloat APF = APFloat(CFP->getValueAPF()); // copy
if (CFP->getType() == Type::FloatTy) if (CFP->getType() == Type::FloatTy)
APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven); APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored);
Out << "ConstantFP::get("; Out << "ConstantFP::get(";
Out << "APFloat("; Out << "APFloat(";
#if HAVE_PRINTF_A #if HAVE_PRINTF_A

View File

@ -482,13 +482,16 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::UNDEF, MVT::f80, Expand); setOperationAction(ISD::UNDEF, MVT::f80, Expand);
setOperationAction(ISD::FCOPYSIGN, MVT::f80, Expand); setOperationAction(ISD::FCOPYSIGN, MVT::f80, Expand);
{ {
bool ignored;
APFloat TmpFlt(+0.0); APFloat TmpFlt(+0.0);
TmpFlt.convert(APFloat::x87DoubleExtended, APFloat::rmNearestTiesToEven); TmpFlt.convert(APFloat::x87DoubleExtended, APFloat::rmNearestTiesToEven,
&ignored);
addLegalFPImmediate(TmpFlt); // FLD0 addLegalFPImmediate(TmpFlt); // FLD0
TmpFlt.changeSign(); TmpFlt.changeSign();
addLegalFPImmediate(TmpFlt); // FLD0/FCHS addLegalFPImmediate(TmpFlt); // FLD0/FCHS
APFloat TmpFlt2(+1.0); APFloat TmpFlt2(+1.0);
TmpFlt2.convert(APFloat::x87DoubleExtended, APFloat::rmNearestTiesToEven); TmpFlt2.convert(APFloat::x87DoubleExtended, APFloat::rmNearestTiesToEven,
&ignored);
addLegalFPImmediate(TmpFlt2); // FLD1 addLegalFPImmediate(TmpFlt2); // FLD1
TmpFlt2.changeSign(); TmpFlt2.changeSign();
addLegalFPImmediate(TmpFlt2); // FLD1/FCHS addLegalFPImmediate(TmpFlt2); // FLD1/FCHS

View File

@ -7856,8 +7856,10 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) {
/// FitsInFPType - Return a Constant* for the specified FP constant if it fits /// FitsInFPType - Return a Constant* for the specified FP constant if it fits
/// in the specified FP type without changing its value. /// in the specified FP type without changing its value.
static Constant *FitsInFPType(ConstantFP *CFP, const fltSemantics &Sem) { static Constant *FitsInFPType(ConstantFP *CFP, const fltSemantics &Sem) {
bool losesInfo;
APFloat F = CFP->getValueAPF(); APFloat F = CFP->getValueAPF();
if (F.convert(Sem, APFloat::rmNearestTiesToEven) == APFloat::opOK) (void)F.convert(Sem, APFloat::rmNearestTiesToEven, &losesInfo);
if (!losesInfo)
return ConstantFP::get(F); return ConstantFP::get(F);
return 0; return 0;
} }

View File

@ -213,13 +213,14 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, const Constant *V,
case Instruction::FPTrunc: case Instruction::FPTrunc:
case Instruction::FPExt: case Instruction::FPExt:
if (const ConstantFP *FPC = dyn_cast<ConstantFP>(V)) { if (const ConstantFP *FPC = dyn_cast<ConstantFP>(V)) {
bool ignored;
APFloat Val = FPC->getValueAPF(); APFloat Val = FPC->getValueAPF();
Val.convert(DestTy == Type::FloatTy ? APFloat::IEEEsingle : Val.convert(DestTy == Type::FloatTy ? APFloat::IEEEsingle :
DestTy == Type::DoubleTy ? APFloat::IEEEdouble : DestTy == Type::DoubleTy ? APFloat::IEEEdouble :
DestTy == Type::X86_FP80Ty ? APFloat::x87DoubleExtended : DestTy == Type::X86_FP80Ty ? APFloat::x87DoubleExtended :
DestTy == Type::FP128Ty ? APFloat::IEEEquad : DestTy == Type::FP128Ty ? APFloat::IEEEquad :
APFloat::Bogus, APFloat::Bogus,
APFloat::rmNearestTiesToEven); APFloat::rmNearestTiesToEven, &ignored);
return ConstantFP::get(Val); return ConstantFP::get(Val);
} }
return 0; // Can't fold. return 0; // Can't fold.
@ -227,10 +228,11 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, const Constant *V,
case Instruction::FPToSI: case Instruction::FPToSI:
if (const ConstantFP *FPC = dyn_cast<ConstantFP>(V)) { if (const ConstantFP *FPC = dyn_cast<ConstantFP>(V)) {
const APFloat &V = FPC->getValueAPF(); const APFloat &V = FPC->getValueAPF();
bool ignored;
uint64_t x[2]; uint64_t x[2];
uint32_t DestBitWidth = cast<IntegerType>(DestTy)->getBitWidth(); uint32_t DestBitWidth = cast<IntegerType>(DestTy)->getBitWidth();
(void) V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI, (void) V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI,
APFloat::rmTowardZero); APFloat::rmTowardZero, &ignored);
APInt Val(DestBitWidth, 2, x); APInt Val(DestBitWidth, 2, x);
return ConstantInt::get(Val); return ConstantInt::get(Val);
} }

View File

@ -373,7 +373,8 @@ ConstantFP *ConstantFP::get(const APFloat &V) {
/// 2.0/1.0 etc, that are known-valid both as double and as the target format. /// 2.0/1.0 etc, that are known-valid both as double and as the target format.
ConstantFP *ConstantFP::get(const Type *Ty, double V) { ConstantFP *ConstantFP::get(const Type *Ty, double V) {
APFloat FV(V); APFloat FV(V);
FV.convert(*TypeToFloatSemantics(Ty), APFloat::rmNearestTiesToEven); bool ignored;
FV.convert(*TypeToFloatSemantics(Ty), APFloat::rmNearestTiesToEven, &ignored);
return get(FV); return get(FV);
} }
@ -955,20 +956,25 @@ bool ConstantInt::isValueValidForType(const Type *Ty, int64_t Val) {
bool ConstantFP::isValueValidForType(const Type *Ty, const APFloat& Val) { bool ConstantFP::isValueValidForType(const Type *Ty, const APFloat& Val) {
// convert modifies in place, so make a copy. // convert modifies in place, so make a copy.
APFloat Val2 = APFloat(Val); APFloat Val2 = APFloat(Val);
bool losesInfo;
switch (Ty->getTypeID()) { switch (Ty->getTypeID()) {
default: default:
return false; // These can't be represented as floating point! return false; // These can't be represented as floating point!
// FIXME rounding mode needs to be more flexible // FIXME rounding mode needs to be more flexible
case Type::FloatTyID: case Type::FloatTyID: {
return &Val2.getSemantics() == &APFloat::IEEEsingle || if (&Val2.getSemantics() == &APFloat::IEEEsingle)
Val2.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven) == return true;
APFloat::opOK; Val2.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &losesInfo);
case Type::DoubleTyID: return !losesInfo;
return &Val2.getSemantics() == &APFloat::IEEEsingle || }
&Val2.getSemantics() == &APFloat::IEEEdouble || case Type::DoubleTyID: {
Val2.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven) == if (&Val2.getSemantics() == &APFloat::IEEEsingle ||
APFloat::opOK; &Val2.getSemantics() == &APFloat::IEEEdouble)
return true;
Val2.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &losesInfo);
return !losesInfo;
}
case Type::X86_FP80TyID: case Type::X86_FP80TyID:
return &Val2.getSemantics() == &APFloat::IEEEsingle || return &Val2.getSemantics() == &APFloat::IEEEsingle ||
&Val2.getSemantics() == &APFloat::IEEEdouble || &Val2.getSemantics() == &APFloat::IEEEdouble ||

View File

@ -302,7 +302,9 @@ static const fltSemantics &SemanticsForType(Type *Ty) {
LLVMValueRef LLVMConstReal(LLVMTypeRef RealTy, double N) { LLVMValueRef LLVMConstReal(LLVMTypeRef RealTy, double N) {
APFloat APN(N); APFloat APN(N);
APN.convert(SemanticsForType(unwrap(RealTy)), APFloat::rmNearestTiesToEven); bool ignored;
APN.convert(SemanticsForType(unwrap(RealTy)), APFloat::rmNearestTiesToEven,
&ignored);
return wrap(ConstantFP::get(APN)); return wrap(ConstantFP::get(APN));
} }