From 43f8e43eb2a166f50c3a077040d8bdb24104433a Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 18 Nov 2010 07:02:37 +0000 Subject: [PATCH] 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 --- lib/Transforms/Scalar/MemCpyOptimizer.cpp | 163 ++++++++++++---------- 1 file changed, 87 insertions(+), 76 deletions(-) diff --git a/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/lib/Transforms/Scalar/MemCpyOptimizer.cpp index f4876eac43b..39f40a1fb9d 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,6 +667,84 @@ bool MemCpyOpt::performCallSlotOptzn(Instruction *cpy, return true; } +/// 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. + 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(MDep->getLength()); + if (!C1) return false; + + uint64_t DepSize = C1->getValue().getZExtValue(); + + 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(); + if (AA.alias(M->getRawDest(), MSize, MDep->getRawSource(), DepSize) != + AliasAnalysis::NoAlias) + return false; + else if (AA.alias(M->getRawDest(), MSize, M->getRawSource(), MSize) != + AliasAnalysis::NoAlias) + return false; + else if (AA.alias(MDep->getRawDest(), DepSize, MDep->getRawSource(), DepSize) + != AliasAnalysis::NoAlias) + return false; + + // 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); + + // 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. + // TODO: Is this worth it if we're creating a less aligned memcpy? For + // example we could be moving from movaps -> movq on x86. + unsigned Align = std::min(MDep->getAlignmentCst()->getZExtValue(), + M->getAlignmentCst()->getZExtValue()); + LLVMContext &Context = M->getContext(); + ConstantInt *AlignCI = ConstantInt::get(Type::getInt32Ty(Context), Align); + Value *Args[5] = { + M->getRawDest(), MDep->getRawSource(), M->getLength(), + AlignCI, M->getVolatileCst() + }; + CallInst *C = CallInst::Create(MemCpyFun, Args, Args+5, "", M); + + + MemoryDependenceAnalysis &MD = getAnalysis(); + + // 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. + MemDepResult dep = MD.getDependency(C); + if (dep.isClobber() && dep.getInst() == MDep) { + MD.removeInstruction(M); + M->eraseFromParent(); + ++NumMemCpyInstr; + return true; + } + + // Otherwise, there was no point in doing this, so we remove the call we + // inserted and act like nothing happened. + MD.removeInstruction(C); + C->eraseFromParent(); + 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 @@ -683,85 +763,16 @@ bool MemCpyOpt::processMemCpy(MemCpyInst *M) { MemDepResult dep = MD.getDependency(M); if (!dep.isClobber()) return false; - if (!isa(dep.getInst())) { - if (CallInst *C = dyn_cast(dep.getInst())) { - bool changed = performCallSlotOptzn(M, M->getDest(), M->getSource(), - cpyLen->getZExtValue(), C); - if (changed) M->eraseFromParent(); - return changed; - } - return false; - } - MemCpyInst *MDep = cast(dep.getInst()); - - // We can only transforms memcpy's where the dest of one is the source of the - // 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(MDep->getLength()); - ConstantInt *C2 = dyn_cast(M->getLength()); - if (!C1 || !C2) - return false; - - uint64_t DepSize = C1->getValue().getZExtValue(); - uint64_t CpySize = C2->getValue().getZExtValue(); - - if (DepSize < CpySize) - 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(); - if (AA.alias(M->getRawDest(), CpySize, MDep->getRawSource(), DepSize) != - AliasAnalysis::NoAlias) - return false; - else if (AA.alias(M->getRawDest(), CpySize, M->getRawSource(), CpySize) != - AliasAnalysis::NoAlias) - return false; - else if (AA.alias(MDep->getRawDest(), DepSize, MDep->getRawSource(), DepSize) - != AliasAnalysis::NoAlias) - return false; - - // 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); + if (MemCpyInst *MDep = dyn_cast(dep.getInst())) + return processMemCpyMemCpyDependence(M, MDep, cpyLen->getZExtValue()); - // 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. - // TODO: Is this worth it if we're creating a less aligned memcpy? For - // example we could be moving from movaps -> movq on x86. - unsigned Align = std::min(MDep->getAlignmentCst()->getZExtValue(), - M->getAlignmentCst()->getZExtValue()); - LLVMContext &Context = M->getContext(); - ConstantInt *AlignCI = ConstantInt::get(Type::getInt32Ty(Context), Align); - Value *Args[5] = { - M->getRawDest(), MDep->getRawSource(), M->getLength(), - AlignCI, M->getVolatileCst() - }; - CallInst *C = CallInst::Create(MemCpyFun, Args, Args+5, "", M); - - // 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) { - MD.removeInstruction(M); - M->eraseFromParent(); - ++NumMemCpyInstr; - return true; + if (CallInst *C = dyn_cast(dep.getInst())) { + bool changed = performCallSlotOptzn(M, M->getDest(), M->getSource(), + cpyLen->getZExtValue(), C); + if (changed) M->eraseFromParent(); + return changed; } - - // Otherwise, there was no point in doing this, so we remove the call we - // inserted and act like nothing happened. - MD.removeInstruction(C); - C->eraseFromParent(); return false; }