Migrate X86 and ARM from using X86ISD::{,I}DIV and ARMISD::MULHILO{U,S} to
[oota-llvm.git] / lib / CodeGen / SelectionDAG / LegalizeDAG.cpp
index 5bcee351ea75d2afef0f94035f871076ececc830..98a2495d28dc1c4a0cfca6d8098f487bfb59acf2 100644 (file)
@@ -15,6 +15,7 @@
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/Target/TargetFrameInfo.h"
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
@@ -456,6 +457,8 @@ void SelectionDAGLegalize::HandleOp(SDOperand Op) {
       // If this is an illegal scalar, expand it into its two component
       // pieces.
       SDOperand X, Y;
+      if (Op.getOpcode() == ISD::TargetConstant)
+        break;  // Allow illegal target nodes.
       ExpandOp(Op, X, Y);
     } else if (MVT::getVectorNumElements(VT) == 1) {
       // If this is an illegal single element vector, convert it to a
@@ -483,17 +486,18 @@ static SDOperand ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP,
   // double.
   MVT::ValueType VT = CFP->getValueType(0);
   bool isDouble = VT == MVT::f64;
-  ConstantFP *LLVMC = ConstantFP::get(isDouble ? Type::DoubleTy :
-                                      Type::FloatTy, CFP->getValue());
+  ConstantFP *LLVMC = ConstantFP::get(MVT::getTypeForValueType(VT),
+                                      CFP->getValueAPF());
   if (!UseCP) {
-    double Val = LLVMC->getValue();
-    return isDouble
-      ? DAG.getConstant(DoubleToBits(Val), MVT::i64)
-      : DAG.getConstant(FloatToBits(Val), MVT::i32);
+    if (VT!=MVT::f64 && VT!=MVT::f32)
+      assert(0 && "Invalid type expansion");
+    return DAG.getConstant(LLVMC->getValueAPF().convertToAPInt().getZExtValue(),
+                           isDouble ? MVT::i64 : MVT::i32);
   }
 
-  if (isDouble && CFP->isExactlyValue((float)CFP->getValue()) &&
+  if (isDouble && CFP->isValueValidForType(MVT::f32, CFP->getValueAPF()) &&
       // Only do this if the target has a native EXTLOAD instruction from f32.
+      // Do not try to be clever about long doubles (so far)
       TLI.isLoadXLegal(ISD::EXTLOAD, MVT::f32)) {
     LLVMC = cast<ConstantFP>(ConstantExpr::getFPTrunc(LLVMC,Type::FloatTy));
     VT = MVT::f32;
@@ -550,12 +554,139 @@ SDOperand ExpandFCOPYSIGNToBitwiseOps(SDNode *Node, MVT::ValueType NVT,
   return Result;
 }
 
+/// ExpandUnalignedStore - Expands an unaligned store to 2 half-size stores.
+static
+SDOperand ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG,
+                               TargetLowering &TLI) {
+  SDOperand Chain = ST->getChain();
+  SDOperand Ptr = ST->getBasePtr();
+  SDOperand Val = ST->getValue();
+  MVT::ValueType VT = Val.getValueType();
+  int Alignment = ST->getAlignment();
+  int SVOffset = ST->getSrcValueOffset();
+  if (MVT::isFloatingPoint(ST->getStoredVT())) {
+    // Expand to a bitconvert of the value to the integer type of the 
+    // same size, then a (misaligned) int store.
+    MVT::ValueType intVT;
+    if (VT==MVT::f64)
+      intVT = MVT::i64;
+    else if (VT==MVT::f32)
+      intVT = MVT::i32;
+    else
+      assert(0 && "Unaligned load of unsupported floating point type");
+
+    SDOperand Result = DAG.getNode(ISD::BIT_CONVERT, intVT, Val);
+    return DAG.getStore(Chain, Result, Ptr, ST->getSrcValue(),
+                        SVOffset, ST->isVolatile(), Alignment);
+  }
+  assert(MVT::isInteger(ST->getStoredVT()) &&
+         "Unaligned store of unknown type.");
+  // Get the half-size VT
+  MVT::ValueType NewStoredVT = ST->getStoredVT() - 1;
+  int NumBits = MVT::getSizeInBits(NewStoredVT);
+  int IncrementSize = NumBits / 8;
+
+  // Divide the stored value in two parts.
+  SDOperand ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
+  SDOperand Lo = Val;
+  SDOperand Hi = DAG.getNode(ISD::SRL, VT, Val, ShiftAmount);
+
+  // Store the two parts
+  SDOperand Store1, Store2;
+  Store1 = DAG.getTruncStore(Chain, TLI.isLittleEndian()?Lo:Hi, Ptr,
+                             ST->getSrcValue(), SVOffset, NewStoredVT,
+                             ST->isVolatile(), Alignment);
+  Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                    DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+  Store2 = DAG.getTruncStore(Chain, TLI.isLittleEndian()?Hi:Lo, Ptr,
+                             ST->getSrcValue(), SVOffset + IncrementSize,
+                             NewStoredVT, ST->isVolatile(), Alignment);
+
+  return DAG.getNode(ISD::TokenFactor, MVT::Other, Store1, Store2);
+}
+
+/// ExpandUnalignedLoad - Expands an unaligned load to 2 half-size loads.
+static
+SDOperand ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG,
+                              TargetLowering &TLI) {
+  int SVOffset = LD->getSrcValueOffset();
+  SDOperand Chain = LD->getChain();
+  SDOperand Ptr = LD->getBasePtr();
+  MVT::ValueType VT = LD->getValueType(0);
+  MVT::ValueType LoadedVT = LD->getLoadedVT();
+  if (MVT::isFloatingPoint(VT)) {
+    // Expand to a (misaligned) integer load of the same size,
+    // then bitconvert to floating point.
+    MVT::ValueType intVT;
+    if (LoadedVT==MVT::f64)
+      intVT = MVT::i64;
+    else if (LoadedVT==MVT::f32)
+      intVT = MVT::i32;
+    else
+      assert(0 && "Unaligned load of unsupported floating point type");
+
+    SDOperand newLoad = DAG.getLoad(intVT, Chain, Ptr, LD->getSrcValue(),
+                                    SVOffset, LD->isVolatile(), 
+                                    LD->getAlignment());
+    SDOperand Result = DAG.getNode(ISD::BIT_CONVERT, LoadedVT, newLoad);
+    if (LoadedVT != VT)
+      Result = DAG.getNode(ISD::FP_EXTEND, VT, Result);
+
+    SDOperand Ops[] = { Result, Chain };
+    return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other), 
+                       Ops, 2);
+  }
+  assert(MVT::isInteger(LoadedVT) && "Unaligned load of unsupported type.");
+  MVT::ValueType NewLoadedVT = LoadedVT - 1;
+  int NumBits = MVT::getSizeInBits(NewLoadedVT);
+  int Alignment = LD->getAlignment();
+  int IncrementSize = NumBits / 8;
+  ISD::LoadExtType HiExtType = LD->getExtensionType();
+
+  // If the original load is NON_EXTLOAD, the hi part load must be ZEXTLOAD.
+  if (HiExtType == ISD::NON_EXTLOAD)
+    HiExtType = ISD::ZEXTLOAD;
+
+  // Load the value in two parts
+  SDOperand Lo, Hi;
+  if (TLI.isLittleEndian()) {
+    Lo = DAG.getExtLoad(ISD::ZEXTLOAD, VT, Chain, Ptr, LD->getSrcValue(),
+                        SVOffset, NewLoadedVT, LD->isVolatile(), Alignment);
+    Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                      DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+    Hi = DAG.getExtLoad(HiExtType, VT, Chain, Ptr, LD->getSrcValue(),
+                        SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
+                        Alignment);
+  } else {
+    Hi = DAG.getExtLoad(HiExtType, VT, Chain, Ptr, LD->getSrcValue(), SVOffset,
+                        NewLoadedVT,LD->isVolatile(), Alignment);
+    Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                      DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+    Lo = DAG.getExtLoad(ISD::ZEXTLOAD, VT, Chain, Ptr, LD->getSrcValue(),
+                        SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
+                        Alignment);
+  }
+
+  // aggregate the two parts
+  SDOperand ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
+  SDOperand Result = DAG.getNode(ISD::SHL, VT, Hi, ShiftAmount);
+  Result = DAG.getNode(ISD::OR, VT, Result, Lo);
+
+  SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+                             Hi.getValue(1));
+
+  SDOperand Ops[] = { Result, TF };
+  return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other), Ops, 2);
+}
 
 /// LegalizeOp - We know that the specified value has a legal type, and
 /// that its operands are legal.  Now ensure that the operation itself
 /// is legal, recursively ensuring that the operands' operations remain
 /// legal.
 SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
+  if (Op.getOpcode() == ISD::TargetConstant) // Allow illegal target nodes.
+    return Op;
+  
   assert(isTypeLegal(Op.getValueType()) &&
          "Caller should expand or promote operands that are not legal!");
   SDNode *Node = Op.Val;
@@ -640,7 +771,6 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     break;
   case ISD::FRAMEADDR:
   case ISD::RETURNADDR:
-  case ISD::FRAME_TO_ARGS_OFFSET:
     // The only option for these nodes is to custom lower them.  If the target
     // does not custom lower them, then return zero.
     Tmp1 = TLI.LowerOperation(Op, DAG);
@@ -649,6 +779,20 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     else
       Result = DAG.getConstant(0, TLI.getPointerTy());
     break;
+  case ISD::FRAME_TO_ARGS_OFFSET: {
+    MVT::ValueType VT = Node->getValueType(0);
+    switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
+    default: assert(0 && "This action is not supported yet!");
+    case TargetLowering::Custom:
+      Result = TLI.LowerOperation(Op, DAG);
+      if (Result.Val) break;
+      // Fall Thru
+    case TargetLowering::Legal:
+      Result = DAG.getConstant(0, VT);
+      break;
+    }
+    }
+    break;
   case ISD::EXCEPTIONADDR: {
     Tmp1 = LegalizeOp(Node->getOperand(0));
     MVT::ValueType VT = Node->getValueType(0);
@@ -749,7 +893,8 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       if (MVT::isInteger(VT))
         Result = DAG.getConstant(0, VT);
       else if (MVT::isFloatingPoint(VT))
-        Result = DAG.getConstantFP(0, VT);
+        Result = DAG.getConstantFP(APFloat(APInt(MVT::getSizeInBits(VT), 0)),
+                                   VT);
       else
         assert(0 && "Unknown value type!");
       break;
@@ -878,13 +1023,21 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     }
     break;
 
-  case ISD::Constant:
+  case ISD::Constant: {
+    ConstantSDNode *CN = cast<ConstantSDNode>(Node);
+    unsigned opAction =
+      TLI.getOperationAction(ISD::Constant, CN->getValueType(0));
+
     // We know we don't need to expand constants here, constants only have one
     // value and we check that it is fine above.
 
-    // FIXME: Maybe we should handle things like targets that don't support full
-    // 32-bit immediates?
+    if (opAction == TargetLowering::Custom) {
+      Tmp1 = TLI.LowerOperation(Result, DAG);
+      if (Tmp1.Val)
+        Result = Tmp1;
+    }
     break;
+  }
   case ISD::ConstantFP: {
     // Spill FP immediates to the constant pool if the target cannot directly
     // codegen them.  Targets often have some immediate values that can be
@@ -903,7 +1056,8 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
 
     // If this is a legal constant, turn it into a TargetConstantFP node.
     if (isLegal) {
-      Result = DAG.getTargetConstantFP(CFP->getValue(), CFP->getValueType(0));
+      Result = DAG.getTargetConstantFP(CFP->getValueAPF(), 
+                                       CFP->getValueType(0));
       break;
     }
 
@@ -957,7 +1111,23 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       AddLegalizedOperand(SDOperand(Node, i), Tmp1);
     }
     return Tmp2;
-        
+   case ISD::EXTRACT_SUBREG: {
+      Tmp1 = LegalizeOp(Node->getOperand(0));
+      ConstantSDNode *idx = dyn_cast<ConstantSDNode>(Node->getOperand(1));
+      assert(idx && "Operand must be a constant");
+      Tmp2 = DAG.getTargetConstant(idx->getValue(), idx->getValueType(0));
+      Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
+    }
+    break;
+  case ISD::INSERT_SUBREG: {
+      Tmp1 = LegalizeOp(Node->getOperand(0));
+      Tmp2 = LegalizeOp(Node->getOperand(1));      
+      ConstantSDNode *idx = dyn_cast<ConstantSDNode>(Node->getOperand(2));
+      assert(idx && "Operand must be a constant");
+      Tmp3 = DAG.getTargetConstant(idx->getValue(), idx->getValueType(0));
+      Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
+    }
+    break;      
   case ISD::BUILD_VECTOR:
     switch (TLI.getOperationAction(ISD::BUILD_VECTOR, Node->getValueType(0))) {
     default: assert(0 && "This action is not supported yet!");
@@ -1244,6 +1414,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
     return Result.getValue(Op.ResNo);
   case ISD::DYNAMIC_STACKALLOC: {
+    MVT::ValueType VT = Node->getValueType(0);
     Tmp1 = LegalizeOp(Node->getOperand(0));  // Legalize the chain.
     Tmp2 = LegalizeOp(Node->getOperand(1));  // Legalize the size.
     Tmp3 = LegalizeOp(Node->getOperand(2));  // Legalize the alignment.
@@ -1251,8 +1422,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
 
     Tmp1 = Result.getValue(0);
     Tmp2 = Result.getValue(1);
-    switch (TLI.getOperationAction(Node->getOpcode(),
-                                   Node->getValueType(0))) {
+    switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
     default: assert(0 && "This action is not supported yet!");
     case TargetLowering::Expand: {
       unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore();
@@ -1260,9 +1430,16 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
              " not tell us which reg is the stack pointer!");
       SDOperand Chain = Tmp1.getOperand(0);
       SDOperand Size  = Tmp2.getOperand(1);
-      SDOperand SP = DAG.getCopyFromReg(Chain, SPReg, Node->getValueType(0));
-      Tmp1 = DAG.getNode(ISD::SUB, Node->getValueType(0), SP, Size);    // Value
-      Tmp2 = DAG.getCopyToReg(SP.getValue(1), SPReg, Tmp1);      // Output chain
+      SDOperand SP = DAG.getCopyFromReg(Chain, SPReg, VT);
+      Chain = SP.getValue(1);
+      unsigned Align = cast<ConstantSDNode>(Tmp3)->getValue();
+      unsigned StackAlign =
+        TLI.getTargetMachine().getFrameInfo()->getStackAlignment();
+      if (Align > StackAlign)
+        SP = DAG.getNode(ISD::AND, VT, SP,
+                         DAG.getConstant(-(uint64_t)Align, VT));
+      Tmp1 = DAG.getNode(ISD::SUB, VT, SP, Size);       // Value
+      Tmp2 = DAG.getCopyToReg(Chain, SPReg, Tmp1);      // Output chain
       Tmp1 = LegalizeOp(Tmp1);
       Tmp2 = LegalizeOp(Tmp2);
       break;
@@ -1491,7 +1668,22 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     
       switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
       default: assert(0 && "This action is not supported yet!");
-      case TargetLowering::Legal: break;
+      case TargetLowering::Legal:
+        // If this is an unaligned load and the target doesn't support it,
+        // expand it.
+        if (!TLI.allowsUnalignedMemoryAccesses()) {
+          unsigned ABIAlignment = TLI.getTargetData()->
+            getABITypeAlignment(MVT::getTypeForValueType(LD->getLoadedVT()));
+          if (LD->getAlignment() < ABIAlignment){
+            Result = ExpandUnalignedLoad(cast<LoadSDNode>(Result.Val), DAG,
+                                         TLI);
+            Tmp3 = Result.getOperand(0);
+            Tmp4 = Result.getOperand(1);
+            Tmp3 = LegalizeOp(Tmp3);
+            Tmp4 = LegalizeOp(Tmp4);
+          }
+        }
+        break;
       case TargetLowering::Custom:
         Tmp1 = TLI.LowerOperation(Tmp3, DAG);
         if (Tmp1.Val) {
@@ -1545,6 +1737,21 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
             Tmp1 = LegalizeOp(Tmp3);
             Tmp2 = LegalizeOp(Tmp3.getValue(1));
           }
+        } else {
+          // If this is an unaligned load and the target doesn't support it,
+          // expand it.
+          if (!TLI.allowsUnalignedMemoryAccesses()) {
+            unsigned ABIAlignment = TLI.getTargetData()->
+              getABITypeAlignment(MVT::getTypeForValueType(LD->getLoadedVT()));
+            if (LD->getAlignment() < ABIAlignment){
+              Result = ExpandUnalignedLoad(cast<LoadSDNode>(Result.Val), DAG,
+                                           TLI);
+              Tmp1 = Result.getOperand(0);
+              Tmp2 = Result.getOperand(1);
+              Tmp1 = LegalizeOp(Tmp1);
+              Tmp2 = LegalizeOp(Tmp2);
+            }
+          }
         }
         break;
       case TargetLowering::Expand:
@@ -1773,16 +1980,22 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       // to phase ordering between legalized code and the dag combiner.  This
       // probably means that we need to integrate dag combiner and legalizer
       // together.
-      if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(ST->getValue())) {
+      // We generally can't do this one for long doubles.
+      if (ConstantFPSDNode *CFP =dyn_cast<ConstantFPSDNode>(ST->getValue())) {
         if (CFP->getValueType(0) == MVT::f32) {
-          Tmp3 = DAG.getConstant(FloatToBits(CFP->getValue()), MVT::i32);
-        } else {
-          assert(CFP->getValueType(0) == MVT::f64 && "Unknown FP type!");
-          Tmp3 = DAG.getConstant(DoubleToBits(CFP->getValue()), MVT::i64);
+          Tmp3 = DAG.getConstant((uint32_t)CFP->getValueAPF().
+                                          convertToAPInt().getZExtValue(),
+                                  MVT::i32);
+          Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+                                SVOffset, isVolatile, Alignment);
+          break;
+        } else if (CFP->getValueType(0) == MVT::f64) {
+          Tmp3 = DAG.getConstant(CFP->getValueAPF().convertToAPInt().
+                                   getZExtValue(), MVT::i64);
+          Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+                                SVOffset, isVolatile, Alignment);
+          break;
         }
-        Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
-                              SVOffset, isVolatile, Alignment);
-        break;
       }
       
       switch (getTypeAction(ST->getStoredVT())) {
@@ -1794,7 +2007,17 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
         MVT::ValueType VT = Tmp3.getValueType();
         switch (TLI.getOperationAction(ISD::STORE, VT)) {
         default: assert(0 && "This action is not supported yet!");
-        case TargetLowering::Legal:  break;
+        case TargetLowering::Legal:
+          // If this is an unaligned store and the target doesn't support it,
+          // expand it.
+          if (!TLI.allowsUnalignedMemoryAccesses()) {
+            unsigned ABIAlignment = TLI.getTargetData()->
+              getABITypeAlignment(MVT::getTypeForValueType(ST->getStoredVT()));
+            if (ST->getAlignment() < ABIAlignment)
+              Result = ExpandUnalignedStore(cast<StoreSDNode>(Result.Val), DAG,
+                                            TLI);
+          }
+          break;
         case TargetLowering::Custom:
           Tmp1 = TLI.LowerOperation(Result, DAG);
           if (Tmp1.Val) Result = Tmp1;
@@ -1907,7 +2130,17 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       MVT::ValueType StVT = cast<StoreSDNode>(Result.Val)->getStoredVT();
       switch (TLI.getStoreXAction(StVT)) {
       default: assert(0 && "This action is not supported yet!");
-      case TargetLowering::Legal: break;
+      case TargetLowering::Legal:
+        // If this is an unaligned store and the target doesn't support it,
+        // expand it.
+        if (!TLI.allowsUnalignedMemoryAccesses()) {
+          unsigned ABIAlignment = TLI.getTargetData()->
+            getABITypeAlignment(MVT::getTypeForValueType(ST->getStoredVT()));
+          if (ST->getAlignment() < ABIAlignment)
+            Result = ExpandUnalignedStore(cast<StoreSDNode>(Result.Val), DAG,
+                                          TLI);
+        }
+        break;
       case TargetLowering::Custom:
         Tmp1 = TLI.LowerOperation(Result, DAG);
         if (Tmp1.Val) Result = Tmp1;
@@ -2344,6 +2577,55 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       if (Tmp1.Val) Result = Tmp1;
       break;
     case TargetLowering::Expand: {
+      MVT::ValueType VT = Op.getValueType();
+      // See if multiply or divide can be lowered using two-result operations.
+      SDVTList VTs = DAG.getVTList(VT, VT);
+      if (Node->getOpcode() == ISD::MUL) {
+        // We just need the low half of the multiply; try both the signed
+        // and unsigned forms. If the target supports both SMUL_LOHI and
+        // UMUL_LOHI, form a preference by checking which forms of plain
+        // MULH it supports.
+        bool HasSMUL_LOHI = TLI.isOperationLegal(ISD::SMUL_LOHI, VT);
+        bool HasUMUL_LOHI = TLI.isOperationLegal(ISD::UMUL_LOHI, VT);
+        bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, VT);
+        bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, VT);
+        unsigned OpToUse = 0;
+        if (HasSMUL_LOHI && !HasMULHS) {
+          OpToUse = ISD::SMUL_LOHI;
+        } else if (HasUMUL_LOHI && !HasMULHU) {
+          OpToUse = ISD::UMUL_LOHI;
+        } else if (HasSMUL_LOHI) {
+          OpToUse = ISD::SMUL_LOHI;
+        } else if (HasUMUL_LOHI) {
+          OpToUse = ISD::UMUL_LOHI;
+        }
+        if (OpToUse) {
+          Result = SDOperand(DAG.getNode(OpToUse, VTs, Tmp1, Tmp2).Val, 0);
+          break;
+        }
+      }
+      if (Node->getOpcode() == ISD::MULHS &&
+          TLI.isOperationLegal(ISD::SMUL_LOHI, VT)) {
+        Result = SDOperand(DAG.getNode(ISD::SMUL_LOHI, VTs, Tmp1, Tmp2).Val, 1);
+        break;
+      }
+      if (Node->getOpcode() == ISD::MULHU && 
+          TLI.isOperationLegal(ISD::UMUL_LOHI, VT)) {
+        Result = SDOperand(DAG.getNode(ISD::UMUL_LOHI, VTs, Tmp1, Tmp2).Val, 1);
+        break;
+      }
+      if (Node->getOpcode() == ISD::SDIV &&
+          TLI.isOperationLegal(ISD::SDIVREM, VT)) {
+        Result = SDOperand(DAG.getNode(ISD::SDIVREM, VTs, Tmp1, Tmp2).Val, 0);
+        break;
+      }
+      if (Node->getOpcode() == ISD::UDIV &&
+          TLI.isOperationLegal(ISD::UDIVREM, VT)) {
+        Result = SDOperand(DAG.getNode(ISD::UDIVREM, VTs, Tmp1, Tmp2).Val, 0);
+        break;
+      }
+
       if (Node->getValueType(0) == MVT::i32) {
         switch (Node->getOpcode()) {
         default:  assert(0 && "Do not know how to expand this integer BinOp!");
@@ -2397,6 +2679,20 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     }
     break;
     
+  case ISD::SMUL_LOHI:
+  case ISD::UMUL_LOHI:
+  case ISD::SDIVREM:
+  case ISD::UDIVREM:
+    // These nodes will only be produced by target-specific lowering, so
+    // they shouldn't be here if they aren't legal.
+    assert(TLI.isOperationLegal(Node->getValueType(0), Node->getValueType(0)) &&
+           "This must be legal!");
+
+    Tmp1 = LegalizeOp(Node->getOperand(0));   // LHS
+    Tmp2 = LegalizeOp(Node->getOperand(1));   // RHS
+    Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
+    break;
+
   case ISD::FCOPYSIGN:  // FCOPYSIGN does not require LHS/RHS to match type!
     Tmp1 = LegalizeOp(Node->getOperand(0));   // LHS
     switch (getTypeAction(Node->getOperand(1).getValueType())) {
@@ -2521,19 +2817,33 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
         if (Tmp1.Val) Result = Tmp1;
       }
       break;
-    case TargetLowering::Expand:
+    case TargetLowering::Expand: {
       unsigned DivOpc= (Node->getOpcode() == ISD::UREM) ? ISD::UDIV : ISD::SDIV;
       bool isSigned = DivOpc == ISD::SDIV;
-      if (MVT::isInteger(Node->getValueType(0))) {
-        if (TLI.getOperationAction(DivOpc, Node->getValueType(0)) ==
+      MVT::ValueType VT = Node->getValueType(0);
+      // See if remainder can be lowered using two-result operations.
+      SDVTList VTs = DAG.getVTList(VT, VT);
+      if (Node->getOpcode() == ISD::SREM &&
+          TLI.isOperationLegal(ISD::SDIVREM, VT)) {
+        Result = SDOperand(DAG.getNode(ISD::SDIVREM, VTs, Tmp1, Tmp2).Val, 1);
+        break;
+      }
+      if (Node->getOpcode() == ISD::UREM &&
+          TLI.isOperationLegal(ISD::UDIVREM, VT)) {
+        Result = SDOperand(DAG.getNode(ISD::UDIVREM, VTs, Tmp1, Tmp2).Val, 1);
+        break;
+      }
+
+      if (MVT::isInteger(VT)) {
+        if (TLI.getOperationAction(DivOpc, VT) ==
             TargetLowering::Legal) {
           // X % Y -> X-X/Y*Y
-          MVT::ValueType VT = Node->getValueType(0);
           Result = DAG.getNode(DivOpc, VT, Tmp1, Tmp2);
           Result = DAG.getNode(ISD::MUL, VT, Result, Tmp2);
           Result = DAG.getNode(ISD::SUB, VT, Tmp1, Result);
         } else {
-          assert(Node->getValueType(0) == MVT::i32 &&
+          assert(VT == MVT::i32 &&
                  "Cannot expand this binary operator!");
           RTLIB::Libcall LC = Node->getOpcode() == ISD::UREM
             ? RTLIB::UREM_I32 : RTLIB::SREM_I32;
@@ -2542,7 +2852,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
         }
       } else {
         // Floating point mod -> fmod libcall.
-        RTLIB::Libcall LC = Node->getValueType(0) == MVT::f32
+        RTLIB::Libcall LC = VT == MVT::f32
           ? RTLIB::REM_F32 : RTLIB::REM_F64;
         SDOperand Dummy;
         Result = ExpandLibCall(TLI.getLibcallName(LC), Node,
@@ -2550,6 +2860,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       }
       break;
     }
+    }
     break;
   case ISD::VAARG: {
     Tmp1 = LegalizeOp(Node->getOperand(0));  // Legalize the chain.
@@ -2722,9 +3033,16 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
   case ISD::CTLZ:
     Tmp1 = LegalizeOp(Node->getOperand(0));   // Op
     switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
-    case TargetLowering::Custom: assert(0 && "Cannot custom handle this yet!");
+    case TargetLowering::Custom:
     case TargetLowering::Legal:
       Result = DAG.UpdateNodeOperands(Result, Tmp1);
+      if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) ==
+          TargetLowering::Custom) {
+        Tmp1 = TLI.LowerOperation(Result, DAG);
+        if (Tmp1.Val) {
+          Result = Tmp1;
+        }
+      }
       break;
     case TargetLowering::Promote: {
       MVT::ValueType OVT = Tmp1.getValueType();
@@ -2744,7 +3062,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
                             DAG.getConstant(MVT::getSizeInBits(NVT), NVT),
                             ISD::SETEQ);
         Result = DAG.getNode(ISD::SELECT, NVT, Tmp2,
-                           DAG.getConstant(MVT::getSizeInBits(OVT),NVT), Tmp1);
+                             DAG.getConstant(MVT::getSizeInBits(OVT),NVT), Tmp1);
         break;
       case ISD::CTLZ:
         // Tmp1 = Tmp1 - (sizeinbits(NVT) - sizeinbits(Old VT))
@@ -2804,7 +3122,11 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
         RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
         switch(Node->getOpcode()) {
         case ISD::FSQRT:
-          LC = VT == MVT::f32 ? RTLIB::SQRT_F32 : RTLIB::SQRT_F64;
+          LC = VT == MVT::f32 ? RTLIB::SQRT_F32 : 
+               VT == MVT::f64 ? RTLIB::SQRT_F64 : 
+               VT == MVT::f80 ? RTLIB::SQRT_F80 :
+               VT == MVT::ppcf128 ? RTLIB::SQRT_PPCF128 :
+               RTLIB::UNKNOWN_LIBCALL;
           break;
         case ISD::FSIN:
           LC = VT == MVT::f32 ? RTLIB::SIN_F32 : RTLIB::SIN_F64;
@@ -2825,8 +3147,12 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     break;
   case ISD::FPOWI: {
     // We always lower FPOWI into a libcall.  No target support it yet.
-    RTLIB::Libcall LC = Node->getValueType(0) == MVT::f32
-      ? RTLIB::POWI_F32 : RTLIB::POWI_F64;
+    RTLIB::Libcall LC = 
+      Node->getValueType(0) == MVT::f32 ? RTLIB::POWI_F32 : 
+      Node->getValueType(0) == MVT::f64 ? RTLIB::POWI_F64 : 
+      Node->getValueType(0) == MVT::f80 ? RTLIB::POWI_F80 : 
+      Node->getValueType(0) == MVT::ppcf128 ? RTLIB::POWI_PPCF128 : 
+      RTLIB::UNKNOWN_LIBCALL;
     SDOperand Dummy;
     Result = ExpandLibCall(TLI.getLibcallName(LC), Node,
                            false/*sign irrelevant*/, Dummy);
@@ -2972,8 +3298,13 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
           SDOperand True, False;
           MVT::ValueType VT =  Node->getOperand(0).getValueType();
           MVT::ValueType NVT = Node->getValueType(0);
-          unsigned ShiftAmt = MVT::getSizeInBits(Node->getValueType(0))-1;
-          Tmp2 = DAG.getConstantFP((double)(1ULL << ShiftAmt), VT);
+          unsigned ShiftAmt = MVT::getSizeInBits(NVT)-1;
+          const uint64_t zero[] = {0, 0};
+          APFloat apf = APFloat(APInt(MVT::getSizeInBits(VT), 2, zero));
+          uint64_t x = 1ULL << ShiftAmt;
+          (void)apf.convertFromZeroExtendedInteger
+            (&x, MVT::getSizeInBits(NVT), false, APFloat::rmNearestTiesToEven);
+          Tmp2 = DAG.getConstantFP(apf, VT);
           Tmp3 = DAG.getSetCC(TLI.getSetCCResultTy(),
                             Node->getOperand(0), Tmp2, ISD::SETLT);
           True = DAG.getNode(ISD::FP_TO_SINT, NVT, Node->getOperand(0));
@@ -2995,22 +3326,42 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       MVT::ValueType VT = Op.getValueType();
       RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
       switch (Node->getOpcode()) {
-      case ISD::FP_TO_SINT:
-        if (Node->getOperand(0).getValueType() == MVT::f32)
+      case ISD::FP_TO_SINT: {
+        MVT::ValueType OVT = Node->getOperand(0).getValueType();
+        if (OVT == MVT::f32)
           LC = (VT == MVT::i32)
             ? RTLIB::FPTOSINT_F32_I32 : RTLIB::FPTOSINT_F32_I64;
-        else
+        else if (OVT == MVT::f64)
           LC = (VT == MVT::i32)
             ? RTLIB::FPTOSINT_F64_I32 : RTLIB::FPTOSINT_F64_I64;
+        else if (OVT == MVT::f80) {
+          assert(VT == MVT::i64);
+          LC = RTLIB::FPTOSINT_F80_I64;
+        }
+        else if (OVT == MVT::ppcf128) {
+          assert(VT == MVT::i64);
+          LC = RTLIB::FPTOSINT_PPCF128_I64;
+        }
         break;
-      case ISD::FP_TO_UINT:
-        if (Node->getOperand(0).getValueType() == MVT::f32)
+      }
+      case ISD::FP_TO_UINT: {
+        MVT::ValueType OVT = Node->getOperand(0).getValueType();
+        if (OVT == MVT::f32)
           LC = (VT == MVT::i32)
             ? RTLIB::FPTOUINT_F32_I32 : RTLIB::FPTOSINT_F32_I64;
-        else
+        else if (OVT == MVT::f64)
           LC = (VT == MVT::i32)
             ? RTLIB::FPTOUINT_F64_I32 : RTLIB::FPTOSINT_F64_I64;
+        else if (OVT == MVT::f80) {
+          LC = (VT == MVT::i32)
+            ? RTLIB::FPTOUINT_F80_I32 : RTLIB::FPTOUINT_F80_I64;
+        }
+        else if (OVT ==  MVT::ppcf128) {
+          assert(VT == MVT::i64);
+          LC = RTLIB::FPTOUINT_PPCF128_I64;
+        }
         break;
+      }
       default: assert(0 && "Unreachable!");
       }
       SDOperand Dummy;
@@ -3026,33 +3377,53 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     }
     break;
 
-  case ISD::FP_ROUND:
-    if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) == 
-        TargetLowering::Expand) {
-      // The only way we can lower this is to turn it into a TRUNCSTORE,
-      // EXTLOAD pair, targetting a temporary location (a stack slot).
-
-      // NOTE: there is a choice here between constantly creating new stack
-      // slots and always reusing the same one.  We currently always create
-      // new ones, as reuse may inhibit scheduling.
-      MVT::ValueType VT = Op.getValueType();    // 32
-      const Type *Ty = MVT::getTypeForValueType(VT);
-      uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty);
-      unsigned Align  = TLI.getTargetData()->getPrefTypeAlignment(Ty);
-      MachineFunction &MF = DAG.getMachineFunction();
-      int SSFI =
-        MF.getFrameInfo()->CreateStackObject(TySize, Align);
-      SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
-      Result = DAG.getTruncStore(DAG.getEntryNode(), Node->getOperand(0),
-                                 StackSlot, NULL, 0, VT);
-      Result = DAG.getLoad(VT, Result, StackSlot, NULL, 0, VT);
-      break;
+  case ISD::FP_EXTEND: 
+  case ISD::FP_ROUND: {
+      MVT::ValueType newVT = Op.getValueType();
+      MVT::ValueType oldVT = Op.getOperand(0).getValueType();
+      if (TLI.getConvertAction(oldVT, newVT) == TargetLowering::Expand) {
+        if (Node->getOpcode() == ISD::FP_ROUND && oldVT == MVT::ppcf128) {
+          SDOperand Lo, Hi;
+          ExpandOp(Node->getOperand(0), Lo, Hi);
+          if (newVT == MVT::f64)
+            Result = Hi;
+          else
+            Result = DAG.getNode(ISD::FP_ROUND, newVT, Hi);
+          break;
+        } else {
+          // The only other way we can lower this is to turn it into a STORE,
+          // LOAD pair, targetting a temporary location (a stack slot).
+
+          // NOTE: there is a choice here between constantly creating new stack
+          // slots and always reusing the same one.  We currently always create
+          // new ones, as reuse may inhibit scheduling.
+          MVT::ValueType slotVT = 
+                  (Node->getOpcode() == ISD::FP_EXTEND) ? oldVT : newVT;
+          const Type *Ty = MVT::getTypeForValueType(slotVT);
+          uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty);
+          unsigned Align  = TLI.getTargetData()->getPrefTypeAlignment(Ty);
+          MachineFunction &MF = DAG.getMachineFunction();
+          int SSFI =
+            MF.getFrameInfo()->CreateStackObject(TySize, Align);
+          SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
+          if (Node->getOpcode() == ISD::FP_EXTEND) {
+            Result = DAG.getStore(DAG.getEntryNode(), Node->getOperand(0),
+                                       StackSlot, NULL, 0);
+            Result = DAG.getExtLoad(ISD::EXTLOAD, newVT,
+                                       Result, StackSlot, NULL, 0, oldVT);
+          } else {
+            Result = DAG.getTruncStore(DAG.getEntryNode(), Node->getOperand(0),
+                                       StackSlot, NULL, 0, newVT);
+            Result = DAG.getLoad(newVT, Result, StackSlot, NULL, 0, newVT);
+          }
+          break;
+        }
+      }
     }
     // FALL THROUGH
   case ISD::ANY_EXTEND:
   case ISD::ZERO_EXTEND:
   case ISD::SIGN_EXTEND:
-  case ISD::FP_EXTEND:
     switch (getTypeAction(Node->getOperand(0).getValueType())) {
     case Expand: assert(0 && "Shouldn't need to expand other operators here!");
     case Legal:
@@ -3140,6 +3511,23 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     }
     break;
   }
+  case ISD::TRAMPOLINE: {
+    SDOperand Ops[6];
+    for (unsigned i = 0; i != 6; ++i)
+      Ops[i] = LegalizeOp(Node->getOperand(i));
+    Result = DAG.UpdateNodeOperands(Result, Ops, 6);
+    // The only option for this node is to custom lower it.
+    Result = TLI.LowerOperation(Result, DAG);
+    assert(Result.Val && "Should always custom lower!");
+
+    // Since trampoline produces two values, make sure to remember that we
+    // legalized both of them.
+    Tmp1 = LegalizeOp(Result.getValue(1));
+    Result = LegalizeOp(Result);
+    AddLegalizedOperand(SDOperand(Node, 0), Result);
+    AddLegalizedOperand(SDOperand(Node, 1), Tmp1);
+    return Op.ResNo ? Tmp1 : Result;
+  }
   }
   
   assert(Result.getValueType() == Op.getValueType() &&
@@ -3587,8 +3975,7 @@ SDOperand SelectionDAGLegalize::ExpandEXTRACT_VECTOR_ELT(SDOperand Op) {
   SDOperand Vec = Op.getOperand(0);
   SDOperand Idx = Op.getOperand(1);
   
-  SDNode *InVal = Vec.Val;
-  MVT::ValueType TVT = InVal->getValueType(0);
+  MVT::ValueType TVT = Vec.getValueType();
   unsigned NumElems = MVT::getVectorNumElements(TVT);
   
   switch (TLI.getOperationAction(ISD::EXTRACT_VECTOR_ELT, TVT)) {
@@ -3605,7 +3992,7 @@ SDOperand SelectionDAGLegalize::ExpandEXTRACT_VECTOR_ELT(SDOperand Op) {
     if (isTypeLegal(TVT)) {
       Vec = LegalizeOp(Vec);
       Op = DAG.UpdateNodeOperands(Op, Vec, Idx);
-      Op = LegalizeOp(Op);
+      return Op;
     }
     break;
   case TargetLowering::Expand:
@@ -3686,7 +4073,7 @@ SDOperand SelectionDAGLegalize::ExpandEXTRACT_SUBVECTOR(SDOperand Op) {
 void SelectionDAGLegalize::LegalizeSetCCOperands(SDOperand &LHS,
                                                  SDOperand &RHS,
                                                  SDOperand &CC) {
-  SDOperand Tmp1, Tmp2, Result;    
+  SDOperand Tmp1, Tmp2, Tmp3, Result;    
   
   switch (getTypeAction(LHS.getValueType())) {
   case Legal:
@@ -3817,8 +4204,27 @@ void SelectionDAGLegalize::LegalizeSetCCOperands(SDOperand &LHS,
 
     SDOperand LHSLo, LHSHi, RHSLo, RHSHi;
     ExpandOp(LHS, LHSLo, LHSHi);
-    ExpandOp(RHS, RHSLo, RHSHi);    
-    switch (cast<CondCodeSDNode>(CC)->get()) {
+    ExpandOp(RHS, RHSLo, RHSHi);
+    ISD::CondCode CCCode = cast<CondCodeSDNode>(CC)->get();
+
+    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.
+      Tmp1 = DAG.getSetCC(TLI.getSetCCResultTy(), LHSHi, RHSHi, ISD::SETEQ);
+      Tmp2 = DAG.getSetCC(TLI.getSetCCResultTy(), LHSLo, RHSLo, CCCode);
+      Tmp3 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2);
+      Tmp1 = DAG.getSetCC(TLI.getSetCCResultTy(), LHSHi, RHSHi, ISD::SETNE);
+      Tmp2 = DAG.getSetCC(TLI.getSetCCResultTy(), LHSHi, RHSHi, CCCode);
+      Tmp1 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2);
+      Tmp1 = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp3);
+      Tmp2 = SDOperand();
+      break;
+    }
+
+    switch (CCCode) {
     case ISD::SETEQ:
     case ISD::SETNE:
       if (RHSLo == RHSHi)
@@ -3850,7 +4256,6 @@ void SelectionDAGLegalize::LegalizeSetCCOperands(SDOperand &LHS,
 
       // FIXME: This generated code sucks.
       ISD::CondCode LowCC;
-      ISD::CondCode CCCode = cast<CondCodeSDNode>(CC)->get();
       switch (CCCode) {
       default: assert(0 && "Unknown integer setcc!");
       case ISD::SETLT:
@@ -3983,7 +4388,7 @@ SDOperand SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
     for (unsigned i = 0, e = NumElems; i != e; ++i) {
       if (ConstantFPSDNode *V = 
           dyn_cast<ConstantFPSDNode>(Node->getOperand(i))) {
-        CV.push_back(ConstantFP::get(OpNTy, V->getValue()));
+        CV.push_back(ConstantFP::get(OpNTy, V->getValueAPF()));
       } else if (ConstantSDNode *V = 
                  dyn_cast<ConstantSDNode>(Node->getOperand(i))) {
         CV.push_back(ConstantInt::get(OpNTy, V->getValue()));
@@ -4349,12 +4754,13 @@ ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source) {
     SDOperand FudgeInReg;
     if (DestTy == MVT::f32)
       FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0);
-    else {
-      assert(DestTy == MVT::f64 && "Unexpected conversion");
+    else if (MVT::getSizeInBits(DestTy) > MVT::getSizeInBits(MVT::f32))
       // FIXME: Avoid the extend by construction the right constantpool?
-      FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, MVT::f64, DAG.getEntryNode(),
+      FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(),
                                   CPIdx, NULL, 0, MVT::f32);
-    }
+    else 
+      assert(0 && "Unexpected conversion");
+
     MVT::ValueType SCVT = SignedConv.getValueType();
     if (SCVT != DestTy) {
       // Destination type needs to be expanded as well. The FADD now we are
@@ -4462,9 +4868,10 @@ SDOperand SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
     if (DestVT == MVT::f64) {
       // do nothing
       Result = Sub;
-    } else {
-     // if f32 then cast to f32
-      Result = DAG.getNode(ISD::FP_ROUND, MVT::f32, Sub);
+    } else if (MVT::getSizeInBits(DestVT) < MVT::getSizeInBits(MVT::f64)) {
+      Result = DAG.getNode(ISD::FP_ROUND, DestVT, Sub);
+    } else if (MVT::getSizeInBits(DestVT) > MVT::getSizeInBits(MVT::f64)) {
+      Result = DAG.getNode(ISD::FP_EXTEND, DestVT, Sub);
     }
     return Result;
   }
@@ -4498,8 +4905,7 @@ SDOperand SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
   if (DestVT == MVT::f32)
     FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0);
   else {
-    assert(DestVT == MVT::f64 && "Unexpected conversion");
-    FudgeInReg = LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, MVT::f64,
+    FudgeInReg = LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, DestVT,
                                            DAG.getEntryNode(), CPIdx,
                                            NULL, 0, MVT::f32));
   }
@@ -5078,11 +5484,15 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
       }
     }
 
-    RTLIB::Libcall LC;
+    RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
     if (Node->getOperand(0).getValueType() == MVT::f32)
       LC = RTLIB::FPTOSINT_F32_I64;
-    else
+    else if (Node->getOperand(0).getValueType() == MVT::f64)
       LC = RTLIB::FPTOSINT_F64_I64;
+    else if (Node->getOperand(0).getValueType() == MVT::f80)
+      LC = RTLIB::FPTOSINT_F80_I64;
+    else if (Node->getOperand(0).getValueType() == MVT::ppcf128)
+      LC = RTLIB::FPTOSINT_PPCF128_I64;
     Lo = ExpandLibCall(TLI.getLibcallName(LC), Node,
                        false/*sign irrelevant*/, Hi);
     break;
@@ -5106,11 +5516,15 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
       }
     }
 
-    RTLIB::Libcall LC;
+    RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
     if (Node->getOperand(0).getValueType() == MVT::f32)
       LC = RTLIB::FPTOUINT_F32_I64;
-    else
+    else if (Node->getOperand(0).getValueType() == MVT::f64)
       LC = RTLIB::FPTOUINT_F64_I64;
+    else if (Node->getOperand(0).getValueType() == MVT::f80)
+      LC = RTLIB::FPTOUINT_F80_I64;
+    else if (Node->getOperand(0).getValueType() == MVT::ppcf128)
+      LC = RTLIB::FPTOUINT_PPCF128_I64;
     Lo = ExpandLibCall(TLI.getLibcallName(LC), Node,
                        false/*sign irrelevant*/, Hi);
     break;
@@ -5320,36 +5734,55 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
     
     bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, NVT);
     bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, NVT);
-    if (HasMULHS || HasMULHU) {
+    bool HasSMUL_LOHI = TLI.isOperationLegal(ISD::SMUL_LOHI, NVT);
+    bool HasUMUL_LOHI = TLI.isOperationLegal(ISD::UMUL_LOHI, NVT);
+    if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) {
       SDOperand LL, LH, RL, RH;
       ExpandOp(Node->getOperand(0), LL, LH);
       ExpandOp(Node->getOperand(1), RL, RH);
-      unsigned SH = MVT::getSizeInBits(RH.getValueType())-1;
-      // FIXME: Move this to the dag combiner.
-      // MULHS implicitly sign extends its inputs.  Check to see if ExpandOp
-      // extended the sign bit of the low half through the upper half, and if so
-      // emit a MULHS instead of the alternate sequence that is valid for any
-      // i64 x i64 multiply.
-      if (HasMULHS &&
-          // is RH an extension of the sign bit of RL?
-          RH.getOpcode() == ISD::SRA && RH.getOperand(0) == RL &&
-          RH.getOperand(1).getOpcode() == ISD::Constant &&
-          cast<ConstantSDNode>(RH.getOperand(1))->getValue() == SH &&
-          // is LH an extension of the sign bit of LL?
-          LH.getOpcode() == ISD::SRA && LH.getOperand(0) == LL &&
-          LH.getOperand(1).getOpcode() == ISD::Constant &&
-          cast<ConstantSDNode>(LH.getOperand(1))->getValue() == SH) {
-        // Low part:
-        Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
-        // High part:
-        Hi = DAG.getNode(ISD::MULHS, NVT, LL, RL);
+      unsigned BitSize = MVT::getSizeInBits(RH.getValueType());
+      unsigned LHSSB = DAG.ComputeNumSignBits(Op.getOperand(0));
+      unsigned RHSSB = DAG.ComputeNumSignBits(Op.getOperand(1));
+      // FIXME: generalize this to handle other bit sizes
+      if (LHSSB == 32 && RHSSB == 32 &&
+          DAG.MaskedValueIsZero(Op.getOperand(0), 0xFFFFFFFF00000000ULL) &&
+          DAG.MaskedValueIsZero(Op.getOperand(1), 0xFFFFFFFF00000000ULL)) {
+        // The inputs are both zero-extended.
+        if (HasUMUL_LOHI) {
+          // We can emit a umul_lohi.
+          Lo = DAG.getNode(ISD::UMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL);
+          Hi = SDOperand(Lo.Val, 1);
+          break;
+        }
+        if (HasMULHU) {
+          // We can emit a mulhu+mul.
+          Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+          Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
+          break;
+        }
         break;
-      } else if (HasMULHU) {
-        // Low part:
-        Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
-        
-        // High part:
-        Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
+      }
+      if (LHSSB > BitSize && RHSSB > BitSize) {
+        // The input values are both sign-extended.
+        if (HasSMUL_LOHI) {
+          // We can emit a smul_lohi.
+          Lo = DAG.getNode(ISD::SMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL);
+          Hi = SDOperand(Lo.Val, 1);
+          break;
+        }
+        if (HasMULHS) {
+          // We can emit a mulhs+mul.
+          Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+          Hi = DAG.getNode(ISD::MULHS, NVT, LL, RL);
+          break;
+        }
+      }
+      if (HasUMUL_LOHI) {
+        // Lo,Hi = umul LHS, RHS.
+        SDOperand UMulLOHI = DAG.getNode(ISD::UMUL_LOHI,
+                                         DAG.getVTList(NVT, NVT), LL, RL);
+        Lo = UMulLOHI;
+        Hi = UMulLOHI.getValue(1);
         RH = DAG.getNode(ISD::MUL, NVT, LL, RH);
         LH = DAG.getNode(ISD::MUL, NVT, LH, RL);
         Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH);
@@ -5358,6 +5791,7 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
       }
     }
 
+    // If nothing else, we can make a libcall.
     Lo = ExpandLibCall(TLI.getLibcallName(RTLIB::MUL_I64), Node,
                        false/*sign irrelevant*/, Hi);
     break;
@@ -5376,23 +5810,35 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
     break;
 
   case ISD::FADD:
-    Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
-                                          ? RTLIB::ADD_F32 : RTLIB::ADD_F64),
+    Lo = ExpandLibCall(TLI.getLibcallName(VT == MVT::f32 ? RTLIB::ADD_F32 : 
+                                          VT == MVT::f64 ? RTLIB::ADD_F64 :
+                                          VT == MVT::ppcf128 ? 
+                                                      RTLIB::ADD_PPCF128 :
+                                          RTLIB::UNKNOWN_LIBCALL),
                        Node, false, Hi);
     break;
   case ISD::FSUB:
-    Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
-                                          ? RTLIB::SUB_F32 : RTLIB::SUB_F64),
+    Lo = ExpandLibCall(TLI.getLibcallName(VT == MVT::f32 ? RTLIB::SUB_F32 :
+                                          VT == MVT::f64 ? RTLIB::SUB_F64 :
+                                          VT == MVT::ppcf128 ? 
+                                                      RTLIB::SUB_PPCF128 :
+                                          RTLIB::UNKNOWN_LIBCALL),
                        Node, false, Hi);
     break;
   case ISD::FMUL:
-    Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
-                                          ? RTLIB::MUL_F32 : RTLIB::MUL_F64),
+    Lo = ExpandLibCall(TLI.getLibcallName(VT == MVT::f32 ? RTLIB::MUL_F32 :
+                                          VT == MVT::f64 ? RTLIB::MUL_F64 :
+                                          VT == MVT::ppcf128 ? 
+                                                      RTLIB::MUL_PPCF128 :
+                                          RTLIB::UNKNOWN_LIBCALL),
                        Node, false, Hi);
     break;
   case ISD::FDIV:
-    Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
-                                          ? RTLIB::DIV_F32 : RTLIB::DIV_F64),
+    Lo = ExpandLibCall(TLI.getLibcallName(VT == MVT::f32 ? RTLIB::DIV_F32 :
+                                          VT == MVT::f64 ? RTLIB::DIV_F64 :
+                                          VT == MVT::ppcf128 ? 
+                                                      RTLIB::DIV_PPCF128 :
+                                          RTLIB::UNKNOWN_LIBCALL),
                        Node, false, Hi);
     break;
   case ISD::FP_EXTEND:
@@ -5401,13 +5847,26 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
   case ISD::FP_ROUND:
     Lo = ExpandLibCall(TLI.getLibcallName(RTLIB::FPROUND_F64_F32),Node,true,Hi);
     break;
+  case ISD::FPOWI:
+    Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32) ? RTLIB::POWI_F32 : 
+                                          (VT == MVT::f64) ? RTLIB::POWI_F64 :
+                                          (VT == MVT::f80) ? RTLIB::POWI_F80 :
+                                          (VT == MVT::ppcf128) ? 
+                                                         RTLIB::POWI_PPCF128 :
+                                          RTLIB::UNKNOWN_LIBCALL),
+                       Node, false, Hi);
+    break;
   case ISD::FSQRT:
   case ISD::FSIN:
   case ISD::FCOS: {
     RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
     switch(Node->getOpcode()) {
     case ISD::FSQRT:
-      LC = (VT == MVT::f32) ? RTLIB::SQRT_F32 : RTLIB::SQRT_F64;
+      LC = (VT == MVT::f32) ? RTLIB::SQRT_F32 : 
+           (VT == MVT::f64) ? RTLIB::SQRT_F64 : 
+           (VT == MVT::f80) ? RTLIB::SQRT_F80 : 
+           (VT == MVT::ppcf128) ? RTLIB::SQRT_PPCF128 : 
+           RTLIB::UNKNOWN_LIBCALL;
       break;
     case ISD::FSIN:
       LC = (VT == MVT::f32) ? RTLIB::SIN_F32 : RTLIB::SIN_F64;
@@ -5452,12 +5911,20 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
   case ISD::UINT_TO_FP: {
     bool isSigned = Node->getOpcode() == ISD::SINT_TO_FP;
     MVT::ValueType SrcVT = Node->getOperand(0).getValueType();
-    RTLIB::Libcall LC;
+    RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
     if (Node->getOperand(0).getValueType() == MVT::i64) {
       if (VT == MVT::f32)
         LC = isSigned ? RTLIB::SINTTOFP_I64_F32 : RTLIB::UINTTOFP_I64_F32;
-      else
+      else if (VT == MVT::f64)
         LC = isSigned ? RTLIB::SINTTOFP_I64_F64 : RTLIB::UINTTOFP_I64_F64;
+      else if (VT == MVT::f80) {
+        assert(isSigned);
+        LC = RTLIB::SINTTOFP_I64_F80;
+      }
+      else if (VT == MVT::ppcf128) {
+        assert(isSigned);
+        LC = RTLIB::SINTTOFP_I64_PPCF128;
+      }
     } else {
       if (VT == MVT::f32)
         LC = isSigned ? RTLIB::SINTTOFP_I32_F32 : RTLIB::UINTTOFP_I32_F32;
@@ -5508,10 +5975,10 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
                                          SDOperand &Hi) {
   assert(MVT::isVector(Op.getValueType()) && "Cannot split non-vector type!");
   SDNode *Node = Op.Val;
-  unsigned NumElements = MVT::getVectorNumElements(Node->getValueType(0));
+  unsigned NumElements = MVT::getVectorNumElements(Op.getValueType());
   assert(NumElements > 1 && "Cannot split a single element vector!");
   unsigned NewNumElts = NumElements/2;
-  MVT::ValueType NewEltVT = MVT::getVectorElementType(Node->getValueType(0));
+  MVT::ValueType NewEltVT = MVT::getVectorElementType(Op.getValueType());
   MVT::ValueType NewVT = MVT::getVectorType(NewEltVT, NewNumElts);
   
   // See if we already split it.
@@ -5533,6 +6000,18 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
     Lo = Node->getOperand(0);
     Hi = Node->getOperand(1);
     break;
+  case ISD::INSERT_VECTOR_ELT: {
+    SplitVectorOp(Node->getOperand(0), Lo, Hi);
+    unsigned Index = cast<ConstantSDNode>(Node->getOperand(2))->getValue();
+    SDOperand ScalarOp = Node->getOperand(1);
+    if (Index < NewNumElts)
+      Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT, Lo, ScalarOp,
+                       DAG.getConstant(Index, TLI.getPointerTy()));
+    else
+      Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT, Hi, ScalarOp,
+                       DAG.getConstant(Index - NewNumElts, TLI.getPointerTy()));
+    break;
+  }
   case ISD::BUILD_VECTOR: {
     SmallVector<SDOperand, 8> LoOps(Node->op_begin(), 
                                     Node->op_begin()+NewNumElts);