Lower memcpy if it makes sense.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42864 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Devang Patel 2007-10-11 17:21:57 +00:00
parent 343960af31
commit f9193de25b
2 changed files with 64 additions and 0 deletions

View File

@ -7669,6 +7669,52 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
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) {

View File

@ -0,0 +1,18 @@
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep call
@.str = internal constant [4 x i8] c"xyz\00" ; <[4 x i8]*> [#uses=1]
define void @foo(i8* %P) {
entry:
%P_addr = alloca i8* ; <i8**> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store i8* %P, i8** %P_addr
%tmp = load i8** %P_addr, align 4 ; <i8*> [#uses=1]
%tmp1 = getelementptr [4 x i8]* @.str, i32 0, i32 0 ; <i8*> [#uses=1]
call void @llvm.memcpy.i32( i8* %tmp, i8* %tmp1, i32 4, i32 1 )
br label %return
return: ; preds = %entry
ret void
}
declare void @llvm.memcpy.i32(i8*, i8*, i32, i32)