summaryrefslogtreecommitdiff
path: root/lib/Transforms/Scalar/MemCpyOptimizer.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-11-18 07:02:37 +0000
committerChris Lattner <sabre@nondot.org>2010-11-18 07:02:37 +0000
commit43f8e43eb2a166f50c3a077040d8bdb24104433a (patch)
tree53ba8d0ba43c3c18c941bc847ed7d0c03f63ad52 /lib/Transforms/Scalar/MemCpyOptimizer.cpp
parent6248065194778c866164b0c10f09f0f0d91b91ac (diff)
downloadllvm-43f8e43eb2a166f50c3a077040d8bdb24104433a.tar.gz
llvm-43f8e43eb2a166f50c3a077040d8bdb24104433a.tar.bz2
llvm-43f8e43eb2a166f50c3a077040d8bdb24104433a.tar.xz
rearrange some code, splitting memcpy/memcpy optimization
out of processMemCpy into its own function. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119687 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar/MemCpyOptimizer.cpp')
-rw-r--r--lib/Transforms/Scalar/MemCpyOptimizer.cpp101
1 files changed, 56 insertions, 45 deletions
diff --git a/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index f4876eac43..39f40a1fb9 100644
--- a/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -325,6 +325,8 @@ namespace {
bool processMemMove(MemMoveInst *M);
bool performCallSlotOptzn(Instruction *cpy, Value *cpyDst, Value *cpySrc,
uint64_t cpyLen, CallInst *C);
+ bool processMemCpyMemCpyDependence(MemCpyInst *M, MemCpyInst *MDep,
+ uint64_t MSize);
bool iterateOnFunction(Function &F);
};
@@ -665,61 +667,34 @@ bool MemCpyOpt::performCallSlotOptzn(Instruction *cpy,
return true;
}
-/// processMemCpy - perform simplification of memcpy's. If we have memcpy A
-/// which copies X to Y, and memcpy B which copies Y to Z, then we can rewrite
-/// B to be a memcpy from X to Z (or potentially a memmove, depending on
-/// circumstances). This allows later passes to remove the first memcpy
-/// altogether.
-bool MemCpyOpt::processMemCpy(MemCpyInst *M) {
- MemoryDependenceAnalysis &MD = getAnalysis<MemoryDependenceAnalysis>();
-
- // We can only optimize statically-sized memcpy's.
- ConstantInt *cpyLen = dyn_cast<ConstantInt>(M->getLength());
- if (!cpyLen) return false;
-
- // The are two possible optimizations we can do for memcpy:
- // a) memcpy-memcpy xform which exposes redundance for DSE.
- // b) call-memcpy xform for return slot optimization.
- MemDepResult dep = MD.getDependency(M);
- if (!dep.isClobber())
- return false;
- if (!isa<MemCpyInst>(dep.getInst())) {
- if (CallInst *C = dyn_cast<CallInst>(dep.getInst())) {
- bool changed = performCallSlotOptzn(M, M->getDest(), M->getSource(),
- cpyLen->getZExtValue(), C);
- if (changed) M->eraseFromParent();
- return changed;
- }
- return false;
- }
-
- MemCpyInst *MDep = cast<MemCpyInst>(dep.getInst());
-
+/// processMemCpyMemCpyDependence - We've found that the (upward scanning)
+/// memory dependence of memcpy 'M' is the memcpy 'MDep'. Try to simplify M to
+/// copy from MDep's input if we can. MSize is the size of M's copy.
+///
+bool MemCpyOpt::processMemCpyMemCpyDependence(MemCpyInst *M, MemCpyInst *MDep,
+ uint64_t MSize) {
// We can only transforms memcpy's where the dest of one is the source of the
- // other
+ // other.
if (M->getSource() != MDep->getDest())
return false;
// Second, the length of the memcpy's must be the same, or the preceeding one
// must be larger than the following one.
ConstantInt *C1 = dyn_cast<ConstantInt>(MDep->getLength());
- ConstantInt *C2 = dyn_cast<ConstantInt>(M->getLength());
- if (!C1 || !C2)
- return false;
+ if (!C1) return false;
uint64_t DepSize = C1->getValue().getZExtValue();
- uint64_t CpySize = C2->getValue().getZExtValue();
- if (DepSize < CpySize)
+ if (DepSize < MSize)
return false;
// Finally, we have to make sure that the dest of the second does not
// alias the source of the first
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
- if (AA.alias(M->getRawDest(), CpySize, MDep->getRawSource(), DepSize) !=
+ if (AA.alias(M->getRawDest(), MSize, MDep->getRawSource(), DepSize) !=
AliasAnalysis::NoAlias)
return false;
- else if (AA.alias(M->getRawDest(), CpySize, M->getRawSource(), CpySize) !=
+ else if (AA.alias(M->getRawDest(), MSize, M->getRawSource(), MSize) !=
AliasAnalysis::NoAlias)
return false;
else if (AA.alias(MDep->getRawDest(), DepSize, MDep->getRawSource(), DepSize)
@@ -728,12 +703,12 @@ bool MemCpyOpt::processMemCpy(MemCpyInst *M) {
// If all checks passed, then we can transform these memcpy's
const Type *ArgTys[3] = { M->getRawDest()->getType(),
- MDep->getRawSource()->getType(),
- M->getLength()->getType() };
- Function *MemCpyFun = Intrinsic::getDeclaration(
- M->getParent()->getParent()->getParent(),
- M->getIntrinsicID(), ArgTys, 3);
-
+ MDep->getRawSource()->getType(),
+ M->getLength()->getType() };
+ Function *MemCpyFun =
+ Intrinsic::getDeclaration(M->getParent()->getParent()->getParent(),
+ M->getIntrinsicID(), ArgTys, 3);
+
// Make sure to use the lesser of the alignment of the source and the dest
// since we're changing where we're reading from, but don't want to increase
// the alignment past what can be read from or written to.
@@ -749,9 +724,13 @@ bool MemCpyOpt::processMemCpy(MemCpyInst *M) {
};
CallInst *C = CallInst::Create(MemCpyFun, Args, Args+5, "", M);
+
+ MemoryDependenceAnalysis &MD = getAnalysis<MemoryDependenceAnalysis>();
+
// If C and M don't interfere, then this is a valid transformation. If they
// did, this would mean that the two sources overlap, which would be bad.
- if (MD.getDependency(C) == dep) {
+ MemDepResult dep = MD.getDependency(C);
+ if (dep.isClobber() && dep.getInst() == MDep) {
MD.removeInstruction(M);
M->eraseFromParent();
++NumMemCpyInstr;
@@ -765,6 +744,38 @@ bool MemCpyOpt::processMemCpy(MemCpyInst *M) {
return false;
}
+
+/// processMemCpy - perform simplification of memcpy's. If we have memcpy A
+/// which copies X to Y, and memcpy B which copies Y to Z, then we can rewrite
+/// B to be a memcpy from X to Z (or potentially a memmove, depending on
+/// circumstances). This allows later passes to remove the first memcpy
+/// altogether.
+bool MemCpyOpt::processMemCpy(MemCpyInst *M) {
+ MemoryDependenceAnalysis &MD = getAnalysis<MemoryDependenceAnalysis>();
+
+ // We can only optimize statically-sized memcpy's.
+ ConstantInt *cpyLen = dyn_cast<ConstantInt>(M->getLength());
+ if (!cpyLen) return false;
+
+ // The are two possible optimizations we can do for memcpy:
+ // a) memcpy-memcpy xform which exposes redundance for DSE.
+ // b) call-memcpy xform for return slot optimization.
+ MemDepResult dep = MD.getDependency(M);
+ if (!dep.isClobber())
+ return false;
+
+ if (MemCpyInst *MDep = dyn_cast<MemCpyInst>(dep.getInst()))
+ return processMemCpyMemCpyDependence(M, MDep, cpyLen->getZExtValue());
+
+ if (CallInst *C = dyn_cast<CallInst>(dep.getInst())) {
+ bool changed = performCallSlotOptzn(M, M->getDest(), M->getSource(),
+ cpyLen->getZExtValue(), C);
+ if (changed) M->eraseFromParent();
+ return changed;
+ }
+ return false;
+}
+
/// processMemMove - Transforms memmove calls to memcpy calls when the src/dst
/// are guaranteed not to alias.
bool MemCpyOpt::processMemMove(MemMoveInst *M) {