From: Owen Anderson Date: Wed, 1 Aug 2007 06:30:51 +0000 (+0000) Subject: Move FastDSE in to DeadStoreElimination. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=a56c34f90bec3e46ff81d6af54a2d0d309a81c4d;p=oota-llvm.git Move FastDSE in to DeadStoreElimination. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40667 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp new file mode 100644 index 00000000000..abc0adec354 --- /dev/null +++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -0,0 +1,387 @@ +//===- FastDSE.cpp - Fast Dead Store Elimination --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Owen Anderson and 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 "fdse" +#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 FDSE : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + FDSE() : 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& possiblyDead); + bool handleEndBlock(BasicBlock& BB, SetVector& possiblyDead); + bool RemoveUndeadPointers(Value* pointer, unsigned pointerSize, + BasicBlock::iterator& BBI, + SmallPtrSet& deadPointers, + SetVector& possiblyDead); + void DeleteDeadInstructionChains(Instruction *I, + SetVector &DeadInsts); + void TranslatePointerBitCasts(Value*& v) { + assert(isa(v->getType()) && "Translating a non-pointer type?"); + + // See through pointer-to-pointer bitcasts + while (isa(v) || isa(v)) + if (BitCastInst* C = dyn_cast(v)) + v = C->getOperand(0); + else if (GetElementPtrInst* G = dyn_cast(v)) + v = G->getOperand(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(); + } + }; + char FDSE::ID = 0; + RegisterPass X("fdse", "Fast Dead Store Elimination"); +} + +FunctionPass *llvm::createFastDeadStoreEliminationPass() { return new FDSE(); } + +bool FDSE::runOnBasicBlock(BasicBlock &BB) { + MemoryDependenceAnalysis& MD = getAnalysis(); + + // Record the last-seen store to this pointer + DenseMap lastStore; + // Record instructions possibly made dead by deleting a store + SetVector 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(BBI) || isa(BBI)) { + Value* pointer = 0; + if (StoreInst* S = dyn_cast(BBI)) + pointer = S->getPointerOperand(); + else if (FreeInst* F = dyn_cast(BBI)) + pointer = F->getPointerOperand(); + + assert(pointer && "Not a free or a store?"); + + 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(dep)) { + if (dep == last) { + + // Remove it! + MD.removeInstruction(last); + + // DCE instructions only used to calculate that store + if (Instruction* D = dyn_cast(last->getOperand(0))) + possiblyDead.insert(D); + if (Instruction* D = dyn_cast(last->getOperand(1))) + possiblyDead.insert(D); + + last->eraseFromParent(); + NumFastStores++; + deletedStore = true; + MadeChange = true; + + break; + } else { + dep = MD.getDependency(BBI, dep); + } + } + } + + // Handle frees whose dependencies are non-trivial + if (FreeInst* F = dyn_cast(BBI)) + if (!deletedStore) + MadeChange |= handleFreeWithNonTrivialDependency(F, MD.getDependency(F), + possiblyDead); + + // Update our most-recent-store map + if (StoreInst* S = dyn_cast(BBI)) + last = S; + else + last = 0; + } + } + + // 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 FDSE::handleFreeWithNonTrivialDependency(FreeInst* F, Instruction* dep, + SetVector& possiblyDead) { + TargetData &TD = getAnalysis(); + AliasAnalysis &AA = getAnalysis(); + MemoryDependenceAnalysis& MD = getAnalysis(); + + if (dep == MemoryDependenceAnalysis::None || + dep == MemoryDependenceAnalysis::NonLocal) + return false; + + StoreInst* dependency = dyn_cast(dep); + if (!dependency) + return false; + + Value* depPointer = dependency->getPointerOperand(); + unsigned depPointerSize = TD.getTypeSize(dependency->getOperand(0)->getType()); + + // 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(dependency->getOperand(0))) + possiblyDead.insert(D); + if (Instruction* D = dyn_cast(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 +bool FDSE::handleEndBlock(BasicBlock& BB, SetVector& possiblyDead) { + TargetData &TD = getAnalysis(); + AliasAnalysis &AA = getAnalysis(); + MemoryDependenceAnalysis& MD = 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); + + // Scan the basic block backwards + for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ){ + --BBI; + + if (deadPointers.empty()) + break; + + Value* killPointer = 0; + unsigned killPointerSize = 0; + + // If we find a store whose pointer is dead... + if (StoreInst* S = dyn_cast(BBI)) { + Value* pointerOperand = S->getPointerOperand(); + // See through pointer-to-pointer bitcasts + TranslatePointerBitCasts(pointerOperand); + + if (deadPointers.count(pointerOperand)){ + // Remove it! + MD.removeInstruction(S); + + // DCE instructions only used to calculate that store + if (Instruction* D = dyn_cast(S->getOperand(0))) + possiblyDead.insert(D); + if (Instruction* D = dyn_cast(S->getOperand(1))) + possiblyDead.insert(D); + + BBI++; + S->eraseFromParent(); + NumFastStores++; + MadeChange = true; + } + + // If we encounter a use of the pointer, it is no longer considered dead + } else if (LoadInst* L = dyn_cast(BBI)) { + killPointer = L->getPointerOperand(); + killPointerSize = TD.getTypeSize(L->getType()); + } else if (VAArgInst* V = dyn_cast(BBI)) { + killPointer = V->getOperand(0); + killPointerSize = TD.getTypeSize(V->getType()); + } else if (FreeInst* F = dyn_cast(BBI)) { + killPointer = F->getPointerOperand(); + killPointerSize = ~0UL; + } else if (AllocaInst* A = dyn_cast(BBI)) { + deadPointers.erase(A); + continue; + } else if (CallSite::get(BBI).getInstruction() != 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) { + // Get size information for the alloca + unsigned pointerSize = ~0UL; + if (ConstantInt* C = dyn_cast((*I)->getArraySize())) + pointerSize = C->getZExtValue() * TD.getTypeSize((*I)->getAllocatedType()); + + // See if the call site touches it + AliasAnalysis::ModRefResult A = AA.getModRefInfo(CallSite::get(BBI), + *I, pointerSize); + 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; + } + + if (!killPointer) + continue; + + // Deal with undead pointers + MadeChange |= RemoveUndeadPointers(killPointer, killPointerSize, BBI, + deadPointers, possiblyDead); + } + + return MadeChange; +} + +bool FDSE::RemoveUndeadPointers(Value* killPointer, unsigned killPointerSize, + BasicBlock::iterator& BBI, + SmallPtrSet& deadPointers, + SetVector& possiblyDead) { + TargetData &TD = getAnalysis(); + AliasAnalysis &AA = getAnalysis(); + MemoryDependenceAnalysis& MD = getAnalysis(); + + bool MadeChange = false; + + std::vector undead; + + for (SmallPtrSet::iterator I = deadPointers.begin(), + E = deadPointers.end(); I != E; ++I) { + // Get size information for the alloca + unsigned pointerSize = ~0UL; + if (ConstantInt* C = dyn_cast((*I)->getArraySize())) + pointerSize = C->getZExtValue() * TD.getTypeSize((*I)->getAllocatedType()); + + // 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! + MD.removeInstruction(S); + + // DCE instructions only used to calculate that store + if (Instruction* D = dyn_cast(S->getOperand(0))) + possiblyDead.insert(D); + if (Instruction* D = dyn_cast(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::iterator I = undead.begin(), E = undead.end(); + I != E; ++I) + deadPointers.erase(*I); + + return MadeChange; +} + +void FDSE::DeleteDeadInstructionChains(Instruction *I, + SetVector &DeadInsts) { + // Instruction must be dead. + if (!I->use_empty() || !isInstructionTriviallyDead(I)) return; + + // Let the memory dependence know + getAnalysis().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(I->getOperand(i))) + DeadInsts.insert(Op); // Attempt to nuke it later. + + I->setOperand(i, 0); // Drop from the operand list. + } + + I->eraseFromParent(); + ++NumFastOther; +} diff --git a/lib/Transforms/Scalar/FastDSE.cpp b/lib/Transforms/Scalar/FastDSE.cpp deleted file mode 100644 index abc0adec354..00000000000 --- a/lib/Transforms/Scalar/FastDSE.cpp +++ /dev/null @@ -1,387 +0,0 @@ -//===- FastDSE.cpp - Fast Dead Store Elimination --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Owen Anderson and 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 "fdse" -#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 FDSE : public FunctionPass { - static char ID; // Pass identification, replacement for typeid - FDSE() : 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& possiblyDead); - bool handleEndBlock(BasicBlock& BB, SetVector& possiblyDead); - bool RemoveUndeadPointers(Value* pointer, unsigned pointerSize, - BasicBlock::iterator& BBI, - SmallPtrSet& deadPointers, - SetVector& possiblyDead); - void DeleteDeadInstructionChains(Instruction *I, - SetVector &DeadInsts); - void TranslatePointerBitCasts(Value*& v) { - assert(isa(v->getType()) && "Translating a non-pointer type?"); - - // See through pointer-to-pointer bitcasts - while (isa(v) || isa(v)) - if (BitCastInst* C = dyn_cast(v)) - v = C->getOperand(0); - else if (GetElementPtrInst* G = dyn_cast(v)) - v = G->getOperand(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(); - } - }; - char FDSE::ID = 0; - RegisterPass X("fdse", "Fast Dead Store Elimination"); -} - -FunctionPass *llvm::createFastDeadStoreEliminationPass() { return new FDSE(); } - -bool FDSE::runOnBasicBlock(BasicBlock &BB) { - MemoryDependenceAnalysis& MD = getAnalysis(); - - // Record the last-seen store to this pointer - DenseMap lastStore; - // Record instructions possibly made dead by deleting a store - SetVector 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(BBI) || isa(BBI)) { - Value* pointer = 0; - if (StoreInst* S = dyn_cast(BBI)) - pointer = S->getPointerOperand(); - else if (FreeInst* F = dyn_cast(BBI)) - pointer = F->getPointerOperand(); - - assert(pointer && "Not a free or a store?"); - - 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(dep)) { - if (dep == last) { - - // Remove it! - MD.removeInstruction(last); - - // DCE instructions only used to calculate that store - if (Instruction* D = dyn_cast(last->getOperand(0))) - possiblyDead.insert(D); - if (Instruction* D = dyn_cast(last->getOperand(1))) - possiblyDead.insert(D); - - last->eraseFromParent(); - NumFastStores++; - deletedStore = true; - MadeChange = true; - - break; - } else { - dep = MD.getDependency(BBI, dep); - } - } - } - - // Handle frees whose dependencies are non-trivial - if (FreeInst* F = dyn_cast(BBI)) - if (!deletedStore) - MadeChange |= handleFreeWithNonTrivialDependency(F, MD.getDependency(F), - possiblyDead); - - // Update our most-recent-store map - if (StoreInst* S = dyn_cast(BBI)) - last = S; - else - last = 0; - } - } - - // 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 FDSE::handleFreeWithNonTrivialDependency(FreeInst* F, Instruction* dep, - SetVector& possiblyDead) { - TargetData &TD = getAnalysis(); - AliasAnalysis &AA = getAnalysis(); - MemoryDependenceAnalysis& MD = getAnalysis(); - - if (dep == MemoryDependenceAnalysis::None || - dep == MemoryDependenceAnalysis::NonLocal) - return false; - - StoreInst* dependency = dyn_cast(dep); - if (!dependency) - return false; - - Value* depPointer = dependency->getPointerOperand(); - unsigned depPointerSize = TD.getTypeSize(dependency->getOperand(0)->getType()); - - // 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(dependency->getOperand(0))) - possiblyDead.insert(D); - if (Instruction* D = dyn_cast(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 -bool FDSE::handleEndBlock(BasicBlock& BB, SetVector& possiblyDead) { - TargetData &TD = getAnalysis(); - AliasAnalysis &AA = getAnalysis(); - MemoryDependenceAnalysis& MD = 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); - - // Scan the basic block backwards - for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ){ - --BBI; - - if (deadPointers.empty()) - break; - - Value* killPointer = 0; - unsigned killPointerSize = 0; - - // If we find a store whose pointer is dead... - if (StoreInst* S = dyn_cast(BBI)) { - Value* pointerOperand = S->getPointerOperand(); - // See through pointer-to-pointer bitcasts - TranslatePointerBitCasts(pointerOperand); - - if (deadPointers.count(pointerOperand)){ - // Remove it! - MD.removeInstruction(S); - - // DCE instructions only used to calculate that store - if (Instruction* D = dyn_cast(S->getOperand(0))) - possiblyDead.insert(D); - if (Instruction* D = dyn_cast(S->getOperand(1))) - possiblyDead.insert(D); - - BBI++; - S->eraseFromParent(); - NumFastStores++; - MadeChange = true; - } - - // If we encounter a use of the pointer, it is no longer considered dead - } else if (LoadInst* L = dyn_cast(BBI)) { - killPointer = L->getPointerOperand(); - killPointerSize = TD.getTypeSize(L->getType()); - } else if (VAArgInst* V = dyn_cast(BBI)) { - killPointer = V->getOperand(0); - killPointerSize = TD.getTypeSize(V->getType()); - } else if (FreeInst* F = dyn_cast(BBI)) { - killPointer = F->getPointerOperand(); - killPointerSize = ~0UL; - } else if (AllocaInst* A = dyn_cast(BBI)) { - deadPointers.erase(A); - continue; - } else if (CallSite::get(BBI).getInstruction() != 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) { - // Get size information for the alloca - unsigned pointerSize = ~0UL; - if (ConstantInt* C = dyn_cast((*I)->getArraySize())) - pointerSize = C->getZExtValue() * TD.getTypeSize((*I)->getAllocatedType()); - - // See if the call site touches it - AliasAnalysis::ModRefResult A = AA.getModRefInfo(CallSite::get(BBI), - *I, pointerSize); - 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; - } - - if (!killPointer) - continue; - - // Deal with undead pointers - MadeChange |= RemoveUndeadPointers(killPointer, killPointerSize, BBI, - deadPointers, possiblyDead); - } - - return MadeChange; -} - -bool FDSE::RemoveUndeadPointers(Value* killPointer, unsigned killPointerSize, - BasicBlock::iterator& BBI, - SmallPtrSet& deadPointers, - SetVector& possiblyDead) { - TargetData &TD = getAnalysis(); - AliasAnalysis &AA = getAnalysis(); - MemoryDependenceAnalysis& MD = getAnalysis(); - - bool MadeChange = false; - - std::vector undead; - - for (SmallPtrSet::iterator I = deadPointers.begin(), - E = deadPointers.end(); I != E; ++I) { - // Get size information for the alloca - unsigned pointerSize = ~0UL; - if (ConstantInt* C = dyn_cast((*I)->getArraySize())) - pointerSize = C->getZExtValue() * TD.getTypeSize((*I)->getAllocatedType()); - - // 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! - MD.removeInstruction(S); - - // DCE instructions only used to calculate that store - if (Instruction* D = dyn_cast(S->getOperand(0))) - possiblyDead.insert(D); - if (Instruction* D = dyn_cast(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::iterator I = undead.begin(), E = undead.end(); - I != E; ++I) - deadPointers.erase(*I); - - return MadeChange; -} - -void FDSE::DeleteDeadInstructionChains(Instruction *I, - SetVector &DeadInsts) { - // Instruction must be dead. - if (!I->use_empty() || !isInstructionTriviallyDead(I)) return; - - // Let the memory dependence know - getAnalysis().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(I->getOperand(i))) - DeadInsts.insert(Op); // Attempt to nuke it later. - - I->setOperand(i, 0); // Drop from the operand list. - } - - I->eraseFromParent(); - ++NumFastOther; -}