From 31805bf2b6e7c732dfce83e1eed61b9e91628375 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 11 Jan 2005 06:19:26 +0000 Subject: [PATCH] Implement MEMCPY natively in terms of rep movs* git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19468 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelPattern.cpp | 46 ++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/Target/X86/X86ISelPattern.cpp b/lib/Target/X86/X86ISelPattern.cpp index 1f4e86644ae..8073342895a 100644 --- a/lib/Target/X86/X86ISelPattern.cpp +++ b/lib/Target/X86/X86ISelPattern.cpp @@ -50,7 +50,6 @@ namespace { computeRegisterProperties(); - setOperationUnsupported(ISD::MEMCPY, MVT::Other); setOperationUnsupported(ISD::MEMMOVE, MVT::Other); setOperationUnsupported(ISD::MUL, MVT::i8); @@ -2088,6 +2087,51 @@ void ISel::Select(SDOperand N) { BuildMI(BB, Opcode, 0); return; } + case ISD::MEMCPY: + Select(N.getOperand(0)); // Select the chain. + unsigned Align = + (unsigned)cast(Node->getOperand(4))->getValue(); + if (Align == 0) Align = 1; + + // Turn the byte code into # iterations + unsigned CountReg; + unsigned Opcode; + switch (Align & 3) { + case 2: // WORD aligned + CountReg = MakeReg(MVT::i32); + if (ConstantSDNode *I = dyn_cast(Node->getOperand(3))) { + BuildMI(BB, X86::MOV32ri, 1, CountReg).addImm(I->getValue()/2); + } else { + unsigned ByteReg = SelectExpr(Node->getOperand(3)); + BuildMI(BB, X86::SHR32ri, 2, CountReg).addReg(ByteReg).addImm(1); + } + Opcode = X86::REP_MOVSW; + break; + case 0: // DWORD aligned + CountReg = MakeReg(MVT::i32); + if (ConstantSDNode *I = dyn_cast(Node->getOperand(3))) { + BuildMI(BB, X86::MOV32ri, 1, CountReg).addImm(I->getValue()/4); + } else { + unsigned ByteReg = SelectExpr(Node->getOperand(3)); + BuildMI(BB, X86::SHR32ri, 2, CountReg).addReg(ByteReg).addImm(2); + } + Opcode = X86::REP_MOVSD; + break; + default: // BYTE aligned + CountReg = SelectExpr(Node->getOperand(3)); + Opcode = X86::REP_MOVSB; + break; + } + + // No matter what the alignment is, we put the source in ESI, the + // destination in EDI, and the count in ECX. + unsigned TmpReg1 = SelectExpr(Node->getOperand(1)); + unsigned TmpReg2 = SelectExpr(Node->getOperand(2)); + BuildMI(BB, X86::MOV32rr, 1, X86::ECX).addReg(CountReg); + BuildMI(BB, X86::MOV32rr, 1, X86::EDI).addReg(TmpReg1); + BuildMI(BB, X86::MOV32rr, 1, X86::ESI).addReg(TmpReg2); + BuildMI(BB, Opcode, 0); + return; } assert(0 && "Should not be reached!"); }