It is pointless to turn a UINT_TO_FP into an
[oota-llvm.git] / lib / CodeGen / SelectionDAG / LegalizeIntegerTypes.cpp
index 2d7b30d139acc81fb00a4525aba068f62f0c835c..699ba604e6a392c86d1c04d8f5a1207786c8495d 100644 (file)
@@ -60,7 +60,6 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
   case ISD::SIGN_EXTEND:
   case ISD::ZERO_EXTEND:
   case ISD::ANY_EXTEND:  Result = PromoteIntRes_INT_EXTEND(N); break;
-  case ISD::FP_ROUND:    Result = PromoteIntRes_FP_ROUND(N); break;
   case ISD::FP_TO_SINT:
   case ISD::FP_TO_UINT:  Result = PromoteIntRes_FP_TO_XINT(N); break;
   case ISD::SETCC:    Result = PromoteIntRes_SETCC(N); break;
@@ -169,15 +168,6 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_INT_EXTEND(SDNode *N) {
   return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0));
 }
 
-SDOperand DAGTypeLegalizer::PromoteIntRes_FP_ROUND(SDNode *N) {
-  // NOTE: Assumes input is legal.
-  if (N->getConstantOperandVal(1) == 0)
-    return DAG.getNode(ISD::FP_ROUND_INREG, N->getOperand(0).getValueType(),
-                       N->getOperand(0), DAG.getValueType(N->getValueType(0)));
-  // If the precision discard isn't needed, just return the operand unrounded.
-  return N->getOperand(0);
-}
-
 SDOperand DAGTypeLegalizer::PromoteIntRes_FP_TO_XINT(SDNode *N) {
   unsigned NewOpc = N->getOpcode();
   MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
@@ -251,11 +241,11 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_BIT_CONVERT(SDNode *N) {
   case ExpandInteger:
   case ExpandFloat:
     break;
-  case Scalarize:
+  case ScalarizeVector:
     // Convert the element to an integer and promote it by hand.
     return DAG.getNode(ISD::ANY_EXTEND, OutVT,
                        BitConvertToInteger(GetScalarizedVector(InOp)));
-  case Split:
+  case SplitVector:
     // For example, i32 = BIT_CONVERT v2i16 on alpha.  Convert the split
     // pieces of the input into integers and reassemble in the final type.
     SDOperand Lo, Hi;
@@ -373,9 +363,9 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_CTTZ(SDNode *N) {
   // The count is the same in the promoted type except if the original
   // value was zero.  This can be handled by setting the bit just off
   // the top of the original type.
-  Op = DAG.getNode(ISD::OR, NVT, Op,
-                   // FIXME: Do this using an APINT constant.
-                   DAG.getConstant(1UL << OVT.getSizeInBits(), NVT));
+  APInt TopBit(NVT.getSizeInBits(), 0);
+  TopBit.set(OVT.getSizeInBits());
+  Op = DAG.getNode(ISD::OR, NVT, Op, DAG.getConstant(TopBit, NVT));
   return DAG.getNode(ISD::CTTZ, NVT, Op);
 }
 
@@ -454,6 +444,7 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_VAARG(SDNode *N) {
   return Tmp;
 }
 
+
 //===----------------------------------------------------------------------===//
 //  Integer Operand Promotion
 //===----------------------------------------------------------------------===//
@@ -1005,7 +996,17 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_SINT(SDNode *N, SDOperand &Lo,
   MVT VT = N->getValueType(0);
   SDOperand Op = N->getOperand(0);
   RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
-  if (VT == MVT::i64) {
+
+  if (VT == MVT::i32) {
+    if (Op.getValueType() == MVT::f32)
+      LC = RTLIB::FPTOSINT_F32_I32;
+    else if (Op.getValueType() == MVT::f64)
+      LC = RTLIB::FPTOSINT_F64_I32;
+    else if (Op.getValueType() == MVT::f80)
+      LC = RTLIB::FPTOSINT_F80_I32;
+    else if (Op.getValueType() == MVT::ppcf128)
+      LC = RTLIB::FPTOSINT_PPCF128_I32;
+  } else if (VT == MVT::i64) {
     if (Op.getValueType() == MVT::f32)
       LC = RTLIB::FPTOSINT_F32_I64;
     else if (Op.getValueType() == MVT::f64)
@@ -1023,9 +1024,8 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_SINT(SDNode *N, SDOperand &Lo,
       LC = RTLIB::FPTOSINT_F80_I128;
     else if (Op.getValueType() == MVT::ppcf128)
       LC = RTLIB::FPTOSINT_PPCF128_I128;
-  } else {
-    assert(0 && "Unexpected fp-to-sint conversion!");
   }
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-sint conversion!");
   SplitInteger(MakeLibCall(LC, VT, &Op, 1, true/*sign irrelevant*/), Lo, Hi);
 }
 
@@ -1034,7 +1034,16 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_UINT(SDNode *N, SDOperand &Lo,
   MVT VT = N->getValueType(0);
   SDOperand Op = N->getOperand(0);
   RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
-  if (VT == MVT::i64) {
+  if (VT == MVT::i32) {
+    if (Op.getValueType() == MVT::f32)
+      LC = RTLIB::FPTOUINT_F32_I32;
+    else if (Op.getValueType() == MVT::f64)
+      LC = RTLIB::FPTOUINT_F64_I32;
+    else if (Op.getValueType() == MVT::f80)
+      LC = RTLIB::FPTOUINT_F80_I32;
+    else if (Op.getValueType() == MVT::ppcf128)
+      LC = RTLIB::FPTOUINT_PPCF128_I32;
+  } else if (VT == MVT::i64) {
     if (Op.getValueType() == MVT::f32)
       LC = RTLIB::FPTOUINT_F32_I64;
     else if (Op.getValueType() == MVT::f64)
@@ -1052,9 +1061,8 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_UINT(SDNode *N, SDOperand &Lo,
       LC = RTLIB::FPTOUINT_F80_I128;
     else if (Op.getValueType() == MVT::ppcf128)
       LC = RTLIB::FPTOUINT_PPCF128_I128;
-  } else {
-    assert(0 && "Unexpected fp-to-uint conversion!");
   }
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-uint conversion!");
   SplitInteger(MakeLibCall(LC, VT, &Op, 1, false/*sign irrelevant*/), Lo, Hi);
 }
 
@@ -1069,8 +1077,8 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N,
 
   MVT VT = N->getValueType(0);
   MVT NVT = TLI.getTypeToTransformTo(VT);
-  SDOperand Ch  = N->getChain();    // Legalize the chain.
-  SDOperand Ptr = N->getBasePtr();  // Legalize the pointer.
+  SDOperand Ch  = N->getChain();
+  SDOperand Ptr = N->getBasePtr();
   ISD::LoadExtType ExtType = N->getExtensionType();
   int SVOffset = N->getSrcValueOffset();
   unsigned Alignment = N->getAlignment();
@@ -1322,14 +1330,14 @@ void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N,
   }
 
   // If nothing else, we can make a libcall.
-  RTLIB::Libcall LC;
-  switch (VT.getSimpleVT()) {
-  default:
-    assert(false && "Unsupported MUL!");
-  case MVT::i64:
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+  if (VT == MVT::i32)
+    LC = RTLIB::MUL_I32;
+  else if (VT == MVT::i64)
     LC = RTLIB::MUL_I64;
-    break;
-  }
+  else if (VT == MVT::i128)
+    LC = RTLIB::MUL_I128;
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported MUL!");
 
   SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
   SplitInteger(MakeLibCall(LC, VT, Ops, 2, true/*sign irrelevant*/), Lo, Hi);
@@ -1337,34 +1345,70 @@ void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N,
 
 void DAGTypeLegalizer::ExpandIntRes_SDIV(SDNode *N,
                                          SDOperand &Lo, SDOperand &Hi) {
-  assert(N->getValueType(0) == MVT::i64 && "Unsupported sdiv!");
+  MVT VT = N->getValueType(0);
+
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+  if (VT == MVT::i32)
+    LC = RTLIB::SDIV_I32;
+  else if (VT == MVT::i64)
+    LC = RTLIB::SDIV_I64;
+  else if (VT == MVT::i128)
+    LC = RTLIB::SDIV_I128;
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SDIV!");
+
   SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
-  SplitInteger(MakeLibCall(RTLIB::SDIV_I64, N->getValueType(0), Ops, 2, true),
-               Lo, Hi);
+  SplitInteger(MakeLibCall(LC, VT, Ops, 2, true), Lo, Hi);
 }
 
 void DAGTypeLegalizer::ExpandIntRes_SREM(SDNode *N,
                                          SDOperand &Lo, SDOperand &Hi) {
-  assert(N->getValueType(0) == MVT::i64 && "Unsupported srem!");
+  MVT VT = N->getValueType(0);
+
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+  if (VT == MVT::i32)
+    LC = RTLIB::SREM_I32;
+  else if (VT == MVT::i64)
+    LC = RTLIB::SREM_I64;
+  else if (VT == MVT::i128)
+    LC = RTLIB::SREM_I128;
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SREM!");
+
   SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
-  SplitInteger(MakeLibCall(RTLIB::SREM_I64, N->getValueType(0), Ops, 2, true),
-               Lo, Hi);
+  SplitInteger(MakeLibCall(LC, VT, Ops, 2, true), Lo, Hi);
 }
 
 void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N,
                                          SDOperand &Lo, SDOperand &Hi) {
-  assert(N->getValueType(0) == MVT::i64 && "Unsupported udiv!");
+  MVT VT = N->getValueType(0);
+
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+  if (VT == MVT::i32)
+    LC = RTLIB::UDIV_I32;
+  else if (VT == MVT::i64)
+    LC = RTLIB::UDIV_I64;
+  else if (VT == MVT::i128)
+    LC = RTLIB::UDIV_I128;
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported UDIV!");
+
   SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
-  SplitInteger(MakeLibCall(RTLIB::UDIV_I64, N->getValueType(0), Ops, 2, false),
-               Lo, Hi);
+  SplitInteger(MakeLibCall(LC, VT, Ops, 2, false), Lo, Hi);
 }
 
 void DAGTypeLegalizer::ExpandIntRes_UREM(SDNode *N,
                                          SDOperand &Lo, SDOperand &Hi) {
-  assert(N->getValueType(0) == MVT::i64 && "Unsupported urem!");
+  MVT VT = N->getValueType(0);
+
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+  if (VT == MVT::i32)
+    LC = RTLIB::UREM_I32;
+  else if (VT == MVT::i64)
+    LC = RTLIB::UREM_I64;
+  else if (VT == MVT::i128)
+    LC = RTLIB::UREM_I128;
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported UREM!");
+
   SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
-  SplitInteger(MakeLibCall(RTLIB::UREM_I64, N->getValueType(0), Ops, 2, false),
-               Lo, Hi);
+  SplitInteger(MakeLibCall(LC, VT, Ops, 2, false), Lo, Hi);
 }
 
 void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N,
@@ -1410,21 +1454,35 @@ void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N,
   }
 
   // Otherwise, emit a libcall.
-  assert(VT == MVT::i64 && "Unsupported shift!");
-
-  RTLIB::Libcall LC;
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
   bool isSigned;
   if (N->getOpcode() == ISD::SHL) {
-    LC = RTLIB::SHL_I64;
     isSigned = false; /*sign irrelevant*/
+    if (VT == MVT::i32)
+      LC = RTLIB::SHL_I32;
+    else if (VT == MVT::i64)
+      LC = RTLIB::SHL_I64;
+    else if (VT == MVT::i128)
+      LC = RTLIB::SHL_I128;
   } else if (N->getOpcode() == ISD::SRL) {
-    LC = RTLIB::SRL_I64;
     isSigned = false;
+    if (VT == MVT::i32)
+      LC = RTLIB::SRL_I32;
+    else if (VT == MVT::i64)
+      LC = RTLIB::SRL_I64;
+    else if (VT == MVT::i128)
+      LC = RTLIB::SRL_I128;
   } else {
     assert(N->getOpcode() == ISD::SRA && "Unknown shift!");
-    LC = RTLIB::SRA_I64;
     isSigned = true;
+    if (VT == MVT::i32)
+      LC = RTLIB::SRA_I32;
+    else if (VT == MVT::i64)
+      LC = RTLIB::SRA_I64;
+    else if (VT == MVT::i128)
+      LC = RTLIB::SRA_I128;
   }
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported shift!");
 
   SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
   SplitInteger(MakeLibCall(LC, VT, Ops, 2, isSigned), Lo, Hi);
@@ -1498,6 +1556,13 @@ void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt,
     } else if (Amt == NVTBits) {
       Lo = DAG.getConstant(0, NVT);
       Hi = InL;
+    } else if (Amt == 1) {
+      // Emit this X << 1 as X+X.
+      SDVTList VTList = DAG.getVTList(NVT, MVT::Flag);
+      SDOperand LoOps[2] = { InL, InL };
+      Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
+      SDOperand HiOps[3] = { InH, InH, Lo.getValue(1) };
+      Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
     } else {
       Lo = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Amt, ShTy));
       Hi = DAG.getNode(ISD::OR, NVT,
@@ -1662,12 +1727,8 @@ bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) {
 
     case ISD::TRUNCATE:        Res = ExpandIntOp_TRUNCATE(N); break;
 
-    case ISD::SINT_TO_FP:
-      Res = ExpandIntOp_SINT_TO_FP(N->getOperand(0), N->getValueType(0));
-      break;
-    case ISD::UINT_TO_FP:
-      Res = ExpandIntOp_UINT_TO_FP(N->getOperand(0), N->getValueType(0));
-      break;
+    case ISD::SINT_TO_FP:      Res = ExpandIntOp_SINT_TO_FP(N); break;
+    case ISD::UINT_TO_FP:      Res = ExpandIntOp_UINT_TO_FP(N); break;
 
     case ISD::BR_CC:     Res = ExpandIntOp_BR_CC(N); break;
     case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break;
@@ -1705,91 +1766,134 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_TRUNCATE(SDNode *N) {
   return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL);
 }
 
-SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDOperand Source,
-                                                     MVT DestTy) {
-  // We know the destination is legal, but that the input needs to be expanded.
-  MVT SourceVT = Source.getValueType();
-
-  // Check to see if the target has a custom way to lower this.  If so, use it.
-  switch (TLI.getOperationAction(ISD::SINT_TO_FP, SourceVT)) {
-  default: assert(0 && "This action not implemented for this operation!");
-  case TargetLowering::Legal:
-  case TargetLowering::Expand:
-    break;   // This case is handled below.
-  case TargetLowering::Custom:
-    SDOperand NV = TLI.LowerOperation(DAG.getNode(ISD::SINT_TO_FP, DestTy,
-                                                  Source), DAG);
-    if (NV.Val) return NV;
-    break;   // The target lowered this.
-  }
+SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDNode *N) {
+  SDOperand Op = N->getOperand(0);
+  MVT SrcVT = Op.getValueType();
+  MVT DstVT = N->getValueType(0);
 
   RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
-  if (SourceVT == MVT::i64) {
-    if (DestTy == MVT::f32)
+  if (SrcVT == MVT::i32) {
+    if (DstVT == MVT::f32)
+      LC = RTLIB::SINTTOFP_I32_F32;
+    else if (DstVT == MVT::f64)
+      LC = RTLIB::SINTTOFP_I32_F64;
+    else if (DstVT == MVT::f80)
+      LC = RTLIB::SINTTOFP_I32_F80;
+    else if (DstVT == MVT::ppcf128)
+      LC = RTLIB::SINTTOFP_I32_PPCF128;
+  } else if (SrcVT == MVT::i64) {
+    if (DstVT == MVT::f32)
       LC = RTLIB::SINTTOFP_I64_F32;
-    else {
-      assert(DestTy == MVT::f64 && "Unknown fp value type!");
+    else if (DstVT == MVT::f64)
       LC = RTLIB::SINTTOFP_I64_F64;
-    }
-  } else if (SourceVT == MVT::i128) {
-    if (DestTy == MVT::f32)
+    else if (DstVT == MVT::f80)
+      LC = RTLIB::SINTTOFP_I64_F80;
+    else if (DstVT == MVT::ppcf128)
+      LC = RTLIB::SINTTOFP_I64_PPCF128;
+  } else if (SrcVT == MVT::i128) {
+    if (DstVT == MVT::f32)
       LC = RTLIB::SINTTOFP_I128_F32;
-    else if (DestTy == MVT::f64)
+    else if (DstVT == MVT::f64)
       LC = RTLIB::SINTTOFP_I128_F64;
-    else if (DestTy == MVT::f80)
+    else if (DstVT == MVT::f80)
       LC = RTLIB::SINTTOFP_I128_F80;
-    else {
-      assert(DestTy == MVT::ppcf128 && "Unknown fp value type!");
+    else if (DstVT == MVT::ppcf128)
       LC = RTLIB::SINTTOFP_I128_PPCF128;
-    }
-  } else {
-    assert(0 && "Unknown int value type!");
   }
-
   assert(LC != RTLIB::UNKNOWN_LIBCALL &&
          "Don't know how to expand this SINT_TO_FP!");
-  return MakeLibCall(LC, DestTy, &Source, 1, true);
-}
 
-SDOperand DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDOperand Source,
-                                                     MVT DestTy) {
-  // We know the destination is legal, but that the input needs to be expanded.
-  assert(getTypeAction(Source.getValueType()) == ExpandInteger &&
-         "This is not an expansion!");
+  return MakeLibCall(LC, DstVT, &Op, 1, true);
+}
 
-  // If this is unsigned, and not supported, first perform the conversion to
-  // signed, then adjust the result if the sign bit is set.
-  SDOperand SignedConv = ExpandIntOp_SINT_TO_FP(Source, DestTy);
+SDOperand DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDNode *N) {
+  SDOperand Op = N->getOperand(0);
+  MVT SrcVT = Op.getValueType();
+  MVT DstVT = N->getValueType(0);
+
+  if (TLI.getOperationAction(ISD::SINT_TO_FP, SrcVT) == TargetLowering::Custom){
+    // Do a signed conversion then adjust the result.
+    SDOperand SignedConv = DAG.getNode(ISD::SINT_TO_FP, DstVT, Op);
+    SignedConv = TLI.LowerOperation(SignedConv, DAG);
+
+    // The result of the signed conversion needs adjusting if the 'sign bit' of
+    // the incoming integer was set.  To handle this, we dynamically test to see
+    // if it is set, and, if so, add a fudge factor.
+
+    const uint64_t F32TwoE32  = 0x4F800000ULL;
+    const uint64_t F32TwoE64  = 0x5F800000ULL;
+    const uint64_t F32TwoE128 = 0x7F800000ULL;
+
+    APInt FF(32, 0);
+    if (SrcVT == MVT::i32)
+      FF = APInt(32, F32TwoE32);
+    else if (SrcVT == MVT::i64)
+      FF = APInt(32, F32TwoE64);
+    else if (SrcVT == MVT::i128)
+      FF = APInt(32, F32TwoE128);
+    else
+      assert(false && "Unsupported UINT_TO_FP!");
+
+    // Check whether the sign bit is set.
+    SDOperand Lo, Hi;
+    GetExpandedInteger(Op, Lo, Hi);
+    SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi,
+                                     DAG.getConstant(0, Hi.getValueType()),
+                                     ISD::SETLT);
+
+    // Build a 64 bit pair (0, FF) in the constant pool, with FF in the lo bits.
+    SDOperand FudgePtr = DAG.getConstantPool(ConstantInt::get(FF.zext(64)),
+                                             TLI.getPointerTy());
+
+    // Get a pointer to FF if the sign bit was set, or to 0 otherwise.
+    SDOperand Zero = DAG.getIntPtrConstant(0);
+    SDOperand Four = DAG.getIntPtrConstant(4);
+    if (TLI.isBigEndian()) std::swap(Zero, Four);
+    SDOperand Offset = DAG.getNode(ISD::SELECT, Zero.getValueType(), SignSet,
+                                   Zero, Four);
+    FudgePtr = DAG.getNode(ISD::ADD, TLI.getPointerTy(), FudgePtr, Offset);
+
+    // Load the value out, extending it from f32 to the destination float type.
+    // FIXME: Avoid the extend by constructing the right constant pool?
+    SDOperand Fudge = DAG.getExtLoad(ISD::EXTLOAD, DstVT, DAG.getEntryNode(),
+                                     FudgePtr, NULL, 0, MVT::f32);
+    return DAG.getNode(ISD::FADD, DstVT, SignedConv, Fudge);
+  }
 
-  // The 64-bit value loaded will be incorrectly if the 'sign bit' of the
-  // incoming integer is set.  To handle this, we dynamically test to see if
-  // it is set, and, if so, add a fudge factor.
-  SDOperand Lo, Hi;
-  GetExpandedInteger(Source, Lo, Hi);
-
-  SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi,
-                                   DAG.getConstant(0, Hi.getValueType()),
-                                   ISD::SETLT);
-  SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4);
-  SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
-                                    SignSet, Four, Zero);
-  uint64_t FF = 0x5f800000ULL;
-  if (TLI.isLittleEndian()) FF <<= 32;
-  Constant *FudgeFactor = ConstantInt::get((Type*)Type::Int64Ty, FF);
-
-  SDOperand CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy());
-  CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset);
-  SDOperand FudgeInReg;
-  if (DestTy == MVT::f32)
-    FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0);
-  else if (DestTy.bitsGT(MVT::f32))
-    // FIXME: Avoid the extend by construction the right constantpool?
-    FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(),
-                                CPIdx, NULL, 0, MVT::f32);
-  else
-    assert(0 && "Unexpected conversion");
+  // Otherwise, use a libcall.
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+  if (SrcVT == MVT::i32) {
+    if (DstVT == MVT::f32)
+      LC = RTLIB::UINTTOFP_I32_F32;
+    else if (DstVT == MVT::f64)
+      LC = RTLIB::UINTTOFP_I32_F64;
+    else if (DstVT == MVT::f80)
+      LC = RTLIB::UINTTOFP_I32_F80;
+    else if (DstVT == MVT::ppcf128)
+      LC = RTLIB::UINTTOFP_I32_PPCF128;
+  } else if (SrcVT == MVT::i64) {
+    if (DstVT == MVT::f32)
+      LC = RTLIB::UINTTOFP_I64_F32;
+    else if (DstVT == MVT::f64)
+      LC = RTLIB::UINTTOFP_I64_F64;
+    else if (DstVT == MVT::f80)
+      LC = RTLIB::UINTTOFP_I64_F80;
+    else if (DstVT == MVT::ppcf128)
+      LC = RTLIB::UINTTOFP_I64_PPCF128;
+  } else if (SrcVT == MVT::i128) {
+    if (DstVT == MVT::f32)
+      LC = RTLIB::UINTTOFP_I128_F32;
+    else if (DstVT == MVT::f64)
+      LC = RTLIB::UINTTOFP_I128_F64;
+    else if (DstVT == MVT::f80)
+      LC = RTLIB::UINTTOFP_I128_F80;
+    else if (DstVT == MVT::ppcf128)
+      LC = RTLIB::UINTTOFP_I128_PPCF128;
+  }
+  assert(LC != RTLIB::UNKNOWN_LIBCALL &&
+         "Don't know how to expand this UINT_TO_FP!");
 
-  return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg);
+  return MakeLibCall(LC, DstVT, &Op, 1, true);
 }
 
 SDOperand DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) {