It is pointless to turn a UINT_TO_FP into an
[oota-llvm.git] / lib / CodeGen / SelectionDAG / LegalizeIntegerTypes.cpp
index 4b927fec0822959ad4d777142353bc6d34419b5b..699ba604e6a392c86d1c04d8f5a1207786c8495d 100644 (file)
 // computation in a larger type.  For example, implementing i8 arithmetic in an
 // i32 register (often needed on powerpc).
 // Expansion is the act of changing a computation in an illegal type into a
-// computation in multiple registers of a smaller type.  For example,
+// computation in two identical registers of a smaller type.  For example,
 // implementing i64 arithmetic in two i32 registers (often needed on 32-bit
 // targets).
 //
 //===----------------------------------------------------------------------===//
 
 #include "LegalizeTypes.h"
-#include "llvm/Constants.h"
 using namespace llvm;
 
 //===----------------------------------------------------------------------===//
@@ -34,6 +33,18 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
   DEBUG(cerr << "Promote integer result: "; N->dump(&DAG); cerr << "\n");
   SDOperand Result = SDOperand();
 
+  // See if the target wants to custom expand this node.
+  if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) ==
+      TargetLowering::Custom) {
+    // If the target wants to, allow it to lower this itself.
+    if (SDNode *P = TLI.ReplaceNodeResults(N, DAG)) {
+      // Everything that once used N now uses P.  We are guaranteed that the
+      // result value types of N and the result value types of P match.
+      ReplaceNodeWith(N, P);
+      return;
+    }
+  }
+
   switch (N->getOpcode()) {
   default:
 #ifndef NDEBUG
@@ -49,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;
@@ -84,6 +94,8 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
   case ISD::EXTRACT_VECTOR_ELT:
     Result = PromoteIntRes_EXTRACT_VECTOR_ELT(N);
     break;
+
+  case ISD::VAARG : Result = PromoteIntRes_VAARG(N); break;
   }
 
   // If Result is null, the sub-method took care of registering the result.
@@ -156,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));
@@ -192,7 +195,7 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_SETCC(SDNode *N) {
 }
 
 SDOperand DAGTypeLegalizer::PromoteIntRes_LOAD(LoadSDNode *N) {
-  // FIXME: Add support for indexed loads.
+  assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!");
   MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
   ISD::LoadExtType ExtType =
     ISD::isNON_EXTLoad(N) ? ISD::EXTLOAD : N->getExtensionType();
@@ -232,17 +235,17 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_BIT_CONVERT(SDNode *N) {
       // The input promotes to the same size.  Convert the promoted value.
       return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedInteger(InOp));
     break;
-  case PromoteFloat:
+  case SoftenFloat:
     // Promote the integer operand by hand.
-    return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetPromotedFloat(InOp));
+    return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetSoftenedFloat(InOp));
   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;
@@ -360,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);
 }
 
@@ -411,6 +414,37 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) {
   return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo);
 }
 
+SDOperand DAGTypeLegalizer::PromoteIntRes_VAARG(SDNode *N) {
+  SDOperand Chain = N->getOperand(0); // Get the chain.
+  SDOperand Ptr = N->getOperand(1); // Get the pointer.
+  MVT VT = N->getValueType(0);
+
+  const Value *V = cast<SrcValueSDNode>(N->getOperand(2))->getValue();
+  SDOperand VAList = DAG.getLoad(TLI.getPointerTy(), Chain, Ptr, V, 0);
+
+  // Increment the arg pointer, VAList, to the next vaarg
+  // FIXME: should the ABI size be used for the increment?  Think of
+  // x86 long double (10 bytes long, but aligned on 4 or 8 bytes) or
+  // integers of unusual size (such MVT::i1, which gives an increment
+  // of zero here!).
+  unsigned Increment = VT.getSizeInBits() / 8;
+  SDOperand Tmp = DAG.getNode(ISD::ADD, TLI.getPointerTy(), VAList,
+                              DAG.getConstant(Increment, TLI.getPointerTy()));
+
+  // Store the incremented VAList to the pointer.
+  Tmp = DAG.getStore(VAList.getValue(1), Tmp, Ptr, V, 0);
+
+  // Load the actual argument out of the arg pointer VAList.
+  Tmp = DAG.getExtLoad(ISD::EXTLOAD, TLI.getTypeToTransformTo(VT), Tmp,
+                       VAList, NULL, 0, VT);
+
+  // Legalized the chain result - switch anything that used the old chain to
+  // use the new one.
+  ReplaceValueWith(SDOperand(N, 1), Tmp.getValue(1));
+  return Tmp;
+}
+
+
 //===----------------------------------------------------------------------===//
 //  Integer Operand Promotion
 //===----------------------------------------------------------------------===//
@@ -421,40 +455,48 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) {
 /// node may need promotion or expansion as well as the specified one.
 bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) {
   DEBUG(cerr << "Promote integer operand: "; N->dump(&DAG); cerr << "\n");
-  SDOperand Res;
-  switch (N->getOpcode()) {
-    default:
-#ifndef NDEBUG
-    cerr << "PromoteIntegerOperand Op #" << OpNo << ": ";
-    N->dump(&DAG); cerr << "\n";
-#endif
-    assert(0 && "Do not know how to promote this operator's operand!");
-    abort();
+  SDOperand Res = SDOperand();
 
-  case ISD::ANY_EXTEND:  Res = PromoteIntOp_ANY_EXTEND(N); break;
-  case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break;
-  case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break;
-  case ISD::TRUNCATE:    Res = PromoteIntOp_TRUNCATE(N); break;
-  case ISD::FP_EXTEND:   Res = PromoteIntOp_FP_EXTEND(N); break;
-  case ISD::FP_ROUND:    Res = PromoteIntOp_FP_ROUND(N); break;
-  case ISD::SINT_TO_FP:
-  case ISD::UINT_TO_FP:  Res = PromoteIntOp_INT_TO_FP(N); break;
-  case ISD::BUILD_PAIR:  Res = PromoteIntOp_BUILD_PAIR(N); break;
-
-  case ISD::SELECT:      Res = PromoteIntOp_SELECT(N, OpNo); break;
-  case ISD::BRCOND:      Res = PromoteIntOp_BRCOND(N, OpNo); break;
-  case ISD::BR_CC:       Res = PromoteIntOp_BR_CC(N, OpNo); break;
-  case ISD::SETCC:       Res = PromoteIntOp_SETCC(N, OpNo); break;
-
-  case ISD::STORE:       Res = PromoteIntOp_STORE(cast<StoreSDNode>(N),
-                                                    OpNo); break;
-
-  case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break;
-  case ISD::INSERT_VECTOR_ELT:
-    Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo);
-    break;
+  if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
+      == TargetLowering::Custom)
+    Res = TLI.LowerOperation(SDOperand(N, OpNo), DAG);
 
-  case ISD::MEMBARRIER:  Res = PromoteIntOp_MEMBARRIER(N); break;
+  if (Res.Val == 0) {
+    switch (N->getOpcode()) {
+      default:
+  #ifndef NDEBUG
+      cerr << "PromoteIntegerOperand Op #" << OpNo << ": ";
+      N->dump(&DAG); cerr << "\n";
+  #endif
+      assert(0 && "Do not know how to promote this operator's operand!");
+      abort();
+
+    case ISD::ANY_EXTEND:  Res = PromoteIntOp_ANY_EXTEND(N); break;
+    case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break;
+    case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break;
+    case ISD::TRUNCATE:    Res = PromoteIntOp_TRUNCATE(N); break;
+    case ISD::FP_EXTEND:   Res = PromoteIntOp_FP_EXTEND(N); break;
+    case ISD::FP_ROUND:    Res = PromoteIntOp_FP_ROUND(N); break;
+    case ISD::SINT_TO_FP:
+    case ISD::UINT_TO_FP:  Res = PromoteIntOp_INT_TO_FP(N); break;
+    case ISD::BUILD_PAIR:  Res = PromoteIntOp_BUILD_PAIR(N); break;
+
+    case ISD::BRCOND:      Res = PromoteIntOp_BRCOND(N, OpNo); break;
+    case ISD::BR_CC:       Res = PromoteIntOp_BR_CC(N, OpNo); break;
+    case ISD::SELECT:      Res = PromoteIntOp_SELECT(N, OpNo); break;
+    case ISD::SELECT_CC:   Res = PromoteIntOp_SELECT_CC(N, OpNo); break;
+    case ISD::SETCC:       Res = PromoteIntOp_SETCC(N, OpNo); break;
+
+    case ISD::STORE:       Res = PromoteIntOp_STORE(cast<StoreSDNode>(N),
+                                                      OpNo); break;
+
+    case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break;
+    case ISD::INSERT_VECTOR_ELT:
+      Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo);
+      break;
+
+    case ISD::MEMBARRIER:  Res = PromoteIntOp_MEMBARRIER(N); break;
+    }
   }
 
   // If the result is null, the sub-method took care of registering results etc.
@@ -568,7 +610,7 @@ SDOperand DAGTypeLegalizer::PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo) {
 }
 
 SDOperand DAGTypeLegalizer::PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo) {
-  assert(OpNo == 2 && "Don't know how to promote this operand");
+  assert(OpNo == 2 && "Don't know how to promote this operand!");
 
   SDOperand LHS = N->getOperand(2);
   SDOperand RHS = N->getOperand(3);
@@ -580,8 +622,20 @@ SDOperand DAGTypeLegalizer::PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo) {
                                 N->getOperand(1), LHS, RHS, N->getOperand(4));
 }
 
+SDOperand DAGTypeLegalizer::PromoteIntOp_SELECT_CC(SDNode *N, unsigned OpNo) {
+  assert(OpNo == 0 && "Don't know how to promote this operand!");
+
+  SDOperand LHS = N->getOperand(0);
+  SDOperand RHS = N->getOperand(1);
+  PromoteSetCCOperands(LHS, RHS, cast<CondCodeSDNode>(N->getOperand(4))->get());
+
+  // The CC (#4) and the possible return values (#2 and #3) have legal types.
+  return DAG.UpdateNodeOperands(SDOperand(N, 0), LHS, RHS, N->getOperand(2),
+                                N->getOperand(3), N->getOperand(4));
+}
+
 SDOperand DAGTypeLegalizer::PromoteIntOp_SETCC(SDNode *N, unsigned OpNo) {
-  assert(OpNo == 0 && "Don't know how to promote this operand");
+  assert(OpNo == 0 && "Don't know how to promote this operand!");
 
   SDOperand LHS = N->getOperand(0);
   SDOperand RHS = N->getOperand(1);
@@ -601,10 +655,6 @@ void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS,
   NewLHS = GetPromotedInteger(NewLHS);
   NewRHS = GetPromotedInteger(NewRHS);
 
-  // If this is an FP compare, the operands have already been extended.
-  if (!NewLHS.getValueType().isInteger())
-    return;
-
   // Otherwise, we have to insert explicit sign or zero extends.  Note
   // that we could insert sign extends for ALL conditions, but zero extend
   // is cheaper on many machines (an AND instead of two shifts), so prefer
@@ -622,7 +672,7 @@ void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS,
     // usually a simpler/cheaper operation, so prefer it.
     NewLHS = DAG.getZeroExtendInReg(NewLHS, VT);
     NewRHS = DAG.getZeroExtendInReg(NewRHS, VT);
-    return;
+    break;
   case ISD::SETGE:
   case ISD::SETGT:
   case ISD::SETLT:
@@ -631,12 +681,12 @@ void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS,
                          DAG.getValueType(VT));
     NewRHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewRHS.getValueType(), NewRHS,
                          DAG.getValueType(VT));
-    return;
+    break;
   }
 }
 
 SDOperand DAGTypeLegalizer::PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo){
-  // FIXME: Add support for indexed stores.
+  assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!");
   SDOperand Ch = N->getChain(), Ptr = N->getBasePtr();
   int SVOffset = N->getSrcValueOffset();
   unsigned Alignment = N->getAlignment();
@@ -736,10 +786,10 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
   Lo = Hi = SDOperand();
 
   // See if the target wants to custom expand this node.
-  if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
-          TargetLowering::Custom) {
+  if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) ==
+      TargetLowering::Custom) {
     // If the target wants to, allow it to lower this itself.
-    if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) {
+    if (SDNode *P = TLI.ReplaceNodeResults(N, DAG)) {
       // Everything that once used N now uses P.  We are guaranteed that the
       // result value types of N and the result value types of P match.
       ReplaceNodeWith(N, P);
@@ -753,19 +803,25 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
     cerr << "ExpandIntegerResult #" << ResNo << ": ";
     N->dump(&DAG); cerr << "\n";
 #endif
-    assert(0&&"Do not know how to expand the result of this operator!");
+    assert(0 && "Do not know how to expand the result of this operator!");
     abort();
 
-  case ISD::UNDEF:       ExpandIntRes_UNDEF(N, Lo, Hi); break;
+  case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break;
+  case ISD::SELECT:       SplitRes_SELECT(N, Lo, Hi); break;
+  case ISD::SELECT_CC:    SplitRes_SELECT_CC(N, Lo, Hi); break;
+  case ISD::UNDEF:        SplitRes_UNDEF(N, Lo, Hi); break;
+
+  case ISD::BIT_CONVERT:        ExpandRes_BIT_CONVERT(N, Lo, Hi); break;
+  case ISD::BUILD_PAIR:         ExpandRes_BUILD_PAIR(N, Lo, Hi); break;
+  case ISD::EXTRACT_ELEMENT:    ExpandRes_EXTRACT_ELEMENT(N, Lo, Hi); break;
+  case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break;
+
   case ISD::Constant:    ExpandIntRes_Constant(N, Lo, Hi); break;
-  case ISD::BUILD_PAIR:  ExpandIntRes_BUILD_PAIR(N, Lo, Hi); break;
-  case ISD::MERGE_VALUES: ExpandIntRes_MERGE_VALUES(N, Lo, Hi); break;
   case ISD::ANY_EXTEND:  ExpandIntRes_ANY_EXTEND(N, Lo, Hi); break;
   case ISD::ZERO_EXTEND: ExpandIntRes_ZERO_EXTEND(N, Lo, Hi); break;
   case ISD::SIGN_EXTEND: ExpandIntRes_SIGN_EXTEND(N, Lo, Hi); break;
   case ISD::AssertZext:  ExpandIntRes_AssertZext(N, Lo, Hi); break;
   case ISD::TRUNCATE:    ExpandIntRes_TRUNCATE(N, Lo, Hi); break;
-  case ISD::BIT_CONVERT: ExpandIntRes_BIT_CONVERT(N, Lo, Hi); break;
   case ISD::SIGN_EXTEND_INREG: ExpandIntRes_SIGN_EXTEND_INREG(N, Lo, Hi); break;
   case ISD::FP_TO_SINT:  ExpandIntRes_FP_TO_SINT(N, Lo, Hi); break;
   case ISD::FP_TO_UINT:  ExpandIntRes_FP_TO_UINT(N, Lo, Hi); break;
@@ -781,8 +837,6 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
   case ISD::SUBC:        ExpandIntRes_ADDSUBC(N, Lo, Hi); break;
   case ISD::ADDE:
   case ISD::SUBE:        ExpandIntRes_ADDSUBE(N, Lo, Hi); break;
-  case ISD::SELECT:      ExpandIntRes_SELECT(N, Lo, Hi); break;
-  case ISD::SELECT_CC:   ExpandIntRes_SELECT_CC(N, Lo, Hi); break;
   case ISD::MUL:         ExpandIntRes_MUL(N, Lo, Hi); break;
   case ISD::SDIV:        ExpandIntRes_SDIV(N, Lo, Hi); break;
   case ISD::SREM:        ExpandIntRes_SREM(N, Lo, Hi); break;
@@ -795,10 +849,6 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
   case ISD::CTLZ:        ExpandIntRes_CTLZ(N, Lo, Hi); break;
   case ISD::CTPOP:       ExpandIntRes_CTPOP(N, Lo, Hi); break;
   case ISD::CTTZ:        ExpandIntRes_CTTZ(N, Lo, Hi); break;
-
-  case ISD::EXTRACT_VECTOR_ELT:
-    ExpandIntRes_EXTRACT_VECTOR_ELT(N, Lo, Hi);
-    break;
   }
 
   // If Lo/Hi is null, the sub-method took care of registering results etc.
@@ -806,12 +856,6 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
     SetExpandedInteger(SDOperand(N, ResNo), Lo, Hi);
 }
 
-void DAGTypeLegalizer::ExpandIntRes_UNDEF(SDNode *N,
-                                          SDOperand &Lo, SDOperand &Hi) {
-  MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
-  Lo = Hi = DAG.getNode(ISD::UNDEF, NVT);
-}
-
 void DAGTypeLegalizer::ExpandIntRes_Constant(SDNode *N,
                                              SDOperand &Lo, SDOperand &Hi) {
   MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
@@ -821,34 +865,6 @@ void DAGTypeLegalizer::ExpandIntRes_Constant(SDNode *N,
   Hi = DAG.getConstant(Cst.lshr(NBitWidth).trunc(NBitWidth), NVT);
 }
 
-void DAGTypeLegalizer::ExpandIntRes_BUILD_PAIR(SDNode *N,
-                                               SDOperand &Lo, SDOperand &Hi) {
-  // Return the operands.
-  Lo = N->getOperand(0);
-  Hi = N->getOperand(1);
-}
-
-void DAGTypeLegalizer::ExpandIntRes_MERGE_VALUES(SDNode *N,
-                                                 SDOperand &Lo, SDOperand &Hi) {
-  // A MERGE_VALUES node can produce any number of values.  We know that the
-  // first illegal one needs to be expanded into Lo/Hi.
-  unsigned i;
-
-  // The string of legal results gets turns into the input operands, which have
-  // the same type.
-  for (i = 0; isTypeLegal(N->getValueType(i)); ++i)
-    ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i)));
-
-  // The first illegal result must be the one that needs to be expanded.
-  GetExpandedInteger(N->getOperand(i), Lo, Hi);
-
-  // Legalize the rest of the results into the input operands whether they are
-  // legal or not.
-  unsigned e = N->getNumValues();
-  for (++i; i != e; ++i)
-    ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i)));
-}
-
 void DAGTypeLegalizer::ExpandIntRes_ANY_EXTEND(SDNode *N,
                                                SDOperand &Lo, SDOperand &Hi) {
   MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
@@ -950,61 +966,6 @@ void DAGTypeLegalizer::ExpandIntRes_TRUNCATE(SDNode *N,
   Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi);
 }
 
-void DAGTypeLegalizer::ExpandIntRes_BIT_CONVERT(SDNode *N,
-                                                SDOperand &Lo, SDOperand &Hi) {
-  MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
-  SDOperand InOp = N->getOperand(0);
-  MVT InVT = InOp.getValueType();
-
-  // Handle some special cases efficiently.
-  switch (getTypeAction(InVT)) {
-    default:
-      assert(false && "Unknown type action!");
-    case Legal:
-    case PromoteInteger:
-      break;
-    case PromoteFloat:
-      // Convert the integer operand instead.
-      SplitInteger(GetPromotedFloat(InOp), Lo, Hi);
-      Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
-      Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
-      return;
-    case ExpandInteger:
-      // Convert the expanded pieces of the input.
-      GetExpandedInteger(InOp, Lo, Hi);
-      Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
-      Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
-      return;
-    case ExpandFloat:
-      // Convert the expanded pieces of the input.
-      GetExpandedFloat(InOp, Lo, Hi);
-      Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
-      Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
-      return;
-    case Split:
-      // Convert the split parts of the input if it was split in two.
-      GetSplitVector(InOp, Lo, Hi);
-      if (Lo.getValueType() == Hi.getValueType()) {
-        if (TLI.isBigEndian())
-          std::swap(Lo, Hi);
-        Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
-        Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
-        return;
-      }
-      break;
-    case Scalarize:
-      // Convert the element instead.
-      SplitInteger(BitConvertToInteger(GetScalarizedVector(InOp)), Lo, Hi);
-      Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
-      Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
-      return;
-  }
-
-  // Lower the bit-convert to a store/load from the stack, then expand the load.
-  SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0));
-  ExpandIntRes_LOAD(cast<LoadSDNode>(Op.Val), Lo, Hi);
-}
-
 void DAGTypeLegalizer::
 ExpandIntRes_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
   GetExpandedInteger(N->getOperand(0), Lo, Hi);
@@ -1035,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)
@@ -1053,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);
 }
 
@@ -1064,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)
@@ -1082,45 +1061,32 @@ 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);
 }
 
 void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N,
                                          SDOperand &Lo, SDOperand &Hi) {
-  // FIXME: Add support for indexed loads.
+  if (ISD::isNormalLoad(N)) {
+    ExpandRes_NormalLoad(N, Lo, Hi);
+    return;
+  }
+
+  assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!");
+
   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();
   bool isVolatile = N->isVolatile();
 
-  assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!");
+  assert(NVT.isByteSized() && "Expanded type not byte sized!");
 
-  if (ExtType == ISD::NON_EXTLOAD) {
-    Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
-                     isVolatile, Alignment);
-    // Increment the pointer to the other half.
-    unsigned IncrementSize = NVT.getSizeInBits()/8;
-    Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
-                      DAG.getIntPtrConstant(IncrementSize));
-    Hi = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
-                     isVolatile, MinAlign(Alignment, IncrementSize));
-
-    // Build a factor node to remember that this load is independent of the
-    // other one.
-    Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
-                     Hi.getValue(1));
-
-    // Handle endianness of the load.
-    if (TLI.isBigEndian())
-      std::swap(Lo, Hi);
-  } else if (N->getMemoryVT().bitsLE(NVT)) {
+  if (N->getMemoryVT().bitsLE(NVT)) {
     MVT EVT = N->getMemoryVT();
 
     Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, EVT,
@@ -1225,26 +1191,6 @@ void DAGTypeLegalizer::ExpandIntRes_BSWAP(SDNode *N,
   Hi = DAG.getNode(ISD::BSWAP, Hi.getValueType(), Hi);
 }
 
-void DAGTypeLegalizer::ExpandIntRes_SELECT(SDNode *N,
-                                           SDOperand &Lo, SDOperand &Hi) {
-  SDOperand LL, LH, RL, RH;
-  GetExpandedInteger(N->getOperand(1), LL, LH);
-  GetExpandedInteger(N->getOperand(2), RL, RH);
-  Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LL, RL);
-  Hi = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LH, RH);
-}
-
-void DAGTypeLegalizer::ExpandIntRes_SELECT_CC(SDNode *N,
-                                              SDOperand &Lo, SDOperand &Hi) {
-  SDOperand LL, LH, RL, RH;
-  GetExpandedInteger(N->getOperand(2), LL, LH);
-  GetExpandedInteger(N->getOperand(3), RL, RH);
-  Lo = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0),
-                   N->getOperand(1), LL, RL, N->getOperand(4));
-  Hi = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0),
-                   N->getOperand(1), LH, RH, N->getOperand(4));
-}
-
 void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N,
                                            SDOperand &Lo, SDOperand &Hi) {
   // Expand the subcomponents.
@@ -1324,14 +1270,13 @@ void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N,
     GetExpandedInteger(N->getOperand(0), LL, LH);
     GetExpandedInteger(N->getOperand(1), RL, RH);
     unsigned OuterBitSize = VT.getSizeInBits();
-    unsigned BitSize = NVT.getSizeInBits();
+    unsigned InnerBitSize = NVT.getSizeInBits();
     unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0));
     unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1));
 
-    if (DAG.MaskedValueIsZero(N->getOperand(0),
-                              APInt::getHighBitsSet(OuterBitSize, LHSSB)) &&
-        DAG.MaskedValueIsZero(N->getOperand(1),
-                              APInt::getHighBitsSet(OuterBitSize, RHSSB))) {
+    APInt HighMask = APInt::getHighBitsSet(OuterBitSize, InnerBitSize);
+    if (DAG.MaskedValueIsZero(N->getOperand(0), HighMask) &&
+        DAG.MaskedValueIsZero(N->getOperand(1), HighMask)) {
       // The inputs are both zero-extended.
       if (HasUMUL_LOHI) {
         // We can emit a umul_lohi.
@@ -1346,7 +1291,7 @@ void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N,
         return;
       }
     }
-    if (LHSSB > BitSize && RHSSB > BitSize) {
+    if (LHSSB > InnerBitSize && RHSSB > InnerBitSize) {
       // The input values are both sign-extended.
       if (HasSMUL_LOHI) {
         // We can emit a smul_lohi.
@@ -1373,44 +1318,97 @@ void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N,
       Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH);
       return;
     }
+    if (HasMULHU) {
+      Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+      Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
+      RH = DAG.getNode(ISD::MUL, NVT, LL, RH);
+      LH = DAG.getNode(ISD::MUL, NVT, LH, RL);
+      Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH);
+      Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH);
+      return;
+    }
   }
 
   // If nothing else, we can make a libcall.
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+  if (VT == MVT::i32)
+    LC = RTLIB::MUL_I32;
+  else if (VT == MVT::i64)
+    LC = RTLIB::MUL_I64;
+  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(RTLIB::MUL_I64, VT, Ops, 2, true/*sign irrelevant*/),
-               Lo, Hi);
+  SplitInteger(MakeLibCall(LC, VT, Ops, 2, true/*sign irrelevant*/), Lo, Hi);
 }
 
 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,
@@ -1456,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);
@@ -1522,41 +1534,6 @@ void DAGTypeLegalizer::ExpandIntRes_CTTZ(SDNode *N,
   Hi = DAG.getConstant(0, NVT);
 }
 
-void DAGTypeLegalizer::ExpandIntRes_EXTRACT_VECTOR_ELT(SDNode *N,
-                                                       SDOperand &Lo,
-                                                       SDOperand &Hi) {
-  SDOperand OldVec = N->getOperand(0);
-  unsigned OldElts = OldVec.getValueType().getVectorNumElements();
-
-  // Convert to a vector of the expanded element type, for example
-  // <2 x i64> -> <4 x i32>.
-  MVT OldVT = N->getValueType(0);
-  MVT NewVT = TLI.getTypeToTransformTo(OldVT);
-  assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() &&
-         "Do not know how to handle this expansion!");
-
-  SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT,
-                                 MVT::getVectorVT(NewVT, 2*OldElts),
-                                 OldVec);
-
-  // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new vector.
-  SDOperand Idx = N->getOperand(1);
-
-  // Make sure the type of Idx is big enough to hold the new values.
-  if (Idx.getValueType().bitsLT(TLI.getPointerTy()))
-    Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx);
-
-  Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, Idx);
-  Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx);
-
-  Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx,
-                    DAG.getConstant(1, Idx.getValueType()));
-  Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx);
-
-  if (TLI.isBigEndian())
-    std::swap(Lo, Hi);
-}
-
 /// ExpandShiftByConstant - N is a shift by a value that needs to be expanded,
 /// and the shift amount is a constant 'Amt'.  Expand the operation.
 void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt,
@@ -1579,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,
@@ -1721,11 +1705,11 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
 /// node may need promotion or expansion as well as the specified one.
 bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) {
   DEBUG(cerr << "Expand integer operand: "; N->dump(&DAG); cerr << "\n");
-  SDOperand Res(0, 0);
+  SDOperand Res = SDOperand();
 
   if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
       == TargetLowering::Custom)
-    Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
+    Res = TLI.LowerOperation(SDOperand(N, OpNo), DAG);
 
   if (Res.Val == 0) {
     switch (N->getOpcode()) {
@@ -1737,25 +1721,22 @@ bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) {
       assert(0 && "Do not know how to expand this operator's operand!");
       abort();
 
+    case ISD::BUILD_VECTOR:    Res = ExpandOp_BUILD_VECTOR(N); break;
+    case ISD::BIT_CONVERT:     Res = ExpandOp_BIT_CONVERT(N); break;
+    case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break;
+
     case ISD::TRUNCATE:        Res = ExpandIntOp_TRUNCATE(N); break;
-    case ISD::BIT_CONVERT:     Res = ExpandIntOp_BIT_CONVERT(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::EXTRACT_ELEMENT: Res = ExpandIntOp_EXTRACT_ELEMENT(N); 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::SETCC:           Res = ExpandIntOp_SETCC(N); break;
+    case ISD::BR_CC:     Res = ExpandIntOp_BR_CC(N); break;
+    case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break;
+    case ISD::SETCC:     Res = ExpandIntOp_SETCC(N); break;
 
     case ISD::STORE:
       Res = ExpandIntOp_STORE(cast<StoreSDNode>(N), OpNo);
       break;
-
-    case ISD::BUILD_VECTOR: Res = ExpandIntOp_BUILD_VECTOR(N); break;
     }
   }
 
@@ -1785,129 +1766,140 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_TRUNCATE(SDNode *N) {
   return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL);
 }
 
-SDOperand DAGTypeLegalizer::ExpandIntOp_BIT_CONVERT(SDNode *N) {
-  if (N->getValueType(0).isVector()) {
-    // An illegal integer type is being converted to a legal vector type.
-    // Make a two element vector out of the expanded parts and convert that
-    // instead, but only if the new vector type is legal (otherwise there
-    // is no point, and it might create expansion loops).  For example, on
-    // x86 this turns v1i64 = BIT_CONVERT i64 into v1i64 = BIT_CONVERT v2i32.
-    MVT OVT = N->getOperand(0).getValueType();
-    MVT NVT = MVT::getVectorVT(TLI.getTypeToTransformTo(OVT), 2);
-
-    if (isTypeLegal(NVT)) {
-      SDOperand Parts[2];
-      GetExpandedInteger(N->getOperand(0), Parts[0], Parts[1]);
-
-      if (TLI.isBigEndian())
-        std::swap(Parts[0], Parts[1]);
-
-      SDOperand Vec = DAG.getNode(ISD::BUILD_VECTOR, NVT, Parts, 2);
-      return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Vec);
-    }
-  }
-
-  // Otherwise, store to a temporary and load out again as the new type.
-  return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0));
-}
-
-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!");
-
-  // 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);
+  return MakeLibCall(LC, DstVT, &Op, 1, true);
+}
 
-  // 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");
+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);
+  }
 
-  return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg);
-}
+  // 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!");
 
-SDOperand DAGTypeLegalizer::ExpandIntOp_EXTRACT_ELEMENT(SDNode *N) {
-  SDOperand Lo, Hi;
-  GetExpandedInteger(N->getOperand(0), Lo, Hi);
-  return cast<ConstantSDNode>(N->getOperand(1))->getValue() ? Hi : Lo;
+  return MakeLibCall(LC, DstVT, &Op, 1, true);
 }
 
 SDOperand DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) {
   SDOperand NewLHS = N->getOperand(2), NewRHS = N->getOperand(3);
   ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(1))->get();
-  ExpandSetCCOperands(NewLHS, NewRHS, CCCode);
+  IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode);
 
   // If ExpandSetCCOperands returned a scalar, we need to compare the result
   // against zero to select between true and false values.
@@ -1922,55 +1914,63 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) {
                                 N->getOperand(4));
 }
 
+SDOperand DAGTypeLegalizer::ExpandIntOp_SELECT_CC(SDNode *N) {
+  SDOperand NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
+  ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(4))->get();
+  IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode);
+
+  // If ExpandSetCCOperands returned a scalar, we need to compare the result
+  // against zero to select between true and false values.
+  if (NewRHS.Val == 0) {
+    NewRHS = DAG.getConstant(0, NewLHS.getValueType());
+    CCCode = ISD::SETNE;
+  }
+
+  // Update N to have the operands specified.
+  return DAG.UpdateNodeOperands(SDOperand(N, 0), NewLHS, NewRHS,
+                                N->getOperand(2), N->getOperand(3),
+                                DAG.getCondCode(CCCode));
+}
+
 SDOperand DAGTypeLegalizer::ExpandIntOp_SETCC(SDNode *N) {
   SDOperand NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
   ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(2))->get();
-  ExpandSetCCOperands(NewLHS, NewRHS, CCCode);
+  IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode);
 
   // If ExpandSetCCOperands returned a scalar, use it.
-  if (NewRHS.Val == 0) return NewLHS;
+  if (NewRHS.Val == 0) {
+    assert(NewLHS.getValueType() == N->getValueType(0) &&
+           "Unexpected setcc expansion!");
+    return NewLHS;
+  }
 
   // Otherwise, update N to have the operands specified.
   return DAG.UpdateNodeOperands(SDOperand(N, 0), NewLHS, NewRHS,
                                 DAG.getCondCode(CCCode));
 }
 
-/// ExpandSetCCOperands - Expand the operands of a comparison.  This code is
-/// shared among BR_CC, SELECT_CC, and SETCC handlers.
-void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS,
-                                           ISD::CondCode &CCCode) {
+/// IntegerExpandSetCCOperands - Expand the operands of a comparison.  This code
+/// is shared among BR_CC, SELECT_CC, and SETCC handlers.
+void DAGTypeLegalizer::IntegerExpandSetCCOperands(SDOperand &NewLHS,
+                                                  SDOperand &NewRHS,
+                                                  ISD::CondCode &CCCode) {
   SDOperand LHSLo, LHSHi, RHSLo, RHSHi;
   GetExpandedInteger(NewLHS, LHSLo, LHSHi);
   GetExpandedInteger(NewRHS, RHSLo, RHSHi);
 
   MVT VT = NewLHS.getValueType();
-  if (VT == MVT::ppcf128) {
-    // FIXME:  This generated code sucks.  We want to generate
-    //         FCMP crN, hi1, hi2
-    //         BNE crN, L:
-    //         FCMP crN, lo1, lo2
-    // The following can be improved, but not that much.
-    SDOperand Tmp1, Tmp2, Tmp3;
-    Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETEQ);
-    Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, CCCode);
-    Tmp3 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2);
-    Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETNE);
-    Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, CCCode);
-    Tmp1 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2);
-    NewLHS = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp3);
-    NewRHS = SDOperand();   // LHS is the result, not a compare.
-    return;
-  }
 
   if (CCCode == ISD::SETEQ || CCCode == ISD::SETNE) {
-    if (RHSLo == RHSHi)
-      if (ConstantSDNode *RHSCST = dyn_cast<ConstantSDNode>(RHSLo))
+    if (RHSLo == RHSHi) {
+      if (ConstantSDNode *RHSCST = dyn_cast<ConstantSDNode>(RHSLo)) {
         if (RHSCST->isAllOnesValue()) {
           // Equality comparison to -1.
           NewLHS = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi);
           NewRHS = RHSLo;
           return;
         }
+      }
+    }
 
     NewLHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo);
     NewRHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi);
@@ -2049,7 +2049,10 @@ void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS,
 }
 
 SDOperand DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) {
-  // FIXME: Add support for indexed stores.
+  if (ISD::isNormalStore(N))
+    return ExpandOp_NormalStore(N, OpNo);
+
+  assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!");
   assert(OpNo == 1 && "Can only expand the stored value so far");
 
   MVT VT = N->getOperand(1).getValueType();
@@ -2061,26 +2064,9 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) {
   bool isVolatile = N->isVolatile();
   SDOperand Lo, Hi;
 
-  assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!");
-
-  if (!N->isTruncatingStore()) {
-    unsigned IncrementSize = 0;
-    GetExpandedInteger(N->getValue(), Lo, Hi);
-    IncrementSize = Hi.getValueType().getSizeInBits()/8;
-
-    if (TLI.isBigEndian())
-      std::swap(Lo, Hi);
-
-    Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(),
-                      SVOffset, isVolatile, Alignment);
+  assert(NVT.isByteSized() && "Expanded type not byte sized!");
 
-    Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
-                      DAG.getIntPtrConstant(IncrementSize));
-    assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!");
-    Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
-                      isVolatile, MinAlign(Alignment, IncrementSize));
-    return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
-  } else if (N->getMemoryVT().bitsLE(NVT)) {
+  if (N->getMemoryVT().bitsLE(NVT)) {
     GetExpandedInteger(N->getValue(), Lo, Hi);
     return DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset,
                              N->getMemoryVT(), isVolatile, Alignment);
@@ -2140,35 +2126,3 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) {
     return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
   }
 }
-
-SDOperand DAGTypeLegalizer::ExpandIntOp_BUILD_VECTOR(SDNode *N) {
-  // The vector type is legal but the element type needs expansion.
-  MVT VecVT = N->getValueType(0);
-  unsigned NumElts = VecVT.getVectorNumElements();
-  MVT OldVT = N->getOperand(0).getValueType();
-  MVT NewVT = TLI.getTypeToTransformTo(OldVT);
-
-  assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() &&
-         "Do not know how to expand this operand!");
-
-  // Build a vector of twice the length out of the expanded elements.
-  // For example <2 x i64> -> <4 x i32>.
-  std::vector<SDOperand> NewElts;
-  NewElts.reserve(NumElts*2);
-
-  for (unsigned i = 0; i < NumElts; ++i) {
-    SDOperand Lo, Hi;
-    GetExpandedInteger(N->getOperand(i), Lo, Hi);
-    if (TLI.isBigEndian())
-      std::swap(Lo, Hi);
-    NewElts.push_back(Lo);
-    NewElts.push_back(Hi);
-  }
-
-  SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR,
-                                 MVT::getVectorVT(NewVT, NewElts.size()),
-                                 &NewElts[0], NewElts.size());
-
-  // Convert the new vector to the old vector type.
-  return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec);
-}