//===- 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/IntrinsicInst.h" #include "llvm/Pass.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/Dominators.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 { TargetData *TD; static char ID; // Pass identification, replacement for typeid DSE() : FunctionPass(&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, MemDepResult Dep); bool handleEndBlock(BasicBlock &BB); bool RemoveUndeadPointers(Value* Ptr, uint64_t killPointerSize, BasicBlock::iterator& BBI, SmallPtrSet& deadPointers); void DeleteDeadInstruction(Instruction *I, SmallPtrSet *deadPointers = 0); // getAnalysisUsage - We require post dominance frontiers (aka Control // Dependence Graph) virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); } }; } char DSE::ID = 0; static RegisterPass X("dse", "Dead Store Elimination"); FunctionPass *llvm::createDeadStoreEliminationPass() { return new DSE(); } bool DSE::runOnBasicBlock(BasicBlock &BB) { MemoryDependenceAnalysis& MD = getAnalysis(); TD = getAnalysisIfAvailable(); 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++; // If we find a store or a free, get its memory dependence. if (!isa(Inst) && !isa(Inst)) continue; // Don't molest volatile stores or do queries that will return "clobber". if (StoreInst *SI = dyn_cast(Inst)) if (SI->isVolatile()) continue; MemDepResult InstDep = MD.getDependency(Inst); // Ignore non-local stores. // FIXME: cross-block DSE would be fun. :) if (InstDep.isNonLocal()) continue; // Handle frees whose dependencies are non-trivial. if (FreeInst *FI = dyn_cast(Inst)) { MadeChange |= handleFreeWithNonTrivialDependency(FI, InstDep); continue; } StoreInst *SI = cast(Inst); // If not a definite must-alias dependency, ignore it. if (!InstDep.isDef()) continue; // If this is a store-store dependence, then the previous store is dead so // long as this store is at least as big as it. if (StoreInst *DepStore = dyn_cast(InstDep.getInst())) if (TD && TD->getTypeStoreSize(DepStore->getOperand(0)->getType()) <= TD->getTypeStoreSize(SI->getOperand(0)->getType())) { // Delete the store and now-dead instructions that feed it. DeleteDeadInstruction(DepStore); NumFastStores++; MadeChange = true; if (BBI != BB.begin()) --BBI; continue; } // If we're storing the same value back to a pointer that we just // loaded from, then the store can be removed. if (LoadInst *DepLoad = dyn_cast(InstDep.getInst())) { if (SI->getPointerOperand() == DepLoad->getPointerOperand() && SI->getOperand(0) == DepLoad) { DeleteDeadInstruction(SI); if (BBI != BB.begin()) --BBI; NumFastStores++; MadeChange = true; continue; } } } // 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; } /// handleFreeWithNonTrivialDependency - Handle frees of entire structures whose /// dependency is a store to a field of that structure. bool DSE::handleFreeWithNonTrivialDependency(FreeInst *F, MemDepResult Dep) { AliasAnalysis &AA = getAnalysis(); StoreInst *Dependency = dyn_cast_or_null(Dep.getInst()); if (!Dependency || Dependency->isVolatile()) return false; Value *DepPointer = Dependency->getPointerOperand()->getUnderlyingObject(); // Check for aliasing. if (AA.alias(F->getPointerOperand(), 1, DepPointer, 1) != AliasAnalysis::MustAlias) return false; // DCE instructions only used to calculate that store DeleteDeadInstruction(Dependency); NumFastStores++; return true; } /// 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) { AliasAnalysis &AA = getAnalysis(); bool MadeChange = false; // Pointers alloca'd in this function are dead in the end block SmallPtrSet 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(I)) deadPointers.insert(AI); // Treat byval arguments the same, stores to them are dead at the end of the // function. for (Function::arg_iterator AI = BB.getParent()->arg_begin(), AE = BB.getParent()->arg_end(); AI != AE; ++AI) if (AI->hasByValAttr()) deadPointers.insert(AI); // Scan the basic block backwards for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ){ --BBI; // If we find a store whose pointer is dead. if (StoreInst* S = dyn_cast(BBI)) { if (!S->isVolatile()) { // See through pointer-to-pointer bitcasts Value* pointerOperand = S->getPointerOperand()->getUnderlyingObject(); // Alloca'd pointers or byval arguments (which are functionally like // alloca's) are valid candidates for removal. if (deadPointers.count(pointerOperand)) { // DCE instructions only used to calculate that store. BBI++; DeleteDeadInstruction(S, &deadPointers); NumFastStores++; MadeChange = true; } } continue; } // We can also remove memcpy's to local variables at the end of a function. if (MemCpyInst *M = dyn_cast(BBI)) { Value *dest = M->getDest()->getUnderlyingObject(); if (deadPointers.count(dest)) { BBI++; DeleteDeadInstruction(M, &deadPointers); NumFastOther++; MadeChange = true; continue; } // Because a memcpy is also a load, we can't skip it if we didn't remove // it. } Value* killPointer = 0; uint64_t killPointerSize = ~0UL; // If we encounter a use of the pointer, it is no longer considered dead if (LoadInst *L = dyn_cast(BBI)) { // However, if this load is unused and not volatile, we can go ahead and // remove it, and not have to worry about it making our pointer undead! if (L->use_empty() && !L->isVolatile()) { BBI++; DeleteDeadInstruction(L, &deadPointers); NumFastOther++; MadeChange = true; continue; } killPointer = L->getPointerOperand(); } else if (VAArgInst* V = dyn_cast(BBI)) { killPointer = V->getOperand(0); } else if (isa(BBI) && isa(cast(BBI)->getLength())) { killPointer = cast(BBI)->getSource(); killPointerSize = cast( cast(BBI)->getLength())->getZExtValue(); } else if (AllocaInst* A = dyn_cast(BBI)) { deadPointers.erase(A); // Dead alloca's can be DCE'd when we reach them if (A->use_empty()) { BBI++; DeleteDeadInstruction(A, &deadPointers); NumFastOther++; MadeChange = true; } 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 dead; for (SmallPtrSet::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 = ~0U; if (TD) { if (AllocaInst* A = dyn_cast(*I)) { if (ConstantInt* C = dyn_cast(A->getArraySize())) pointerSize = C->getZExtValue() * TD->getTypeAllocSize(A->getAllocatedType()); } else { const PointerType* PT = cast( cast(*I)->getType()); pointerSize = TD->getTypeAllocSize(PT->getElementType()); } } // 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::iterator I = dead.begin(), E = dead.end(); I != E; ++I) deadPointers.erase(*I); continue; } else if (isInstructionTriviallyDead(BBI)) { // For any non-memory-affecting non-terminators, DCE them as we reach them Instruction *Inst = BBI; BBI++; DeleteDeadInstruction(Inst, &deadPointers); NumFastOther++; MadeChange = true; continue; } if (!killPointer) continue; killPointer = killPointer->getUnderlyingObject(); // Deal with undead pointers MadeChange |= RemoveUndeadPointers(killPointer, killPointerSize, BBI, deadPointers); } 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, uint64_t killPointerSize, BasicBlock::iterator &BBI, SmallPtrSet& deadPointers) { AliasAnalysis &AA = getAnalysis(); // If the kill pointer can be easily reduced to an alloca, // don't bother doing extraneous AA queries. if (deadPointers.count(killPointer)) { deadPointers.erase(killPointer); return false; } // A global can't be in the dead pointer set. if (isa(killPointer)) return false; bool MadeChange = false; SmallVector undead; for (SmallPtrSet::iterator I = deadPointers.begin(), E = deadPointers.end(); I != E; ++I) { // Get size information for the alloca. unsigned pointerSize = ~0U; if (TD) { if (AllocaInst* A = dyn_cast(*I)) { if (ConstantInt* C = dyn_cast(A->getArraySize())) pointerSize = C->getZExtValue() * TD->getTypeAllocSize(A->getAllocatedType()); } else { const PointerType* PT = cast(cast(*I)->getType()); pointerSize = TD->getTypeAllocSize(PT->getElementType()); } } // See if this pointer could alias it AliasAnalysis::AliasResult A = AA.alias(*I, pointerSize, killPointer, killPointerSize); // If it must-alias and a store, we can delete it if (isa(BBI) && A == AliasAnalysis::MustAlias) { StoreInst* S = cast(BBI); // Remove it! BBI++; DeleteDeadInstruction(S, &deadPointers); NumFastStores++; MadeChange = true; continue; // Otherwise, it is undead } else if (A != AliasAnalysis::NoAlias) undead.push_back(*I); } for (SmallVector::iterator I = undead.begin(), E = undead.end(); I != E; ++I) deadPointers.erase(*I); return MadeChange; } /// DeleteDeadInstruction - Delete this instruction. Before we do, go through /// and zero out all the operands of this instruction. If any of them become /// dead, delete them and the computation tree that feeds them. /// /// If ValueSet is non-null, remove any deleted instructions from it as well. /// void DSE::DeleteDeadInstruction(Instruction *I, SmallPtrSet *ValueSet) { SmallVector NowDeadInsts; NowDeadInsts.push_back(I); --NumFastOther; // Before we touch this instruction, remove it from memdep! MemoryDependenceAnalysis &MDA = getAnalysis(); while (!NowDeadInsts.empty()) { Instruction *DeadInst = NowDeadInsts.back(); NowDeadInsts.pop_back(); ++NumFastOther; // This instruction is dead, zap it, in stages. Start by removing it from // MemDep, which needs to know the operands and needs it to be in the // function. MDA.removeInstruction(DeadInst); for (unsigned op = 0, e = DeadInst->getNumOperands(); op != e; ++op) { Value *Op = DeadInst->getOperand(op); DeadInst->setOperand(op, 0); // If this operand just became dead, add it to the NowDeadInsts list. if (!Op->use_empty()) continue; if (Instruction *OpI = dyn_cast(Op)) if (isInstructionTriviallyDead(OpI)) NowDeadInsts.push_back(OpI); } DeadInst->eraseFromParent(); if (ValueSet) ValueSet->erase(DeadInst); } }