rearrange some code, splitting memcpy/memcpy optimization
authorChris Lattner <sabre@nondot.org>
Thu, 18 Nov 2010 07:02:37 +0000 (07:02 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 18 Nov 2010 07:02:37 +0000 (07:02 +0000)
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

index f4876eac43bfb755698ec0ce61407f18db00b94d..39f40a1fb9d5dbbeca5bcffe272c2f1635603ac2 100644 (file)
@@ -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) {