mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-07 14:33:15 +00:00
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:
parent
7111b02c73
commit
23a98551ab
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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 =
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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());
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 ||
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user