[llvm-commits] [llvm] r49419 - in /llvm/trunk: include/llvm/ include/llvm/Transforms/ lib/Transforms/Scalar/ test/Transforms/GVN/ test/Transforms/MemCpyOpt/ tools/llvm-ld/ tools/opt/

Chris Lattner clattner at apple.com
Sat Apr 19 17:20:52 PDT 2008


On Apr 9, 2008, at 1:23 AM, Owen Anderson wrote:

> Author: resistor
> Date: Wed Apr  9 03:23:16 2008
> New Revision: 49419
>
> URL: http://llvm.org/viewvc/llvm-project?rev=49419&view=rev
> Log:
> Factor a bunch of functionality related to memcpy and memset  
> transforms out of
> GVN and into its own pass.

Hi Owen,

> +//===- MemCpyOptimizer.cpp - Optimize use of memcpy and friends  
> -----------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open  
> Source
> +// License. See LICENSE.TXT for details.
> +//
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +//
> +// This pass performs various transformations related to  
> eliminating memcpy
> +// calls, or transforming sets of stores into memset's.
> +//
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//

Ok.

> +#define DEBUG_TYPE "memcpyopt"
> +#include "llvm/Transforms/Scalar.h"
> +#include "llvm/BasicBlock.h"
> +#include "llvm/Constants.h"
> +#include "llvm/DerivedTypes.h"
> +#include "llvm/Function.h"
> +#include "llvm/IntrinsicInst.h"
> +#include "llvm/Instructions.h"
> +#include "llvm/ParameterAttributes.h"
> +#include "llvm/Value.h"
> +#include "llvm/ADT/DepthFirstIterator.h"
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/ADT/Statistic.h"
> +#include "llvm/Analysis/Dominators.h"
> +#include "llvm/Analysis/AliasAnalysis.h"
> +#include "llvm/Analysis/MemoryDependenceAnalysis.h"
> +#include "llvm/Support/CFG.h"
> +#include "llvm/Support/CommandLine.h"
> +#include "llvm/Support/Compiler.h"
> +#include "llvm/Support/Debug.h"
> +#include "llvm/Support/GetElementPtrTypeIterator.h"
> +#include "llvm/Target/TargetData.h"
> +#include <list>

Please prune down this list, and the list in GVN.cpp.  BasicBlock.h  
and Value.h aren't needed, perhaps others as well.

>
> +using namespace llvm;
> +
> +STATISTIC(NumMemCpyInstr, "Number of memcpy instructions deleted");
> +STATISTIC(NumMemSetInfer, "Number of memsets inferred");
> +
> +namespace {
> +  cl::opt<bool>
> +  FormMemSet("form-memset-from-stores",
> +             cl::desc("Transform straight-line stores to memsets"),
> +             cl::init(true), cl::Hidden);
> +}

I think this can be removed now.  If Evan doesn't like it, he can  
complain ;-)

> +/// processInstruction - When calculating availability, handle an  
> instruction
> +/// by inserting it into the appropriate sets
> +bool MemCpyOpt::processInstruction(Instruction *I,
> +                                   SmallVectorImpl<Instruction*>  
> &toErase) {

This can be merged into iterateOnFunction

>
> +  if (StoreInst *SI = dyn_cast<StoreInst>(I))
> +    return processStore(SI, toErase);
> +
> +  if (MemCpyInst* M = dyn_cast<MemCpyInst>(I)) {
> +    MemoryDependenceAnalysis& MD =  
> getAnalysis<MemoryDependenceAnalysis>();
> +
> +    // 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
> +    Instruction* dep = MD.getDependency(M);
> +    if (dep == MemoryDependenceAnalysis::None ||
> +        dep == MemoryDependenceAnalysis::NonLocal)
> +      return false;
> +    if (MemCpyInst *MemCpy = dyn_cast<MemCpyInst>(dep))
> +      return processMemCpy(M, MemCpy, toErase);
> +    if (CallInst* C = dyn_cast<CallInst>(dep))
> +      return performCallSlotOptzn(M, C, toErase);
> +    return false;

This should go into processMemCpy, to make an analog of processStore.

> +// MemCpyOpt::iterateOnFunction - Executes one iteration of GVN
> +bool MemCpyOpt::iterateOnFunction(Function &F) {
> +  bool changed_function = false;
> +
> +  DominatorTree &DT = getAnalysis<DominatorTree>();
> +
> +  SmallVector<Instruction*, 8> toErase;
> +
> +  // Top-down walk of the dominator tree
> +  for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()),
> +         E = df_end(DT.getRootNode()); DI != E; ++DI) {

I don't think there is any reason for this code to walk the function  
in DF order, just walk in normal BB order.

>
> +
> +    BasicBlock* BB = DI->getBlock();
> +    for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
> +         BI != BE;) {
> +      changed_function |= processInstruction(BI, toErase);
> +      if (toErase.empty()) {
> +        ++BI;
> +        continue;
> +      }
> +
> +      // If we need some instructions deleted, do it now.
> +      NumMemCpyInstr += toErase.size();
> +
> +      // Avoid iterator invalidation.
> +      bool AtStart = BI == BB->begin();
> +      if (!AtStart)
> +        --BI;
> +
> +      for (SmallVector<Instruction*, 4>::iterator I =  
> toErase.begin(),
> +           E = toErase.end(); I != E; ++I)
> +        (*I)->eraseFromParent();
> +
> +      if (AtStart)
> +        BI = BB->begin();
> +      else
> +        ++BI;
> +
> +      toErase.clear();

Can this deletion logic be simplified?  The memset and store  
simplifiers can delete stuff in place, right?

-Chris




More information about the llvm-commits mailing list