Implement the custom lowering hook right, returning values for all of the
[oota-llvm.git] / lib / Target / X86 / X86ISelLowering.cpp
index 6f02ae4da090fa7964a092e3c7f0f13697c3df78..3d0194126d73f2ea10ab52b4717d6d2a0cec1c79 100644 (file)
@@ -18,6 +18,7 @@
 #include "X86TargetMachine.h"
 #include "llvm/CallingConv.h"
 #include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
 #include "llvm/Function.h"
 #include "llvm/Intrinsics.h"
 #include "llvm/ADT/VectorExtras.h"
@@ -66,9 +67,9 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
   addLegalAddressScale(3);
   
   // Set up the register classes.
-  addRegisterClass(MVT::i8, X86::R8RegisterClass);
-  addRegisterClass(MVT::i16, X86::R16RegisterClass);
-  addRegisterClass(MVT::i32, X86::R32RegisterClass);
+  addRegisterClass(MVT::i8, X86::GR8RegisterClass);
+  addRegisterClass(MVT::i16, X86::GR16RegisterClass);
+  addRegisterClass(MVT::i32, X86::GR32RegisterClass);
 
   // Promote all UINT_TO_FP to larger SINT_TO_FP's, as X86 doesn't have this
   // operation.
@@ -206,10 +207,6 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
     addRegisterClass(MVT::f32, X86::FR32RegisterClass);
     addRegisterClass(MVT::f64, X86::FR64RegisterClass);
 
-    // SSE has no load+extend ops
-    setOperationAction(ISD::EXTLOAD,  MVT::f32, Expand);
-    setOperationAction(ISD::ZEXTLOAD, MVT::f32, Expand);
-
     // Use ANDPD to simulate FABS.
     setOperationAction(ISD::FABS , MVT::f64, Custom);
     setOperationAction(ISD::FABS , MVT::f32, Custom);
@@ -368,8 +365,8 @@ X86TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
   FormalArgs.clear();
   FormalArgLocs.clear();
 
-  // This sets BytesToPopOnReturn, BytesCallerReserves, etc. which have to be set
-  // before the rest of the function can be lowered.
+  // This sets BytesToPopOnReturn, BytesCallerReserves, etc. which have to be
+  // set before the rest of the function can be lowered.
   if (F.getCallingConv() == CallingConv::Fast && EnableFastCC)
     PreprocessFastCCArguments(Args, F, DAG);
   else
@@ -413,10 +410,13 @@ static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
   return VReg;
 }
 
-/// getFormalArgSize - Return the minimum size of the stack frame needed to store
-/// an object of the specified type.
-static unsigned getFormalArgSize(MVT::ValueType ObjectVT) {
-  unsigned ObjSize = 0;
+/// HowToPassCCCArgument - Returns how an formal argument of the specified type
+/// should be passed. If it is through stack, returns the size of the stack
+/// frame; if it is through XMM register, returns the number of XMM registers
+/// are needed.
+static void
+HowToPassCCCArgument(MVT::ValueType ObjectVT, unsigned NumXMMRegs,
+                     unsigned &ObjSize, unsigned &ObjXMMRegs) {
   switch (ObjectVT) {
   default: assert(0 && "Unhandled argument type!");
   case MVT::i1:
@@ -426,8 +426,18 @@ static unsigned getFormalArgSize(MVT::ValueType ObjectVT) {
   case MVT::i64: ObjSize = 8; break;
   case MVT::f32: ObjSize = 4; break;
   case MVT::f64: ObjSize = 8; break;
+  case MVT::v16i8:
+  case MVT::v8i16:
+  case MVT::v4i32:
+  case MVT::v2i64:
+  case MVT::v4f32:
+  case MVT::v2f64:
+    if (NumXMMRegs < 3)
+      ObjXMMRegs = 1;
+    else
+      ObjSize = 16;
+    break;
   }
-  return ObjSize;
 }
 
 /// getFormalArgObjects - Returns itself if Op is a FORMAL_ARGUMENTS, otherwise
@@ -440,7 +450,7 @@ static std::vector<SDOperand> getFormalArgObjects(SDOperand Op) {
     assert(Op.getOpcode() == ISD::AssertSext ||
            Op.getOpcode() == ISD::AssertZext);
     Objs.push_back(Op.getOperand(0));
-  } else if (Opc == ISD::FP_ROUND) {
+  } else if (Opc == ISD::FP_ROUND || Opc == ISD::VBIT_CONVERT) {
     Objs.push_back(Op.getOperand(0));
   } else if (Opc == ISD::BUILD_PAIR) {
     Objs.push_back(Op.getOperand(0));
@@ -466,6 +476,8 @@ void X86TargetLowering::PreprocessCCCArguments(std::vector<SDOperand>Args,
   //    ...
   //
   unsigned ArgOffset = 0;   // Frame mechanisms handle retaddr slot
+  unsigned NumXMMRegs = 0;  // XMM regs used for parameter passing.
+  unsigned XMMArgRegs[] = { X86::XMM0, X86::XMM1, X86::XMM2 };
   for (unsigned i = 0; i < NumArgs; ++i) {
     SDOperand Op = Args[i];
     std::vector<SDOperand> Objs = getFormalArgObjects(Op);
@@ -474,16 +486,29 @@ void X86TargetLowering::PreprocessCCCArguments(std::vector<SDOperand>Args,
       SDOperand Obj = *I;
       MVT::ValueType ObjectVT = Obj.getValueType();
       unsigned ArgIncrement = 4;
-      unsigned ObjSize = getFormalArgSize(ObjectVT);
-      if (ObjSize == 8)
-        ArgIncrement = 8;
-
-      // Create the frame index object for this incoming parameter...
-      int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
-      std::pair<FALocInfo, FALocInfo> Loc =
-        std::make_pair(FALocInfo(FALocInfo::StackFrameLoc, FI), FALocInfo());
-      FormalArgLocs.push_back(Loc);
-      ArgOffset += ArgIncrement;   // Move on to the next argument...
+      unsigned ObjSize = 0;
+      unsigned ObjXMMRegs = 0;
+      HowToPassCCCArgument(ObjectVT, NumXMMRegs, ObjSize, ObjXMMRegs);
+      if (ObjSize >= 8)
+        ArgIncrement = ObjSize;
+
+      if (ObjXMMRegs) {
+        // Passed in a XMM register.
+        unsigned Reg = AddLiveIn(MF, XMMArgRegs[NumXMMRegs],
+                                 X86::VR128RegisterClass);
+        std::pair<FALocInfo, FALocInfo> Loc =
+          std::make_pair(FALocInfo(FALocInfo::LiveInRegLoc, Reg, ObjectVT),
+                         FALocInfo());
+        FormalArgLocs.push_back(Loc);
+        NumXMMRegs += ObjXMMRegs;
+      } else {
+        // Create the frame index object for this incoming parameter...
+        int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
+        std::pair<FALocInfo, FALocInfo> Loc =
+          std::make_pair(FALocInfo(FALocInfo::StackFrameLoc, FI), FALocInfo());
+        FormalArgLocs.push_back(Loc);
+        ArgOffset += ArgIncrement;   // Move on to the next argument...
+      }
     }
   }
 
@@ -497,18 +522,29 @@ void X86TargetLowering::PreprocessCCCArguments(std::vector<SDOperand>Args,
 }
 
 void X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG) {
-  unsigned NumArgs = Op.Val->getNumValues();
+  unsigned NumArgs = Op.Val->getNumValues() - 1;
   MachineFunction &MF = DAG.getMachineFunction();
-  MachineFrameInfo *MFI = MF.getFrameInfo();
 
   for (unsigned i = 0; i < NumArgs; ++i) {
-    // Create the SelectionDAG nodes corresponding to a load from this parameter
-    unsigned FI = FormalArgLocs[i].first.Loc;
-    SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
-    SDOperand ArgValue = DAG.getLoad(Op.Val->getValueType(i),DAG.getEntryNode(),
-                                     FIN, DAG.getSrcValue(NULL));
+    std::pair<FALocInfo, FALocInfo> Loc = FormalArgLocs[i];
+    SDOperand ArgValue;
+    if (Loc.first.Kind == FALocInfo::StackFrameLoc) {
+      // Create the SelectionDAG nodes corresponding to a load from this
+      // parameter.
+      unsigned FI = FormalArgLocs[i].first.Loc;
+      SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
+      ArgValue = DAG.getLoad(Op.Val->getValueType(i),
+                             DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL));
+    } else {
+      // Must be a CopyFromReg
+      ArgValue= DAG.getCopyFromReg(DAG.getEntryNode(), Loc.first.Loc,
+                                   Loc.first.Typ);
+    }
     FormalArgs.push_back(ArgValue);
   }
+  // Provide a chain.  Note that this isn't the right one, but it works as well
+  // as before.
+  FormalArgs.push_back(DAG.getEntryNode());
 }
 
 std::pair<SDOperand, SDOperand>
@@ -519,6 +555,11 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy,
   // Count how many bytes are to be pushed on the stack.
   unsigned NumBytes = 0;
 
+  // Keep track of the number of XMM regs passed so far.
+  unsigned NumXMMRegs = 0;
+  unsigned XMMArgRegs[] = { X86::XMM0, X86::XMM1, X86::XMM2 };
+
+  std::vector<SDOperand> RegValuesToPass;
   if (Args.empty()) {
     // Save zero bytes.
     Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(0, getPointerTy()));
@@ -537,6 +578,12 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy,
       case MVT::f64:
         NumBytes += 8;
         break;
+      case MVT::Vector:
+        if (NumXMMRegs < 3)
+          ++NumXMMRegs;
+        else
+          NumBytes += 16;
+        break;
       }
 
     Chain = DAG.getCALLSEQ_START(Chain,
@@ -544,13 +591,10 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy,
 
     // Arguments go on the stack in reverse order, as specified by the ABI.
     unsigned ArgOffset = 0;
+    NumXMMRegs = 0;
     SDOperand StackPtr = DAG.getRegister(X86::ESP, MVT::i32);
     std::vector<SDOperand> Stores;
-
     for (unsigned i = 0, e = Args.size(); i != e; ++i) {
-      SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
-      PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
-
       switch (getValueType(Args[i].second)) {
       default: assert(0 && "Unexpected ValueType for argument!");
       case MVT::i1:
@@ -565,21 +609,40 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy,
 
         // FALL THROUGH
       case MVT::i32:
-      case MVT::f32:
+      case MVT::f32: {
+        SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
+        PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
         Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
                                      Args[i].first, PtrOff,
                                      DAG.getSrcValue(NULL)));
         ArgOffset += 4;
         break;
+      }
       case MVT::i64:
-      case MVT::f64:
+      case MVT::f64: {
+        SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
+        PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
         Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
                                      Args[i].first, PtrOff,
                                      DAG.getSrcValue(NULL)));
         ArgOffset += 8;
         break;
       }
+      case MVT::Vector:
+        if (NumXMMRegs < 3) {
+          RegValuesToPass.push_back(Args[i].first);
+          NumXMMRegs++;
+        } else {
+          SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
+          PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
+          Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                       Args[i].first, PtrOff,
+                                       DAG.getSrcValue(NULL)));
+          ArgOffset += 16;
+        }
+      }
     }
+  if (!Stores.empty())
     Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, Stores);
   }
 
@@ -610,16 +673,35 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy,
     break;
   }
 
+  // Build a sequence of copy-to-reg nodes chained together with token chain
+  // and flag operands which copy the outgoing args into registers.
+  SDOperand InFlag;
+  for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
+    unsigned CCReg = XMMArgRegs[i];
+    SDOperand RegToPass = RegValuesToPass[i];
+    assert(RegToPass.getValueType() == MVT::Vector);
+    unsigned NumElems =
+      cast<ConstantSDNode>(*(RegToPass.Val->op_end()-2))->getValue();
+    MVT::ValueType EVT = cast<VTSDNode>(*(RegToPass.Val->op_end()-1))->getVT();
+    MVT::ValueType PVT = getVectorType(EVT, NumElems);
+    SDOperand CCRegNode = DAG.getRegister(CCReg, PVT);
+    RegToPass = DAG.getNode(ISD::VBIT_CONVERT, PVT, RegToPass);
+    Chain = DAG.getCopyToReg(Chain, CCRegNode, RegToPass, InFlag);
+    InFlag = Chain.getValue(1);
+  }
+
   std::vector<MVT::ValueType> NodeTys;
   NodeTys.push_back(MVT::Other);   // Returns a chain
   NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use.
   std::vector<SDOperand> Ops;
   Ops.push_back(Chain);
   Ops.push_back(Callee);
+  if (InFlag.Val)
+    Ops.push_back(InFlag);
 
   // FIXME: Do not generate X86ISD::TAILCALL for now.
   Chain = DAG.getNode(X86ISD::CALL, NodeTys, Ops);
-  SDOperand InFlag = Chain.getValue(1);
+  InFlag = Chain.getValue(1);
 
   NodeTys.clear();
   NodeTys.push_back(MVT::Other);   // Returns a chain
@@ -698,6 +780,16 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy,
         RetVal = DAG.getNode(ISD::FP_ROUND, MVT::f32, RetVal);
       break;
     }
+    case MVT::Vector: {
+      const PackedType *PTy = cast<PackedType>(RetTy);
+      MVT::ValueType EVT;
+      MVT::ValueType LVT;
+      unsigned NumRegs = getPackedTypeBreakdown(PTy, EVT, LVT);
+      assert(NumRegs == 1 && "Unsupported type!");
+      RetVal = DAG.getCopyFromReg(Chain, X86::XMM0, EVT, InFlag);
+      Chain = RetVal.getValue(1);
+      break;
+    }
     }
   }
 
@@ -741,9 +833,15 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy,
 static unsigned FASTCC_NUM_INT_ARGS_INREGS = 0;
 
 
+/// HowToPassFastCCArgument - Returns how an formal argument of the specified
+/// type should be passed. If it is through stack, returns the size of the stack
+/// frame; if it is through integer or XMM register, returns the number of
+/// integer or XMM registers are needed.
 static void
-HowToPassFastCCArgument(MVT::ValueType ObjectVT, unsigned NumIntRegs,
-                        unsigned &ObjSize, unsigned &ObjIntRegs) {
+HowToPassFastCCArgument(MVT::ValueType ObjectVT,
+                        unsigned NumIntRegs, unsigned NumXMMRegs,
+                        unsigned &ObjSize, unsigned &ObjIntRegs,
+                        unsigned &ObjXMMRegs) {
   ObjSize = 0;
   NumIntRegs = 0;
 
@@ -782,6 +880,17 @@ HowToPassFastCCArgument(MVT::ValueType ObjectVT, unsigned NumIntRegs,
   case MVT::f64:
     ObjSize = 8;
     break;
+  case MVT::v16i8:
+  case MVT::v8i16:
+  case MVT::v4i32:
+  case MVT::v2i64:
+  case MVT::v4f32:
+  case MVT::v2f64:
+    if (NumXMMRegs < 3)
+      ObjXMMRegs = 1;
+    else
+      ObjSize = 16;
+    break;
   }
 }
 
@@ -805,6 +914,8 @@ X86TargetLowering::PreprocessFastCCArguments(std::vector<SDOperand>Args,
   // 0 (neither EAX or EDX used), 1 (EAX is used) or 2 (EAX and EDX are both
   // used).
   unsigned NumIntRegs = 0;
+  unsigned NumXMMRegs = 0;  // XMM regs used for parameter passing.
+  unsigned XMMArgRegs[] = { X86::XMM0, X86::XMM1, X86::XMM2 };
   
   for (unsigned i = 0; i < NumArgs; ++i) {
     SDOperand Op = Args[i];
@@ -816,54 +927,68 @@ X86TargetLowering::PreprocessFastCCArguments(std::vector<SDOperand>Args,
       unsigned ArgIncrement = 4;
       unsigned ObjSize = 0;
       unsigned ObjIntRegs = 0;
+      unsigned ObjXMMRegs = 0;
 
-      HowToPassFastCCArgument(ObjectVT, NumIntRegs, ObjSize, ObjIntRegs);
-      if (ObjSize == 8)
-        ArgIncrement = 8;
+      HowToPassFastCCArgument(ObjectVT, NumIntRegs, NumXMMRegs,
+                              ObjSize, ObjIntRegs, ObjXMMRegs);
+      if (ObjSize >= 8)
+        ArgIncrement = ObjSize;
 
       unsigned Reg;
       std::pair<FALocInfo,FALocInfo> Loc = std::make_pair(FALocInfo(),
                                                           FALocInfo());
       if (ObjIntRegs) {
-        NumIntRegs += ObjIntRegs;
         switch (ObjectVT) {
         default: assert(0 && "Unhandled argument type!");
         case MVT::i1:
         case MVT::i8:
           Reg = AddLiveIn(MF, NumIntRegs ? X86::DL : X86::AL,
-                          X86::R8RegisterClass);
+                          X86::GR8RegisterClass);
           Loc.first.Kind = FALocInfo::LiveInRegLoc;
           Loc.first.Loc = Reg;
           Loc.first.Typ = MVT::i8;
           break;
         case MVT::i16:
           Reg = AddLiveIn(MF, NumIntRegs ? X86::DX : X86::AX,
-                          X86::R16RegisterClass);
+                          X86::GR16RegisterClass);
           Loc.first.Kind = FALocInfo::LiveInRegLoc;
           Loc.first.Loc = Reg;
           Loc.first.Typ = MVT::i16;
           break;
         case MVT::i32:
           Reg = AddLiveIn(MF, NumIntRegs ? X86::EDX : X86::EAX,
-                          X86::R32RegisterClass);
+                          X86::GR32RegisterClass);
           Loc.first.Kind = FALocInfo::LiveInRegLoc;
           Loc.first.Loc = Reg;
           Loc.first.Typ = MVT::i32;
           break;
         case MVT::i64:
           Reg = AddLiveIn(MF, NumIntRegs ? X86::EDX : X86::EAX,
-                          X86::R32RegisterClass);
+                          X86::GR32RegisterClass);
           Loc.first.Kind = FALocInfo::LiveInRegLoc;
           Loc.first.Loc = Reg;
           Loc.first.Typ = MVT::i32;
           if (ObjIntRegs == 2) {
-            Reg = AddLiveIn(MF, X86::EDX, X86::R32RegisterClass);
+            Reg = AddLiveIn(MF, X86::EDX, X86::GR32RegisterClass);
             Loc.second.Kind = FALocInfo::LiveInRegLoc;
             Loc.second.Loc = Reg;
             Loc.second.Typ = MVT::i32;
           }
           break;
+        case MVT::v16i8:
+        case MVT::v8i16:
+        case MVT::v4i32:
+        case MVT::v2i64:
+        case MVT::v4f32:
+        case MVT::v2f64:
+          Reg = AddLiveIn(MF, XMMArgRegs[NumXMMRegs], X86::VR128RegisterClass);
+          Loc.first.Kind = FALocInfo::LiveInRegLoc;
+          Loc.first.Loc = Reg;
+          Loc.first.Typ = ObjectVT;
+          break;
         }
+        NumIntRegs += ObjIntRegs;
+        NumXMMRegs += ObjXMMRegs;
       }
       if (ObjSize) {
         int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
@@ -909,44 +1034,60 @@ X86TargetLowering::PreprocessFastCCArguments(std::vector<SDOperand>Args,
   case MVT::f64:
     MF.addLiveOut(X86::ST0);
     break;
+  case MVT::Vector: {
+    const PackedType *PTy = cast<PackedType>(F.getReturnType());
+    MVT::ValueType EVT;
+    MVT::ValueType LVT;
+    unsigned NumRegs = getPackedTypeBreakdown(PTy, EVT, LVT);
+    assert(NumRegs == 1 && "Unsupported type!");
+    MF.addLiveOut(X86::XMM0);
+    break;
+  }
   }
 }
+
 void
 X86TargetLowering::LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG) {
-  unsigned NumArgs = Op.Val->getNumValues();
+  unsigned NumArgs = Op.Val->getNumValues()-1;
   MachineFunction &MF = DAG.getMachineFunction();
-  MachineFrameInfo *MFI = MF.getFrameInfo();
 
   for (unsigned i = 0; i < NumArgs; ++i) {
     MVT::ValueType VT = Op.Val->getValueType(i);
     std::pair<FALocInfo, FALocInfo> Loc = FormalArgLocs[i];
     SDOperand ArgValue;
     if (Loc.first.Kind == FALocInfo::StackFrameLoc) {
-      // Create the SelectionDAG nodes corresponding to a load from this parameter
+      // Create the SelectionDAG nodes corresponding to a load from this
+      // parameter.
       SDOperand FIN = DAG.getFrameIndex(Loc.first.Loc, MVT::i32);
-      ArgValue = DAG.getLoad(Op.Val->getValueType(i),DAG.getEntryNode(), FIN,
+      ArgValue = DAG.getLoad(Op.Val->getValueType(i), DAG.getEntryNode(), FIN,
                              DAG.getSrcValue(NULL));
     } else {
       // Must be a CopyFromReg
-      ArgValue= DAG.getCopyFromReg(DAG.getRoot(), Loc.first.Loc, Loc.first.Typ);
+      ArgValue= DAG.getCopyFromReg(DAG.getEntryNode(), Loc.first.Loc,
+                                   Loc.first.Typ);
     }
 
     if (Loc.second.Kind != FALocInfo::None) {
       SDOperand ArgValue2;
       if (Loc.second.Kind == FALocInfo::StackFrameLoc) {
-        // Create the SelectionDAG nodes corresponding to a load from this parameter
+        // Create the SelectionDAG nodes corresponding to a load from this
+        // parameter.
         SDOperand FIN = DAG.getFrameIndex(Loc.second.Loc, MVT::i32);
-        ArgValue2 = DAG.getLoad(Op.Val->getValueType(i),DAG.getEntryNode(), FIN,
-                                DAG.getSrcValue(NULL));
+        ArgValue2 = DAG.getLoad(Op.Val->getValueType(i), DAG.getEntryNode(),
+                                FIN, DAG.getSrcValue(NULL));
       } else {
         // Must be a CopyFromReg
-        ArgValue2 = DAG.getCopyFromReg(DAG.getRoot(),
+        ArgValue2 = DAG.getCopyFromReg(DAG.getEntryNode(),
                                        Loc.second.Loc, Loc.second.Typ);
       }
       ArgValue = DAG.getNode(ISD::BUILD_PAIR, VT, ArgValue, ArgValue2);
     }
     FormalArgs.push_back(ArgValue);
   }
+
+  // Provide a chain.  Note that this isn't the right one, but it works as well
+  // as before.
+  FormalArgs.push_back(DAG.getEntryNode());
 }
 
 std::pair<SDOperand, SDOperand>
@@ -1133,7 +1274,8 @@ X86TargetLowering::LowerFastCCCallTo(SDOperand Chain, const Type *RetTy,
     Ops.push_back(InFlag);
 
   // FIXME: Do not generate X86ISD::TAILCALL for now.
-  Chain = DAG.getNode(X86ISD::CALL, NodeTys, Ops);
+  Chain = DAG.getNode(isTailCall ? X86ISD::TAILCALL : X86ISD::CALL,
+                      NodeTys, Ops);
   InFlag = Chain.getValue(1);
 
   NodeTys.clear();
@@ -1428,7 +1570,7 @@ X86TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
 
     // Load the old value of the high byte of the control word...
     unsigned OldCW =
-      F->getSSARegMap()->createVirtualRegister(X86::R16RegisterClass);
+      F->getSSARegMap()->createVirtualRegister(X86::GR16RegisterClass);
     addFrameReference(BuildMI(BB, X86::MOV16rm, 4, OldCW), CWFrameIdx);
 
     // Set the high part to be round to zero...
@@ -2423,7 +2565,7 @@ X86TargetLowering::LowerBUILD_VECTOR(SDOperand Op, SelectionDAG &DAG) {
       }
     }
 
-    // Take advantage of the fact R32 to VR128 scalar_to_vector (i.e. movd)
+    // Take advantage of the fact GR32 to VR128 scalar_to_vector (i.e. movd)
     // clears the upper bits. 
     // FIXME: we can do the same for v4f32 case when we know both parts of
     // the lower half come from scalar_to_vector (loadf32). We should do
@@ -2606,10 +2748,55 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDOperand Op, SelectionDAG &DAG) {
   }
 
   if (NumElems == 4) {
-    // Break it into (shuffle shuffle_hi, shuffle_lo).
     MVT::ValueType MaskVT = PermMask.getValueType();
     MVT::ValueType MaskEVT = MVT::getVectorBaseType(MaskVT);
-    std::map<unsigned, std::pair<int, int> > Locs;
+    std::vector<std::pair<int, int> > Locs;
+    Locs.reserve(NumElems);
+    std::vector<SDOperand> Mask1(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT));
+    std::vector<SDOperand> Mask2(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT));
+    unsigned NumHi = 0;
+    unsigned NumLo = 0;
+    // If no more than two elements come from either vector. This can be
+    // implemented with two shuffles. First shuffle gather the elements.
+    // The second shuffle, which takes the first shuffle as both of its
+    // vector operands, put the elements into the right order.
+    for (unsigned i = 0; i != NumElems; ++i) {
+      SDOperand Elt = PermMask.getOperand(i);
+      if (Elt.getOpcode() == ISD::UNDEF) {
+        Locs[i] = std::make_pair(-1, -1);
+      } else {
+        unsigned Val = cast<ConstantSDNode>(Elt)->getValue();
+        if (Val < NumElems) {
+          Locs[i] = std::make_pair(0, NumLo);
+          Mask1[NumLo] = Elt;
+          NumLo++;
+        } else {
+          Locs[i] = std::make_pair(1, NumHi);
+          if (2+NumHi < NumElems)
+            Mask1[2+NumHi] = Elt;
+          NumHi++;
+        }
+      }
+    }
+    if (NumLo <= 2 && NumHi <= 2) {
+      V1 = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
+                       DAG.getNode(ISD::BUILD_VECTOR, MaskVT, Mask1));
+      for (unsigned i = 0; i != NumElems; ++i) {
+        if (Locs[i].first == -1)
+          continue;
+        else {
+          unsigned Idx = (i < NumElems/2) ? 0 : NumElems;
+          Idx += Locs[i].first * (NumElems/2) + Locs[i].second;
+          Mask2[i] = DAG.getConstant(Idx, MaskEVT);
+        }
+      }
+
+      return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V1,
+                         DAG.getNode(ISD::BUILD_VECTOR, MaskVT, Mask2));
+    }
+
+    // Break it into (shuffle shuffle_hi, shuffle_lo).
+    Locs.clear();
     std::vector<SDOperand> LoMask(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT));
     std::vector<SDOperand> HiMask(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT));
     std::vector<SDOperand> *MaskPtr = &LoMask;
@@ -2637,10 +2824,12 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDOperand Op, SelectionDAG &DAG) {
       }
     }
 
-    SDOperand LoShuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
-                                      DAG.getNode(ISD::BUILD_VECTOR, MaskVT, LoMask));
-    SDOperand HiShuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
-                                      DAG.getNode(ISD::BUILD_VECTOR, MaskVT, HiMask));
+    SDOperand LoShuffle =
+      DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
+                  DAG.getNode(ISD::BUILD_VECTOR, MaskVT, LoMask));
+    SDOperand HiShuffle = 
+      DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
+                  DAG.getNode(ISD::BUILD_VECTOR, MaskVT, HiMask));
     std::vector<SDOperand> MaskOps;
     for (unsigned i = 0; i != NumElems; ++i) {
       if (Locs[i].first == -1) {
@@ -2717,7 +2906,7 @@ X86TargetLowering::LowerEXTRACT_VECTOR_ELT(SDOperand Op, SelectionDAG &DAG) {
 
 SDOperand
 X86TargetLowering::LowerINSERT_VECTOR_ELT(SDOperand Op, SelectionDAG &DAG) {
-  // Transform it so it match pinsrw which expects a 16-bit value in a R32
+  // Transform it so it match pinsrw which expects a 16-bit value in a GR32
   // as its second argument.
   MVT::ValueType VT = Op.getValueType();
   MVT::ValueType BaseVT = MVT::getVectorBaseType(VT);
@@ -2748,7 +2937,7 @@ X86TargetLowering::LowerINSERT_VECTOR_ELT(SDOperand Op, SelectionDAG &DAG) {
       Idx <<= 1;
       if (MVT::isFloatingPoint(N1.getValueType())) {
         if (N1.getOpcode() == ISD::LOAD) {
-          // Just load directly from f32mem to R32.
+          // Just load directly from f32mem to GR32.
           N1 = DAG.getLoad(MVT::i32, N1.getOperand(0), N1.getOperand(1),
                            N1.getOperand(2));
         } else {
@@ -2803,12 +2992,14 @@ SDOperand
 X86TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
   GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
   SDOperand Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(),
-                                 DAG.getTargetGlobalAddress(GV, getPointerTy()));
+                                 DAG.getTargetGlobalAddress(GV,
+                                                            getPointerTy()));
   if (Subtarget->isTargetDarwin()) {
     // With PIC, the address is actually $g + Offset.
     if (getTargetMachine().getRelocationModel() == Reloc::PIC)
       Result = DAG.getNode(ISD::ADD, getPointerTy(),
-                           DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()), Result);
+                           DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()),
+                           Result);
 
     // For Darwin, external and weak symbols are indirect, so we want to load
     // the value at address GV, not the value of GV itself. This means that
@@ -2827,12 +3018,14 @@ SDOperand
 X86TargetLowering::LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG) {
   const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();
   SDOperand Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(),
-                                 DAG.getTargetExternalSymbol(Sym, getPointerTy()));
+                                 DAG.getTargetExternalSymbol(Sym,
+                                                             getPointerTy()));
   if (Subtarget->isTargetDarwin()) {
     // With PIC, the address is actually $g + Offset.
     if (getTargetMachine().getRelocationModel() == Reloc::PIC)
       Result = DAG.getNode(ISD::ADD, getPointerTy(),
-                           DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()), Result);
+                           DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()),
+                           Result);
   }
 
   return Result;
@@ -3216,7 +3409,8 @@ SDOperand X86TargetLowering::LowerJumpTable(SDOperand Op, SelectionDAG &DAG) {
     // With PIC, the address is actually $g + Offset.
     if (getTargetMachine().getRelocationModel() == Reloc::PIC)
       Result = DAG.getNode(ISD::ADD, getPointerTy(),
-                           DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()), Result);    
+                           DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()),
+                           Result);    
   }
 
   return Result;
@@ -3319,13 +3513,17 @@ SDOperand X86TargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG) {
 SDOperand
 X86TargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) {
   if (FormalArgs.size() == 0) {
-    unsigned CC = cast<ConstantSDNode>(Op.getOperand(0))->getValue();
+    unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
     if (CC == CallingConv::Fast && EnableFastCC)
       LowerFastCCArguments(Op, DAG);
     else
       LowerCCCArguments(Op, DAG);
   }
-  return FormalArgs[Op.ResNo];
+  
+  // Return the new list of results.
+  std::vector<MVT::ValueType> RetVTs(Op.Val->value_begin(),
+                                     Op.Val->value_end());
+  return DAG.getNode(ISD::MERGE_VALUES, RetVTs, FormalArgs);
 }
 
 SDOperand X86TargetLowering::LowerMEMSET(SDOperand Op, SelectionDAG &DAG) {
@@ -3341,7 +3539,7 @@ SDOperand X86TargetLowering::LowerMEMSET(SDOperand Op, SelectionDAG &DAG) {
   if ((Align & 3) != 0 ||
       (I && I->getValue() < Subtarget->getMinRepStrSizeThreshold())) {
     MVT::ValueType IntPtr = getPointerTy();
-    const Type *IntPtrTy = getTargetData().getIntPtrType();
+    const Type *IntPtrTy = getTargetData()->getIntPtrType();
     std::vector<std::pair<SDOperand, const Type*> > Args;
     Args.push_back(std::make_pair(Op.getOperand(1), IntPtrTy));
     // Extend the ubyte argument to be an int value for the call.
@@ -3474,7 +3672,7 @@ SDOperand X86TargetLowering::LowerMEMCPY(SDOperand Op, SelectionDAG &DAG) {
   if ((Align & 3) != 0 ||
       (I && I->getValue() < Subtarget->getMinRepStrSizeThreshold())) {
     MVT::ValueType IntPtr = getPointerTy();
-    const Type *IntPtrTy = getTargetData().getIntPtrType();
+    const Type *IntPtrTy = getTargetData()->getIntPtrType();
     std::vector<std::pair<SDOperand, const Type*> > Args;
     Args.push_back(std::make_pair(Op.getOperand(1), IntPtrTy));
     Args.push_back(std::make_pair(Op.getOperand(2), IntPtrTy));
@@ -3821,14 +4019,34 @@ getRegClassForInlineAsmConstraint(const std::string &Constraint,
     default: break;  // Unknown constriant letter
     case 'r':   // GENERAL_REGS
     case 'R':   // LEGACY_REGS
-      return make_vector<unsigned>(X86::EAX, X86::EBX, X86::ECX, X86::EDX,
-                                   X86::ESI, X86::EDI, X86::EBP, X86::ESP, 0);
+      if (VT == MVT::i32)
+        return make_vector<unsigned>(X86::EAX, X86::EDX, X86::ECX, X86::EBX,
+                                     X86::ESI, X86::EDI, X86::EBP, X86::ESP, 0);
+      else if (VT == MVT::i16)
+        return make_vector<unsigned>(X86::AX, X86::DX, X86::CX, X86::BX, 
+                                     X86::SI, X86::DI, X86::BP, X86::SP, 0);
+      else if (VT == MVT::i8)
+        return make_vector<unsigned>(X86::AL, X86::DL, X86::CL, X86::DL, 0);
+      break;
     case 'l':   // INDEX_REGS
-      return make_vector<unsigned>(X86::EAX, X86::EBX, X86::ECX, X86::EDX,
-                                   X86::ESI, X86::EDI, X86::EBP, 0);
+      if (VT == MVT::i32)
+        return make_vector<unsigned>(X86::EAX, X86::EDX, X86::ECX, X86::EBX,
+                                     X86::ESI, X86::EDI, X86::EBP, 0);
+      else if (VT == MVT::i16)
+        return make_vector<unsigned>(X86::AX, X86::DX, X86::CX, X86::BX, 
+                                     X86::SI, X86::DI, X86::BP, 0);
+      else if (VT == MVT::i8)
+        return make_vector<unsigned>(X86::AL, X86::DL, X86::CL, X86::DL, 0);
+      break;
     case 'q':   // Q_REGS (GENERAL_REGS in 64-bit mode)
     case 'Q':   // Q_REGS
-      return make_vector<unsigned>(X86::EAX, X86::EBX, X86::ECX, X86::EDX, 0);
+      if (VT == MVT::i32)
+        return make_vector<unsigned>(X86::EAX, X86::EDX, X86::ECX, X86::EBX, 0);
+      else if (VT == MVT::i16)
+        return make_vector<unsigned>(X86::AX, X86::DX, X86::CX, X86::BX, 0);
+      else if (VT == MVT::i8)
+        return make_vector<unsigned>(X86::AL, X86::DL, X86::CL, X86::DL, 0);
+        break;
     case 'x':   // SSE_REGS if SSE1 allowed
       if (Subtarget->hasSSE1())
         return make_vector<unsigned>(X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,