Ejemplo n.º 1
0
/// HandleFree - Handle frees of entire structures whose dependency is a store
/// to a field of that structure.
bool DSE::HandleFree(CallInst *F) {
  MemDepResult Dep = MD->getDependency(F);
  do {
    if (Dep.isNonLocal()) return false;
    
    Instruction *Dependency = Dep.getInst();
    if (!hasMemoryWrite(Dependency) || !isRemovable(Dependency))
      return false;
  
    Value *DepPointer =
      getStoredPointerOperand(Dependency)->getUnderlyingObject();

    // Check for aliasing.
    if (!AA->isMustAlias(F->getArgOperand(0), DepPointer))
      return false;
  
    // DCE instructions only used to calculate that store
    DeleteDeadInstruction(Dependency, *MD);
    ++NumFastStores;

    // Inst's old Dependency is now deleted. Compute the next dependency,
    // which may also be dead, as in
    //    s[0] = 0;
    //    s[1] = 0; // This has just been deleted.
    //    free(s);
    Dep = MD->getDependency(F);
  } while (!Dep.isNonLocal());
  
  return true;
}
Ejemplo n.º 2
0
/// Handle frees of entire structures whose dependency is a store
/// to a field of that structure.
static bool handleFree(CallInst *F, AliasAnalysis *AA,
                       MemoryDependenceResults *MD, DominatorTree *DT,
                       const TargetLibraryInfo *TLI,
                       InstOverlapIntervalsTy &IOL,
                       DenseMap<Instruction*, size_t> *InstrOrdering) {
  bool MadeChange = false;

  MemoryLocation Loc = MemoryLocation(F->getOperand(0));
  SmallVector<BasicBlock *, 16> Blocks;
  Blocks.push_back(F->getParent());
  const DataLayout &DL = F->getModule()->getDataLayout();

  while (!Blocks.empty()) {
    BasicBlock *BB = Blocks.pop_back_val();
    Instruction *InstPt = BB->getTerminator();
    if (BB == F->getParent()) InstPt = F;

    MemDepResult Dep =
        MD->getPointerDependencyFrom(Loc, false, InstPt->getIterator(), BB);
    while (Dep.isDef() || Dep.isClobber()) {
      Instruction *Dependency = Dep.getInst();
      if (!hasMemoryWrite(Dependency, *TLI) || !isRemovable(Dependency))
        break;

      Value *DepPointer =
          GetUnderlyingObject(getStoredPointerOperand(Dependency), DL);

      // Check for aliasing.
      if (!AA->isMustAlias(F->getArgOperand(0), DepPointer))
        break;

      DEBUG(dbgs() << "DSE: Dead Store to soon to be freed memory:\n  DEAD: "
                   << *Dependency << '\n');

      // DCE instructions only used to calculate that store.
      BasicBlock::iterator BBI(Dependency);
      deleteDeadInstruction(Dependency, &BBI, *MD, *TLI, IOL, InstrOrdering);
      ++NumFastStores;
      MadeChange = true;

      // Inst's old Dependency is now deleted. Compute the next dependency,
      // which may also be dead, as in
      //    s[0] = 0;
      //    s[1] = 0; // This has just been deleted.
      //    free(s);
      Dep = MD->getPointerDependencyFrom(Loc, false, BBI, BB);
    }

    if (Dep.isNonLocal())
      findUnconditionalPreds(Blocks, BB, DT);
  }

  return MadeChange;
}
Ejemplo n.º 3
0
DataDependence::DepInfo DataDependence::getDepInfo(MemDepResult dep) {
  if (dep.isClobber())
    return DepInfo(dep.getInst(), Clobber);
  if (dep.isDef())
    return DepInfo(dep.getInst(), Def);
  if (dep.isNonFuncLocal())
    return DepInfo(dep.getInst(), NonFuncLocal);
  if (dep.isUnknown())
    return DepInfo(dep.getInst(), Unknown);
  if (dep.isNonLocal())
    return DepInfo(dep.getInst(), NonLocal);
  llvm_unreachable("unknown dependence type");
}
Ejemplo n.º 4
0
/// HandleFree - Handle frees of entire structures whose dependency is a store
/// to a field of that structure.
bool DSE::HandleFree(CallInst *F) {
  bool MadeChange = false;

  MemoryLocation Loc = MemoryLocation(F->getOperand(0));
  SmallVector<BasicBlock *, 16> Blocks;
  Blocks.push_back(F->getParent());
  const DataLayout &DL = F->getModule()->getDataLayout();

  while (!Blocks.empty()) {
    BasicBlock *BB = Blocks.pop_back_val();
    Instruction *InstPt = BB->getTerminator();
    if (BB == F->getParent()) InstPt = F;

    MemDepResult Dep = MD->getPointerDependencyFrom(Loc, false, InstPt, BB);
    while (Dep.isDef() || Dep.isClobber()) {
      Instruction *Dependency = Dep.getInst();
      if (!hasMemoryWrite(Dependency, *TLI) || !isRemovable(Dependency))
        break;

      Value *DepPointer =
          GetUnderlyingObject(getStoredPointerOperand(Dependency), DL);

      // Check for aliasing.
      if (!AA->isMustAlias(F->getArgOperand(0), DepPointer))
        break;

      Instruction *Next = std::next(BasicBlock::iterator(Dependency));

      // DCE instructions only used to calculate that store
      DeleteDeadInstruction(Dependency, *MD, *TLI);
      ++NumFastStores;
      MadeChange = true;

      // Inst's old Dependency is now deleted. Compute the next dependency,
      // which may also be dead, as in
      //    s[0] = 0;
      //    s[1] = 0; // This has just been deleted.
      //    free(s);
      Dep = MD->getPointerDependencyFrom(Loc, false, Next, BB);
    }

    if (Dep.isNonLocal())
      FindUnconditionalPreds(Blocks, BB, DT);
  }

  return MadeChange;
}
Ejemplo n.º 5
0
bool MemDepPrinter::runOnFunction(Function &F) {
  this->F = &F;
  MemoryDependenceAnalysis &MDA = getAnalysis<MemoryDependenceAnalysis>();

  // All this code uses non-const interfaces because MemDep is not
  // const-friendly, though nothing is actually modified.
  for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
    Instruction *Inst = &*I;

    if (!Inst->mayReadFromMemory() && !Inst->mayWriteToMemory())
      continue;

    MemDepResult Res = MDA.getDependency(Inst);
    if (!Res.isNonLocal()) {
      Deps[Inst].insert(std::make_pair(getInstTypePair(Res),
                                       static_cast<BasicBlock *>(nullptr)));
    } else if (CallSite CS = cast<Value>(Inst)) {
      const MemoryDependenceAnalysis::NonLocalDepInfo &NLDI =
        MDA.getNonLocalCallDependency(CS);

      DepSet &InstDeps = Deps[Inst];
      for (MemoryDependenceAnalysis::NonLocalDepInfo::const_iterator
           I = NLDI.begin(), E = NLDI.end(); I != E; ++I) {
        const MemDepResult &Res = I->getResult();
        InstDeps.insert(std::make_pair(getInstTypePair(Res), I->getBB()));
      }
    } else {
      SmallVector<NonLocalDepResult, 4> NLDI;
      assert( (isa<LoadInst>(Inst) || isa<StoreInst>(Inst) ||
               isa<VAArgInst>(Inst)) && "Unknown memory instruction!"); 
      MDA.getNonLocalPointerDependency(Inst, NLDI);

      DepSet &InstDeps = Deps[Inst];
      for (SmallVectorImpl<NonLocalDepResult>::const_iterator
           I = NLDI.begin(), E = NLDI.end(); I != E; ++I) {
        const MemDepResult &Res = I->getResult();
        InstDeps.insert(std::make_pair(getInstTypePair(Res), I->getBB()));
      }
    }
  }

  return false;
}
Ejemplo n.º 6
0
bool MemDepPrinter::runOnFunction(Function &F) {
  this->F = &F;
  MemoryDependenceResults &MDA = getAnalysis<MemoryDependenceWrapperPass>().getMemDep();

  // All this code uses non-const interfaces because MemDep is not
  // const-friendly, though nothing is actually modified.
  for (auto &I : instructions(F)) {
    Instruction *Inst = &I;

    if (!Inst->mayReadFromMemory() && !Inst->mayWriteToMemory())
      continue;

    MemDepResult Res = MDA.getDependency(Inst);
    if (!Res.isNonLocal()) {
      Deps[Inst].insert(std::make_pair(getInstTypePair(Res),
                                       static_cast<BasicBlock *>(nullptr)));
    } else if (auto CS = CallSite(Inst)) {
      const MemoryDependenceResults::NonLocalDepInfo &NLDI =
        MDA.getNonLocalCallDependency(CS);

      DepSet &InstDeps = Deps[Inst];
      for (const NonLocalDepEntry &I : NLDI) {
        const MemDepResult &Res = I.getResult();
        InstDeps.insert(std::make_pair(getInstTypePair(Res), I.getBB()));
      }
    } else {
      SmallVector<NonLocalDepResult, 4> NLDI;
      assert( (isa<LoadInst>(Inst) || isa<StoreInst>(Inst) ||
               isa<VAArgInst>(Inst)) && "Unknown memory instruction!"); 
      MDA.getNonLocalPointerDependency(Inst, NLDI);

      DepSet &InstDeps = Deps[Inst];
      for (const NonLocalDepResult &I : NLDI) {
        const MemDepResult &Res = I.getResult();
        InstDeps.insert(std::make_pair(getInstTypePair(Res), I.getBB()));
      }
    }
  }

  return false;
}
/// getNonLocalPointerDepFromBB - Perform a dependency query based on
/// pointer/pointeesize starting at the end of StartBB.  Add any clobber/def
/// results to the results vector and keep track of which blocks are visited in
/// 'Visited'.
///
/// This has special behavior for the first block queries (when SkipFirstBlock
/// is true).  In this special case, it ignores the contents of the specified
/// block and starts returning dependence info for its predecessors.
///
/// This function returns false on success, or true to indicate that it could
/// not compute dependence information for some reason.  This should be treated
/// as a clobber dependence on the first instruction in the predecessor block.
bool MemoryDependenceAnalysis::
getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize,
                            bool isLoad, BasicBlock *StartBB,
                            SmallVectorImpl<NonLocalDepEntry> &Result,
                            DenseMap<BasicBlock*, Value*> &Visited,
                            bool SkipFirstBlock) {
  
  // Look up the cached info for Pointer.
  ValueIsLoadPair CacheKey(Pointer, isLoad);
  
  std::pair<BBSkipFirstBlockPair, NonLocalDepInfo> *CacheInfo =
    &NonLocalPointerDeps[CacheKey];
  NonLocalDepInfo *Cache = &CacheInfo->second;

  // If we have valid cached information for exactly the block we are
  // investigating, just return it with no recomputation.
  if (CacheInfo->first == BBSkipFirstBlockPair(StartBB, SkipFirstBlock)) {
    // We have a fully cached result for this query then we can just return the
    // cached results and populate the visited set.  However, we have to verify
    // that we don't already have conflicting results for these blocks.  Check
    // to ensure that if a block in the results set is in the visited set that
    // it was for the same pointer query.
    if (!Visited.empty()) {
      for (NonLocalDepInfo::iterator I = Cache->begin(), E = Cache->end();
           I != E; ++I) {
        DenseMap<BasicBlock*, Value*>::iterator VI = Visited.find(I->first);
        if (VI == Visited.end() || VI->second == Pointer) continue;
        
        // We have a pointer mismatch in a block.  Just return clobber, saying
        // that something was clobbered in this result.  We could also do a
        // non-fully cached query, but there is little point in doing this.
        return true;
      }
    }
    
    for (NonLocalDepInfo::iterator I = Cache->begin(), E = Cache->end();
         I != E; ++I) {
      Visited.insert(std::make_pair(I->first, Pointer));
      if (!I->second.isNonLocal())
        Result.push_back(*I);
    }
    ++NumCacheCompleteNonLocalPtr;
    return false;
  }
  
  // Otherwise, either this is a new block, a block with an invalid cache
  // pointer or one that we're about to invalidate by putting more info into it
  // than its valid cache info.  If empty, the result will be valid cache info,
  // otherwise it isn't.
  if (Cache->empty())
    CacheInfo->first = BBSkipFirstBlockPair(StartBB, SkipFirstBlock);
  else
    CacheInfo->first = BBSkipFirstBlockPair();
  
  SmallVector<BasicBlock*, 32> Worklist;
  Worklist.push_back(StartBB);
  
  // Keep track of the entries that we know are sorted.  Previously cached
  // entries will all be sorted.  The entries we add we only sort on demand (we
  // don't insert every element into its sorted position).  We know that we
  // won't get any reuse from currently inserted values, because we don't
  // revisit blocks after we insert info for them.
  unsigned NumSortedEntries = Cache->size();
  DEBUG(AssertSorted(*Cache));
  
  while (!Worklist.empty()) {
    BasicBlock *BB = Worklist.pop_back_val();
    
    // Skip the first block if we have it.
    if (!SkipFirstBlock) {
      // Analyze the dependency of *Pointer in FromBB.  See if we already have
      // been here.
      assert(Visited.count(BB) && "Should check 'visited' before adding to WL");

      // Get the dependency info for Pointer in BB.  If we have cached
      // information, we will use it, otherwise we compute it.
      DEBUG(AssertSorted(*Cache, NumSortedEntries));
      MemDepResult Dep = GetNonLocalInfoForBlock(Pointer, PointeeSize, isLoad,
                                                 BB, Cache, NumSortedEntries);
      
      // If we got a Def or Clobber, add this to the list of results.
      if (!Dep.isNonLocal()) {
        Result.push_back(NonLocalDepEntry(BB, Dep));
        continue;
      }
    }
    
    // If 'Pointer' is an instruction defined in this block, then we need to do
    // phi translation to change it into a value live in the predecessor block.
    // If phi translation fails, then we can't continue dependence analysis.
    Instruction *PtrInst = dyn_cast<Instruction>(Pointer);
    bool NeedsPHITranslation = PtrInst && PtrInst->getParent() == BB;
    
    // If no PHI translation is needed, just add all the predecessors of this
    // block to scan them as well.
    if (!NeedsPHITranslation) {
      SkipFirstBlock = false;
      for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) {
        // Verify that we haven't looked at this block yet.
        std::pair<DenseMap<BasicBlock*,Value*>::iterator, bool>
          InsertRes = Visited.insert(std::make_pair(*PI, Pointer));
        if (InsertRes.second) {
          // First time we've looked at *PI.
          Worklist.push_back(*PI);
          continue;
        }
        
        // If we have seen this block before, but it was with a different
        // pointer then we have a phi translation failure and we have to treat
        // this as a clobber.
        if (InsertRes.first->second != Pointer)
          goto PredTranslationFailure;
      }
      continue;
    }
    
    // If we do need to do phi translation, then there are a bunch of different
    // cases, because we have to find a Value* live in the predecessor block. We
    // know that PtrInst is defined in this block at least.
    
    // If this is directly a PHI node, just use the incoming values for each
    // pred as the phi translated version.
    if (PHINode *PtrPHI = dyn_cast<PHINode>(PtrInst)) {
      for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) {
        BasicBlock *Pred = *PI;
        Value *PredPtr = PtrPHI->getIncomingValueForBlock(Pred);
        
        // Check to see if we have already visited this pred block with another
        // pointer.  If so, we can't do this lookup.  This failure can occur
        // with PHI translation when a critical edge exists and the PHI node in
        // the successor translates to a pointer value different than the
        // pointer the block was first analyzed with.
        std::pair<DenseMap<BasicBlock*,Value*>::iterator, bool>
          InsertRes = Visited.insert(std::make_pair(Pred, PredPtr));

        if (!InsertRes.second) {
          // If the predecessor was visited with PredPtr, then we already did
          // the analysis and can ignore it.
          if (InsertRes.first->second == PredPtr)
            continue;
          
          // Otherwise, the block was previously analyzed with a different
          // pointer.  We can't represent the result of this case, so we just
          // treat this as a phi translation failure.
          goto PredTranslationFailure;
        }

        // We may have added values to the cache list before this PHI
        // translation.  If so, we haven't done anything to ensure that the
        // cache remains sorted.  Sort it now (if needed) so that recursive
        // invocations of getNonLocalPointerDepFromBB that could reuse the cache
        // value will only see properly sorted cache arrays.
        if (Cache && NumSortedEntries != Cache->size())
          std::sort(Cache->begin(), Cache->end());
        Cache = 0;
        
        // FIXME: it is entirely possible that PHI translating will end up with
        // the same value.  Consider PHI translating something like:
        // X = phi [x, bb1], [y, bb2].  PHI translating for bb1 doesn't *need*
        // to recurse here, pedantically speaking.
        
        // If we have a problem phi translating, fall through to the code below
        // to handle the failure condition.
        if (getNonLocalPointerDepFromBB(PredPtr, PointeeSize, isLoad, Pred,
                                        Result, Visited))
          goto PredTranslationFailure;
      }

      // Refresh the CacheInfo/Cache pointer so that it isn't invalidated.
      CacheInfo = &NonLocalPointerDeps[CacheKey];
      Cache = &CacheInfo->second;
      NumSortedEntries = Cache->size();
      
      // Since we did phi translation, the "Cache" set won't contain all of the
      // results for the query.  This is ok (we can still use it to accelerate
      // specific block queries) but we can't do the fastpath "return all
      // results from the set"  Clear out the indicator for this.
      CacheInfo->first = BBSkipFirstBlockPair();
      SkipFirstBlock = false;
      continue;
    }
    
    // TODO: BITCAST, GEP.
    
    //   cerr << "MEMDEP: Could not PHI translate: " << *Pointer;
    //   if (isa<BitCastInst>(PtrInst) || isa<GetElementPtrInst>(PtrInst))
    //     cerr << "OP:\t\t\t\t" << *PtrInst->getOperand(0);
  PredTranslationFailure:
    
    if (Cache == 0) {
      // Refresh the CacheInfo/Cache pointer if it got invalidated.
      CacheInfo = &NonLocalPointerDeps[CacheKey];
      Cache = &CacheInfo->second;
      NumSortedEntries = Cache->size();
    } else if (NumSortedEntries != Cache->size()) {
      std::sort(Cache->begin(), Cache->end());
      NumSortedEntries = Cache->size();
    }

    // Since we did phi translation, the "Cache" set won't contain all of the
    // results for the query.  This is ok (we can still use it to accelerate
    // specific block queries) but we can't do the fastpath "return all
    // results from the set"  Clear out the indicator for this.
    CacheInfo->first = BBSkipFirstBlockPair();
    
    // If *nothing* works, mark the pointer as being clobbered by the first
    // instruction in this block.
    //
    // If this is the magic first block, return this as a clobber of the whole
    // incoming value.  Since we can't phi translate to one of the predecessors,
    // we have to bail out.
    if (SkipFirstBlock)
      return true;
    
    for (NonLocalDepInfo::reverse_iterator I = Cache->rbegin(); ; ++I) {
      assert(I != Cache->rend() && "Didn't find current block??");
      if (I->first != BB)
        continue;
      
      assert(I->second.isNonLocal() &&
             "Should only be here with transparent block");
      I->second = MemDepResult::getClobber(BB->begin());
      ReverseNonLocalPtrDeps[BB->begin()].insert(CacheKey.getOpaqueValue());
      Result.push_back(*I);
      break;
    }
  }

  // Okay, we're done now.  If we added new values to the cache, re-sort it.
  switch (Cache->size()-NumSortedEntries) {
  case 0:
    // done, no new entries.
    break;
  case 2: {
    // Two new entries, insert the last one into place.
    NonLocalDepEntry Val = Cache->back();
    Cache->pop_back();
    NonLocalDepInfo::iterator Entry =
    std::upper_bound(Cache->begin(), Cache->end()-1, Val);
    Cache->insert(Entry, Val);
    // FALL THROUGH.
  }
  case 1:
    // One new entry, Just insert the new value at the appropriate position.
    if (Cache->size() != 1) {
      NonLocalDepEntry Val = Cache->back();
      Cache->pop_back();
      NonLocalDepInfo::iterator Entry =
        std::upper_bound(Cache->begin(), Cache->end(), Val);
      Cache->insert(Entry, Val);
    }
    break;
  default:
    // Added many values, do a full scale sort.
    std::sort(Cache->begin(), Cache->end());
  }
  DEBUG(AssertSorted(*Cache));
  return false;
}
/// GetNonLocalInfoForBlock - Compute the memdep value for BB with
/// Pointer/PointeeSize using either cached information in Cache or by doing a
/// lookup (which may use dirty cache info if available).  If we do a lookup,
/// add the result to the cache.
MemDepResult MemoryDependenceAnalysis::
GetNonLocalInfoForBlock(Value *Pointer, uint64_t PointeeSize,
                        bool isLoad, BasicBlock *BB,
                        NonLocalDepInfo *Cache, unsigned NumSortedEntries) {
  
  // Do a binary search to see if we already have an entry for this block in
  // the cache set.  If so, find it.
  NonLocalDepInfo::iterator Entry =
    std::upper_bound(Cache->begin(), Cache->begin()+NumSortedEntries,
                     std::make_pair(BB, MemDepResult()));
  if (Entry != Cache->begin() && prior(Entry)->first == BB)
    --Entry;
  
  MemDepResult *ExistingResult = 0;
  if (Entry != Cache->begin()+NumSortedEntries && Entry->first == BB)
    ExistingResult = &Entry->second;
  
  // If we have a cached entry, and it is non-dirty, use it as the value for
  // this dependency.
  if (ExistingResult && !ExistingResult->isDirty()) {
    ++NumCacheNonLocalPtr;
    return *ExistingResult;
  }    
  
  // Otherwise, we have to scan for the value.  If we have a dirty cache
  // entry, start scanning from its position, otherwise we scan from the end
  // of the block.
  BasicBlock::iterator ScanPos = BB->end();
  if (ExistingResult && ExistingResult->getInst()) {
    assert(ExistingResult->getInst()->getParent() == BB &&
           "Instruction invalidated?");
    ++NumCacheDirtyNonLocalPtr;
    ScanPos = ExistingResult->getInst();
    
    // Eliminating the dirty entry from 'Cache', so update the reverse info.
    ValueIsLoadPair CacheKey(Pointer, isLoad);
    RemoveFromReverseMap(ReverseNonLocalPtrDeps, ScanPos,
                         CacheKey.getOpaqueValue());
  } else {
    ++NumUncacheNonLocalPtr;
  }
  
  // Scan the block for the dependency.
  MemDepResult Dep = getPointerDependencyFrom(Pointer, PointeeSize, isLoad, 
                                              ScanPos, BB);
  
  // If we had a dirty entry for the block, update it.  Otherwise, just add
  // a new entry.
  if (ExistingResult)
    *ExistingResult = Dep;
  else
    Cache->push_back(std::make_pair(BB, Dep));
  
  // If the block has a dependency (i.e. it isn't completely transparent to
  // the value), remember the reverse association because we just added it
  // to Cache!
  if (Dep.isNonLocal())
    return Dep;
  
  // Keep the ReverseNonLocalPtrDeps map up to date so we can efficiently
  // update MemDep when we remove instructions.
  Instruction *Inst = Dep.getInst();
  assert(Inst && "Didn't depend on anything?");
  ValueIsLoadPair CacheKey(Pointer, isLoad);
  ReverseNonLocalPtrDeps[Inst].insert(CacheKey.getOpaqueValue());
  return Dep;
}
/// getNonLocalCallDependency - Perform a full dependency query for the
/// specified call, 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.
///
/// This returns a reference to an internal data structure that may be
/// invalidated on the next non-local query or when an instruction is
/// removed.  Clients must copy this data if they want it around longer than
/// that.
const MemoryDependenceAnalysis::NonLocalDepInfo &
MemoryDependenceAnalysis::getNonLocalCallDependency(CallSite QueryCS) {
  assert(getDependency(QueryCS.getInstruction()).isNonLocal() &&
 "getNonLocalCallDependency should only be used on calls with non-local deps!");
  PerInstNLInfo &CacheP = NonLocalDeps[QueryCS.getInstruction()];
  NonLocalDepInfo &Cache = CacheP.first;

  /// DirtyBlocks - This is the set of blocks that need to be recomputed.  In
  /// the cached case, this can happen due to instructions being deleted etc. In
  /// the uncached case, this starts out as the set of predecessors we care
  /// about.
  SmallVector<BasicBlock*, 32> DirtyBlocks;
  
  if (!Cache.empty()) {
    // Okay, we have a cache entry.  If we know it is not dirty, just return it
    // with no computation.
    if (!CacheP.second) {
      NumCacheNonLocal++;
      return Cache;
    }
    
    // If we already have a partially computed set of results, scan them to
    // determine what is dirty, seeding our initial DirtyBlocks worklist.
    for (NonLocalDepInfo::iterator I = Cache.begin(), E = Cache.end();
       I != E; ++I)
      if (I->second.isDirty())
        DirtyBlocks.push_back(I->first);
    
    // Sort the cache so that we can do fast binary search lookups below.
    std::sort(Cache.begin(), Cache.end());
    
    ++NumCacheDirtyNonLocal;
    //cerr << "CACHED CASE: " << DirtyBlocks.size() << " dirty: "
    //     << Cache.size() << " cached: " << *QueryInst;
  } else {
    // Seed DirtyBlocks with each of the preds of QueryInst's block.
    BasicBlock *QueryBB = QueryCS.getInstruction()->getParent();
    for (BasicBlock **PI = PredCache->GetPreds(QueryBB); *PI; ++PI)
      DirtyBlocks.push_back(*PI);
    NumUncacheNonLocal++;
  }
  
  // isReadonlyCall - If this is a read-only call, we can be more aggressive.
  bool isReadonlyCall = AA->onlyReadsMemory(QueryCS);

  SmallPtrSet<BasicBlock*, 64> Visited;
  
  unsigned NumSortedEntries = Cache.size();
  DEBUG(AssertSorted(Cache));
  
  // Iterate while we still have blocks to update.
  while (!DirtyBlocks.empty()) {
    BasicBlock *DirtyBB = DirtyBlocks.back();
    DirtyBlocks.pop_back();
    
    // Already processed this block?
    if (!Visited.insert(DirtyBB))
      continue;
    
    // Do a binary search to see if we already have an entry for this block in
    // the cache set.  If so, find it.
    DEBUG(AssertSorted(Cache, NumSortedEntries));
    NonLocalDepInfo::iterator Entry = 
      std::upper_bound(Cache.begin(), Cache.begin()+NumSortedEntries,
                       std::make_pair(DirtyBB, MemDepResult()));
    if (Entry != Cache.begin() && prior(Entry)->first == DirtyBB)
      --Entry;
    
    MemDepResult *ExistingResult = 0;
    if (Entry != Cache.begin()+NumSortedEntries && 
        Entry->first == DirtyBB) {
      // If we already have an entry, and if it isn't already dirty, the block
      // is done.
      if (!Entry->second.isDirty())
        continue;
      
      // Otherwise, remember this slot so we can update the value.
      ExistingResult = &Entry->second;
    }
    
    // If the dirty entry has a pointer, start scanning from it so we don't have
    // to rescan the entire block.
    BasicBlock::iterator ScanPos = DirtyBB->end();
    if (ExistingResult) {
      if (Instruction *Inst = ExistingResult->getInst()) {
        ScanPos = Inst;
        // We're removing QueryInst's use of Inst.
        RemoveFromReverseMap(ReverseNonLocalDeps, Inst,
                             QueryCS.getInstruction());
      }
    }
    
    // Find out if this block has a local dependency for QueryInst.
    MemDepResult Dep;
    
    if (ScanPos != DirtyBB->begin()) {
      Dep = getCallSiteDependencyFrom(QueryCS, isReadonlyCall,ScanPos, DirtyBB);
    } else if (DirtyBB != &DirtyBB->getParent()->getEntryBlock()) {
      // No dependence found.  If this is the entry block of the function, it is
      // a clobber, otherwise it is non-local.
      Dep = MemDepResult::getNonLocal();
    } else {
      Dep = MemDepResult::getClobber(ScanPos);
    }
    
    // If we had a dirty entry for the block, update it.  Otherwise, just add
    // a new entry.
    if (ExistingResult)
      *ExistingResult = Dep;
    else
      Cache.push_back(std::make_pair(DirtyBB, Dep));
    
    // If the block has a dependency (i.e. it isn't completely transparent to
    // the value), remember the association!
    if (!Dep.isNonLocal()) {
      // Keep the ReverseNonLocalDeps map up to date so we can efficiently
      // update this when we remove instructions.
      if (Instruction *Inst = Dep.getInst())
        ReverseNonLocalDeps[Inst].insert(QueryCS.getInstruction());
    } else {
    
      // If the block *is* completely transparent to the load, we need to check
      // the predecessors of this block.  Add them to our worklist.
      for (BasicBlock **PI = PredCache->GetPreds(DirtyBB); *PI; ++PI)
        DirtyBlocks.push_back(*PI);
    }
  }
  
  return Cache;
}
Ejemplo n.º 10
0
void DataDependence::processDepResult(Instruction *inst, 
    MemoryDependenceAnalysis &MDA, AliasAnalysis &AA) {
  // TODO: This is probably a good place to check of the dependency
  // information is calculated on-demand
  MemDepResult Res = MDA.getDependency(inst);


  if (!Res.isNonLocal()) {
    // local results (not-non-local) can be simply handled. They are just
    // a pair of insturctions and a dependency type

    // Get dependency information
    DepInfo newInfo;
    newInfo = getDepInfo(Res);

#ifdef MK_DEBUG
    //errs() << "[DEBUG] newInfo depInst == " << Res.getInst() << '\n';
    if (Res.getInst() == NULL) {
      errs() << "[DEBUG] NULL dependency found, dep type: "
             << depTypeToString(newInfo.Type_) << '\n';
    }
#endif

    // Save into map
    assert(newInfo.valid());
    LocalDeps_[inst] = newInfo;
  }
  else {
    // Handle NonLocal dependencies. The function call
    // getNonLocalPointerDependency() assumes that a result of NonLocal
    // has already been encountered
    
    // Get dependency information
    DepInfo newInfo;
    newInfo = getDepInfo(Res);

    assert(newInfo.Type_ == NonLocal);
    assert(Res.isNonLocal());

    SmallVector<NonLocalDepResult, 4> NLDep;
    if (LoadInst *LI = dyn_cast<LoadInst>(inst)) {
      if (!LI->isUnordered()) {
        // FIXME: Handle atomic/volatile loads.
        errs() << "[WARNING] atomic/volatile loads are not handled\n";
        assert(false && "atomic/volatile loads not handled");
        //Deps[Inst].insert(std::make_pair(getInstTypePair(0, Unknown),
                                         //static_cast<BasicBlock *>(0)));
        return;
      }
      AliasAnalysis::Location Loc = AA.getLocation(LI);
      MDA.getNonLocalPointerDependency(Loc, true, LI->getParent(), NLDep);
    } 
    else if (StoreInst *SI = dyn_cast<StoreInst>(inst)) {
      if (!SI->isUnordered()) {
        // FIXME: Handle atomic/volatile stores.
        errs() << "[WARNING] atomic/volatile stores are not handled\n";
        assert(false && "atomic/volatile stores not handled");
        //Deps[Inst].insert(std::make_pair(getInstTypePair(0, Unknown),
                                         //static_cast<BasicBlock *>(0)));
        return;
      }
      AliasAnalysis::Location Loc = AA.getLocation(SI);
      MDA.getNonLocalPointerDependency(Loc, false, SI->getParent(), 
          NLDep);
    } 
    else if (VAArgInst *VI = dyn_cast<VAArgInst>(inst)) {
      AliasAnalysis::Location Loc = AA.getLocation(VI);
      MDA.getNonLocalPointerDependency(Loc, false, VI->getParent(), 
          NLDep);
    } 
    else {
      llvm_unreachable("Unknown memory instruction!");
    }

#ifdef MK_DEBUG
    errs() << "[DEBUG] NLDep.size() == " << NLDep.size() << '\n';
#endif
    for (auto I = NLDep.begin(), E = NLDep.end(); I != E; ++I) {
      NonLocalDeps_[inst].push_back(*I);
    }
  } // end else
}
Ejemplo n.º 11
0
bool DSE::runOnBasicBlock(BasicBlock &BB) {
  bool MadeChange = false;
  
  // Do a top-down walk on the BB.
  for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ) {
    Instruction *Inst = BBI++;
    
    // Handle 'free' calls specially.
    if (CallInst *F = isFreeCall(Inst)) {
      MadeChange |= HandleFree(F);
      continue;
    }
    
    // If we find something that writes memory, get its memory dependence.
    if (!hasMemoryWrite(Inst))
      continue;

    MemDepResult InstDep = MD->getDependency(Inst);
    
    // Ignore non-local store liveness.
    // FIXME: cross-block DSE would be fun. :)
    if (InstDep.isNonLocal() || 
        // Ignore self dependence, which happens in the entry block of the
        // function.
        InstDep.getInst() == Inst)
      continue;
     
    // If we're storing the same value back to a pointer that we just
    // loaded from, then the store can be removed.
    if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
      if (LoadInst *DepLoad = dyn_cast<LoadInst>(InstDep.getInst())) {
        if (SI->getPointerOperand() == DepLoad->getPointerOperand() &&
            SI->getOperand(0) == DepLoad && !SI->isVolatile()) {
          DEBUG(dbgs() << "DSE: Remove Store Of Load from same pointer:\n  "
                       << "LOAD: " << *DepLoad << "\n  STORE: " << *SI << '\n');
          
          // DeleteDeadInstruction can delete the current instruction.  Save BBI
          // in case we need it.
          WeakVH NextInst(BBI);
          
          DeleteDeadInstruction(SI, *MD);
          
          if (NextInst == 0)  // Next instruction deleted.
            BBI = BB.begin();
          else if (BBI != BB.begin())  // Revisit this instruction if possible.
            --BBI;
          ++NumFastStores;
          MadeChange = true;
          continue;
        }
      }
    }
    
    // Figure out what location is being stored to.
    AliasAnalysis::Location Loc = getLocForWrite(Inst, *AA);

    // If we didn't get a useful location, fail.
    if (Loc.Ptr == 0)
      continue;
    
    while (!InstDep.isNonLocal()) {
      // Get the memory clobbered by the instruction we depend on.  MemDep will
      // skip any instructions that 'Loc' clearly doesn't interact with.  If we
      // end up depending on a may- or must-aliased load, then we can't optimize
      // away the store and we bail out.  However, if we depend on on something
      // that overwrites the memory location we *can* potentially optimize it.
      //
      // Find out what memory location the dependant instruction stores.
      Instruction *DepWrite = InstDep.getInst();
      AliasAnalysis::Location DepLoc = getLocForWrite(DepWrite, *AA);
      // If we didn't get a useful location, or if it isn't a size, bail out.
      if (DepLoc.Ptr == 0)
        break;

      // If we find a write that is a) removable (i.e., non-volatile), b) is
      // completely obliterated by the store to 'Loc', and c) which we know that
      // 'Inst' doesn't load from, then we can remove it.
      if (isRemovable(DepWrite) && isCompleteOverwrite(Loc, DepLoc, *AA) &&
          !isPossibleSelfRead(Inst, Loc, DepWrite, *AA)) {
        DEBUG(dbgs() << "DSE: Remove Dead Store:\n  DEAD: "
              << *DepWrite << "\n  KILLER: " << *Inst << '\n');
        
        // Delete the store and now-dead instructions that feed it.
        DeleteDeadInstruction(DepWrite, *MD);
        ++NumFastStores;
        MadeChange = true;
        
        // DeleteDeadInstruction can delete the current instruction in loop
        // cases, reset BBI.
        BBI = Inst;
        if (BBI != BB.begin())
          --BBI;
        break;
      }
      
      // If this is a may-aliased store that is clobbering the store value, we
      // can keep searching past it for another must-aliased pointer that stores
      // to the same location.  For example, in:
      //   store -> P
      //   store -> Q
      //   store -> P
      // we can remove the first store to P even though we don't know if P and Q
      // alias.
      if (DepWrite == &BB.front()) break;
      
      // Can't look past this instruction if it might read 'Loc'.
      if (AA->getModRefInfo(DepWrite, Loc) & AliasAnalysis::Ref)
        break;
        
      InstDep = MD->getPointerDependencyFrom(Loc, false, DepWrite, &BB);
    }
  }
  
  // If this block ends in a return, unwind, or unreachable, all allocas are
  // dead at its end, which means stores to them are also dead.
  if (BB.getTerminator()->getNumSuccessors() == 0)
    MadeChange |= handleEndBlock(BB);
  
  return MadeChange;
}
Ejemplo n.º 12
0
bool MemDepPrinter::runOnFunction(Function &F) {
  this->F = &F;
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  MemoryDependenceAnalysis &MDA = getAnalysis<MemoryDependenceAnalysis>();

  // All this code uses non-const interfaces because MemDep is not
  // const-friendly, though nothing is actually modified.
  for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
    Instruction *Inst = &*I;

    if (!Inst->mayReadFromMemory() && !Inst->mayWriteToMemory())
      continue;

    MemDepResult Res = MDA.getDependency(Inst);
    if (!Res.isNonLocal()) {
      Deps[Inst].insert(std::make_pair(getInstTypePair(Res),
                                       static_cast<BasicBlock *>(nullptr)));
    } else if (CallSite CS = cast<Value>(Inst)) {
      const MemoryDependenceAnalysis::NonLocalDepInfo &NLDI =
        MDA.getNonLocalCallDependency(CS);

      DepSet &InstDeps = Deps[Inst];
      for (MemoryDependenceAnalysis::NonLocalDepInfo::const_iterator
           I = NLDI.begin(), E = NLDI.end(); I != E; ++I) {
        const MemDepResult &Res = I->getResult();
        InstDeps.insert(std::make_pair(getInstTypePair(Res), I->getBB()));
      }
    } else {
      SmallVector<NonLocalDepResult, 4> NLDI;
      if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
        if (!LI->isUnordered()) {
          // FIXME: Handle atomic/volatile loads.
          Deps[Inst].insert(std::make_pair(getInstTypePair(nullptr, Unknown),
                                           static_cast<BasicBlock *>(nullptr)));
          continue;
        }
        AliasAnalysis::Location Loc = AA.getLocation(LI);
        MDA.getNonLocalPointerDependency(Loc, true, LI->getParent(), NLDI);
      } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
        if (!SI->isUnordered()) {
          // FIXME: Handle atomic/volatile stores.
          Deps[Inst].insert(std::make_pair(getInstTypePair(nullptr, Unknown),
                                           static_cast<BasicBlock *>(nullptr)));
          continue;
        }
        AliasAnalysis::Location Loc = AA.getLocation(SI);
        MDA.getNonLocalPointerDependency(Loc, false, SI->getParent(), NLDI);
      } else if (VAArgInst *VI = dyn_cast<VAArgInst>(Inst)) {
        AliasAnalysis::Location Loc = AA.getLocation(VI);
        MDA.getNonLocalPointerDependency(Loc, false, VI->getParent(), NLDI);
      } else {
        llvm_unreachable("Unknown memory instruction!");
      }

      DepSet &InstDeps = Deps[Inst];
      for (SmallVectorImpl<NonLocalDepResult>::const_iterator
           I = NLDI.begin(), E = NLDI.end(); I != E; ++I) {
        const MemDepResult &Res = I->getResult();
        InstDeps.insert(std::make_pair(getInstTypePair(Res), I->getBB()));
      }
    }
  }

  return false;
}
Ejemplo n.º 13
0
bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
  if (SI->isVolatile()) return false;
  
  if (TD == 0) return false;

  // Detect cases where we're performing call slot forwarding, but
  // happen to be using a load-store pair to implement it, rather than
  // a memcpy.
  if (LoadInst *LI = dyn_cast<LoadInst>(SI->getOperand(0))) {
    if (!LI->isVolatile() && LI->hasOneUse()) {
      MemDepResult ldep = MD->getDependency(LI);
      CallInst *C = 0;
      if (ldep.isClobber() && !isa<MemCpyInst>(ldep.getInst()))
        C = dyn_cast<CallInst>(ldep.getInst());

      if (C) {
        // Check that nothing touches the dest of the "copy" between
        // the call and the store.
        MemDepResult sdep = MD->getDependency(SI);
        if (!sdep.isNonLocal()) {
          bool FoundCall = false;
          for (BasicBlock::iterator I = SI, E = sdep.getInst(); I != E; --I) {
            if (&*I == C) {
              FoundCall = true;
              break;
            }
          }
          if (!FoundCall)
            C = 0;
        }
      }

      if (C) {
        bool changed = performCallSlotOptzn(LI,
                        SI->getPointerOperand()->stripPointerCasts(), 
                        LI->getPointerOperand()->stripPointerCasts(),
                        TD->getTypeStoreSize(SI->getOperand(0)->getType()), C);
        if (changed) {
          MD->removeInstruction(SI);
          SI->eraseFromParent();
          MD->removeInstruction(LI);
          LI->eraseFromParent();
          ++NumMemCpyInstr;
          return true;
        }
      }
    }
  }
  
  // There are two cases that are interesting for this code to handle: memcpy
  // and memset.  Right now we only handle memset.
  
  // Ensure that the value being stored is something that can be memset'able a
  // byte at a time like "0" or "-1" or any width, as well as things like
  // 0xA0A0A0A0 and 0.0.
  if (Value *ByteVal = isBytewiseValue(SI->getOperand(0)))
    if (Instruction *I = tryMergingIntoMemset(SI, SI->getPointerOperand(),
                                              ByteVal)) {
      BBI = I;  // Don't invalidate iterator.
      return true;
    }
  
  return false;
}