Typo.
[oota-llvm.git] / lib / CodeGen / SelectionDAG / LegalizeDAGTypes.cpp
index e46f1bd2bbcbdcbe6cb41b950c269439923caba2..5ecda4851810d35787968e660bcf31626cfc6144 100644 (file)
 
 #define DEBUG_TYPE "legalize-types"
 #include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Alignment.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
 using namespace llvm;
@@ -55,14 +58,14 @@ class VISIBILITY_HIDDEN DAGTypeLegalizer {
   };
   
   enum LegalizeAction {
-    Legal,      // The target natively supports this operation.
-    Promote,    // This operation should be executed in a larger type.
-    Expand      // Try to expand this to other ops, otherwise use a libcall.
+    Legal,      // The target natively supports this type.
+    Promote,    // This type should be executed in a larger type.
+    Expand      // This type should be split into two types of half the size.
   };
   
   /// ValueTypeActions - This is a bitvector that contains two bits for each
-  /// value type, where the two bits correspond to the LegalizeAction enum.
-  /// This can be queried with "getTypeAction(VT)".
+  /// simple value type, where the two bits correspond to the LegalizeAction
+  /// enum.  This can be queried with "getTypeAction(VT)".
   TargetLowering::ValueTypeActionImpl ValueTypeActions;
   
   /// getTypeAction - Return how we should legalize values of this type, either
@@ -87,7 +90,7 @@ class VISIBILITY_HIDDEN DAGTypeLegalizer {
   DenseMap<SDOperand, SDOperand> PromotedNodes;
   
   /// ExpandedNodes - For nodes that need to be expanded this map indicates
-  /// which which operands are the expanded version of the input.
+  /// which operands are the expanded version of the input.
   DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > ExpandedNodes;
   
   /// Worklist - This defines a worklist of nodes to process.  In order to be
@@ -96,7 +99,7 @@ class VISIBILITY_HIDDEN DAGTypeLegalizer {
   SmallVector<SDNode*, 128> Worklist;
   
 public:
-  DAGTypeLegalizer(SelectionDAG &dag)
+  explicit DAGTypeLegalizer(SelectionDAG &dag)
     : TLI(dag.getTargetLoweringInfo()), DAG(dag),
     ValueTypeActions(TLI.getValueTypeActions()) {
     assert(MVT::LAST_VALUETYPE <= 32 &&
@@ -117,9 +120,22 @@ private:
   }    
   void SetPromotedOp(SDOperand Op, SDOperand Result);
 
+  /// GetPromotedZExtOp - Get a promoted operand and zero extend it to the final
+  /// size.
+  SDOperand GetPromotedZExtOp(SDOperand Op) {
+    MVT::ValueType OldVT = Op.getValueType();
+    Op = GetPromotedOp(Op);
+    return DAG.getZeroExtendInReg(Op, OldVT);
+  }    
+  
   void GetExpandedOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
   void SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi);
-    
+  
+  // Common routines.
+  SDOperand CreateStackStoreLoad(SDOperand Op, MVT::ValueType DestVT);
+  SDOperand HandleMemIntrinsic(SDNode *N);
+  void SplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
+
   // Result Promotion.
   void PromoteResult(SDNode *N, unsigned ResNo);
   SDOperand PromoteResult_UNDEF(SDNode *N);
@@ -127,9 +143,15 @@ private:
   SDOperand PromoteResult_TRUNCATE(SDNode *N);
   SDOperand PromoteResult_INT_EXTEND(SDNode *N);
   SDOperand PromoteResult_FP_ROUND(SDNode *N);
+  SDOperand PromoteResult_FP_TO_XINT(SDNode *N);
   SDOperand PromoteResult_SETCC(SDNode *N);
   SDOperand PromoteResult_LOAD(LoadSDNode *N);
   SDOperand PromoteResult_SimpleIntBinOp(SDNode *N);
+  SDOperand PromoteResult_SHL(SDNode *N);
+  SDOperand PromoteResult_SRA(SDNode *N);
+  SDOperand PromoteResult_SRL(SDNode *N);
+  SDOperand PromoteResult_SELECT   (SDNode *N);
+  SDOperand PromoteResult_SELECT_CC(SDNode *N);
   
   // Result Expansion.
   void ExpandResult(SDNode *N, unsigned ResNo);
@@ -139,10 +161,15 @@ private:
   void ExpandResult_ANY_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void ExpandResult_ZERO_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void ExpandResult_SIGN_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi);
+  void ExpandResult_BIT_CONVERT(SDNode *N, SDOperand &Lo, SDOperand &Hi);
+  void ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void ExpandResult_LOAD       (LoadSDNode *N, SDOperand &Lo, SDOperand &Hi);
 
   void ExpandResult_Logical    (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+  void ExpandResult_BSWAP      (SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void ExpandResult_ADDSUB     (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+  void ExpandResult_ADDSUBC    (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+  void ExpandResult_ADDSUBE    (SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void ExpandResult_SELECT     (SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void ExpandResult_SELECT_CC  (SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void ExpandResult_MUL        (SDNode *N, SDOperand &Lo, SDOperand &Hi);
@@ -157,15 +184,24 @@ private:
   SDOperand PromoteOperand_ANY_EXTEND(SDNode *N);
   SDOperand PromoteOperand_ZERO_EXTEND(SDNode *N);
   SDOperand PromoteOperand_SIGN_EXTEND(SDNode *N);
+  SDOperand PromoteOperand_TRUNCATE(SDNode *N);
   SDOperand PromoteOperand_FP_EXTEND(SDNode *N);
   SDOperand PromoteOperand_FP_ROUND(SDNode *N);
+  SDOperand PromoteOperand_INT_TO_FP(SDNode *N);
   SDOperand PromoteOperand_SELECT(SDNode *N, unsigned OpNo);
   SDOperand PromoteOperand_BRCOND(SDNode *N, unsigned OpNo);
+  SDOperand PromoteOperand_BR_CC(SDNode *N, unsigned OpNo);
+  SDOperand PromoteOperand_SETCC(SDNode *N, unsigned OpNo);
   SDOperand PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo);
-  
+
+  void PromoteSetCCOperands(SDOperand &LHS,SDOperand &RHS, ISD::CondCode Code);
+
   // Operand Expansion.
   bool ExpandOperand(SDNode *N, unsigned OperandNo);
   SDOperand ExpandOperand_TRUNCATE(SDNode *N);
+  SDOperand ExpandOperand_BIT_CONVERT(SDNode *N);
+  SDOperand ExpandOperand_UINT_TO_FP(SDOperand Source, MVT::ValueType DestTy);
+  SDOperand ExpandOperand_SINT_TO_FP(SDOperand Source, MVT::ValueType DestTy);
   SDOperand ExpandOperand_EXTRACT_ELEMENT(SDNode *N);
   SDOperand ExpandOperand_SETCC(SDNode *N);
   SDOperand ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo);
@@ -190,7 +226,7 @@ void DAGTypeLegalizer::run() {
   DAG.setRoot(SDOperand());
   
   // Walk all nodes in the graph, assigning them a NodeID of 'ReadyToProcess'
-  // (and remembering them) if they are leafs and assigning 'NewNode' if
+  // (and remembering them) if they are leaves and assigning 'NewNode' if
   // non-leaves.
   for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
        E = DAG.allnodes_end(); I != E; ++I) {
@@ -244,7 +280,7 @@ void DAGTypeLegalizer::run() {
       }
     }
 
-    // If the node needs revisitation, don't add all users to the worklist etc.
+    // If the node needs revisiting, don't add all users to the worklist etc.
     if (NeedsRevisit)
       continue;
     
@@ -328,7 +364,7 @@ void DAGTypeLegalizer::MarkNewNodes(SDNode *N) {
   // Okay, we know that this node is new.  Recursively walk all of its operands
   // to see if they are new also.  The depth of this walk is bounded by the size
   // of the new tree that was constructed (usually 2-3 nodes), so we don't worry
-  // about revisitation of nodes.
+  // about revisiting of nodes.
   //
   // As we walk the operands, keep track of the number of nodes that are
   // processed.  If non-zero, this will become the new nodeid of this node.
@@ -385,7 +421,6 @@ void DAGTypeLegalizer::SetPromotedOp(SDOperand Op, SDOperand Result) {
   OpEntry = Result;
 }
 
-
 void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo, 
                                      SDOperand &Hi) {
   std::pair<SDOperand, SDOperand> &Entry = ExpandedNodes[Op];
@@ -409,6 +444,76 @@ void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo,
     MarkNewNodes(Hi.Val);
 }
 
+SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op, 
+                                                 MVT::ValueType DestVT) {
+  // Create the stack frame object.
+  SDOperand FIPtr = DAG.CreateStackTemporary(DestVT);
+  
+  // Emit a store to the stack slot.
+  SDOperand Store = DAG.getStore(DAG.getEntryNode(), Op, FIPtr, NULL, 0);
+  // Result is a load from the stack slot.
+  return DAG.getLoad(DestVT, Store, FIPtr, NULL, 0);
+}
+
+/// HandleMemIntrinsic - This handles memcpy/memset/memmove with invalid
+/// operands.  This promotes or expands the operands as required.
+SDOperand DAGTypeLegalizer::HandleMemIntrinsic(SDNode *N) {
+  // The chain and pointer [operands #0 and #1] are always valid types.
+  SDOperand Chain = N->getOperand(0);
+  SDOperand Ptr   = N->getOperand(1);
+  SDOperand Op2   = N->getOperand(2);
+  
+  // Op #2 is either a value (memset) or a pointer.  Promote it if required.
+  switch (getTypeAction(Op2.getValueType())) {
+  default: assert(0 && "Unknown action for pointer/value operand");
+  case Legal: break;
+  case Promote: Op2 = GetPromotedOp(Op2); break;
+  }
+  
+  // The length could have any action required.
+  SDOperand Length = N->getOperand(3);
+  switch (getTypeAction(Length.getValueType())) {
+  default: assert(0 && "Unknown action for memop operand");
+  case Legal: break;
+  case Promote: Length = GetPromotedZExtOp(Length); break;
+  case Expand:
+    SDOperand Dummy;  // discard the high part.
+    GetExpandedOp(Length, Length, Dummy);
+    break;
+  }
+  
+  SDOperand Align = N->getOperand(4);
+  switch (getTypeAction(Align.getValueType())) {
+  default: assert(0 && "Unknown action for memop operand");
+  case Legal: break;
+  case Promote: Align = GetPromotedZExtOp(Align); break;
+  }
+  
+  SDOperand AlwaysInline = N->getOperand(5);
+  switch (getTypeAction(AlwaysInline.getValueType())) {
+  default: assert(0 && "Unknown action for memop operand");
+  case Legal: break;
+  case Promote: AlwaysInline = GetPromotedZExtOp(AlwaysInline); break;
+  }
+  
+  SDOperand Ops[] = { Chain, Ptr, Op2, Length, Align, AlwaysInline };
+  return DAG.UpdateNodeOperands(SDOperand(N, 0), Ops, 6);
+}
+
+/// SplitOp - Return the lower and upper halves of Op's bits in a value type
+/// half the size of Op's.
+void DAGTypeLegalizer::SplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) {
+  unsigned NVTBits = MVT::getSizeInBits(Op.getValueType())/2;
+  assert(MVT::getSizeInBits(Op.getValueType()) == 2*NVTBits &&
+         "Cannot split odd sized integer type");
+  MVT::ValueType NVT = MVT::getIntegerType(NVTBits);
+  Lo = DAG.getNode(ISD::TRUNCATE, NVT, Op);
+  Hi = DAG.getNode(ISD::SRL, Op.getValueType(), Op,
+                   DAG.getConstant(NVTBits, TLI.getShiftAmountTy()));
+  Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi);
+}
+
+
 //===----------------------------------------------------------------------===//
 //  Result Promotion
 //===----------------------------------------------------------------------===//
@@ -416,7 +521,7 @@ void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo,
 /// PromoteResult - This method is called when a result of a node is found to be
 /// in need of promotion to a larger type.  At this point, the node may also
 /// have invalid operands or may have other results that need expansion, we just
-/// know that (at least) the one result needs promotion.
+/// know that (at least) one result needs promotion.
 void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) {
   DEBUG(cerr << "Promote node result: "; N->dump(&DAG); cerr << "\n");
   SDOperand Result = SDOperand();
@@ -431,22 +536,31 @@ void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) {
     abort();
   case ISD::UNDEF:    Result = PromoteResult_UNDEF(N); break;
   case ISD::Constant: Result = PromoteResult_Constant(N); break;
-    
+
   case ISD::TRUNCATE:    Result = PromoteResult_TRUNCATE(N); break;
   case ISD::SIGN_EXTEND:
   case ISD::ZERO_EXTEND:
   case ISD::ANY_EXTEND:  Result = PromoteResult_INT_EXTEND(N); break;
   case ISD::FP_ROUND:    Result = PromoteResult_FP_ROUND(N); break;
-    
+  case ISD::FP_TO_SINT:
+  case ISD::FP_TO_UINT:  Result = PromoteResult_FP_TO_XINT(N); break;
   case ISD::SETCC:    Result = PromoteResult_SETCC(N); break;
   case ISD::LOAD:     Result = PromoteResult_LOAD(cast<LoadSDNode>(N)); break;
-    
+
   case ISD::AND:
   case ISD::OR:
   case ISD::XOR:
   case ISD::ADD:
   case ISD::SUB:
   case ISD::MUL:      Result = PromoteResult_SimpleIntBinOp(N); break;
+
+  case ISD::SHL:      Result = PromoteResult_SHL(N); break;
+  case ISD::SRA:      Result = PromoteResult_SRA(N); break;
+  case ISD::SRL:      Result = PromoteResult_SRL(N); break;
+
+  case ISD::SELECT:    Result = PromoteResult_SELECT(N); break;
+  case ISD::SELECT_CC: Result = PromoteResult_SELECT_CC(N); break;
+
   }      
   
   // If Result is null, the sub-method took care of registering the result.
@@ -470,46 +584,53 @@ SDOperand DAGTypeLegalizer::PromoteResult_Constant(SDNode *N) {
 }
 
 SDOperand DAGTypeLegalizer::PromoteResult_TRUNCATE(SDNode *N) {
-  MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+  SDOperand Res;
+
   switch (getTypeAction(N->getOperand(0).getValueType())) {
   default: assert(0 && "Unknown type action!");
-  case Legal: {
-    SDOperand Res = N->getOperand(0);
-    assert(Res.getValueType() >= NVT && "Truncation doesn't make sense!");
-    if (Res.getValueType() > NVT)             // Truncate to NVT instead of VT
-      return DAG.getNode(ISD::TRUNCATE, NVT, Res);
-    return Res;
-  }
-  case Promote:
-    // The truncation is not required, because we don't guarantee anything
-    // about high bits anyway.
-    return GetPromotedOp(N->getOperand(0));
+  case Legal:
   case Expand:
-    // Truncate the low part of the expanded value to the result type
-    SDOperand Lo, Hi;
-    GetExpandedOp(N->getOperand(0), Lo, Hi);
-    return DAG.getNode(ISD::TRUNCATE, NVT, Lo);
+    Res = N->getOperand(0);
+    break;
+  case Promote:
+    Res = GetPromotedOp(N->getOperand(0));
+    break;
   }
+
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+  assert(MVT::getSizeInBits(Res.getValueType()) >= MVT::getSizeInBits(NVT) &&
+         "Truncation doesn't make sense!");
+  if (Res.getValueType() == NVT)
+    return Res;
+
+  // Truncate to NVT instead of VT
+  return DAG.getNode(ISD::TRUNCATE, NVT, Res);
 }
+
 SDOperand DAGTypeLegalizer::PromoteResult_INT_EXTEND(SDNode *N) {
   MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
-  switch (getTypeAction(N->getOperand(0).getValueType())) {
-  default: assert(0 && "BUG: Smaller reg should have been promoted!");
-  case Legal:
-    // Input is legal?  Just do extend all the way to the larger type.
-    return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0));
-  case Promote:
-    // Get promoted operand if it is smaller.
+
+  if (getTypeAction(N->getOperand(0).getValueType()) == Promote) {
     SDOperand Res = GetPromotedOp(N->getOperand(0));
-    // The high bits are not guaranteed to be anything.  Insert an extend.
-    if (N->getOpcode() == ISD::SIGN_EXTEND)
-      return DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res,
-                         DAG.getValueType(N->getOperand(0).getValueType()));
-    if (N->getOpcode() == ISD::ZERO_EXTEND)
-      return DAG.getZeroExtendInReg(Res, N->getOperand(0).getValueType());
-    assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!");
-    return Res;
+    assert(MVT::getSizeInBits(Res.getValueType()) <= MVT::getSizeInBits(NVT) &&
+           "Extension doesn't make sense!");
+
+    // If the result and operand types are the same after promotion, simplify
+    // to an in-register extension.
+    if (NVT == Res.getValueType()) {
+      // The high bits are not guaranteed to be anything.  Insert an extend.
+      if (N->getOpcode() == ISD::SIGN_EXTEND)
+        return DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res,
+                           DAG.getValueType(N->getOperand(0).getValueType()));
+      if (N->getOpcode() == ISD::ZERO_EXTEND)
+        return DAG.getZeroExtendInReg(Res, N->getOperand(0).getValueType());
+      assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!");
+      return Res;
+    }
   }
+
+  // Otherwise, just extend the original operand all the way to the larger type.
+  return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0));
 }
 
 SDOperand DAGTypeLegalizer::PromoteResult_FP_ROUND(SDNode *N) {
@@ -518,6 +639,30 @@ SDOperand DAGTypeLegalizer::PromoteResult_FP_ROUND(SDNode *N) {
                      N->getOperand(0), DAG.getValueType(N->getValueType(0)));
 }
 
+SDOperand DAGTypeLegalizer::PromoteResult_FP_TO_XINT(SDNode *N) {
+  SDOperand Op = N->getOperand(0);
+  // If the operand needed to be promoted, do so now.
+  if (getTypeAction(Op.getValueType()) == Promote)
+    // The input result is prerounded, so we don't have to do anything special.
+    Op = GetPromotedOp(Op);
+  
+  unsigned NewOpc = N->getOpcode();
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+  
+  // If we're promoting a UINT to a larger size, check to see if the new node
+  // will be legal.  If it isn't, check to see if FP_TO_SINT is legal, since
+  // we can use that instead.  This allows us to generate better code for
+  // FP_TO_UINT for small destination sizes on targets where FP_TO_UINT is not
+  // legal, such as PowerPC.
+  if (N->getOpcode() == ISD::FP_TO_UINT) {
+    if (!TLI.isOperationLegal(ISD::FP_TO_UINT, NVT) &&
+        (TLI.isOperationLegal(ISD::FP_TO_SINT, NVT) ||
+         TLI.getOperationAction(ISD::FP_TO_SINT, NVT)==TargetLowering::Custom))
+      NewOpc = ISD::FP_TO_SINT;
+  }
+
+  return DAG.getNode(NewOpc, NVT, Op);
+}
 
 SDOperand DAGTypeLegalizer::PromoteResult_SETCC(SDNode *N) {
   assert(isTypeLegal(TLI.getSetCCResultTy()) && "SetCC type is not legal??");
@@ -533,8 +678,8 @@ SDOperand DAGTypeLegalizer::PromoteResult_LOAD(LoadSDNode *N) {
                                  N->getSrcValue(), N->getSrcValueOffset(),
                                  N->getLoadedVT(), N->isVolatile(),
                                  N->getAlignment());
-  
-  // Legalized the chain result, switching anything that used the old chain to
+
+  // Legalized the chain result - switch anything that used the old chain to
   // use the new one.
   ReplaceLegalValueWith(SDOperand(N, 1), Res.getValue(1));
   return Res;
@@ -549,6 +694,42 @@ SDOperand DAGTypeLegalizer::PromoteResult_SimpleIntBinOp(SDNode *N) {
   return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
 }
 
+SDOperand DAGTypeLegalizer::PromoteResult_SHL(SDNode *N) {
+  return DAG.getNode(ISD::SHL, TLI.getTypeToTransformTo(N->getValueType(0)),
+                     GetPromotedOp(N->getOperand(0)), N->getOperand(1));
+}
+
+SDOperand DAGTypeLegalizer::PromoteResult_SRA(SDNode *N) {
+  // The input value must be properly sign extended.
+  MVT::ValueType VT = N->getValueType(0);
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
+  SDOperand Res = GetPromotedOp(N->getOperand(0));
+  Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, DAG.getValueType(VT));
+  return DAG.getNode(ISD::SRA, NVT, Res, N->getOperand(1));
+}
+
+SDOperand DAGTypeLegalizer::PromoteResult_SRL(SDNode *N) {
+  // The input value must be properly zero extended.
+  MVT::ValueType VT = N->getValueType(0);
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
+  SDOperand Res = GetPromotedZExtOp(N->getOperand(0));
+  return DAG.getNode(ISD::SRL, NVT, Res, N->getOperand(1));
+}
+
+SDOperand DAGTypeLegalizer::PromoteResult_SELECT(SDNode *N) {
+  SDOperand LHS = GetPromotedOp(N->getOperand(1));
+  SDOperand RHS = GetPromotedOp(N->getOperand(2));
+  return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0),LHS,RHS);
+}
+
+SDOperand DAGTypeLegalizer::PromoteResult_SELECT_CC(SDNode *N) {
+  SDOperand LHS = GetPromotedOp(N->getOperand(2));
+  SDOperand RHS = GetPromotedOp(N->getOperand(3));
+  return DAG.getNode(ISD::SELECT_CC, LHS.getValueType(), N->getOperand(0),
+                     N->getOperand(1), LHS, RHS, N->getOperand(4));
+}
+
+
 //===----------------------------------------------------------------------===//
 //  Result Expansion
 //===----------------------------------------------------------------------===//
@@ -556,11 +737,26 @@ SDOperand DAGTypeLegalizer::PromoteResult_SimpleIntBinOp(SDNode *N) {
 /// ExpandResult - This method is called when the specified result of the
 /// specified node is found to need expansion.  At this point, the node may also
 /// have invalid operands or may have other results that need promotion, we just
-/// know that (at least) the one result needs expansion.
+/// know that (at least) one result needs expansion.
 void DAGTypeLegalizer::ExpandResult(SDNode *N, unsigned ResNo) {
   DEBUG(cerr << "Expand node result: "; N->dump(&DAG); cerr << "\n");
   SDOperand Lo, Hi;
   Lo = Hi = SDOperand();
+
+  // If this is a single-result node, see if the target wants to custom expand
+  // it.
+  if (N->getNumValues() == 1 &&
+      TLI.getOperationAction(N->getOpcode(),
+                             N->getValueType(0)) == TargetLowering::Custom) {
+    // If the target wants to, allow it to lower this itself.
+    std::pair<SDOperand,SDOperand> P = TLI.ExpandOperationResult(N, DAG);
+    if (P.first.Val) {
+      Lo = P.first;
+      Hi = P.second;
+      return;
+    }
+  }
+  
   switch (N->getOpcode()) {
   default:
 #ifndef NDEBUG
@@ -576,13 +772,20 @@ void DAGTypeLegalizer::ExpandResult(SDNode *N, unsigned ResNo) {
   case ISD::ANY_EXTEND:  ExpandResult_ANY_EXTEND(N, Lo, Hi); break;
   case ISD::ZERO_EXTEND: ExpandResult_ZERO_EXTEND(N, Lo, Hi); break;
   case ISD::SIGN_EXTEND: ExpandResult_SIGN_EXTEND(N, Lo, Hi); break;
+  case ISD::BIT_CONVERT: ExpandResult_BIT_CONVERT(N, Lo, Hi); break;
+  case ISD::SIGN_EXTEND_INREG: ExpandResult_SIGN_EXTEND_INREG(N, Lo, Hi); break;
   case ISD::LOAD:        ExpandResult_LOAD(cast<LoadSDNode>(N), Lo, Hi); break;
     
   case ISD::AND:
   case ISD::OR:
   case ISD::XOR:         ExpandResult_Logical(N, Lo, Hi); break;
+  case ISD::BSWAP:       ExpandResult_BSWAP(N, Lo, Hi); break;
   case ISD::ADD:
   case ISD::SUB:         ExpandResult_ADDSUB(N, Lo, Hi); break;
+  case ISD::ADDC:
+  case ISD::SUBC:        ExpandResult_ADDSUBC(N, Lo, Hi); break;
+  case ISD::ADDE:
+  case ISD::SUBE:        ExpandResult_ADDSUBE(N, Lo, Hi); break;
   case ISD::SELECT:      ExpandResult_SELECT(N, Lo, Hi); break;
   case ISD::SELECT_CC:   ExpandResult_SELECT_CC(N, Lo, Hi); break;
   case ISD::MUL:         ExpandResult_MUL(N, Lo, Hi); break;
@@ -599,13 +802,13 @@ void DAGTypeLegalizer::ExpandResult(SDNode *N, unsigned ResNo) {
 
 void DAGTypeLegalizer::ExpandResult_UNDEF(SDNode *N,
                                           SDOperand &Lo, SDOperand &Hi) {
-  MVT::ValueType NVT = TLI.getTypeToExpandTo(N->getValueType(0));
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
   Lo = Hi = DAG.getNode(ISD::UNDEF, NVT);
 }
 
 void DAGTypeLegalizer::ExpandResult_Constant(SDNode *N,
                                              SDOperand &Lo, SDOperand &Hi) {
-  MVT::ValueType NVT = TLI.getTypeToExpandTo(N->getValueType(0));
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
   uint64_t Cst = cast<ConstantSDNode>(N)->getValue();
   Lo = DAG.getConstant(Cst, NVT);
   Hi = DAG.getConstant(Cst >> MVT::getSizeInBits(NVT), NVT);
@@ -618,70 +821,134 @@ void DAGTypeLegalizer::ExpandResult_BUILD_PAIR(SDNode *N,
   Hi = N->getOperand(1);
 }
 
-void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N, 
+void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N,
                                                SDOperand &Lo, SDOperand &Hi) {
-  
-  MVT::ValueType NVT = TLI.getTypeToExpandTo(N->getValueType(0));
-  // The low part is any extension of the input (which degenerates to a copy).
-  Lo = DAG.getNode(ISD::ANY_EXTEND, NVT, N->getOperand(0));
-  Hi = DAG.getNode(ISD::UNDEF, NVT);   // The high part is undefined.
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+  SDOperand Op = N->getOperand(0);
+  if (MVT::getSizeInBits(Op.getValueType()) <= MVT::getSizeInBits(NVT)) {
+    // The low part is any extension of the input (which degenerates to a copy).
+    Lo = DAG.getNode(ISD::ANY_EXTEND, NVT, Op);
+    Hi = DAG.getNode(ISD::UNDEF, NVT);   // The high part is undefined.
+  } else {
+    // For example, extension of an i48 to an i64.  The operand type necessarily
+    // promotes to the result type, so will end up being expanded too.
+    assert(getTypeAction(Op.getValueType()) == Promote &&
+           "Don't know how to expand this result!");
+    SDOperand Res = GetPromotedOp(Op);
+    assert(Res.getValueType() == N->getValueType(0) &&
+           "Operand over promoted?");
+    // Split the promoted operand.  This will simplify when it is expanded.
+    SplitOp(Res, Lo, Hi);
+  }
 }
 
 void DAGTypeLegalizer::ExpandResult_ZERO_EXTEND(SDNode *N,
                                                 SDOperand &Lo, SDOperand &Hi) {
-  MVT::ValueType NVT = TLI.getTypeToExpandTo(N->getValueType(0));
-  // The low part is zero extension of the input (which degenerates to a copy).
-  Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, N->getOperand(0));
-  Hi = DAG.getConstant(0, NVT);   // The high part is just a zero.
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+  SDOperand Op = N->getOperand(0);
+  if (MVT::getSizeInBits(Op.getValueType()) <= MVT::getSizeInBits(NVT)) {
+    // The low part is zero extension of the input (which degenerates to a copy).
+    Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, N->getOperand(0));
+    Hi = DAG.getConstant(0, NVT);   // The high part is just a zero.
+  } else {
+    // For example, extension of an i48 to an i64.  The operand type necessarily
+    // promotes to the result type, so will end up being expanded too.
+    assert(getTypeAction(Op.getValueType()) == Promote &&
+           "Don't know how to expand this result!");
+    SDOperand Res = GetPromotedOp(Op);
+    assert(Res.getValueType() == N->getValueType(0) &&
+           "Operand over promoted?");
+    // Split the promoted operand.  This will simplify when it is expanded.
+    SplitOp(Res, Lo, Hi);
+    unsigned ExcessBits =
+      MVT::getSizeInBits(Op.getValueType()) - MVT::getSizeInBits(NVT);
+    Hi = DAG.getZeroExtendInReg(Hi, MVT::getIntegerType(ExcessBits));
+  }
 }
 
 void DAGTypeLegalizer::ExpandResult_SIGN_EXTEND(SDNode *N,
                                                 SDOperand &Lo, SDOperand &Hi) {
-  MVT::ValueType NVT = TLI.getTypeToExpandTo(N->getValueType(0));
-  // The low part is sign extension of the input (which degenerates to a copy).
-  Lo = DAG.getNode(ISD::SIGN_EXTEND, NVT, N->getOperand(0));
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+  SDOperand Op = N->getOperand(0);
+  if (MVT::getSizeInBits(Op.getValueType()) <= MVT::getSizeInBits(NVT)) {
+    // The low part is sign extension of the input (which degenerates to a copy).
+    Lo = DAG.getNode(ISD::SIGN_EXTEND, NVT, N->getOperand(0));
+    // The high part is obtained by SRA'ing all but one of the bits of low part.
+    unsigned LoSize = MVT::getSizeInBits(NVT);
+    Hi = DAG.getNode(ISD::SRA, NVT, Lo,
+                     DAG.getConstant(LoSize-1, TLI.getShiftAmountTy()));
+  } else {
+    // For example, extension of an i48 to an i64.  The operand type necessarily
+    // promotes to the result type, so will end up being expanded too.
+    assert(getTypeAction(Op.getValueType()) == Promote &&
+           "Don't know how to expand this result!");
+    SDOperand Res = GetPromotedOp(Op);
+    assert(Res.getValueType() == N->getValueType(0) &&
+           "Operand over promoted?");
+    // Split the promoted operand.  This will simplify when it is expanded.
+    SplitOp(Res, Lo, Hi);
+    unsigned ExcessBits =
+      MVT::getSizeInBits(Op.getValueType()) - MVT::getSizeInBits(NVT);
+    Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi,
+                     DAG.getValueType(MVT::getIntegerType(ExcessBits)));
+  }
+}
 
-  // The high part is obtained by SRA'ing all but one of the bits of low part.
-  unsigned LoSize = MVT::getSizeInBits(NVT);
-  Hi = DAG.getNode(ISD::SRA, NVT, Lo,
-                   DAG.getConstant(LoSize-1, TLI.getShiftAmountTy()));
+void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N,
+                                                SDOperand &Lo, SDOperand &Hi) {
+  // Lower the bit-convert to a store/load from the stack, then expand the load.
+  SDOperand Op = CreateStackStoreLoad(N->getOperand(0), N->getValueType(0));
+  ExpandResult_LOAD(cast<LoadSDNode>(Op.Val), Lo, Hi);
 }
 
+void DAGTypeLegalizer::
+ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
+  GetExpandedOp(N->getOperand(0), Lo, Hi);
+  MVT::ValueType EVT = cast<VTSDNode>(N->getOperand(1))->getVT();
+
+  if (MVT::getSizeInBits(EVT) <= MVT::getSizeInBits(Lo.getValueType())) {
+    // sext_inreg the low part if needed.
+    Lo = DAG.getNode(ISD::SIGN_EXTEND_INREG, Lo.getValueType(), Lo,
+                     N->getOperand(1));
+
+    // The high part gets the sign extension from the lo-part.  This handles
+    // things like sextinreg V:i64 from i8.
+    Hi = DAG.getNode(ISD::SRA, Hi.getValueType(), Lo,
+                     DAG.getConstant(MVT::getSizeInBits(Hi.getValueType())-1,
+                                     TLI.getShiftAmountTy()));
+  } else {
+    // For example, extension of an i48 to an i64.  Leave the low part alone,
+    // sext_inreg the high part.
+    unsigned ExcessBits =
+      MVT::getSizeInBits(EVT) - MVT::getSizeInBits(Lo.getValueType());
+    Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi,
+                     DAG.getValueType(MVT::getIntegerType(ExcessBits)));
+  }
+}
 
 void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,
                                          SDOperand &Lo, SDOperand &Hi) {
   MVT::ValueType VT = N->getValueType(0);
-  MVT::ValueType NVT = TLI.getTypeToExpandTo(VT);
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
   SDOperand Ch  = N->getChain();    // Legalize the chain.
   SDOperand Ptr = N->getBasePtr();  // Legalize the pointer.
   ISD::LoadExtType ExtType = N->getExtensionType();
   int SVOffset = N->getSrcValueOffset();
   unsigned Alignment = N->getAlignment();
   bool isVolatile = N->isVolatile();
-  
+
+  assert(!(MVT::getSizeInBits(NVT) & 7) && "Expanded type not byte sized!");
+
   if (ExtType == ISD::NON_EXTLOAD) {
     Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
                      isVolatile, Alignment);
-    if (VT == MVT::f32 || VT == MVT::f64) {
-      assert(0 && "FIXME: softfp should use promotion!");
-#if 0
-      // f32->i32 or f64->i64 one to one expansion.
-      // Remember that we legalized the chain.
-      AddLegalizedOperand(SDOperand(Node, 1), LegalizeOp(Lo.getValue(1)));
-      // Recursively expand the new load.
-      if (getTypeAction(NVT) == Expand)
-        ExpandOp(Lo, Lo, Hi);
-      break;
-#endif
-    }
-    
     // Increment the pointer to the other half.
-    unsigned IncrementSize = MVT::getSizeInBits(Lo.getValueType())/8;
+    unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
     Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
                       getIntPtrConstant(IncrementSize));
     Hi = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
-                     isVolatile, std::max(Alignment, 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),
@@ -690,32 +957,15 @@ void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,
     // Handle endianness of the load.
     if (!TLI.isLittleEndian())
       std::swap(Lo, Hi);
-  } else {
+  } else if (MVT::getSizeInBits(N->getLoadedVT()) <= MVT::getSizeInBits(NVT)) {
     MVT::ValueType EVT = N->getLoadedVT();
-    
-    if (VT == MVT::f64 && EVT == MVT::f32) {
-      assert(0 && "FIXME: softfp should use promotion!");
-#if 0
-      // f64 = EXTLOAD f32 should expand to LOAD, FP_EXTEND
-      SDOperand Load = DAG.getLoad(EVT, Ch, Ptr, N->getSrcValue(),
-                                   SVOffset, isVolatile, Alignment);
-      // Remember that we legalized the chain.
-      AddLegalizedOperand(SDOperand(Node, 1), LegalizeOp(Load.getValue(1)));
-      ExpandOp(DAG.getNode(ISD::FP_EXTEND, VT, Load), Lo, Hi);
-      break;
-#endif
-    }
-    
-    if (EVT == NVT)
-      Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(),
-                       SVOffset, isVolatile, Alignment);
-    else
-      Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(),
-                          SVOffset, EVT, isVolatile,
-                          Alignment);
+
+    Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, EVT,
+                        isVolatile, Alignment);
+
     // Remember the chain.
     Ch = Lo.getValue(1);
-    
+
     if (ExtType == ISD::SEXTLOAD) {
       // The high part is obtained by SRA'ing all but one of the bits of the
       // lo part.
@@ -730,13 +980,70 @@ void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,
       // The high part is undefined.
       Hi = DAG.getNode(ISD::UNDEF, NVT);
     }
+  } else if (TLI.isLittleEndian()) {
+    // Little-endian - low bits are at low addresses.
+    Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
+                     isVolatile, Alignment);
+
+    unsigned ExcessBits =
+      MVT::getSizeInBits(N->getLoadedVT()) - MVT::getSizeInBits(NVT);
+    MVT::ValueType NEVT = MVT::getIntegerType(ExcessBits);
+
+    // Increment the pointer to the other half.
+    unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
+    Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                      getIntPtrConstant(IncrementSize));
+    Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(),
+                        SVOffset+IncrementSize, NEVT,
+                        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));
+  } else {
+    // Big-endian - high bits are at low addresses.  Favor aligned loads at
+    // the cost of some bit-fiddling.
+    MVT::ValueType EVT = N->getLoadedVT();
+    unsigned EBytes = (MVT::getSizeInBits(EVT) + 7)/8;
+    unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
+    unsigned ExcessBits = (EBytes - IncrementSize)*8;
+
+    // Load both the high bits and maybe some of the low bits.
+    Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
+                        MVT::getIntegerType(MVT::getSizeInBits(EVT)-ExcessBits),
+                        isVolatile, Alignment);
+
+    // Increment the pointer to the other half.
+    Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                      getIntPtrConstant(IncrementSize));
+    // Load the rest of the low bits.
+    Lo = DAG.getExtLoad(ISD::ZEXTLOAD, NVT, Ch, Ptr, N->getSrcValue(),
+                        SVOffset+IncrementSize, MVT::getIntegerType(ExcessBits),
+                        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));
+
+    if (ExcessBits < MVT::getSizeInBits(NVT)) {
+      // Transfer low bits from the bottom of Hi to the top of Lo.
+      Lo = DAG.getNode(ISD::OR, NVT, Lo,
+                       DAG.getNode(ISD::SHL, NVT, Hi,
+                                   DAG.getConstant(ExcessBits,
+                                                   TLI.getShiftAmountTy())));
+      // Move high bits to the right position in Hi.
+      Hi = DAG.getNode(ExtType == ISD::SEXTLOAD ? ISD::SRA : ISD::SRL, NVT, Hi,
+                       DAG.getConstant(MVT::getSizeInBits(NVT) - ExcessBits,
+                                       TLI.getShiftAmountTy()));
+    }
   }
-  
-  // Legalized the chain result, switching anything that used the old chain to
+
+  // Legalized the chain result - switch anything that used the old chain to
   // use the new one.
   ReplaceLegalValueWith(SDOperand(N, 1), Ch);
-}  
-
+}
 
 void DAGTypeLegalizer::ExpandResult_Logical(SDNode *N,
                                             SDOperand &Lo, SDOperand &Hi) {
@@ -747,6 +1054,13 @@ void DAGTypeLegalizer::ExpandResult_Logical(SDNode *N,
   Hi = DAG.getNode(N->getOpcode(), LL.getValueType(), LH, RH);
 }
 
+void DAGTypeLegalizer::ExpandResult_BSWAP(SDNode *N,
+                                          SDOperand &Lo, SDOperand &Hi) {
+  GetExpandedOp(N->getOperand(0), Hi, Lo);  // Note swapped operands.
+  Lo = DAG.getNode(ISD::BSWAP, Lo.getValueType(), Lo);
+  Hi = DAG.getNode(ISD::BSWAP, Hi.getValueType(), Hi);
+}
+
 void DAGTypeLegalizer::ExpandResult_SELECT(SDNode *N,
                                            SDOperand &Lo, SDOperand &Hi) {
   SDOperand LL, LH, RL, RH;
@@ -775,32 +1089,14 @@ void DAGTypeLegalizer::ExpandResult_SELECT_CC(SDNode *N,
 
 void DAGTypeLegalizer::ExpandResult_ADDSUB(SDNode *N,
                                            SDOperand &Lo, SDOperand &Hi) {
-  MVT::ValueType VT = N->getValueType(0);
-  
-  // If the target wants to custom expand this, let them.
-  if (TLI.getOperationAction(N->getOpcode(), VT) ==
-      TargetLowering::Custom) {
-    SDOperand Op = TLI.LowerOperation(SDOperand(N, 0), DAG);
-    // FIXME: Do a replace all uses with here!
-    assert(0 && "Custom not impl yet!");
-    if (Op.Val) {
-#if 0
-      ExpandOp(Op, Lo, Hi);
-#endif
-      return;
-    }
-  }
-  
   // Expand the subcomponents.
   SDOperand LHSL, LHSH, RHSL, RHSH;
   GetExpandedOp(N->getOperand(0), LHSL, LHSH);
   GetExpandedOp(N->getOperand(1), RHSL, RHSH);
   SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
-  SDOperand LoOps[2], HiOps[3];
-  LoOps[0] = LHSL;
-  LoOps[1] = RHSL;
-  HiOps[0] = LHSH;
-  HiOps[1] = RHSH;
+  SDOperand LoOps[2] = { LHSL, RHSL };
+  SDOperand HiOps[3] = { LHSH, RHSH };
+
   if (N->getOpcode() == ISD::ADD) {
     Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
     HiOps[2] = Lo.getValue(1);
@@ -812,24 +1108,54 @@ void DAGTypeLegalizer::ExpandResult_ADDSUB(SDNode *N,
   }
 }
 
+void DAGTypeLegalizer::ExpandResult_ADDSUBC(SDNode *N,
+                                            SDOperand &Lo, SDOperand &Hi) {
+  // Expand the subcomponents.
+  SDOperand LHSL, LHSH, RHSL, RHSH;
+  GetExpandedOp(N->getOperand(0), LHSL, LHSH);
+  GetExpandedOp(N->getOperand(1), RHSL, RHSH);
+  SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
+  SDOperand LoOps[2] = { LHSL, RHSL };
+  SDOperand HiOps[3] = { LHSH, RHSH };
+
+  if (N->getOpcode() == ISD::ADDC) {
+    Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
+    HiOps[2] = Lo.getValue(1);
+    Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
+  } else {
+    Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2);
+    HiOps[2] = Lo.getValue(1);
+    Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3);
+  }
+
+  // Legalized the flag result - switch anything that used the old flag to
+  // use the new one.
+  ReplaceLegalValueWith(SDOperand(N, 1), Hi.getValue(1));
+}
+
+void DAGTypeLegalizer::ExpandResult_ADDSUBE(SDNode *N,
+                                            SDOperand &Lo, SDOperand &Hi) {
+  // Expand the subcomponents.
+  SDOperand LHSL, LHSH, RHSL, RHSH;
+  GetExpandedOp(N->getOperand(0), LHSL, LHSH);
+  GetExpandedOp(N->getOperand(1), RHSL, RHSH);
+  SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
+  SDOperand LoOps[3] = { LHSL, RHSL, N->getOperand(2) };
+  SDOperand HiOps[3] = { LHSH, RHSH };
+
+  Lo = DAG.getNode(N->getOpcode(), VTList, LoOps, 3);
+  HiOps[2] = Lo.getValue(1);
+  Hi = DAG.getNode(N->getOpcode(), VTList, HiOps, 3);
+
+  // Legalized the flag result - switch anything that used the old flag to
+  // use the new one.
+  ReplaceLegalValueWith(SDOperand(N, 1), Hi.getValue(1));
+}
 
 void DAGTypeLegalizer::ExpandResult_MUL(SDNode *N,
                                         SDOperand &Lo, SDOperand &Hi) {
   MVT::ValueType VT = N->getValueType(0);
-  MVT::ValueType NVT = TLI.getTypeToExpandTo(VT);
-  
-  // If the target wants to custom expand this, let them.
-  if (TLI.getOperationAction(ISD::MUL, VT) == TargetLowering::Custom) {
-    SDOperand New = TLI.LowerOperation(SDOperand(N, 0), DAG);
-    if (New.Val) {
-      // FIXME: Do a replace all uses with here!
-      assert(0 && "Custom not impl yet!");
-#if 0
-      ExpandOp(New, Lo, Hi);
-#endif
-      return;
-    }
-  }
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
   
   bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, NVT);
   bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, NVT);
@@ -839,7 +1165,7 @@ void DAGTypeLegalizer::ExpandResult_MUL(SDNode *N,
     SDOperand LL, LH, RL, RH;
     GetExpandedOp(N->getOperand(0), LL, LH);
     GetExpandedOp(N->getOperand(1), RL, RH);
-    unsigned BitSize = MVT::getSizeInBits(RH.getValueType());
+    unsigned BitSize = MVT::getSizeInBits(NVT);
     unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0));
     unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1));
     
@@ -903,21 +1229,6 @@ void DAGTypeLegalizer::ExpandResult_Shift(SDNode *N,
                                           SDOperand &Lo, SDOperand &Hi) {
   MVT::ValueType VT = N->getValueType(0);
   
-  // If the target wants custom lowering, do so.
-  if (TLI.getOperationAction(N->getOpcode(), VT) == TargetLowering::Custom) {
-    SDOperand Op = TLI.LowerOperation(SDOperand(N, 0), DAG);
-    if (Op.Val) {
-      // Now that the custom expander is done, expand the result, which is
-      // still VT.
-      // FIXME: Do a replace all uses with here!
-      abort();
-#if 0
-      ExpandOp(Op, Lo, Hi);
-#endif
-      return;
-    }
-  }
-  
   // If we can emit an efficient shift operation, do so now.  Check to see if 
   // the RHS is a constant.
   if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
@@ -941,7 +1252,7 @@ void DAGTypeLegalizer::ExpandResult_Shift(SDNode *N,
   
   // Next check to see if the target supports this SHL_PARTS operation or if it
   // will custom expand it.
-  MVT::ValueType NVT = TLI.getTypeToExpandTo(VT);
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
   TargetLowering::LegalizeAction Action = TLI.getOperationAction(PartsOpc, NVT);
   if ((Action == TargetLowering::Legal && TLI.isTypeLegal(NVT)) ||
       Action == TargetLowering::Custom) {
@@ -1052,6 +1363,8 @@ bool DAGTypeLegalizer::
 ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
   MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
   unsigned NVTBits = MVT::getSizeInBits(NVT);
+  assert(!(NVTBits & (NVTBits - 1)) &&
+         "Expanded integer type size not a power of two!");
 
   uint64_t HighBitMask = NVTBits, KnownZero, KnownOne;
   DAG.ComputeMaskedBits(N->getOperand(1), HighBitMask, KnownZero, KnownOne);
@@ -1113,6 +1426,7 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
   return true;
 }
 
+
 //===----------------------------------------------------------------------===//
 //  Operand Promotion
 //===----------------------------------------------------------------------===//
@@ -1136,13 +1450,22 @@ bool DAGTypeLegalizer::PromoteOperand(SDNode *N, unsigned OpNo) {
   case ISD::ANY_EXTEND:  Res = PromoteOperand_ANY_EXTEND(N); break;
   case ISD::ZERO_EXTEND: Res = PromoteOperand_ZERO_EXTEND(N); break;
   case ISD::SIGN_EXTEND: Res = PromoteOperand_SIGN_EXTEND(N); break;
+  case ISD::TRUNCATE:    Res = PromoteOperand_TRUNCATE(N); break;
   case ISD::FP_EXTEND:   Res = PromoteOperand_FP_EXTEND(N); break;
   case ISD::FP_ROUND:    Res = PromoteOperand_FP_ROUND(N); break;
+  case ISD::SINT_TO_FP:
+  case ISD::UINT_TO_FP:  Res = PromoteOperand_INT_TO_FP(N); break;
     
   case ISD::SELECT:      Res = PromoteOperand_SELECT(N, OpNo); break;
   case ISD::BRCOND:      Res = PromoteOperand_BRCOND(N, OpNo); break;
+  case ISD::BR_CC:       Res = PromoteOperand_BR_CC(N, OpNo); break;
+  case ISD::SETCC:       Res = PromoteOperand_SETCC(N, OpNo); break;
+
   case ISD::STORE:       Res = PromoteOperand_STORE(cast<StoreSDNode>(N),
                                                     OpNo); break;
+  case ISD::MEMSET:
+  case ISD::MEMCPY:
+  case ISD::MEMMOVE:     Res = HandleMemIntrinsic(N); break;
   }
   
   // If the result is null, the sub-method took care of registering results etc.
@@ -1174,6 +1497,7 @@ SDOperand DAGTypeLegalizer::PromoteOperand_ZERO_EXTEND(SDNode *N) {
   Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op);
   return DAG.getZeroExtendInReg(Op, N->getOperand(0).getValueType());
 }
+
 SDOperand DAGTypeLegalizer::PromoteOperand_SIGN_EXTEND(SDNode *N) {
   SDOperand Op = GetPromotedOp(N->getOperand(0));
   Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op);
@@ -1181,15 +1505,32 @@ SDOperand DAGTypeLegalizer::PromoteOperand_SIGN_EXTEND(SDNode *N) {
                      Op, DAG.getValueType(N->getOperand(0).getValueType()));
 }
 
+SDOperand DAGTypeLegalizer::PromoteOperand_TRUNCATE(SDNode *N) {
+  SDOperand Op = GetPromotedOp(N->getOperand(0));
+  return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), Op);
+}
+
 SDOperand DAGTypeLegalizer::PromoteOperand_FP_EXTEND(SDNode *N) {
   SDOperand Op = GetPromotedOp(N->getOperand(0));
   return DAG.getNode(ISD::FP_EXTEND, N->getValueType(0), Op);
 }
+
 SDOperand DAGTypeLegalizer::PromoteOperand_FP_ROUND(SDNode *N) {
   SDOperand Op = GetPromotedOp(N->getOperand(0));
   return DAG.getNode(ISD::FP_ROUND, N->getValueType(0), Op);
 }
 
+SDOperand DAGTypeLegalizer::PromoteOperand_INT_TO_FP(SDNode *N) {
+  SDOperand In = GetPromotedOp(N->getOperand(0));
+  MVT::ValueType OpVT = N->getOperand(0).getValueType();
+  if (N->getOpcode() == ISD::UINT_TO_FP)
+    In = DAG.getZeroExtendInReg(In, OpVT);
+  else
+    In = DAG.getNode(ISD::SIGN_EXTEND_INREG, In.getValueType(),
+                     In, DAG.getValueType(OpVT));
+  
+  return DAG.UpdateNodeOperands(SDOperand(N, 0), In);
+}
 
 SDOperand DAGTypeLegalizer::PromoteOperand_SELECT(SDNode *N, unsigned OpNo) {
   assert(OpNo == 0 && "Only know how to promote condition");
@@ -1208,7 +1549,6 @@ SDOperand DAGTypeLegalizer::PromoteOperand_SELECT(SDNode *N, unsigned OpNo) {
                                 N->getOperand(2));
 }
 
-
 SDOperand DAGTypeLegalizer::PromoteOperand_BRCOND(SDNode *N, unsigned OpNo) {
   assert(OpNo == 1 && "only know how to promote condition");
   SDOperand Cond = GetPromotedOp(N->getOperand(1));  // Promote the condition.
@@ -1226,6 +1566,74 @@ SDOperand DAGTypeLegalizer::PromoteOperand_BRCOND(SDNode *N, unsigned OpNo) {
                                 N->getOperand(2));
 }
 
+SDOperand DAGTypeLegalizer::PromoteOperand_BR_CC(SDNode *N, unsigned OpNo) {
+  assert(OpNo == 2 && "Don't know how to promote this operand");
+  
+  SDOperand LHS = N->getOperand(2);
+  SDOperand RHS = N->getOperand(3);
+  PromoteSetCCOperands(LHS, RHS, cast<CondCodeSDNode>(N->getOperand(1))->get());
+  
+  // The chain (Op#0), CC (#1) and basic block destination (Op#4) are always
+  // legal types.
+  return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
+                                N->getOperand(1), LHS, RHS, N->getOperand(4));
+}
+
+SDOperand DAGTypeLegalizer::PromoteOperand_SETCC(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(2))->get());
+
+  // The CC (#2) is always legal.
+  return DAG.UpdateNodeOperands(SDOperand(N, 0), LHS, RHS, N->getOperand(2));
+}
+
+/// PromoteSetCCOperands - Promote the operands of a comparison.  This code is
+/// shared among BR_CC, SELECT_CC, and SETCC handlers.
+void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS,
+                                            ISD::CondCode CCCode) {
+  MVT::ValueType VT = NewLHS.getValueType();
+  
+  // Get the promoted values.
+  NewLHS = GetPromotedOp(NewLHS);
+  NewRHS = GetPromotedOp(NewRHS);
+  
+  // If this is an FP compare, the operands have already been extended.
+  if (!MVT::isInteger(NewLHS.getValueType()))
+    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
+  // it.
+  switch (CCCode) {
+  default: assert(0 && "Unknown integer comparison!");
+  case ISD::SETEQ:
+  case ISD::SETNE:
+  case ISD::SETUGE:
+  case ISD::SETUGT:
+  case ISD::SETULE:
+  case ISD::SETULT:
+    // ALL of these operations will work if we either sign or zero extend
+    // the operands (including the unsigned comparisons!).  Zero extend is
+    // usually a simpler/cheaper operation, so prefer it.
+    NewLHS = DAG.getZeroExtendInReg(NewLHS, VT);
+    NewRHS = DAG.getZeroExtendInReg(NewRHS, VT);
+    return;
+  case ISD::SETGE:
+  case ISD::SETGT:
+  case ISD::SETLT:
+  case ISD::SETLE:
+    NewLHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewLHS.getValueType(), NewLHS,
+                         DAG.getValueType(VT));
+    NewRHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewRHS.getValueType(), NewRHS,
+                         DAG.getValueType(VT));
+    return;
+  }
+}
+
 SDOperand DAGTypeLegalizer::PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo){
   SDOperand Ch = N->getChain(), Ptr = N->getBasePtr();
   int SVOffset = N->getSrcValueOffset();
@@ -1264,10 +1672,21 @@ bool DAGTypeLegalizer::ExpandOperand(SDNode *N, unsigned OpNo) {
     abort();
     
   case ISD::TRUNCATE:        Res = ExpandOperand_TRUNCATE(N); break;
+  case ISD::BIT_CONVERT:     Res = ExpandOperand_BIT_CONVERT(N); break;
+
+  case ISD::SINT_TO_FP:
+    Res = ExpandOperand_SINT_TO_FP(N->getOperand(0), N->getValueType(0));
+    break;
+  case ISD::UINT_TO_FP:
+    Res = ExpandOperand_UINT_TO_FP(N->getOperand(0), N->getValueType(0)); 
+    break;
   case ISD::EXTRACT_ELEMENT: Res = ExpandOperand_EXTRACT_ELEMENT(N); break;
   case ISD::SETCC:           Res = ExpandOperand_SETCC(N); break;
 
   case ISD::STORE: Res = ExpandOperand_STORE(cast<StoreSDNode>(N), OpNo); break;
+  case ISD::MEMSET:
+  case ISD::MEMCPY:
+  case ISD::MEMMOVE:     Res = HandleMemIntrinsic(N); break;
   }
   
   // If the result is null, the sub-method took care of registering results etc.
@@ -1297,6 +1716,88 @@ SDOperand DAGTypeLegalizer::ExpandOperand_TRUNCATE(SDNode *N) {
   return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL);
 }
 
+SDOperand DAGTypeLegalizer::ExpandOperand_BIT_CONVERT(SDNode *N) {
+  return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0));
+}
+
+SDOperand DAGTypeLegalizer::ExpandOperand_SINT_TO_FP(SDOperand Source, 
+                                                     MVT::ValueType DestTy) {
+  // We know the destination is legal, but that the input needs to be expanded.
+  assert(Source.getValueType() == MVT::i64 && "Only handle expand from i64!");
+  
+  // Check to see if the target has a custom way to lower this.  If so, use it.
+  switch (TLI.getOperationAction(ISD::SINT_TO_FP, Source.getValueType())) {
+  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.
+  }
+  
+  RTLIB::Libcall LC;
+  if (DestTy == MVT::f32)
+    LC = RTLIB::SINTTOFP_I64_F32;
+  else {
+    assert(DestTy == MVT::f64 && "Unknown fp value type!");
+    LC = RTLIB::SINTTOFP_I64_F64;
+  }
+  
+  assert(0 && "FIXME: no libcalls yet!");
+  abort();
+#if 0
+  assert(TLI.getLibcallName(LC) && "Don't know how to expand this SINT_TO_FP!");
+  Source = DAG.getNode(ISD::SINT_TO_FP, DestTy, Source);
+  SDOperand UnusedHiPart;
+  return ExpandLibCall(TLI.getLibcallName(LC), Source.Val, true, UnusedHiPart);
+#endif
+}
+
+SDOperand DAGTypeLegalizer::ExpandOperand_UINT_TO_FP(SDOperand Source, 
+                                                     MVT::ValueType DestTy) {
+  // We know the destination is legal, but that the input needs to be expanded.
+  assert(getTypeAction(Source.getValueType()) == Expand &&
+         "This is not an expansion!");
+  assert(Source.getValueType() == MVT::i64 && "Only handle expand from i64!");
+  
+  // 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 = ExpandOperand_SINT_TO_FP(Source, DestTy);
+
+  // 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;
+  GetExpandedOp(Source, Lo, Hi);
+  
+  SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultTy(), Hi,
+                                   DAG.getConstant(0, Hi.getValueType()),
+                                   ISD::SETLT);
+  SDOperand Zero = getIntPtrConstant(0), Four = 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::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 (MVT::getSizeInBits(DestTy) > MVT::getSizeInBits(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");
+  
+  return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg);
+}
+
 SDOperand DAGTypeLegalizer::ExpandOperand_EXTRACT_ELEMENT(SDNode *N) {
   SDOperand Lo, Hi;
   GetExpandedOp(N->getOperand(0), Lo, Hi);
@@ -1316,7 +1817,7 @@ SDOperand DAGTypeLegalizer::ExpandOperand_SETCC(SDNode *N) {
                                 DAG.getCondCode(CCCode));
 }
 
-/// ExpandSetCCOperands - Expand the operands to a comparison.  This code is
+/// 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) {
@@ -1433,80 +1934,144 @@ void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS,
   NewRHS = SDOperand();
 }
 
-
 SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) {
   assert(OpNo == 1 && "Can only expand the stored value so far");
-  assert(!N->isTruncatingStore() && "Can't expand truncstore!");
 
-  unsigned IncrementSize = 0;
+  MVT::ValueType VT = N->getOperand(1).getValueType();
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
+  SDOperand Ch  = N->getChain();
+  SDOperand Ptr = N->getBasePtr();
+  int SVOffset = N->getSrcValueOffset();
+  unsigned Alignment = N->getAlignment();
+  bool isVolatile = N->isVolatile();
   SDOperand Lo, Hi;
-  
-  // If this is a vector type, then we have to calculate the increment as
-  // the product of the element size in bytes, and the number of elements
-  // in the high half of the vector.
-  if (MVT::isVector(N->getValue().getValueType())) {
-    assert(0 && "Vectors not supported yet");
-#if 0
-    SDNode *InVal = ST->getValue().Val;
-    unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(0));
-    MVT::ValueType EVT = MVT::getVectorElementType(InVal->getValueType(0));
-    
-    // Figure out if there is a simple type corresponding to this Vector
-    // type.  If so, convert to the vector type.
-    MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
-    if (TLI.isTypeLegal(TVT)) {
-      // Turn this into a normal store of the vector type.
-      Tmp3 = LegalizeOp(Node->getOperand(1));
-      Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
-                            SVOffset, isVolatile, Alignment);
-      Result = LegalizeOp(Result);
-      break;
-    } else if (NumElems == 1) {
-      // Turn this into a normal store of the scalar type.
-      Tmp3 = ScalarizeVectorOp(Node->getOperand(1));
-      Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
-                            SVOffset, isVolatile, Alignment);
-      // The scalarized value type may not be legal, e.g. it might require
-      // promotion or expansion.  Relegalize the scalar store.
-      return LegalizeOp(Result);
+
+  assert(!(MVT::getSizeInBits(NVT) & 7) && "Expanded type not byte sized!");
+
+  if (!N->isTruncatingStore()) {
+    unsigned IncrementSize = 0;
+
+    // If this is a vector type, then we have to calculate the increment as
+    // the product of the element size in bytes, and the number of elements
+    // in the high half of the vector.
+    if (MVT::isVector(N->getValue().getValueType())) {
+      assert(0 && "Vectors not supported yet");
+  #if 0
+      SDNode *InVal = ST->getValue().Val;
+      unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(0));
+      MVT::ValueType EVT = MVT::getVectorElementType(InVal->getValueType(0));
+
+      // Figure out if there is a simple type corresponding to this Vector
+      // type.  If so, convert to the vector type.
+      MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
+      if (TLI.isTypeLegal(TVT)) {
+        // Turn this into a normal store of the vector type.
+        Tmp3 = LegalizeOp(Node->getOperand(1));
+        Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+                              SVOffset, isVolatile, Alignment);
+        Result = LegalizeOp(Result);
+        break;
+      } else if (NumElems == 1) {
+        // Turn this into a normal store of the scalar type.
+        Tmp3 = ScalarizeVectorOp(Node->getOperand(1));
+        Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+                              SVOffset, isVolatile, Alignment);
+        // The scalarized value type may not be legal, e.g. it might require
+        // promotion or expansion.  Relegalize the scalar store.
+        return LegalizeOp(Result);
+      } else {
+        SplitVectorOp(Node->getOperand(1), Lo, Hi);
+        IncrementSize = NumElems/2 * MVT::getSizeInBits(EVT)/8;
+      }
+  #endif
     } else {
-      SplitVectorOp(Node->getOperand(1), Lo, Hi);
-      IncrementSize = NumElems/2 * MVT::getSizeInBits(EVT)/8;
+      GetExpandedOp(N->getValue(), Lo, Hi);
+      IncrementSize = Hi.Val ? MVT::getSizeInBits(Hi.getValueType())/8 : 0;
+
+      if (!TLI.isLittleEndian())
+        std::swap(Lo, Hi);
     }
-#endif
+
+    Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(),
+                      SVOffset, isVolatile, Alignment);
+
+    assert(Hi.Val && "FIXME: int <-> float should be handled with promote!");
+  #if 0
+    if (Hi.Val == NULL) {
+      // Must be int <-> float one-to-one expansion.
+      return Lo;
+    }
+  #endif
+
+    Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                      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 (MVT::getSizeInBits(N->getStoredVT()) <= MVT::getSizeInBits(NVT)) {
+    GetExpandedOp(N->getValue(), Lo, Hi);
+    return DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset,
+                             N->getStoredVT(), isVolatile, Alignment);
+  } else if (TLI.isLittleEndian()) {
+    // Little-endian - low bits are at low addresses.
+    GetExpandedOp(N->getValue(), Lo, Hi);
+
+    Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset,
+                      isVolatile, Alignment);
+
+    unsigned ExcessBits =
+      MVT::getSizeInBits(N->getStoredVT()) - MVT::getSizeInBits(NVT);
+    MVT::ValueType NEVT = MVT::getIntegerType(ExcessBits);
+
+    // Increment the pointer to the other half.
+    unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
+    Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                      getIntPtrConstant(IncrementSize));
+    Hi = DAG.getTruncStore(Ch, Hi, Ptr, N->getSrcValue(),
+                           SVOffset+IncrementSize, NEVT,
+                           isVolatile, MinAlign(Alignment, IncrementSize));
+    return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
   } else {
+    // Big-endian - high bits are at low addresses.  Favor aligned stores at
+    // the cost of some bit-fiddling.
     GetExpandedOp(N->getValue(), Lo, Hi);
-    IncrementSize = Hi.Val ? MVT::getSizeInBits(Hi.getValueType())/8 : 0;
-    
-    if (!TLI.isLittleEndian())
-      std::swap(Lo, Hi);
-  }
-  
-  SDOperand Chain    = N->getChain();
-  SDOperand Ptr      = N->getBasePtr();
-  int SVOffset       = N->getSrcValueOffset();
-  unsigned Alignment = N->getAlignment();
-  bool isVolatile    = N->isVolatile();
-  
-  Lo = DAG.getStore(Chain, Lo, Ptr, N->getSrcValue(),
-                    SVOffset, isVolatile, Alignment);
-  
-  assert(Hi.Val && "FIXME: int <-> float should be handled with promote!");
-#if 0
-  if (Hi.Val == NULL) {
-    // Must be int <-> float one-to-one expansion.
-    return Lo;
+
+    MVT::ValueType EVT = N->getStoredVT();
+    unsigned EBytes = (MVT::getSizeInBits(EVT) + 7)/8;
+    unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
+    unsigned ExcessBits = (EBytes - IncrementSize)*8;
+    MVT::ValueType HiVT =
+      MVT::getIntegerType(MVT::getSizeInBits(EVT)-ExcessBits);
+
+    if (ExcessBits < MVT::getSizeInBits(NVT)) {
+      // Transfer high bits from the top of Lo to the bottom of Hi.
+      Hi = DAG.getNode(ISD::SHL, NVT, Hi,
+                       DAG.getConstant(MVT::getSizeInBits(NVT) - ExcessBits,
+                                       TLI.getShiftAmountTy()));
+      Hi = DAG.getNode(ISD::OR, NVT, Hi,
+                       DAG.getNode(ISD::SRL, NVT, Lo,
+                                   DAG.getConstant(ExcessBits,
+                                                   TLI.getShiftAmountTy())));
+    }
+
+    // Store both the high bits and maybe some of the low bits.
+    Hi = DAG.getTruncStore(Ch, Hi, Ptr, N->getSrcValue(),
+                           SVOffset, HiVT, isVolatile, Alignment);
+
+    // Increment the pointer to the other half.
+    Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                      getIntPtrConstant(IncrementSize));
+    // Store the lowest ExcessBits bits in the second half.
+    Lo = DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(),
+                           SVOffset+IncrementSize,
+                           MVT::getIntegerType(ExcessBits),
+                           isVolatile, MinAlign(Alignment, IncrementSize));
+    return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
   }
-#endif
-  
-  Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
-                    getIntPtrConstant(IncrementSize));
-  assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!");
-  Hi = DAG.getStore(Chain, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
-                    isVolatile, std::max(Alignment, IncrementSize));
-  return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
 }
 
+
 //===----------------------------------------------------------------------===//
 //  Entry Point
 //===----------------------------------------------------------------------===//
@@ -1519,4 +2084,3 @@ SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) {
 void SelectionDAG::LegalizeTypes() {
   DAGTypeLegalizer(*this).run();
 }
-