//===- DeadStoreElimination.cpp - Fast Dead Store Elimination -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a trivial dead store elimination that only considers
// basic-block local redundant stores.
//
// FIXME: This should eventually be extended to be a post-dominator tree
// traversal.  Doing so would be pretty trivial.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "dse"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Support/Compiler.h"
using namespace llvm;

STATISTIC(NumFastStores, "Number of stores deleted");
STATISTIC(NumFastOther , "Number of other instrs removed");

namespace {
  struct VISIBILITY_HIDDEN DSE : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    DSE() : FunctionPass((intptr_t)&ID) {}

    virtual bool runOnFunction(Function &F) {
      bool Changed = false;
      for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
        Changed |= runOnBasicBlock(*I);
      return Changed;
    }

    bool runOnBasicBlock(BasicBlock &BB);
    bool handleFreeWithNonTrivialDependency(FreeInst* F,
                                            Instruction* dependency,
                                        SetVector<Instruction*>& possiblyDead);
    bool handleEndBlock(BasicBlock& BB, SetVector<Instruction*>& possiblyDead);
    bool RemoveUndeadPointers(Value* pointer,
                              BasicBlock::iterator& BBI,
                              SmallPtrSet<AllocaInst*, 64>& deadPointers, 
                              SetVector<Instruction*>& possiblyDead);
    void DeleteDeadInstructionChains(Instruction *I,
                                     SetVector<Instruction*> &DeadInsts);
    
    /// Find the base pointer that a pointer came from
    /// Because this is used to find pointers that originate
    /// from allocas, it is safe to ignore GEP indices, since
    /// either the store will be in the alloca, and thus dead,
    /// or beyond the end of the alloca, and thus undefined.
    void TranslatePointerBitCasts(Value*& v, bool zeroGepsOnly = false) {
      assert(isa<PointerType>(v->getType()) &&
             "Translating a non-pointer type?");
      while (true) {
        if (BitCastInst* C = dyn_cast<BitCastInst>(v))
          v = C->getOperand(0);
        else if (GetElementPtrInst* G = dyn_cast<GetElementPtrInst>(v))
          if (!zeroGepsOnly || G->hasAllZeroIndices()) {
            v = G->getOperand(0);
          } else {
            break;
          }
        else
          break;
      }
    }

    // getAnalysisUsage - We require post dominance frontiers (aka Control
    // Dependence Graph)
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      AU.addRequired<TargetData>();
      AU.addRequired<AliasAnalysis>();
      AU.addRequired<MemoryDependenceAnalysis>();
      AU.addPreserved<AliasAnalysis>();
      AU.addPreserved<MemoryDependenceAnalysis>();
    }
  };
  char DSE::ID = 0;
  RegisterPass<DSE> X("dse", "Dead Store Elimination");
}

FunctionPass *llvm::createDeadStoreEliminationPass() { return new DSE(); }

bool DSE::runOnBasicBlock(BasicBlock &BB) {
  MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
  TargetData &TD = getAnalysis<TargetData>();  

  // Record the last-seen store to this pointer
  DenseMap<Value*, StoreInst*> lastStore;
  // Record instructions possibly made dead by deleting a store
  SetVector<Instruction*> possiblyDead;
  
  bool MadeChange = false;
  
  // Do a top-down walk on the BB
  for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end();
       BBI != BBE; ++BBI) {
    // If we find a store or a free...
    if (!isa<StoreInst>(BBI) && !isa<FreeInst>(BBI))
      continue;
      
    Value* pointer = 0;
    if (StoreInst* S = dyn_cast<StoreInst>(BBI)) {
      if (!S->isVolatile())
        pointer = S->getPointerOperand();
      else
        continue;
    } else
      pointer = cast<FreeInst>(BBI)->getPointerOperand();
      
    TranslatePointerBitCasts(pointer, true);
    StoreInst*& last = lastStore[pointer];
    bool deletedStore = false;
      
    // ... to a pointer that has been stored to before...
    if (last) {
      Instruction* dep = MD.getDependency(BBI);
        
      // ... and no other memory dependencies are between them....
      while (dep != MemoryDependenceAnalysis::None &&
             dep != MemoryDependenceAnalysis::NonLocal &&
             isa<StoreInst>(dep)) {
        if (dep != last ||
             TD.getTypeStoreSize(last->getOperand(0)->getType()) >
             TD.getTypeStoreSize(BBI->getOperand(0)->getType())) {
          dep = MD.getDependency(BBI, dep);
          continue;
        }
        
        // Remove it!
        MD.removeInstruction(last);
          
        // DCE instructions only used to calculate that store
        if (Instruction* D = dyn_cast<Instruction>(last->getOperand(0)))
          possiblyDead.insert(D);
        if (Instruction* D = dyn_cast<Instruction>(last->getOperand(1)))
          possiblyDead.insert(D);
          
        last->eraseFromParent();
        NumFastStores++;
        deletedStore = true;
        MadeChange = true;
          
        break;
      }
    }
    
    // Handle frees whose dependencies are non-trivial.
    if (FreeInst* F = dyn_cast<FreeInst>(BBI)) {
      if (!deletedStore)
        MadeChange |= handleFreeWithNonTrivialDependency(F,
                                                         MD.getDependency(F),
                                                         possiblyDead);
      // No known stores after the free
      last = 0;
    } else {
      // Update our most-recent-store map.
      last = cast<StoreInst>(BBI);
    }
  }
  
  // If this block ends in a return, unwind, unreachable, and eventually
  // tailcall, then all allocas are dead at its end.
  if (BB.getTerminator()->getNumSuccessors() == 0)
    MadeChange |= handleEndBlock(BB, possiblyDead);
  
  // Do a trivial DCE
  while (!possiblyDead.empty()) {
    Instruction *I = possiblyDead.back();
    possiblyDead.pop_back();
    DeleteDeadInstructionChains(I, possiblyDead);
  }
  
  return MadeChange;
}

/// handleFreeWithNonTrivialDependency - Handle frees of entire structures whose
/// dependency is a store to a field of that structure
bool DSE::handleFreeWithNonTrivialDependency(FreeInst* F, Instruction* dep,
                                       SetVector<Instruction*>& possiblyDead) {
  TargetData &TD = getAnalysis<TargetData>();
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
  
  if (dep == MemoryDependenceAnalysis::None ||
      dep == MemoryDependenceAnalysis::NonLocal)
    return false;
  
  StoreInst* dependency = dyn_cast<StoreInst>(dep);
  if (!dependency)
    return false;
  else if (dependency->isVolatile())
    return false;
  
  Value* depPointer = dependency->getPointerOperand();
  const Type* depType = dependency->getOperand(0)->getType();
  unsigned depPointerSize = TD.getTypeStoreSize(depType);
  
  // Check for aliasing
  AliasAnalysis::AliasResult A = AA.alias(F->getPointerOperand(), ~0UL,
                                          depPointer, depPointerSize);
    
  if (A == AliasAnalysis::MustAlias) {
    // Remove it!
    MD.removeInstruction(dependency);

    // DCE instructions only used to calculate that store
    if (Instruction* D = dyn_cast<Instruction>(dependency->getOperand(0)))
      possiblyDead.insert(D);
    if (Instruction* D = dyn_cast<Instruction>(dependency->getOperand(1)))
      possiblyDead.insert(D);

    dependency->eraseFromParent();
    NumFastStores++;
    return true;
  }
  
  return false;
}

/// handleEndBlock - Remove dead stores to stack-allocated locations in the
/// function end block.  Ex:
/// %A = alloca i32
/// ...
/// store i32 1, i32* %A
/// ret void
bool DSE::handleEndBlock(BasicBlock& BB,
                         SetVector<Instruction*>& possiblyDead) {
  TargetData &TD = getAnalysis<TargetData>();
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
  
  bool MadeChange = false;
  
  // Pointers alloca'd in this function are dead in the end block
  SmallPtrSet<AllocaInst*, 64> deadPointers;
  
  // Find all of the alloca'd pointers in the entry block
  BasicBlock *Entry = BB.getParent()->begin();
  for (BasicBlock::iterator I = Entry->begin(), E = Entry->end(); I != E; ++I)
    if (AllocaInst *AI = dyn_cast<AllocaInst>(I))
      deadPointers.insert(AI);
  
  // Scan the basic block backwards
  for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ){
    --BBI;
    
    if (deadPointers.empty())
      break;
    
    // If we find a store whose pointer is dead...
    if (StoreInst* S = dyn_cast<StoreInst>(BBI)) {
      if (!S->isVolatile()) {
        Value* pointerOperand = S->getPointerOperand();
        // See through pointer-to-pointer bitcasts
        TranslatePointerBitCasts(pointerOperand);
      
        if (isa<AllocaInst>(pointerOperand) && 
            deadPointers.count(cast<AllocaInst>(pointerOperand))) {
          // Remove it!
          MD.removeInstruction(S);
        
          // DCE instructions only used to calculate that store
          if (Instruction* D = dyn_cast<Instruction>(S->getOperand(0)))
            possiblyDead.insert(D);
          if (Instruction* D = dyn_cast<Instruction>(S->getOperand(1)))
            possiblyDead.insert(D);
        
          BBI++;
          S->eraseFromParent();
          NumFastStores++;
          MadeChange = true;
        }
      }
      
      continue;
    }
    
    Value* killPointer = 0;
    
    // If we encounter a use of the pointer, it is no longer considered dead
    if (LoadInst* L = dyn_cast<LoadInst>(BBI)) {
      killPointer = L->getPointerOperand();
    } else if (VAArgInst* V = dyn_cast<VAArgInst>(BBI)) {
      killPointer = V->getOperand(0);
    } else if (AllocaInst* A = dyn_cast<AllocaInst>(BBI)) {
      deadPointers.erase(A);
      continue;
    } else if (CallSite::get(BBI).getInstruction() != 0) {
      // If this call does not access memory, it can't
      // be undeadifying any of our pointers.
      CallSite CS = CallSite::get(BBI);
      if (AA.doesNotAccessMemory(CS))
        continue;
      
      unsigned modRef = 0;
      unsigned other = 0;
      
      // Remove any pointers made undead by the call from the dead set
      std::vector<Instruction*> dead;
      for (SmallPtrSet<AllocaInst*, 64>::iterator I = deadPointers.begin(),
           E = deadPointers.end(); I != E; ++I) {
        // HACK: if we detect that our AA is imprecise, it's not
        // worth it to scan the rest of the deadPointers set.  Just
        // assume that the AA will return ModRef for everything, and
        // go ahead and bail.
        if (modRef >= 16 && other == 0) {
          deadPointers.clear();
          return MadeChange;
        }
        
        // Get size information for the alloca
        unsigned pointerSize = ~0UL;
        if (ConstantInt* C = dyn_cast<ConstantInt>((*I)->getArraySize()))
          pointerSize = C->getZExtValue() * \
                        TD.getABITypeSize((*I)->getAllocatedType());
        
        // See if the call site touches it
        AliasAnalysis::ModRefResult A = AA.getModRefInfo(CS, *I, pointerSize);
        
        if (A == AliasAnalysis::ModRef)
          modRef++;
        else
          other++;
        
        if (A == AliasAnalysis::ModRef || A == AliasAnalysis::Ref)
          dead.push_back(*I);
      }

      for (std::vector<Instruction*>::iterator I = dead.begin(), E = dead.end();
           I != E; ++I)
        if (AllocaInst *AI = dyn_cast<AllocaInst>(*I))
          deadPointers.erase(AI);
      
      continue;
    }
    
    if (!killPointer)
      continue;
    
    TranslatePointerBitCasts(killPointer);
    
    // Deal with undead pointers
    MadeChange |= RemoveUndeadPointers(killPointer, BBI,
                                       deadPointers, possiblyDead);
  }
  
  return MadeChange;
}

/// RemoveUndeadPointers - check for uses of a pointer that make it
/// undead when scanning for dead stores to alloca's.
bool DSE::RemoveUndeadPointers(Value* killPointer,
                                BasicBlock::iterator& BBI,
                                SmallPtrSet<AllocaInst*, 64>& deadPointers, 
                                SetVector<Instruction*>& possiblyDead) {
  TargetData &TD = getAnalysis<TargetData>();
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
                                  
  // If the kill pointer can be easily reduced to an alloca,
  // don't bother doing extraneous AA queries
  if (AllocaInst* A = dyn_cast<AllocaInst>(killPointer)) {
    if (deadPointers.count(A))
      deadPointers.erase(A);
    return false;
  } else if (isa<GlobalValue>(killPointer)) {
    // A global can't be in the dead pointer set
    return false;
  }
  
  bool MadeChange = false;
  
  std::vector<Instruction*> undead;
    
  for (SmallPtrSet<AllocaInst*, 64>::iterator I = deadPointers.begin(),
      E = deadPointers.end(); I != E; ++I) {
    // Get size information for the alloca
    unsigned pointerSize = ~0UL;
    if (ConstantInt* C = dyn_cast<ConstantInt>((*I)->getArraySize()))
      pointerSize = C->getZExtValue() * \
                    TD.getABITypeSize((*I)->getAllocatedType());
      
    // See if this pointer could alias it
    AliasAnalysis::AliasResult A = AA.alias(*I, pointerSize,
                                            killPointer, ~0UL);

    // If it must-alias and a store, we can delete it
    if (isa<StoreInst>(BBI) && A == AliasAnalysis::MustAlias) {
      StoreInst* S = cast<StoreInst>(BBI);

      // Remove it!
      MD.removeInstruction(S);

      // DCE instructions only used to calculate that store
      if (Instruction* D = dyn_cast<Instruction>(S->getOperand(0)))
        possiblyDead.insert(D);
      if (Instruction* D = dyn_cast<Instruction>(S->getOperand(1)))
        possiblyDead.insert(D);

      BBI++;
      S->eraseFromParent();
      NumFastStores++;
      MadeChange = true;

      continue;

      // Otherwise, it is undead
      } else if (A != AliasAnalysis::NoAlias)
        undead.push_back(*I);
  }

  for (std::vector<Instruction*>::iterator I = undead.begin(), E = undead.end();
       I != E; ++I)
    if (AllocaInst *AI = dyn_cast<AllocaInst>(*I))
      deadPointers.erase(AI);
  
  return MadeChange;
}

/// DeleteDeadInstructionChains - takes an instruction and a setvector of
/// dead instructions.  If I is dead, it is erased, and its operands are
/// checked for deadness.  If they are dead, they are added to the dead
/// setvector.
void DSE::DeleteDeadInstructionChains(Instruction *I,
                                      SetVector<Instruction*> &DeadInsts) {
  // Instruction must be dead.
  if (!I->use_empty() || !isInstructionTriviallyDead(I)) return;

  // Let the memory dependence know
  getAnalysis<MemoryDependenceAnalysis>().removeInstruction(I);

  // See if this made any operands dead.  We do it this way in case the
  // instruction uses the same operand twice.  We don't want to delete a
  // value then reference it.
  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
    if (I->getOperand(i)->hasOneUse())
      if (Instruction* Op = dyn_cast<Instruction>(I->getOperand(i)))
        DeadInsts.insert(Op);      // Attempt to nuke it later.
    
    I->setOperand(i, 0);         // Drop from the operand list.
  }

  I->eraseFromParent();
  ++NumFastOther;
}
