This situation can occur:
[oota-llvm.git] / lib / Target / ARM / ARMISelLowering.cpp
index dfe3bec9a585aa3aaf9588c8b6e1495ed57d3026..cfb98cb21cccc3c09a67ecf6db727ee79992b616 100644 (file)
@@ -197,19 +197,15 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
   setOperationAction(ISD::GLOBAL_OFFSET_TABLE, MVT::i32, Custom);
   setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
 
-  // Expand mem operations genericly.
-  setOperationAction(ISD::MEMSET          , MVT::Other, Expand);
-  setOperationAction(ISD::MEMCPY          , MVT::Other, Custom);
-  setOperationAction(ISD::MEMMOVE         , MVT::Other, Expand);
-
   // Use the default implementation.
-  setOperationAction(ISD::VASTART           , MVT::Other, Expand);
+  setOperationAction(ISD::VASTART           , MVT::Other, Custom);
   setOperationAction(ISD::VAARG             , MVT::Other, Expand);
   setOperationAction(ISD::VACOPY            , MVT::Other, Expand);
   setOperationAction(ISD::VAEND             , MVT::Other, Expand);
   setOperationAction(ISD::STACKSAVE,          MVT::Other, Expand); 
   setOperationAction(ISD::STACKRESTORE,       MVT::Other, Expand);
   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Expand);
+  setOperationAction(ISD::MEMBARRIER        , MVT::Other, Expand);
 
   if (!Subtarget->hasV6Ops()) {
     setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
@@ -240,16 +236,6 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
   setOperationAction(ISD::BR_CC    , MVT::f64,   Custom);
   setOperationAction(ISD::BR_JT    , MVT::Other, Custom);
 
-  setOperationAction(ISD::VASTART,       MVT::Other, Custom);
-  setOperationAction(ISD::VACOPY,        MVT::Other, Expand); 
-  setOperationAction(ISD::VAEND,         MVT::Other, Expand);
-  setOperationAction(ISD::STACKSAVE,     MVT::Other, Expand); 
-  setOperationAction(ISD::STACKRESTORE,  MVT::Other, Expand);
-
-  // FP Constants can't be immediates.
-  setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
-  setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
-
   // We don't support sin/cos/fmod/copysign/pow
   setOperationAction(ISD::FSIN     , MVT::f64, Expand);
   setOperationAction(ISD::FSIN     , MVT::f32, Expand);
@@ -257,16 +243,20 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
   setOperationAction(ISD::FCOS     , MVT::f64, Expand);
   setOperationAction(ISD::FREM     , MVT::f64, Expand);
   setOperationAction(ISD::FREM     , MVT::f32, Expand);
-  setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom);
-  setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom);
+  if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb()) {
+    setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom);
+    setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom);
+  }
   setOperationAction(ISD::FPOW     , MVT::f64, Expand);
   setOperationAction(ISD::FPOW     , MVT::f32, Expand);
   
   // int <-> fp are custom expanded into bit_convert + ARMISD ops.
-  setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
-  setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
-  setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
-  setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
+  if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb()) {
+    setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
+    setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
+    setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
+    setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
+  }
 
   // We have target-specific dag combine patterns for the following nodes:
   // ARMISD::FMRRD  - No need to call setTargetDAGCombine
@@ -373,19 +363,19 @@ static bool FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode,
 }
 
 static void
-HowToPassArgument(MVT::ValueType ObjectVT, unsigned NumGPRs,
+HowToPassArgument(MVT ObjectVT, unsigned NumGPRs,
                   unsigned StackOffset, unsigned &NeededGPRs,
                   unsigned &NeededStackSize, unsigned &GPRPad,
-                  unsigned &StackPad, unsigned Flags) {
+                  unsigned &StackPad, ISD::ArgFlagsTy Flags) {
   NeededStackSize = 0;
   NeededGPRs = 0;
   StackPad = 0;
   GPRPad = 0;
-  unsigned align = (Flags >> ISD::ParamFlags::OrigAlignmentOffs);
+  unsigned align = Flags.getOrigAlign();
   GPRPad = NumGPRs % ((align + 3)/4);
   StackPad = StackOffset % align;
   unsigned firstGPR = NumGPRs + GPRPad;
-  switch (ObjectVT) {
+  switch (ObjectVT.getSimpleVT()) {
   default: assert(0 && "Unhandled argument type!");
   case MVT::i32:
   case MVT::f32:
@@ -410,7 +400,7 @@ HowToPassArgument(MVT::ValueType ObjectVT, unsigned NumGPRs,
 /// ARMISD:CALL <- callseq_end chain. Also add input and output parameter
 /// nodes.
 SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
-  MVT::ValueType RetVT= Op.Val->getValueType(0);
+  MVT RetVT= Op.Val->getValueType(0);
   SDOperand Chain    = Op.getOperand(0);
   unsigned CallConv  = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
   assert((CallConv == CallingConv::C ||
@@ -429,8 +419,9 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
     unsigned ObjGPRs;
     unsigned StackPad;
     unsigned GPRPad;
-    MVT::ValueType ObjectVT = Op.getOperand(5+2*i).getValueType();
-    unsigned Flags = Op.getConstantOperandVal(5+2*i+1);
+    MVT ObjectVT = Op.getOperand(5+2*i).getValueType();
+    ISD::ArgFlagsTy Flags =
+      cast<ARG_FLAGSSDNode>(Op.getOperand(5+2*i+1))->getArgFlags();
     HowToPassArgument(ObjectVT, NumGPRs, NumBytes, ObjGPRs, ObjSize,
                       GPRPad, StackPad, Flags);
     NumBytes += ObjSize + StackPad;
@@ -453,8 +444,9 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
   std::vector<SDOperand> MemOpChains;
   for (unsigned i = 0; i != NumOps; ++i) {
     SDOperand Arg = Op.getOperand(5+2*i);
-    unsigned Flags = Op.getConstantOperandVal(5+2*i+1);
-    MVT::ValueType ArgVT = Arg.getValueType();
+    ISD::ArgFlagsTy Flags =
+      cast<ARG_FLAGSSDNode>(Op.getOperand(5+2*i+1))->getArgFlags();
+    MVT ArgVT = Arg.getValueType();
 
     unsigned ObjSize;
     unsigned ObjGPRs;
@@ -465,7 +457,7 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
     NumGPRs += GPRPad;
     ArgOffset += StackPad;
     if (ObjGPRs > 0) {
-      switch (ArgVT) {
+      switch (ArgVT.getSimpleVT()) {
       default: assert(0 && "Unexpected ValueType for argument!");
       case MVT::i32:
         RegsToPass.push_back(std::make_pair(GPRArgRegs[NumGPRs], Arg));
@@ -595,7 +587,7 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
     InFlag = Chain.getValue(1);
   }
 
-  std::vector<MVT::ValueType> NodeTys;
+  std::vector<MVT> NodeTys;
   NodeTys.push_back(MVT::Other);   // Returns a chain
   NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use.
 
@@ -625,7 +617,7 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
   NodeTys.clear();
 
   // If the call has results, copy the values out of the ret val registers.
-  switch (RetVT) {
+  switch (RetVT.getSimpleVT()) {
   default: assert(0 && "Unexpected ret value!");
   case MVT::Other:
     break;
@@ -716,7 +708,7 @@ static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) {
 // be used to form addressing mode. These wrapped nodes will be selected
 // into MOVi.
 static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
-  MVT::ValueType PtrVT = Op.getValueType();
+  MVT PtrVT = Op.getValueType();
   ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
   SDOperand Res;
   if (CP->isMachineConstantPoolEntry())
@@ -732,7 +724,7 @@ static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
 SDOperand
 ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,
                                                  SelectionDAG &DAG) {
-  MVT::ValueType PtrVT = getPointerTy();
+  MVT PtrVT = getPointerTy();
   unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
   ARMConstantPoolValue *CPV =
     new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, ARMCP::CPValue,
@@ -752,7 +744,7 @@ ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,
   Entry.Ty = (const Type *) Type::Int32Ty;
   Args.push_back(Entry);
   std::pair<SDOperand, SDOperand> CallResult =
-    LowerCallTo(Chain, (const Type *) Type::Int32Ty, false, false,
+    LowerCallTo(Chain, (const Type *) Type::Int32Ty, false, false, false,
                 CallingConv::C, false,
                 DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG);
   return CallResult.first;
@@ -766,7 +758,7 @@ ARMTargetLowering::LowerToTLSExecModels(GlobalAddressSDNode *GA,
   GlobalValue *GV = GA->getGlobal();
   SDOperand Offset;
   SDOperand Chain = DAG.getEntryNode();
-  MVT::ValueType PtrVT = getPointerTy();
+  MVT PtrVT = getPointerTy();
   // Get the Thread Pointer
   SDOperand ThreadPointer = DAG.getNode(ARMISD::THREAD_POINTER, PtrVT);
 
@@ -815,7 +807,7 @@ ARMTargetLowering::LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG) {
 
 SDOperand ARMTargetLowering::LowerGlobalAddressELF(SDOperand Op,
                                                    SelectionDAG &DAG) {
-  MVT::ValueType PtrVT = getPointerTy();
+  MVT PtrVT = getPointerTy();
   GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
   Reloc::Model RelocM = getTargetMachine().getRelocationModel();
   if (RelocM == Reloc::PIC_) {
@@ -848,7 +840,7 @@ static bool GVIsIndirectSymbol(GlobalValue *GV, Reloc::Model RelocM) {
 
 SDOperand ARMTargetLowering::LowerGlobalAddressDarwin(SDOperand Op,
                                                       SelectionDAG &DAG) {
-  MVT::ValueType PtrVT = getPointerTy();
+  MVT PtrVT = getPointerTy();
   GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
   Reloc::Model RelocM = getTargetMachine().getRelocationModel();
   bool IsIndirect = GVIsIndirectSymbol(GV, RelocM);
@@ -883,7 +875,7 @@ SDOperand ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDOperand Op,
                                                       SelectionDAG &DAG){
   assert(Subtarget->isTargetELF() &&
          "GLOBAL OFFSET TABLE not implemented for non-ELF targets");
-  MVT::ValueType PtrVT = getPointerTy();
+  MVT PtrVT = getPointerTy();
   unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
   ARMConstantPoolValue *CPV = new ARMConstantPoolValue("_GLOBAL_OFFSET_TABLE_",
                                                        ARMPCLabelIndex,
@@ -896,7 +888,7 @@ SDOperand ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDOperand Op,
 }
 
 static SDOperand LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG) {
-  MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
+  MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
   unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getValue();
   switch (IntNo) {
   default: return SDOperand();    // Don't custom lower most intrinsics.
@@ -909,18 +901,17 @@ static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
                               unsigned VarArgsFrameIndex) {
   // vastart just stores the address of the VarArgsFrameIndex slot into the
   // memory location argument.
-  MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
+  MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
   SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
-  SrcValueSDNode *SV = cast<SrcValueSDNode>(Op.getOperand(2));
-  return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV->getValue(),
-                      SV->getOffset());
+  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
+  return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV, 0);
 }
 
 static SDOperand LowerFORMAL_ARGUMENT(SDOperand Op, SelectionDAG &DAG,
-                                      unsigned *vRegs, unsigned ArgNo,
-                                      unsigned &NumGPRs, unsigned &ArgOffset) {
+                                      unsigned ArgNo, unsigned &NumGPRs,
+                                      unsigned &ArgOffset) {
   MachineFunction &MF = DAG.getMachineFunction();
-  MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType();
+  MVT ObjectVT = Op.getValue(ArgNo).getValueType();
   SDOperand Root = Op.getOperand(0);
   std::vector<SDOperand> ArgValues;
   MachineRegisterInfo &RegInfo = MF.getRegInfo();
@@ -933,7 +924,8 @@ static SDOperand LowerFORMAL_ARGUMENT(SDOperand Op, SelectionDAG &DAG,
   unsigned ObjGPRs;
   unsigned GPRPad;
   unsigned StackPad;
-  unsigned Flags = Op.getConstantOperandVal(ArgNo + 3);
+  ISD::ArgFlagsTy Flags =
+    cast<ARG_FLAGSSDNode>(Op.getOperand(ArgNo + 3))->getArgFlags();
   HowToPassArgument(ObjectVT, NumGPRs, ArgOffset, ObjGPRs,
                     ObjSize, GPRPad, StackPad, Flags);
   NumGPRs += GPRPad;
@@ -943,19 +935,16 @@ static SDOperand LowerFORMAL_ARGUMENT(SDOperand Op, SelectionDAG &DAG,
   if (ObjGPRs == 1) {
     unsigned VReg = RegInfo.createVirtualRegister(&ARM::GPRRegClass);
     RegInfo.addLiveIn(GPRArgRegs[NumGPRs], VReg);
-    vRegs[NumGPRs] = VReg;
     ArgValue = DAG.getCopyFromReg(Root, VReg, MVT::i32);
     if (ObjectVT == MVT::f32)
       ArgValue = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, ArgValue);
   } else if (ObjGPRs == 2) {
     unsigned VReg = RegInfo.createVirtualRegister(&ARM::GPRRegClass);
     RegInfo.addLiveIn(GPRArgRegs[NumGPRs], VReg);
-    vRegs[NumGPRs] = VReg;
     ArgValue = DAG.getCopyFromReg(Root, VReg, MVT::i32);
 
     VReg = RegInfo.createVirtualRegister(&ARM::GPRRegClass);
     RegInfo.addLiveIn(GPRArgRegs[NumGPRs+1], VReg);
-    vRegs[NumGPRs+1] = VReg;
     SDOperand ArgValue2 = DAG.getCopyFromReg(Root, VReg, MVT::i32);
 
     assert(ObjectVT != MVT::i64 && "i64 should already be lowered");
@@ -964,22 +953,15 @@ static SDOperand LowerFORMAL_ARGUMENT(SDOperand Op, SelectionDAG &DAG,
   NumGPRs += ObjGPRs;
 
   if (ObjSize) {
-    // If the argument is actually used, emit a load from the right stack
-    // slot.
-    if (!Op.Val->hasNUsesOfValue(0, ArgNo)) {
-      MachineFrameInfo *MFI = MF.getFrameInfo();
-      int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
-      SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
-      if (ObjGPRs == 0)
-        ArgValue = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
-      else {
-        SDOperand ArgValue2 = DAG.getLoad(MVT::i32, Root, FIN, NULL, 0);
-        assert(ObjectVT != MVT::i64 && "i64 should already be lowered");
-        ArgValue = DAG.getNode(ARMISD::FMDRR, MVT::f64, ArgValue, ArgValue2);
-      }
-    } else {
-      // Don't emit a dead load.
-      ArgValue = DAG.getNode(ISD::UNDEF, ObjectVT);
+    MachineFrameInfo *MFI = MF.getFrameInfo();
+    int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
+    SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
+    if (ObjGPRs == 0)
+      ArgValue = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
+    else {
+      SDOperand ArgValue2 = DAG.getLoad(MVT::i32, Root, FIN, NULL, 0);
+      assert(ObjectVT != MVT::i64 && "i64 should already be lowered");
+      ArgValue = DAG.getNode(ARMISD::FMDRR, MVT::f64, ArgValue, ArgValue2);
     }
 
     ArgOffset += ObjSize;   // Move on to the next argument.
@@ -994,11 +976,10 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) {
   SDOperand Root = Op.getOperand(0);
   unsigned ArgOffset = 0;   // Frame mechanisms handle retaddr slot
   unsigned NumGPRs = 0;     // GPRs used for parameter passing.
-  unsigned VRegs[4];
 
   unsigned NumArgs = Op.Val->getNumValues()-1;
   for (unsigned ArgNo = 0; ArgNo < NumArgs; ++ArgNo)
-    ArgValues.push_back(LowerFORMAL_ARGUMENT(Op, DAG, VRegs, ArgNo,
+    ArgValues.push_back(LowerFORMAL_ARGUMENT(Op, DAG, ArgNo,
                                              NumGPRs, ArgOffset));
 
   bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
@@ -1044,7 +1025,7 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) {
   ArgValues.push_back(Root);
 
   // Return the new list of results.
-  std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(),
+  std::vector<MVT> RetVT(Op.Val->value_begin(),
                                     Op.Val->value_end());
   return DAG.getNode(ISD::MERGE_VALUES, RetVT, &ArgValues[0], ArgValues.size());
 }
@@ -1142,7 +1123,7 @@ static SDOperand getVFPCmp(SDOperand LHS, SDOperand RHS, SelectionDAG &DAG) {
 
 static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG,
                                 const ARMSubtarget *ST) {
-  MVT::ValueType VT = Op.getValueType();
+  MVT VT = Op.getValueType();
   SDOperand LHS = Op.getOperand(0);
   SDOperand RHS = Op.getOperand(1);
   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
@@ -1214,7 +1195,7 @@ SDOperand ARMTargetLowering::LowerBR_JT(SDOperand Op, SelectionDAG &DAG) {
   SDOperand Table = Op.getOperand(1);
   SDOperand Index = Op.getOperand(2);
 
-  MVT::ValueType PTy = getPointerTy();
+  MVT PTy = getPointerTy();
   JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
   ARMFunctionInfo *AFI = DAG.getMachineFunction().getInfo<ARMFunctionInfo>();
   SDOperand UId =  DAG.getConstant(AFI->createJumpTableUId(), PTy);
@@ -1223,7 +1204,7 @@ SDOperand ARMTargetLowering::LowerBR_JT(SDOperand Op, SelectionDAG &DAG) {
   Index = DAG.getNode(ISD::MUL, PTy, Index, DAG.getConstant(4, PTy));
   SDOperand Addr = DAG.getNode(ISD::ADD, PTy, Index, Table);
   bool isPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_;
-  Addr = DAG.getLoad(isPIC ? (MVT::ValueType)MVT::i32 : PTy,
+  Addr = DAG.getLoad(isPIC ? (MVT)MVT::i32 : PTy,
                      Chain, Addr, NULL, 0);
   Chain = Addr.getValue(1);
   if (isPIC)
@@ -1239,7 +1220,7 @@ static SDOperand LowerFP_TO_INT(SDOperand Op, SelectionDAG &DAG) {
 }
 
 static SDOperand LowerINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
-  MVT::ValueType VT = Op.getValueType();
+  MVT VT = Op.getValueType();
   unsigned Opc =
     Op.getOpcode() == ISD::SINT_TO_FP ? ARMISD::SITOF : ARMISD::UITOF;
 
@@ -1251,8 +1232,8 @@ static SDOperand LowerFCOPYSIGN(SDOperand Op, SelectionDAG &DAG) {
   // Implement fcopysign with a fabs and a conditional fneg.
   SDOperand Tmp0 = Op.getOperand(0);
   SDOperand Tmp1 = Op.getOperand(1);
-  MVT::ValueType VT = Op.getValueType();
-  MVT::ValueType SrcVT = Tmp1.getValueType();
+  MVT VT = Op.getValueType();
+  MVT SrcVT = Tmp1.getValueType();
   SDOperand AbsVal = DAG.getNode(ISD::FABS, VT, Tmp0);
   SDOperand Cmp = getVFPCmp(Tmp1, DAG.getConstantFP(0.0, SrcVT), DAG);
   SDOperand ARMCC = DAG.getConstant(ARMCC::LT, MVT::i32);
@@ -1260,24 +1241,37 @@ static SDOperand LowerFCOPYSIGN(SDOperand Op, SelectionDAG &DAG) {
   return DAG.getNode(ARMISD::CNEG, VT, AbsVal, AbsVal, ARMCC, CCR, Cmp);
 }
 
-SDOperand ARMTargetLowering::LowerMEMCPYInline(SDOperand Chain,
-                                               SDOperand Dest,
-                                               SDOperand Source,
-                                               unsigned Size,
-                                               unsigned Align,
-                                               SelectionDAG &DAG) {
+SDOperand
+ARMTargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG,
+                                           SDOperand Chain,
+                                           SDOperand Dst, SDOperand Src,
+                                           SDOperand Size, unsigned Align,
+                                           bool AlwaysInline,
+                                         const Value *DstSV, uint64_t DstSVOff,
+                                         const Value *SrcSV, uint64_t SrcSVOff){
   // Do repeated 4-byte loads and stores. To be improved.
-  assert((Align & 3) == 0 && "Expected 4-byte aligned addresses!");
-  unsigned BytesLeft = Size & 3;
-  unsigned NumMemOps = Size >> 2;
+  // This requires 4-byte alignment.
+  if ((Align & 3) != 0)
+    return SDOperand();
+  // This requires the copy size to be a constant, preferrably
+  // within a subtarget-specific limit.
+  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
+  if (!ConstantSize)
+    return SDOperand();
+  uint64_t SizeVal = ConstantSize->getValue();
+  if (!AlwaysInline && SizeVal > getSubtarget()->getMaxInlineSizeThreshold())
+    return SDOperand();
+
+  unsigned BytesLeft = SizeVal & 3;
+  unsigned NumMemOps = SizeVal >> 2;
   unsigned EmittedNumMemOps = 0;
-  unsigned SrcOff = 0, DstOff = 0;
-  MVT::ValueType VT = MVT::i32;
+  MVT VT = MVT::i32;
   unsigned VTSize = 4;
   unsigned i = 0;
   const unsigned MAX_LOADS_IN_LDM = 6;
   SDOperand TFOps[MAX_LOADS_IN_LDM];
   SDOperand Loads[MAX_LOADS_IN_LDM];
+  uint64_t SrcOff = 0, DstOff = 0;
 
   // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the
   // same number of stores.  The loads and stores will get combined into
@@ -1286,9 +1280,9 @@ SDOperand ARMTargetLowering::LowerMEMCPYInline(SDOperand Chain,
     for (i = 0;
          i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
       Loads[i] = DAG.getLoad(VT, Chain,
-                             DAG.getNode(ISD::ADD, MVT::i32, Source,
+                             DAG.getNode(ISD::ADD, MVT::i32, Src,
                                          DAG.getConstant(SrcOff, MVT::i32)),
-                             NULL, 0);
+                             SrcSV, SrcSVOff + SrcOff);
       TFOps[i] = Loads[i].getValue(1);
       SrcOff += VTSize;
     }
@@ -1297,9 +1291,9 @@ SDOperand ARMTargetLowering::LowerMEMCPYInline(SDOperand Chain,
     for (i = 0;
          i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
       TFOps[i] = DAG.getStore(Chain, Loads[i],
-                           DAG.getNode(ISD::ADD, MVT::i32, Dest, 
+                           DAG.getNode(ISD::ADD, MVT::i32, Dst, 
                                        DAG.getConstant(DstOff, MVT::i32)),
-                           NULL, 0);
+                           DstSV, DstSVOff + DstOff);
       DstOff += VTSize;
     }
     Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &TFOps[0], i);
@@ -1323,9 +1317,9 @@ SDOperand ARMTargetLowering::LowerMEMCPYInline(SDOperand Chain,
     }
 
     Loads[i] = DAG.getLoad(VT, Chain,
-                           DAG.getNode(ISD::ADD, MVT::i32, Source,
+                           DAG.getNode(ISD::ADD, MVT::i32, Src,
                                        DAG.getConstant(SrcOff, MVT::i32)),
-                           NULL, 0);
+                           SrcSV, SrcSVOff + SrcOff);
     TFOps[i] = Loads[i].getValue(1);
     ++i;
     SrcOff += VTSize;
@@ -1345,9 +1339,9 @@ SDOperand ARMTargetLowering::LowerMEMCPYInline(SDOperand Chain,
     }
 
     TFOps[i] = DAG.getStore(Chain, Loads[i],
-                            DAG.getNode(ISD::ADD, MVT::i32, Dest, 
+                            DAG.getNode(ISD::ADD, MVT::i32, Dst, 
                                         DAG.getConstant(DstOff, MVT::i32)),
-                            NULL, 0);
+                            DstSV, DstSVOff + DstOff);
     ++i;
     DstOff += VTSize;
     BytesLeft -= VTSize;
@@ -1423,7 +1417,6 @@ SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   case ISD::RETURNADDR:    break;
   case ISD::FRAMEADDR:     break;
   case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG);
-  case ISD::MEMCPY:        return LowerMEMCPY(Op, DAG);
   case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
       
       
@@ -1543,7 +1536,7 @@ SDOperand ARMTargetLowering::PerformDAGCombine(SDNode *N,
 /// isLegalAddressImmediate - Return true if the integer value can be used
 /// as the offset of the target addressing mode for load / store of the
 /// given type.
-static bool isLegalAddressImmediate(int64_t V, MVT::ValueType VT,
+static bool isLegalAddressImmediate(int64_t V, MVT VT,
                                     const ARMSubtarget *Subtarget) {
   if (V == 0)
     return true;
@@ -1553,7 +1546,7 @@ static bool isLegalAddressImmediate(int64_t V, MVT::ValueType VT,
       return false;
 
     unsigned Scale = 1;
-    switch (VT) {
+    switch (VT.getSimpleVT()) {
     default: return false;
     case MVT::i1:
     case MVT::i8:
@@ -1572,21 +1565,21 @@ static bool isLegalAddressImmediate(int64_t V, MVT::ValueType VT,
     if ((V & (Scale - 1)) != 0)
       return false;
     V /= Scale;
-    return V == V & ((1LL << 5) - 1);
+    return V == (V & ((1LL << 5) - 1));
   }
 
   if (V < 0)
     V = - V;
-  switch (VT) {
+  switch (VT.getSimpleVT()) {
   default: return false;
   case MVT::i1:
   case MVT::i8:
   case MVT::i32:
     // +- imm12
-    return V == V & ((1LL << 12) - 1);
+    return V == (V & ((1LL << 12) - 1));
   case MVT::i16:
     // +- imm8
-    return V == V & ((1LL << 8) - 1);
+    return V == (V & ((1LL << 8) - 1));
   case MVT::f32:
   case MVT::f64:
     if (!Subtarget->hasVFP2())
@@ -1594,7 +1587,7 @@ static bool isLegalAddressImmediate(int64_t V, MVT::ValueType VT,
     if ((V & 3) != 0)
       return false;
     V >>= 2;
-    return V == V & ((1LL << 8) - 1);
+    return V == (V & ((1LL << 8) - 1));
   }
 }
 
@@ -1622,7 +1615,7 @@ bool ARMTargetLowering::isLegalAddressingMode(const AddrMode &AM,
       return false;
     
     int Scale = AM.Scale;
-    switch (getValueType(Ty)) {
+    switch (getValueType(Ty).getSimpleVT()) {
     default: return false;
     case MVT::i1:
     case MVT::i8:
@@ -1657,7 +1650,7 @@ bool ARMTargetLowering::isLegalAddressingMode(const AddrMode &AM,
 }
 
 
-static bool getIndexedAddressParts(SDNode *Ptr, MVT::ValueType VT,
+static bool getIndexedAddressParts(SDNode *Ptr, MVT VT,
                                    bool isSEXTLoad, SDOperand &Base,
                                    SDOperand &Offset, bool &isInc,
                                    SelectionDAG &DAG) {
@@ -1724,7 +1717,7 @@ ARMTargetLowering::getPreIndexedAddressParts(SDNode *N, SDOperand &Base,
   if (Subtarget->isThumb())
     return false;
 
-  MVT::ValueType VT;
+  MVT VT;
   SDOperand Ptr;
   bool isSEXTLoad = false;
   if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
@@ -1758,7 +1751,7 @@ bool ARMTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
   if (Subtarget->isThumb())
     return false;
 
-  MVT::ValueType VT;
+  MVT VT;
   SDOperand Ptr;
   bool isSEXTLoad = false;
   if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
@@ -1780,13 +1773,12 @@ bool ARMTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
 }
 
 void ARMTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
-                                                       uint64_t Mask,
-                                                       uint64_t &KnownZero, 
-                                                       uint64_t &KnownOne,
+                                                       const APInt &Mask,
+                                                       APInt &KnownZero, 
+                                                       APInt &KnownOne,
                                                        const SelectionDAG &DAG,
                                                        unsigned Depth) const {
-  KnownZero = 0;
-  KnownOne = 0;
+  KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
   switch (Op.getOpcode()) {
   default: break;
   case ARMISD::CMOV: {
@@ -1794,7 +1786,7 @@ void ARMTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
     DAG.ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
     if (KnownZero == 0 && KnownOne == 0) return;
 
-    uint64_t KnownZeroRHS, KnownOneRHS;
+    APInt KnownZeroRHS, KnownOneRHS;
     DAG.ComputeMaskedBits(Op.getOperand(1), Mask,
                           KnownZeroRHS, KnownOneRHS, Depth+1);
     KnownZero &= KnownZeroRHS;
@@ -1824,7 +1816,7 @@ ARMTargetLowering::getConstraintType(const std::string &Constraint) const {
 
 std::pair<unsigned, const TargetRegisterClass*> 
 ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
-                                                MVT::ValueType VT) const {
+                                                MVT VT) const {
   if (Constraint.size() == 1) {
     // GCC RS6000 Constraint Letters
     switch (Constraint[0]) {
@@ -1846,7 +1838,7 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
 
 std::vector<unsigned> ARMTargetLowering::
 getRegClassForInlineAsmConstraint(const std::string &Constraint,
-                                  MVT::ValueType VT) const {
+                                  MVT VT) const {
   if (Constraint.size() != 1)
     return std::vector<unsigned>();