summaryrefslogtreecommitdiff
path: root/lib/Target/X86/X86SelectionDAGInfo.cpp
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2014-03-18 20:04:34 +0000
committerHans Wennborg <hans@hanshq.net>2014-03-18 20:04:34 +0000
commit523f800e90f21861a5b6bb9f7c432c8799168bde (patch)
treeb2894a46095eb1dde65307e5e09f8318c6330c14 /lib/Target/X86/X86SelectionDAGInfo.cpp
parent172c31844b3b8216313bcb7b7e20ad8ecbc71d5f (diff)
X86 memcpy lowering: use "rep movs" even when esi is used as base pointer
For functions where esi is used as base pointer, we would previously fall back from lowering memcpy with "rep movs" because that clobbers esi. With this patch, we just store esi in another physical register, and restore it afterwards. This adds a little bit of register preassure, but the more efficient memcpy should be worth it. Differential Revision: http://llvm-reviews.chandlerc.com/D2968 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204174 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/X86/X86SelectionDAGInfo.cpp')
-rw-r--r--lib/Target/X86/X86SelectionDAGInfo.cpp42
1 files changed, 29 insertions, 13 deletions
diff --git a/lib/Target/X86/X86SelectionDAGInfo.cpp b/lib/Target/X86/X86SelectionDAGInfo.cpp
index b9c620fddc4..3b3ab2a83a1 100644
--- a/lib/Target/X86/X86SelectionDAGInfo.cpp
+++ b/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;