diff options
author | Chris Lattner <sabre@nondot.org> | 2010-11-18 07:02:37 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-11-18 07:02:37 +0000 |
commit | 43f8e43eb2a166f50c3a077040d8bdb24104433a (patch) | |
tree | 53ba8d0ba43c3c18c941bc847ed7d0c03f63ad52 /lib/Transforms/Scalar/MemCpyOptimizer.cpp | |
parent | 6248065194778c866164b0c10f09f0f0d91b91ac (diff) |
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.cpp | 101 |
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) { |