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 | 7e9b2ea3bfc68d3b8d057c3c69b5b520210aadd8 (patch) | |
| tree | be3245834358d4b1089a15f85a6f7fc3cf495abc /llvm | |
| parent | ac5701319b417ec8d3f81f2312d9bf8c26ec6e86 (diff) | |
| download | bcm5719-llvm-7e9b2ea3bfc68d3b8d057c3c69b5b520210aadd8.tar.gz bcm5719-llvm-7e9b2ea3bfc68d3b8d057c3c69b5b520210aadd8.zip  | |
rearrange some code, splitting memcpy/memcpy optimization
out of processMemCpy into its own function.
llvm-svn: 119687
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp | 101 | 
1 files changed, 56 insertions, 45 deletions
diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp index f4876eac43b..39f40a1fb9d 100644 --- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/llvm/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) {  | 

