Add a "loses information" return value to APFloat::convert
authorDale Johannesen <dalej@apple.com>
Thu, 9 Oct 2008 23:00:39 +0000 (23:00 +0000)
committerDale Johannesen <dalej@apple.com>
Thu, 9 Oct 2008 23:00:39 +0000 (23:00 +0000)
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

15 files changed:
include/llvm/ADT/APFloat.h
include/llvm/CodeGen/SelectionDAGNodes.h
lib/AsmParser/llvmAsmParser.y
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/CodeGen/SelectionDAG/FastISel.cpp
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
lib/ExecutionEngine/ExecutionEngine.cpp
lib/Support/APFloat.cpp
lib/Target/CBackend/CBackend.cpp
lib/Target/CppBackend/CPPBackend.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Transforms/Scalar/InstructionCombining.cpp
lib/VMCore/ConstantFold.cpp
lib/VMCore/Constants.cpp
lib/VMCore/Core.cpp

index 8566a5783903e051541d28c04c5526bca463e5ba..f6456a004634eb3cf0bc9ab2eb724536bb3f977b 100644 (file)
@@ -216,9 +216,9 @@ namespace llvm {
     void copySign(const APFloat &);
 
     /* Conversions.  */
-    opStatus convert(const fltSemantics &, roundingMode);
+    opStatus convert(const fltSemantics &, roundingMode, bool *);
     opStatus convertToInteger(integerPart *, unsigned int, bool,
-                              roundingMode) const;
+                              roundingMode, bool *) const;
     opStatus convertFromAPInt(const APInt &,
                               bool, roundingMode);
     opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int,
@@ -299,7 +299,7 @@ namespace llvm {
     opStatus handleOverflow(roundingMode);
     bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const;
     opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool,
-                                          roundingMode) const;
+                                          roundingMode, bool *) const;
     opStatus convertFromUnsignedParts(const integerPart *, unsigned int,
                                       roundingMode);
     opStatus convertFromHexadecimalString(const char *, roundingMode);
index 8ab6152905741595d717ba3e6d6a25dd371bd781..e1d1eda2a7c4abe193be5d1a81ab07a74fa0657e 100644 (file)
@@ -1756,12 +1756,13 @@ public:
   /// convenient to write "2.0" and the like.  Without this function we'd 
   /// have to duplicate its logic everywhere it's called.
   bool isExactlyValue(double V) const {
+    bool ignored;
     // convert is not supported on this type
     if (&Value->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble)
       return false;
     APFloat Tmp(V);
     Tmp.convert(Value->getValueAPF().getSemantics(),
-                APFloat::rmNearestTiesToEven);
+                APFloat::rmNearestTiesToEven, &ignored);
     return isExactlyValue(Tmp);
   }
   bool isExactlyValue(const APFloat& V) const;
index 9dc070230d81da97880d01007266518b1c7ab699..a7a4bc00ef875dba2c9cb1f6bd0e342240d7c0dd 100644 (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
     // 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);
+        Ty==Type::FloatTy) {
+      bool ignored;
+      D.ConstPoolFP->convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven,
+                             &ignored);
+    }
     return ConstantFP::get(*D.ConstPoolFP);
 
   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");
     // 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);
+    if (&$2->getSemantics()==&APFloat::IEEEdouble && $1==Type::FloatTy) {
+      bool ignored;
+      $2->convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven,
+                  &ignored);
+    }
     $$ = ConstantFP::get(*$2);
     delete $2;
     CHECK_FOR_ERROR
index 1321c040d11b577039666c9c1aa2422ba61017ec..63ada0c81b2b5a58fd0e10a18215384f51c196f4 100644 (file)
@@ -1000,8 +1000,11 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
       // api needed to prevent premature destruction
       APInt api = CFP->getValueAPF().bitcastToAPInt();
       const uint64_t *p = api.getRawData();
+      // Convert to double so we can print the approximate val as a comment.
       APFloat DoubleVal = CFP->getValueAPF();
-      DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven);
+      bool ignored;
+      DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
+                        &ignored);
       if (TD->isBigEndian()) {
         O << TAI->getData16bitsDirective() << uint16_t(p[0] >> 48)
           << '\t' << TAI->getCommentString()
index f9cfeb1e972f6992bdbeb92f96edc5c44d4dedcf..77e9bda46f4ef580808346056b64c6949898da5e 100644 (file)
@@ -93,8 +93,10 @@ unsigned FastISel::getRegForValue(Value *V) {
 
       uint64_t x[2];
       uint32_t IntBitWidth = IntVT.getSizeInBits();
-      if (!Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true,
-                                APFloat::rmTowardZero) != APFloat::opOK) {
+      bool isExact;
+      (void) Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true,
+                                APFloat::rmTowardZero, &isExact);
+      if (isExact) {
         APInt IntVal(IntBitWidth, 2, x);
 
         unsigned IntegerReg = getRegForValue(ConstantInt::get(IntVal));
@@ -711,8 +713,10 @@ unsigned FastISel::FastEmit_rf_(MVT::SimpleValueType VT, ISD::NodeType Opcode,
 
     uint64_t x[2];
     uint32_t IntBitWidth = IntVT.getSizeInBits();
-    if (Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true,
-                             APFloat::rmTowardZero) != APFloat::opOK)
+    bool isExact;
+    (void) Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true,
+                             APFloat::rmTowardZero, &isExact);
+    if (!isExact)
       return 0;
     APInt IntVal(IntBitWidth, 2, x);
 
index cacffe41622901e3804c810706aa420ed14a14b5..f75d39293e238cf4516c2e185117564f5168c6d5 100644 (file)
@@ -84,8 +84,10 @@ bool ConstantFPSDNode::isValueValidForType(MVT VT,
   
   // convert modifies in place, so make a copy.
   APFloat Val2 = APFloat(Val);
-  return Val2.convert(*MVTToAPFloatSemantics(VT),
-                      APFloat::rmNearestTiesToEven) == APFloat::opOK;
+  bool losesInfo;
+  (void) Val2.convert(*MVTToAPFloatSemantics(VT), APFloat::rmNearestTiesToEven,
+                      &losesInfo);
+  return !losesInfo;
 }
 
 //===----------------------------------------------------------------------===//
@@ -118,7 +120,7 @@ bool ISD::isBuildVectorAllOnes(const SDNode *N) {
       return false;
   } else if (isa<ConstantFPSDNode>(NotZero)) {
     if (!cast<ConstantFPSDNode>(NotZero)->getValueAPF().
-                convertToAPInt().isAllOnesValue())
+                bitcastToAPInt().isAllOnesValue())
       return false;
   } else
     return false;
@@ -2124,29 +2126,32 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) {
         V.clearSign();
         return getConstantFP(V, VT);
       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.
         // FIXME need to be more flexible about rounding mode.
         (void)V.convert(*MVTToAPFloatSemantics(VT),
-                        APFloat::rmNearestTiesToEven);
+                        APFloat::rmNearestTiesToEven, &ignored);
         return getConstantFP(V, VT);
+      }
       case ISD::FP_TO_SINT:
       case ISD::FP_TO_UINT: {
         integerPart x;
+        bool ignored;
         assert(integerPartWidth >= 64);
         // FIXME need to be more flexible about rounding mode.
         APFloat::opStatus s = V.convertToInteger(&x, 64U,
                               Opcode==ISD::FP_TO_SINT,
-                              APFloat::rmTowardZero);
+                              APFloat::rmTowardZero, &ignored);
         if (s==APFloat::opInvalidOp)     // inexact is OK, in fact usual
           break;
         return getConstant(x, VT);
       }
       case ISD::BIT_CONVERT:
         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)
-          return getConstant(V.convertToAPInt().getZExtValue(), VT);
+          return getConstant(V.bitcastToAPInt().getZExtValue(), VT);
         break;
       }
     }
@@ -5245,7 +5250,7 @@ void SDNode::print(raw_ostream &OS, const SelectionDAG *G) const {
       OS << '<' << CSDN->getValueAPF().convertToDouble() << '>';
     else {
       OS << "<APFloat(";
-      CSDN->getValueAPF().convertToAPInt().dump();
+      CSDN->getValueAPF().bitcastToAPInt().dump();
       OS << ")>";
     }
   } else if (const GlobalAddressSDNode *GADN =
index 0731672f8812e6ca510dec560504eb64011d77af..acc89c9e858307f0838ddda401c7128f230b1d39 100644 (file)
@@ -498,9 +498,10 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
       else if (Op0->getType() == Type::X86_FP80Ty) {
         APFloat apf = APFloat(GV.IntVal);
         uint64_t v;
+        bool ignored;
         (void)apf.convertToInteger(&v, BitWidth,
                                    CE->getOpcode()==Instruction::FPToSI, 
-                                   APFloat::rmTowardZero);
+                                   APFloat::rmTowardZero, &ignored);
         GV.IntVal = v; // endian?
       }
       return GV;
index a8691f495ab46638ffac18e1cbf3e2764558777a..a65e55afb56d4a50eadbcc199e4efd3d5018d7e5 100644 (file)
@@ -788,6 +788,7 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)
   integerPart scratch[4];
   integerPart *fullSignificand;
   lostFraction lost_fraction;
+  bool ignored;
 
   assert(semantics == rhs.semantics);
 
@@ -836,7 +837,7 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)
     semantics = &extendedSemantics;
 
     APFloat extendedAddend(*addend);
-    status = extendedAddend.convert(extendedSemantics, rmTowardZero);
+    status = extendedAddend.convert(extendedSemantics, rmTowardZero, &ignored);
     assert(status == opOK);
     lost_fraction = addOrSubtractSignificand(extendedAddend, false);
 
@@ -1528,8 +1529,9 @@ APFloat::mod(const APFloat &rhs, roundingMode rounding_mode)
 
   int parts = partCount();
   integerPart *x = new integerPart[parts];
+  bool ignored;
   fs = V.convertToInteger(x, parts * integerPartWidth, true,
-                          rmNearestTiesToEven);
+                          rmNearestTiesToEven, &ignored);
   if (fs==opInvalidOp)
     return fs;
 
@@ -1670,9 +1672,16 @@ APFloat::compare(const APFloat &rhs) const
   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::convert(const fltSemantics &toSemantics,
-                 roundingMode rounding_mode)
+                 roundingMode rounding_mode, bool *losesInfo)
 {
   lostFraction lostFraction;
   unsigned int newPartCount, oldPartCount;
@@ -1718,38 +1727,41 @@ APFloat::convert(const fltSemantics &toSemantics,
     exponent += toSemantics.precision - semantics->precision;
     semantics = &toSemantics;
     fs = normalize(rounding_mode, lostFraction);
+    *losesInfo = (fs != opOK);
   } else if (category == fcNaN) {
     int shift = toSemantics.precision - semantics->precision;
     // Do this now so significandParts gets the right answer
     const fltSemantics *oldSemantics = semantics;
     semantics = &toSemantics;
-    fs = opOK;
+    *losesInfo = false;
     // No normalization here, just truncate
     if (shift>0)
       APInt::tcShiftLeft(significandParts(), newPartCount, shift);
     else if (shift < 0) {
       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
       // 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
       // hardware sets this bit when converting a lower-precision NaN to
       // x87 long double).
       if (APInt::tcLSB(significandParts(), newPartCount) < ushift)
-        fs = opInexact;
+        *losesInfo = true;
       if (oldSemantics == &APFloat::x87DoubleExtended && 
           (!(*significandParts() & 0x8000000000000000ULL) ||
            !(*significandParts() & 0x4000000000000000ULL)))
-        fs = opInexact;
+        *losesInfo = true;
       APInt::tcShiftRight(significandParts(), newPartCount, ushift);
     }
     // 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
     // don't currently do it.  You're really supposed to get
     // an invalid operation signal at runtime, but nobody does that.
+    fs = opOK;
   } else {
     semantics = &toSemantics;
     fs = opOK;
+    *losesInfo = false;
   }
 
   return fs;
@@ -1768,7 +1780,8 @@ APFloat::convert(const fltSemantics &toSemantics,
 APFloat::opStatus
 APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width,
                                       bool isSigned,
-                                      roundingMode rounding_mode) const
+                                      roundingMode rounding_mode,
+                                      bool *isExact) const
 {
   lostFraction lost_fraction;
   const integerPart *src;
@@ -1776,6 +1789,8 @@ APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width,
 
   assertArithmeticOK(*semantics);
 
+  *isExact = false;
+
   /* Handle the three special cases first.  */
   if(category == fcInfinity || category == fcNaN)
     return opInvalidOp;
@@ -1785,7 +1800,8 @@ APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width,
   if(category == fcZero) {
     APInt::tcSet(parts, 0, dstPartsCount);
     // Negative zero can't be represented as an int.
-    return sign ? opInexact : opOK;
+    *isExact = !sign;
+    return opOK;
   }
 
   src = significandParts();
@@ -1857,24 +1873,31 @@ APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width,
       return opInvalidOp;
   }
 
-  if (lost_fraction == lfExactlyZero)
+  if (lost_fraction == lfExactlyZero) {
+    *isExact = true;
     return opOK;
-  else
+  else
     return opInexact;
 }
 
 /* Same as convertToSignExtendedInteger, except we provide
    deterministic values in case of an invalid operation exception,
    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::convertToInteger(integerPart *parts, unsigned int width,
                           bool isSigned,
-                          roundingMode rounding_mode) const
+                          roundingMode rounding_mode, bool *isExact) const
 {
   opStatus fs;
 
-  fs = convertToSignExtendedInteger(parts, width, isSigned, rounding_mode);
+  fs = convertToSignExtendedInteger(parts, width, isSigned, rounding_mode, 
+                                    isExact);
 
   if (fs == opInvalidOp) {
     unsigned int bits, dstPartsCount;
index 96ae40c33943c80094d28cf14c43b8f70b8caa54..9a7974808440371fdcebef87b402dce47698017e 100644 (file)
@@ -832,12 +832,13 @@ void CWriter::printConstantVector(ConstantVector *CP, bool Static) {
 // only deal in IEEE FP).
 //
 static bool isFPCSafeToPrint(const ConstantFP *CFP) {
+  bool ignored;
   // Do long doubles in hex for now.
   if (CFP->getType()!=Type::FloatTy && CFP->getType()!=Type::DoubleTy)
     return false;
   APFloat APF = APFloat(CFP->getValueAPF());  // copy
   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
   char Buffer[100];
   sprintf(Buffer, "%a", APF.convertToDouble());
index 21e6735b3298032d35ad8b01f8b44bea7abd0f3d..fb836638e5f4eb13650908a424edebe8d02f3703 100644 (file)
@@ -218,9 +218,10 @@ namespace {
   // This makes sure that conversion to/from floating yields the same binary
   // result so that we don't lose precision.
   void CppWriter::printCFP(const ConstantFP *CFP) {
+    bool ignored;
     APFloat APF = APFloat(CFP->getValueAPF());  // copy
     if (CFP->getType() == Type::FloatTy)
-      APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven);
+      APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored);
     Out << "ConstantFP::get(";
     Out << "APFloat(";
 #if HAVE_PRINTF_A
index d74588e6285ae4998eb6db7a57497e37523b673d..d5b2b44cf1532543034ba5fc72e70f99e2ea0fe6 100644 (file)
@@ -482,13 +482,16 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
   setOperationAction(ISD::UNDEF,     MVT::f80, Expand);
   setOperationAction(ISD::FCOPYSIGN, MVT::f80, Expand);
   {
+    bool ignored;
     APFloat TmpFlt(+0.0);
-    TmpFlt.convert(APFloat::x87DoubleExtended, APFloat::rmNearestTiesToEven);
+    TmpFlt.convert(APFloat::x87DoubleExtended, APFloat::rmNearestTiesToEven,
+                   &ignored);
     addLegalFPImmediate(TmpFlt);  // FLD0
     TmpFlt.changeSign();
     addLegalFPImmediate(TmpFlt);  // FLD0/FCHS
     APFloat TmpFlt2(+1.0);
-    TmpFlt2.convert(APFloat::x87DoubleExtended, APFloat::rmNearestTiesToEven);
+    TmpFlt2.convert(APFloat::x87DoubleExtended, APFloat::rmNearestTiesToEven,
+                    &ignored);
     addLegalFPImmediate(TmpFlt2);  // FLD1
     TmpFlt2.changeSign();
     addLegalFPImmediate(TmpFlt2);  // FLD1/FCHS
index 8cb5e4fe12ec79a2d1552fd099a0ac3d8a87f15c..60da031a377d21b63e3f4d8c2c4fd3f619e992d9 100644 (file)
@@ -7856,8 +7856,10 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) {
 /// FitsInFPType - Return a Constant* for the specified FP constant if it fits
 /// in the specified FP type without changing its value.
 static Constant *FitsInFPType(ConstantFP *CFP, const fltSemantics &Sem) {
+  bool losesInfo;
   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 0;
 }
index 92561096d5dc1440acb9045acb3f26a01d97f191..93ee7fe59aeaa44c9330f3d4549d75f4a7276064 100644 (file)
@@ -213,13 +213,14 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, const Constant *V,
   case Instruction::FPTrunc:
   case Instruction::FPExt:
     if (const ConstantFP *FPC = dyn_cast<ConstantFP>(V)) {
+      bool ignored;
       APFloat Val = FPC->getValueAPF();
       Val.convert(DestTy == Type::FloatTy ? APFloat::IEEEsingle :
                   DestTy == Type::DoubleTy ? APFloat::IEEEdouble :
                   DestTy == Type::X86_FP80Ty ? APFloat::x87DoubleExtended :
                   DestTy == Type::FP128Ty ? APFloat::IEEEquad :
                   APFloat::Bogus,
-                  APFloat::rmNearestTiesToEven);
+                  APFloat::rmNearestTiesToEven, &ignored);
       return ConstantFP::get(Val);
     }
     return 0; // Can't fold.
@@ -227,10 +228,11 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, const Constant *V,
   case Instruction::FPToSI:
     if (const ConstantFP *FPC = dyn_cast<ConstantFP>(V)) {
       const APFloat &V = FPC->getValueAPF();
+      bool ignored;
       uint64_t x[2]; 
       uint32_t DestBitWidth = cast<IntegerType>(DestTy)->getBitWidth();
       (void) V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI,
-                                APFloat::rmTowardZero);
+                                APFloat::rmTowardZero, &ignored);
       APInt Val(DestBitWidth, 2, x);
       return ConstantInt::get(Val);
     }
index 4471cfde34d65995dd8f33d1544ea236b78159db..b0dd16396832fa7f2ca2b73a69684385e4c5235e 100644 (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.
 ConstantFP *ConstantFP::get(const Type *Ty, double V) {
   APFloat FV(V);
-  FV.convert(*TypeToFloatSemantics(Ty), APFloat::rmNearestTiesToEven);
+  bool ignored;
+  FV.convert(*TypeToFloatSemantics(Ty), APFloat::rmNearestTiesToEven, &ignored);
   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) {
   // convert modifies in place, so make a copy.
   APFloat Val2 = APFloat(Val);
+  bool losesInfo;
   switch (Ty->getTypeID()) {
   default:
     return false;         // These can't be represented as floating point!
 
   // FIXME rounding mode needs to be more flexible
-  case Type::FloatTyID:
-    return &Val2.getSemantics() == &APFloat::IEEEsingle ||
-           Val2.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven) == 
-              APFloat::opOK;
-  case Type::DoubleTyID:
-    return &Val2.getSemantics() == &APFloat::IEEEsingle || 
-           &Val2.getSemantics() == &APFloat::IEEEdouble ||
-           Val2.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven) == 
-             APFloat::opOK;
+  case Type::FloatTyID: {
+    if (&Val2.getSemantics() == &APFloat::IEEEsingle)
+      return true;
+    Val2.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &losesInfo);
+    return !losesInfo;
+  }
+  case Type::DoubleTyID: {
+    if (&Val2.getSemantics() == &APFloat::IEEEsingle ||
+        &Val2.getSemantics() == &APFloat::IEEEdouble)
+      return true;
+    Val2.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &losesInfo);
+    return !losesInfo;
+  }
   case Type::X86_FP80TyID:
     return &Val2.getSemantics() == &APFloat::IEEEsingle || 
            &Val2.getSemantics() == &APFloat::IEEEdouble ||
index a802373f82c3a5a65298dd1714829e0cde23b4e2..afc1c905fc02f5bd124fc8ba3e453b4660d00680 100644 (file)
@@ -302,7 +302,9 @@ static const fltSemantics &SemanticsForType(Type *Ty) {
 
 LLVMValueRef LLVMConstReal(LLVMTypeRef RealTy, double 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));
 }