Skip to content
MemoryDependenceAnalysis.cpp 19.3 KiB
Newer Older
//===- MemoryDependenceAnalysis.cpp - Mem Deps Implementation  --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements an analysis that determines, for a given memory
// operation, what preceding memory operations it depends on.  It builds on 
// alias analysis information, and tries to provide a lazy, caching interface to
// a common kind of alias information query.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Function.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetData.h"
using namespace llvm;

STATISTIC(NumCacheNonlocal, "Number of cached non-local responses");
STATISTIC(NumUncacheNonlocal, "Number of uncached non-local responses");

char MemoryDependenceAnalysis::ID = 0;
  
// Register this pass...
static RegisterPass<MemoryDependenceAnalysis> X("memdep",
                                     "Memory Dependence Analysis", false, true);

/// getAnalysisUsage - Does not modify anything.  It uses Alias Analysis.
///
void MemoryDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequiredTransitive<AliasAnalysis>();
  AU.addRequiredTransitive<TargetData>();
}

/// getCallSiteDependency - Private helper for finding the local dependencies
/// of a call site.
MemDepResult MemoryDependenceAnalysis::
getCallSiteDependency(CallSite C, BasicBlock::iterator ScanIt,
                      BasicBlock *BB) {
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  TargetData &TD = getAnalysis<TargetData>();
  // Walk backwards through the block, looking for dependencies
  while (ScanIt != BB->begin()) {
    Instruction *Inst = --ScanIt;
    
    // If this inst is a memory op, get the pointer it accessed
Chris Lattner's avatar
Chris Lattner committed
    Value *Pointer = 0;
    uint64_t PointerSize = 0;
    if (StoreInst *S = dyn_cast<StoreInst>(Inst)) {
      Pointer = S->getPointerOperand();
      PointerSize = TD.getTypeStoreSize(S->getOperand(0)->getType());
    } else if (AllocationInst *AI = dyn_cast<AllocationInst>(Inst)) {
      Pointer = AI;
      if (ConstantInt *C = dyn_cast<ConstantInt>(AI->getArraySize()))
        // Use ABI size (size between elements), not store size (size of one
        // element without padding).
Chris Lattner's avatar
Chris Lattner committed
        PointerSize = C->getZExtValue() *
                      TD.getABITypeSize(AI->getAllocatedType());
Chris Lattner's avatar
Chris Lattner committed
        PointerSize = ~0UL;
    } else if (VAArgInst *V = dyn_cast<VAArgInst>(Inst)) {
      Pointer = V->getOperand(0);
      PointerSize = TD.getTypeStoreSize(V->getType());
    } else if (FreeInst *F = dyn_cast<FreeInst>(Inst)) {
      Pointer = F->getPointerOperand();
      
      // FreeInsts erase the entire structure
Chris Lattner's avatar
Chris Lattner committed
      PointerSize = ~0UL;
    } else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
      if (AA.getModRefBehavior(CallSite::get(Inst)) ==
            AliasAnalysis::DoesNotAccessMemory)
Chris Lattner's avatar
Chris Lattner committed
        continue;
      return MemDepResult::get(Inst);
Chris Lattner's avatar
Chris Lattner committed
    if (AA.getModRefInfo(C, Pointer, PointerSize) != AliasAnalysis::NoModRef)
      return MemDepResult::get(Inst);
  return MemDepResult::getNonLocal();
/// getNonLocalDependency - Perform a full dependency query for the
/// specified instruction, returning the set of blocks that the value is
/// potentially live across.  The returned set of results will include a
/// "NonLocal" result for all blocks where the value is live across.
///
/// This method assumes the instruction returns a "nonlocal" dependency
/// within its own block.
///
void MemoryDependenceAnalysis::
getNonLocalDependency(Instruction *QueryInst,
                      SmallVectorImpl<std::pair<BasicBlock*, 
                                                      MemDepResult> > &Result) {
  assert(getDependency(QueryInst).isNonLocal() &&
     "getNonLocalDependency should only be used on insts with non-local deps!");
  DenseMap<BasicBlock*, DepResultTy> &Cache = NonLocalDeps[QueryInst];

  /// DirtyBlocks - This is the set of blocks that need to be recomputed.  This
  /// can happen due to instructions being deleted etc.
  SmallVector<BasicBlock*, 32> DirtyBlocks;
  if (!Cache.empty()) {
    // If we already have a partially computed set of results, scan them to
    // determine what is dirty, seeding our initial DirtyBlocks worklist.
    // FIXME: In the "don't need to be updated" case, this is expensive, why not
    // have a per-"cache" flag saying it is undirty?
    for (DenseMap<BasicBlock*, DepResultTy>::iterator I = Cache.begin(),
         E = Cache.end(); I != E; ++I)
      if (I->second.getInt() == Dirty)
        DirtyBlocks.push_back(I->first);
    NumCacheNonlocal++;
  } else {
    // Seed DirtyBlocks with each of the preds of QueryInst's block.
    BasicBlock *QueryBB = QueryInst->getParent();
    DirtyBlocks.append(pred_begin(QueryBB), pred_end(QueryBB));
  // Iterate while we still have blocks to update.
  while (!DirtyBlocks.empty()) {
    BasicBlock *DirtyBB = DirtyBlocks.back();
    DirtyBlocks.pop_back();
    // Get the entry for this block.  Note that this relies on DepResultTy
    // default initializing to Dirty.
    DepResultTy &DirtyBBEntry = Cache[DirtyBB];

    // If DirtyBBEntry isn't dirty, it ended up on the worklist multiple times.
    if (DirtyBBEntry.getInt() != Dirty) continue;
    // Find out if this block has a local dependency for QueryInst.
    // FIXME: If the dirty entry has an instruction pointer, scan from it!
    // FIXME: Don't convert back and forth for MemDepResult <-> DepResultTy.
    DirtyBBEntry = ConvFromResult(getDependencyFrom(QueryInst, DirtyBB->end(),
                                                    DirtyBB));
    // If the block has a dependency (i.e. it isn't completely transparent to
    // the value), remember it!
    if (DirtyBBEntry.getInt() != NonLocal) {
      // Keep the ReverseNonLocalDeps map up to date so we can efficiently
      // update this when we remove  instructions.
      if (Instruction *Inst = DirtyBBEntry.getPointer())
        ReverseNonLocalDeps[Inst].insert(QueryInst);
      continue;
    // If the block *is* completely transparent to the load, we need to check
    // the predecessors of this block.  Add them to our worklist.
    for (pred_iterator I = pred_begin(DirtyBB), E = pred_end(DirtyBB);
         I != E; ++I)
      DirtyBlocks.push_back(*I);
  // Copy the result into the output set.
  for (DenseMap<BasicBlock*, DepResultTy>::iterator I = Cache.begin(),
       E = Cache.end(); I != E; ++I)
    Result.push_back(std::make_pair(I->first, ConvToResult(I->second)));
/// getDependency - Return the instruction on which a memory operation
Dan Gohman's avatar
Dan Gohman committed
/// depends.  The local parameter indicates if the query should only
/// evaluate dependencies within the same basic block.
MemDepResult MemoryDependenceAnalysis::
getDependencyFrom(Instruction *QueryInst, BasicBlock::iterator ScanIt, 
                  BasicBlock *BB) {
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  TargetData &TD = getAnalysis<TargetData>();
  
  // Get the pointer value for which dependence will be determined
  Value *MemPtr = 0;
  uint64_t MemSize = 0;
  bool MemVolatile = false;
  
  if (StoreInst* S = dyn_cast<StoreInst>(QueryInst)) {
    MemPtr = S->getPointerOperand();
    MemSize = TD.getTypeStoreSize(S->getOperand(0)->getType());
    MemVolatile = S->isVolatile();
  } else if (LoadInst* L = dyn_cast<LoadInst>(QueryInst)) {
    MemPtr = L->getPointerOperand();
    MemSize = TD.getTypeStoreSize(L->getType());
    MemVolatile = L->isVolatile();
  } else if (VAArgInst* V = dyn_cast<VAArgInst>(QueryInst)) {
    MemPtr = V->getOperand(0);
    MemSize = TD.getTypeStoreSize(V->getType());
  } else if (FreeInst* F = dyn_cast<FreeInst>(QueryInst)) {
    MemPtr = F->getPointerOperand();
    // FreeInsts erase the entire structure, not just a field.
    MemSize = ~0UL;
  } else if (isa<CallInst>(QueryInst) || isa<InvokeInst>(QueryInst))
    return getCallSiteDependency(CallSite::get(QueryInst), ScanIt, BB);
  else  // Non-memory instructions depend on nothing.
  // Walk backwards through the basic block, looking for dependencies
  while (ScanIt != BB->begin()) {
    Instruction *Inst = --ScanIt;

    // If the access is volatile and this is a volatile load/store, return a
    // dependence.
    if (MemVolatile &&
        ((isa<LoadInst>(Inst) && cast<LoadInst>(Inst)->isVolatile()) ||
         (isa<StoreInst>(Inst) && cast<StoreInst>(Inst)->isVolatile())))
      return MemDepResult::get(Inst);

    // MemDep is broken w.r.t. loads: it says that two loads of the same pointer
    // depend on each other.  :(
    // FIXME: ELIMINATE THIS!
    if (LoadInst *L = dyn_cast<LoadInst>(Inst)) {
      Value *Pointer = L->getPointerOperand();
      uint64_t PointerSize = TD.getTypeStoreSize(L->getType());
      // If we found a pointer, check if it could be the same as our pointer
      AliasAnalysis::AliasResult R =
        AA.alias(Pointer, PointerSize, MemPtr, MemSize);
      if (R == AliasAnalysis::NoAlias)
        continue;
      
      // May-alias loads don't depend on each other without a dependence.
      if (isa<LoadInst>(QueryInst) && R == AliasAnalysis::MayAlias)
        continue;
      return MemDepResult::get(Inst);
    }
    
    // FIXME: This claims that an access depends on the allocation.  This may
    // make sense, but is dubious at best.  It would be better to fix GVN to
    // handle a 'None' Query.
    if (AllocationInst *AI = dyn_cast<AllocationInst>(Inst)) {
      Value *Pointer = AI;
      uint64_t PointerSize;
      if (ConstantInt *C = dyn_cast<ConstantInt>(AI->getArraySize()))
        // Use ABI size (size between elements), not store size (size of one
        // element without padding).
        PointerSize = C->getZExtValue() * 
          TD.getABITypeSize(AI->getAllocatedType());
      AliasAnalysis::AliasResult R =
        AA.alias(Pointer, PointerSize, MemPtr, MemSize);
        continue;
      return MemDepResult::get(Inst);
    
    // See if this instruction mod/ref's the pointer.
    AliasAnalysis::ModRefResult MRR = AA.getModRefInfo(Inst, MemPtr, MemSize);

    if (MRR == AliasAnalysis::NoModRef)
    // Loads don't depend on read-only instructions.
    if (isa<LoadInst>(QueryInst) && MRR == AliasAnalysis::Ref)
    return MemDepResult::get(Inst);
  // If we found nothing, return the non-local flag.
/// getDependency - Return the instruction on which a memory operation
/// depends.
MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) {
  Instruction *ScanPos = QueryInst;
  
  // Check for a cached result
  DepResultTy &LocalCache = LocalDeps[QueryInst];
  
  // If the cached entry is non-dirty, just return it.
  if (LocalCache.getInt() != Dirty)
    return ConvToResult(LocalCache);
    
  // Otherwise, if we have a dirty entry, we know we can start the scan at that
  // instruction, which may save us some work.
  if (Instruction *Inst = LocalCache.getPointer())
    ScanPos = Inst;
  
  // Do the scan.
  MemDepResult Res = 
    getDependencyFrom(QueryInst, ScanPos, QueryInst->getParent());  
  
  // Remember the result!
  // FIXME: Don't convert back and forth!  Make a shared helper function.
  LocalCache = ConvFromResult(Res);
  if (Instruction *I = Res.getInst())
Chris Lattner's avatar
Chris Lattner committed
    ReverseLocalDeps[I].insert(QueryInst);
/// dropInstruction - Remove an instruction from the analysis, making 
/// absolutely conservative assumptions when updating the cache.  This is
/// useful, for example when an instruction is changed rather than removed.
void MemoryDependenceAnalysis::dropInstruction(Instruction* drop) {
  LocalDepMapType::iterator depGraphEntry = LocalDeps.find(drop);
  if (depGraphEntry != LocalDeps.end())
    if (Instruction *Inst = depGraphEntry->second.getPointer())
Chris Lattner's avatar
Chris Lattner committed
      ReverseLocalDeps[Inst].erase(drop);
  
  // Drop dependency information for things that depended on this instr
Chris Lattner's avatar
Chris Lattner committed
  SmallPtrSet<Instruction*, 4>& set = ReverseLocalDeps[drop];
  for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
       I != E; ++I)
Chris Lattner's avatar
Chris Lattner committed
  ReverseLocalDeps.erase(drop);
  for (DenseMap<BasicBlock*, DepResultTy>::iterator DI =
Chris Lattner's avatar
Chris Lattner committed
         NonLocalDeps[drop].begin(), DE = NonLocalDeps[drop].end();
    if (Instruction *Inst = DI->second.getPointer())
Chris Lattner's avatar
Chris Lattner committed
      ReverseNonLocalDeps[Inst].erase(drop);
Chris Lattner's avatar
Chris Lattner committed
  if (ReverseNonLocalDeps.count(drop)) {
    SmallPtrSet<Instruction*, 4>& set =
Chris Lattner's avatar
Chris Lattner committed
      ReverseNonLocalDeps[drop];
    for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
         I != E; ++I)
      for (DenseMap<BasicBlock*, DepResultTy>::iterator DI =
Chris Lattner's avatar
Chris Lattner committed
           NonLocalDeps[*I].begin(), DE = NonLocalDeps[*I].end();
        if (DI->second == DepResultTy(drop, Normal))
          // FIXME: Why not remember the old insertion point??
          DI->second = DepResultTy(0, Dirty);
Chris Lattner's avatar
Chris Lattner committed
  ReverseNonLocalDeps.erase(drop);
  NonLocalDeps.erase(drop);
/// removeInstruction - Remove an instruction from the dependence analysis,
/// updating the dependence of instructions that previously depended on it.
/// This method attempts to keep the cache coherent using the reverse map.
void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) {
  // Walk through the Non-local dependencies, removing this one as the value
  // for any cached queries.
  for (DenseMap<BasicBlock*, DepResultTy>::iterator DI =
Chris Lattner's avatar
Chris Lattner committed
       NonLocalDeps[RemInst].begin(), DE = NonLocalDeps[RemInst].end();
    if (Instruction *Inst = DI->second.getPointer())
Chris Lattner's avatar
Chris Lattner committed
      ReverseNonLocalDeps[Inst].erase(RemInst);
David Greene's avatar
 
David Greene committed

  // Shortly after this, we will look for things that depend on RemInst.  In
  // order to update these, we'll need a new dependency to base them on.  We
  // could completely delete any entries that depend on this, but it is better
  // to make a more accurate approximation where possible.  Compute that better
  // approximation if we can.
  // If we have a cached local dependence query for this instruction, remove it.
  LocalDepMapType::iterator LocalDepEntry = LocalDeps.find(RemInst);
  if (LocalDepEntry != LocalDeps.end()) {
    DepResultTy LocalDep = LocalDepEntry->second;
    // Remove this local dependency info.
    LocalDeps.erase(LocalDepEntry);
    // Remove us from DepInst's reverse set now that the local dep info is gone.
    if (Instruction *Inst = LocalDep.getPointer())
Chris Lattner's avatar
Chris Lattner committed
      ReverseLocalDeps[Inst].erase(RemInst);

    // If we have unconfirmed info, don't trust it.
      // If we have a confirmed non-local flag, use it.
      if (LocalDep.getInt() == NonLocal || LocalDep.getInt() == None) {
        // The only time this dependency is confirmed is if it is non-local.
      } else {
        // If we have dep info for RemInst, set them to it.
        Instruction *NDI = next(BasicBlock::iterator(LocalDep.getPointer()));
        if (NDI != RemInst) // Don't use RemInst for the new dependency!
          NewDependency = DepResultTy(NDI, Dirty);
David Greene's avatar
 
David Greene committed
    }
  // If we don't already have a local dependency answer for this instruction,
  // use the immediate successor of RemInst.  We use the successor because
  // getDependence starts by checking the immediate predecessor of what is in
  // the cache.
  if (NewDependency == DepResultTy(0, Dirty))
    NewDependency = DepResultTy(next(BasicBlock::iterator(RemInst)), Dirty);
  // Loop over all of the things that depend on the instruction we're removing.
  // 
Chris Lattner's avatar
Chris Lattner committed
  ReverseDepMapType::iterator ReverseDepIt = ReverseLocalDeps.find(RemInst);
  if (ReverseDepIt != ReverseLocalDeps.end()) {
    SmallPtrSet<Instruction*, 4> &ReverseDeps = ReverseDepIt->second;
    for (SmallPtrSet<Instruction*, 4>::iterator I = ReverseDeps.begin(),
         E = ReverseDeps.end(); I != E; ++I) {
      Instruction *InstDependingOnRemInst = *I;
      
      // If we thought the instruction depended on itself (possible for
      // unconfirmed dependencies) ignore the update.
      if (InstDependingOnRemInst == RemInst) continue;
      
      // Insert the new dependencies.
      LocalDeps[InstDependingOnRemInst] = NewDependency;
      
      // If our NewDependency is an instruction, make sure to remember that new
      // things depend on it.
      if (Instruction *Inst = NewDependency.getPointer())
Chris Lattner's avatar
Chris Lattner committed
        ReverseLocalDeps[Inst].insert(InstDependingOnRemInst);
Chris Lattner's avatar
Chris Lattner committed
    ReverseLocalDeps.erase(RemInst);
Chris Lattner's avatar
Chris Lattner committed
  ReverseDepIt = ReverseNonLocalDeps.find(RemInst);
  if (ReverseDepIt != ReverseNonLocalDeps.end()) {
    SmallPtrSet<Instruction*, 4>& set = ReverseDepIt->second;
    for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
         I != E; ++I)
Chris Lattner's avatar
Chris Lattner committed
      for (DenseMap<BasicBlock*, DepResultTy>::iterator
           DI = NonLocalDeps[*I].begin(), DE = NonLocalDeps[*I].end();
        if (DI->second == DepResultTy(RemInst, Normal))
          // FIXME: Why not remember the old insertion point??
          DI->second = DepResultTy(0, Dirty);
Chris Lattner's avatar
Chris Lattner committed
    ReverseNonLocalDeps.erase(ReverseDepIt);
Chris Lattner's avatar
Chris Lattner committed
  NonLocalDeps.erase(RemInst);
David Greene's avatar
 
David Greene committed

  getAnalysis<AliasAnalysis>().deleteValue(RemInst);
  DEBUG(verifyRemoved(RemInst));

/// verifyRemoved - Verify that the specified instruction does not occur
/// in our internal data structures.
void MemoryDependenceAnalysis::verifyRemoved(Instruction *D) const {
  for (LocalDepMapType::const_iterator I = LocalDeps.begin(),
       E = LocalDeps.end(); I != E; ++I) {
    assert(I->first != D && "Inst occurs in data structures");
    assert(I->second.getPointer() != D &&
           "Inst occurs in data structures");
  }
  
  for (NonLocalDepMapType::const_iterator I = NonLocalDeps.begin(),
       E = NonLocalDeps.end(); I != E; ++I) {
    assert(I->first != D && "Inst occurs in data structures");
    for (DenseMap<BasicBlock*, DepResultTy>::iterator II = I->second.begin(),
         EE = I->second.end(); II  != EE; ++II)
      assert(II->second.getPointer() != D && "Inst occurs in data structures");
  }
  
  for (ReverseDepMapType::const_iterator I = ReverseLocalDeps.begin(),
       E = ReverseLocalDeps.end(); I != E; ++I)
    for (SmallPtrSet<Instruction*, 4>::const_iterator II = I->second.begin(),
         EE = I->second.end(); II != EE; ++II)
      assert(*II != D && "Inst occurs in data structures");
  
  for (ReverseDepMapType::const_iterator I = ReverseNonLocalDeps.begin(),
       E = ReverseNonLocalDeps.end();
       I != E; ++I)
    for (SmallPtrSet<Instruction*, 4>::const_iterator II = I->second.begin(),
         EE = I->second.end(); II != EE; ++II)
      assert(*II != D && "Inst occurs in data structures");
}