diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/X86/X86SelectionDAGInfo.cpp | 42 | 
1 files changed, 29 insertions, 13 deletions
diff --git a/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp b/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp index b9c620fddc4..3b3ab2a83a1 100644 --- a/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp +++ b/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp @@ -200,13 +200,11 @@ X86SelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl,        SrcPtrInfo.getAddrSpace() >= 256)      return SDValue(); -  // ESI might be used as a base pointer, in that case we can't simply overwrite -  // the register.  Fall back to generic code. +  // If ESI is used as a base pointer, we must preserve it when doing rep movs.    const X86RegisterInfo *TRI =        static_cast<const X86RegisterInfo *>(DAG.getTarget().getRegisterInfo()); -  if (TRI->hasBasePointer(DAG.getMachineFunction()) && -      TRI->getBaseRegister() == X86::ESI) -    return SDValue(); +  bool PreserveESI = TRI->hasBasePointer(DAG.getMachineFunction()) && +                     TRI->getBaseRegister() == X86::ESI;    MVT AVT;    if (Align & 1) @@ -225,27 +223,45 @@ X86SelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl,    SDValue Count = DAG.getIntPtrConstant(CountVal);    unsigned BytesLeft = SizeVal % UBytes; -  SDValue InFlag(0, 0); + +  if (PreserveESI) { +    // Save ESI to a physical register. (We cannot use a virtual register +    // because if it is spilled we wouldn't be able to reload it.) +    // We don't glue this because the register dependencies are explicit. +    Chain = DAG.getCopyToReg(Chain, dl, X86::EDX, +                             DAG.getRegister(X86::ESI, MVT::i32)); +  } + +  SDValue InGlue(0, 0);    Chain  = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX :                                                                X86::ECX, -                            Count, InFlag); -  InFlag = Chain.getValue(1); +                            Count, InGlue); +  InGlue = Chain.getValue(1);    Chain  = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI :                                                                X86::EDI, -                            Dst, InFlag); -  InFlag = Chain.getValue(1); +                            Dst, InGlue); +  InGlue = Chain.getValue(1);    Chain  = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RSI :                                                                X86::ESI, -                            Src, InFlag); -  InFlag = Chain.getValue(1); +                            Src, InGlue); +  InGlue = Chain.getValue(1);    SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue); -  SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag }; +  SDValue Ops[] = { Chain, DAG.getValueType(AVT), InGlue }; +  // FIXME: Make X86rep_movs explicitly use FCX, RDI, RSI instead of glue.    SDValue RepMovs = DAG.getNode(X86ISD::REP_MOVS, dl, Tys, Ops,                                  array_lengthof(Ops)); +  if (PreserveESI) { +    InGlue = RepMovs.getValue(1); +    RepMovs = DAG.getCopyToReg(RepMovs, dl, X86::ESI, +                               DAG.getRegister(X86::EDX, MVT::i32), InGlue); +  } +    SmallVector<SDValue, 4> Results;    Results.push_back(RepMovs); + +    if (BytesLeft) {      // Handle the last 1 - 7 bytes.      unsigned Offset = SizeVal - BytesLeft;  | 

