Lower memcpy if it makes sense.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42864 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 2311f1e..5ff9714 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -7669,6 +7669,52 @@
         MI->setAlignment(ConstantInt::get(Type::Int32Ty, Align));
         Changed = true;
       }
+
+      // If MemCpyInst length is 1/2/4/8 bytes then replace memcpy with load/store
+      ConstantInt *MemOpLength = dyn_cast<ConstantInt>(CI.getOperand(3));
+      if (isa<MemCpyInst>(MI))
+        if (MemOpLength) {
+        unsigned Size = MemOpLength->getZExtValue();
+        unsigned Align = cast<ConstantInt>(CI.getOperand(4))->getZExtValue();
+        const PointerType *PTy = cast<PointerType>(CI.getOperand(1)->getType());
+        const Type *MTy = PTy->getElementType();
+        PointerType *NewPtrTy = NULL;
+        if (MTy == Type::Int8Ty) {
+          if (Size == 8)
+            NewPtrTy = PointerType::get(Type::Int64Ty);
+          else if (Size == 4)
+            NewPtrTy = PointerType::get(Type::Int32Ty);
+          else if (Size == 2)
+            NewPtrTy = PointerType::get(Type::Int16Ty);
+          else if (Size == 1)
+            NewPtrTy = PointerType::get(Type::Int8Ty);
+        } else if (MTy == Type::Int16Ty) {
+          if (Size == 4)
+            NewPtrTy = PointerType::get(Type::Int64Ty);
+          else if (Size == 2)
+            NewPtrTy = PointerType::get(Type::Int32Ty);
+          else if (Size == 1)
+            NewPtrTy = PointerType::get(Type::Int16Ty);
+        } else if (MTy == Type::Int32Ty) {
+          if (Size == 2)
+            NewPtrTy = PointerType::get(Type::Int64Ty);
+          else if (Size == 1)
+            NewPtrTy = PointerType::get(Type::Int32Ty);
+        } else if (MTy == Type::Int64Ty) {
+          if (Size == 1)
+            NewPtrTy = PointerType::get(Type::Int64Ty);
+        }
+        if (NewPtrTy)
+        {
+          Value *Src = InsertCastBefore(Instruction::BitCast, CI.getOperand(2), NewPtrTy, CI);
+          Value *Dest = InsertCastBefore(Instruction::BitCast, CI.getOperand(1), NewPtrTy, CI);
+          Value *L = new LoadInst(Src, "tmp", false, Align, &CI);
+          Value *NS = new StoreInst(L, Dest, false, Align, &CI);
+          CI.replaceAllUsesWith(NS);
+          Changed = true;
+          return EraseInstFromFunction(CI);
+        }
+      }
     } else if (isa<MemSetInst>(MI)) {
       unsigned Alignment = GetOrEnforceKnownAlignment(MI->getDest(), TD);
       if (MI->getAlignment()->getZExtValue() < Alignment) {