Implement MEMCPY natively in terms of rep movs*
authorChris Lattner <sabre@nondot.org>
Tue, 11 Jan 2005 06:19:26 +0000 (06:19 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 11 Jan 2005 06:19:26 +0000 (06:19 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19468 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelPattern.cpp

index 1f4e86644ae4558f23157e89ad8465063caecaf8..8073342895a35b64a7cdb1ee56682aa786fa4720 100644 (file)
@@ -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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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!");
 }