aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2004-10-12 04:52:52 +0000
committerChris Lattner <sabre@nondot.org>2004-10-12 04:52:52 +0000
commit35b9e48cfd315d3c7010f985a694d81c7c2ae5d0 (patch)
treeb68604fda8fd969a633159be9ccee99e2da756ab /lib/Transforms
parentb18dfebb3aa13339305691af600563c6a7f50db3 (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.cpp49
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);
}