diff options
author | Chris Lattner <sabre@nondot.org> | 2004-10-12 04:52:52 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2004-10-12 04:52:52 +0000 |
commit | 35b9e48cfd315d3c7010f985a694d81c7c2ae5d0 (patch) | |
tree | b68604fda8fd969a633159be9ccee99e2da756ab /lib/Transforms | |
parent | b18dfebb3aa13339305691af600563c6a7f50db3 (diff) |
Transform memmove -> memcpy when the source is obviously constant memory.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16932 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 763ffe1d01..2155b78b5d 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -35,10 +35,8 @@ #define DEBUG_TYPE "instcombine" #include "llvm/Transforms/Scalar.h" -#include "llvm/Instructions.h" -#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" #include "llvm/Pass.h" -#include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/GlobalVariable.h" #include "llvm/Target/TargetData.h" @@ -3094,23 +3092,42 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { // CallInst simplification // Instruction *InstCombiner::visitCallInst(CallInst &CI) { + // Intrinsics cannot occur in an invoke, so handle them here instead of in // visitCallSite. - if (Function *F = CI.getCalledFunction()) - switch (F->getIntrinsicID()) { - case Intrinsic::memmove: - case Intrinsic::memcpy: - case Intrinsic::memset: - // memmove/cpy/set of zero bytes is a noop. - if (Constant *NumBytes = dyn_cast<Constant>(CI.getOperand(3))) { - if (NumBytes->isNullValue()) - return EraseInstFromFunction(CI); - } - break; - default: - break; + if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(&CI)) { + bool Changed = false; + + // memmove/cpy/set of zero bytes is a noop. + if (Constant *NumBytes = dyn_cast<Constant>(MI->getLength())) { + if (NumBytes->isNullValue()) return EraseInstFromFunction(CI); + + // FIXME: Increase alignment here. + + if (ConstantInt *CI = dyn_cast<ConstantInt>(NumBytes)) + if (CI->getRawValue() == 1) { + // Replace the instruction with just byte operations. We would + // transform other cases to loads/stores, but we don't know if + // alignment is sufficient. + } } + // If we have a memmove and the source operation is a constant global, + // then the source and dest pointers can't alias, so we can change this + // into a call to memcpy. + if (MemMoveInst *MMI = dyn_cast<MemMoveInst>(MI)) + if (GlobalVariable *GVSrc = dyn_cast<GlobalVariable>(MMI->getSource())) + if (GVSrc->isConstant()) { + Module *M = CI.getParent()->getParent()->getParent(); + Function *MemCpy = M->getOrInsertFunction("llvm.memcpy", + CI.getCalledFunction()->getFunctionType()); + CI.setOperand(0, MemCpy); + Changed = true; + } + + if (Changed) return &CI; + } + return visitCallSite(&CI); } |