diff options
Diffstat (limited to 'contrib/llvm/lib/Transforms/Scalar/ADCE.cpp')
| -rw-r--r-- | contrib/llvm/lib/Transforms/Scalar/ADCE.cpp | 738 |
1 files changed, 0 insertions, 738 deletions
diff --git a/contrib/llvm/lib/Transforms/Scalar/ADCE.cpp b/contrib/llvm/lib/Transforms/Scalar/ADCE.cpp deleted file mode 100644 index 7f7460c5746a..000000000000 --- a/contrib/llvm/lib/Transforms/Scalar/ADCE.cpp +++ /dev/null @@ -1,738 +0,0 @@ -//===- ADCE.cpp - Code to perform dead code elimination -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the Aggressive Dead Code Elimination pass. This pass -// optimistically assumes that all instructions are dead until proven otherwise, -// allowing it to eliminate dead computations that other DCE passes do not -// catch, particularly involving loop computations. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Transforms/Scalar/ADCE.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DepthFirstIterator.h" -#include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/PostOrderIterator.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/DomTreeUpdater.h" -#include "llvm/Analysis/GlobalsModRef.h" -#include "llvm/Analysis/IteratedDominanceFrontier.h" -#include "llvm/Analysis/PostDominators.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CFG.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/PassManager.h" -#include "llvm/IR/Use.h" -#include "llvm/IR/Value.h" -#include "llvm/Pass.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Scalar.h" -#include <cassert> -#include <cstddef> -#include <utility> - -using namespace llvm; - -#define DEBUG_TYPE "adce" - -STATISTIC(NumRemoved, "Number of instructions removed"); -STATISTIC(NumBranchesRemoved, "Number of branch instructions removed"); - -// This is a temporary option until we change the interface to this pass based -// on optimization level. -static cl::opt<bool> RemoveControlFlowFlag("adce-remove-control-flow", - cl::init(true), cl::Hidden); - -// This option enables removing of may-be-infinite loops which have no other -// effect. -static cl::opt<bool> RemoveLoops("adce-remove-loops", cl::init(false), - cl::Hidden); - -namespace { - -/// Information about Instructions -struct InstInfoType { - /// True if the associated instruction is live. - bool Live = false; - - /// Quick access to information for block containing associated Instruction. - struct BlockInfoType *Block = nullptr; -}; - -/// Information about basic blocks relevant to dead code elimination. -struct BlockInfoType { - /// True when this block contains a live instructions. - bool Live = false; - - /// True when this block ends in an unconditional branch. - bool UnconditionalBranch = false; - - /// True when this block is known to have live PHI nodes. - bool HasLivePhiNodes = false; - - /// Control dependence sources need to be live for this block. - bool CFLive = false; - - /// Quick access to the LiveInfo for the terminator, - /// holds the value &InstInfo[Terminator] - InstInfoType *TerminatorLiveInfo = nullptr; - - /// Corresponding BasicBlock. - BasicBlock *BB = nullptr; - - /// Cache of BB->getTerminator(). - Instruction *Terminator = nullptr; - - /// Post-order numbering of reverse control flow graph. - unsigned PostOrder; - - bool terminatorIsLive() const { return TerminatorLiveInfo->Live; } -}; - -class AggressiveDeadCodeElimination { - Function &F; - - // ADCE does not use DominatorTree per se, but it updates it to preserve the - // analysis. - DominatorTree *DT; - PostDominatorTree &PDT; - - /// Mapping of blocks to associated information, an element in BlockInfoVec. - /// Use MapVector to get deterministic iteration order. - MapVector<BasicBlock *, BlockInfoType> BlockInfo; - bool isLive(BasicBlock *BB) { return BlockInfo[BB].Live; } - - /// Mapping of instructions to associated information. - DenseMap<Instruction *, InstInfoType> InstInfo; - bool isLive(Instruction *I) { return InstInfo[I].Live; } - - /// Instructions known to be live where we need to mark - /// reaching definitions as live. - SmallVector<Instruction *, 128> Worklist; - - /// Debug info scopes around a live instruction. - SmallPtrSet<const Metadata *, 32> AliveScopes; - - /// Set of blocks with not known to have live terminators. - SmallSetVector<BasicBlock *, 16> BlocksWithDeadTerminators; - - /// The set of blocks which we have determined whose control - /// dependence sources must be live and which have not had - /// those dependences analyzed. - SmallPtrSet<BasicBlock *, 16> NewLiveBlocks; - - /// Set up auxiliary data structures for Instructions and BasicBlocks and - /// initialize the Worklist to the set of must-be-live Instruscions. - void initialize(); - - /// Return true for operations which are always treated as live. - bool isAlwaysLive(Instruction &I); - - /// Return true for instrumentation instructions for value profiling. - bool isInstrumentsConstant(Instruction &I); - - /// Propagate liveness to reaching definitions. - void markLiveInstructions(); - - /// Mark an instruction as live. - void markLive(Instruction *I); - - /// Mark a block as live. - void markLive(BlockInfoType &BB); - void markLive(BasicBlock *BB) { markLive(BlockInfo[BB]); } - - /// Mark terminators of control predecessors of a PHI node live. - void markPhiLive(PHINode *PN); - - /// Record the Debug Scopes which surround live debug information. - void collectLiveScopes(const DILocalScope &LS); - void collectLiveScopes(const DILocation &DL); - - /// Analyze dead branches to find those whose branches are the sources - /// of control dependences impacting a live block. Those branches are - /// marked live. - void markLiveBranchesFromControlDependences(); - - /// Remove instructions not marked live, return if any instruction was - /// removed. - bool removeDeadInstructions(); - - /// Identify connected sections of the control flow graph which have - /// dead terminators and rewrite the control flow graph to remove them. - void updateDeadRegions(); - - /// Set the BlockInfo::PostOrder field based on a post-order - /// numbering of the reverse control flow graph. - void computeReversePostOrder(); - - /// Make the terminator of this block an unconditional branch to \p Target. - void makeUnconditional(BasicBlock *BB, BasicBlock *Target); - -public: - AggressiveDeadCodeElimination(Function &F, DominatorTree *DT, - PostDominatorTree &PDT) - : F(F), DT(DT), PDT(PDT) {} - - bool performDeadCodeElimination(); -}; - -} // end anonymous namespace - -bool AggressiveDeadCodeElimination::performDeadCodeElimination() { - initialize(); - markLiveInstructions(); - return removeDeadInstructions(); -} - -static bool isUnconditionalBranch(Instruction *Term) { - auto *BR = dyn_cast<BranchInst>(Term); - return BR && BR->isUnconditional(); -} - -void AggressiveDeadCodeElimination::initialize() { - auto NumBlocks = F.size(); - - // We will have an entry in the map for each block so we grow the - // structure to twice that size to keep the load factor low in the hash table. - BlockInfo.reserve(NumBlocks); - size_t NumInsts = 0; - - // Iterate over blocks and initialize BlockInfoVec entries, count - // instructions to size the InstInfo hash table. - for (auto &BB : F) { - NumInsts += BB.size(); - auto &Info = BlockInfo[&BB]; - Info.BB = &BB; - Info.Terminator = BB.getTerminator(); - Info.UnconditionalBranch = isUnconditionalBranch(Info.Terminator); - } - - // Initialize instruction map and set pointers to block info. - InstInfo.reserve(NumInsts); - for (auto &BBInfo : BlockInfo) - for (Instruction &I : *BBInfo.second.BB) - InstInfo[&I].Block = &BBInfo.second; - - // Since BlockInfoVec holds pointers into InstInfo and vice-versa, we may not - // add any more elements to either after this point. - for (auto &BBInfo : BlockInfo) - BBInfo.second.TerminatorLiveInfo = &InstInfo[BBInfo.second.Terminator]; - - // Collect the set of "root" instructions that are known live. - for (Instruction &I : instructions(F)) - if (isAlwaysLive(I)) - markLive(&I); - - if (!RemoveControlFlowFlag) - return; - - if (!RemoveLoops) { - // This stores state for the depth-first iterator. In addition - // to recording which nodes have been visited we also record whether - // a node is currently on the "stack" of active ancestors of the current - // node. - using StatusMap = DenseMap<BasicBlock *, bool>; - - class DFState : public StatusMap { - public: - std::pair<StatusMap::iterator, bool> insert(BasicBlock *BB) { - return StatusMap::insert(std::make_pair(BB, true)); - } - - // Invoked after we have visited all children of a node. - void completed(BasicBlock *BB) { (*this)[BB] = false; } - - // Return true if \p BB is currently on the active stack - // of ancestors. - bool onStack(BasicBlock *BB) { - auto Iter = find(BB); - return Iter != end() && Iter->second; - } - } State; - - State.reserve(F.size()); - // Iterate over blocks in depth-first pre-order and - // treat all edges to a block already seen as loop back edges - // and mark the branch live it if there is a back edge. - for (auto *BB: depth_first_ext(&F.getEntryBlock(), State)) { - Instruction *Term = BB->getTerminator(); - if (isLive(Term)) - continue; - - for (auto *Succ : successors(BB)) - if (State.onStack(Succ)) { - // back edge.... - markLive(Term); - break; - } - } - } - - // Mark blocks live if there is no path from the block to a - // return of the function. - // We do this by seeing which of the postdomtree root children exit the - // program, and for all others, mark the subtree live. - for (auto &PDTChild : children<DomTreeNode *>(PDT.getRootNode())) { - auto *BB = PDTChild->getBlock(); - auto &Info = BlockInfo[BB]; - // Real function return - if (isa<ReturnInst>(Info.Terminator)) { - LLVM_DEBUG(dbgs() << "post-dom root child is a return: " << BB->getName() - << '\n';); - continue; - } - - // This child is something else, like an infinite loop. - for (auto DFNode : depth_first(PDTChild)) - markLive(BlockInfo[DFNode->getBlock()].Terminator); - } - - // Treat the entry block as always live - auto *BB = &F.getEntryBlock(); - auto &EntryInfo = BlockInfo[BB]; - EntryInfo.Live = true; - if (EntryInfo.UnconditionalBranch) - markLive(EntryInfo.Terminator); - - // Build initial collection of blocks with dead terminators - for (auto &BBInfo : BlockInfo) - if (!BBInfo.second.terminatorIsLive()) - BlocksWithDeadTerminators.insert(BBInfo.second.BB); -} - -bool AggressiveDeadCodeElimination::isAlwaysLive(Instruction &I) { - // TODO -- use llvm::isInstructionTriviallyDead - if (I.isEHPad() || I.mayHaveSideEffects()) { - // Skip any value profile instrumentation calls if they are - // instrumenting constants. - if (isInstrumentsConstant(I)) - return false; - return true; - } - if (!I.isTerminator()) - return false; - if (RemoveControlFlowFlag && (isa<BranchInst>(I) || isa<SwitchInst>(I))) - return false; - return true; -} - -// Check if this instruction is a runtime call for value profiling and -// if it's instrumenting a constant. -bool AggressiveDeadCodeElimination::isInstrumentsConstant(Instruction &I) { - // TODO -- move this test into llvm::isInstructionTriviallyDead - if (CallInst *CI = dyn_cast<CallInst>(&I)) - if (Function *Callee = CI->getCalledFunction()) - if (Callee->getName().equals(getInstrProfValueProfFuncName())) - if (isa<Constant>(CI->getArgOperand(0))) - return true; - return false; -} - -void AggressiveDeadCodeElimination::markLiveInstructions() { - // Propagate liveness backwards to operands. - do { - // Worklist holds newly discovered live instructions - // where we need to mark the inputs as live. - while (!Worklist.empty()) { - Instruction *LiveInst = Worklist.pop_back_val(); - LLVM_DEBUG(dbgs() << "work live: "; LiveInst->dump();); - - for (Use &OI : LiveInst->operands()) - if (Instruction *Inst = dyn_cast<Instruction>(OI)) - markLive(Inst); - - if (auto *PN = dyn_cast<PHINode>(LiveInst)) - markPhiLive(PN); - } - - // After data flow liveness has been identified, examine which branch - // decisions are required to determine live instructions are executed. - markLiveBranchesFromControlDependences(); - - } while (!Worklist.empty()); -} - -void AggressiveDeadCodeElimination::markLive(Instruction *I) { - auto &Info = InstInfo[I]; - if (Info.Live) - return; - - LLVM_DEBUG(dbgs() << "mark live: "; I->dump()); - Info.Live = true; - Worklist.push_back(I); - - // Collect the live debug info scopes attached to this instruction. - if (const DILocation *DL = I->getDebugLoc()) - collectLiveScopes(*DL); - - // Mark the containing block live - auto &BBInfo = *Info.Block; - if (BBInfo.Terminator == I) { - BlocksWithDeadTerminators.remove(BBInfo.BB); - // For live terminators, mark destination blocks - // live to preserve this control flow edges. - if (!BBInfo.UnconditionalBranch) - for (auto *BB : successors(I->getParent())) - markLive(BB); - } - markLive(BBInfo); -} - -void AggressiveDeadCodeElimination::markLive(BlockInfoType &BBInfo) { - if (BBInfo.Live) - return; - LLVM_DEBUG(dbgs() << "mark block live: " << BBInfo.BB->getName() << '\n'); - BBInfo.Live = true; - if (!BBInfo.CFLive) { - BBInfo.CFLive = true; - NewLiveBlocks.insert(BBInfo.BB); - } - - // Mark unconditional branches at the end of live - // blocks as live since there is no work to do for them later - if (BBInfo.UnconditionalBranch) - markLive(BBInfo.Terminator); -} - -void AggressiveDeadCodeElimination::collectLiveScopes(const DILocalScope &LS) { - if (!AliveScopes.insert(&LS).second) - return; - - if (isa<DISubprogram>(LS)) - return; - - // Tail-recurse through the scope chain. - collectLiveScopes(cast<DILocalScope>(*LS.getScope())); -} - -void AggressiveDeadCodeElimination::collectLiveScopes(const DILocation &DL) { - // Even though DILocations are not scopes, shove them into AliveScopes so we - // don't revisit them. - if (!AliveScopes.insert(&DL).second) - return; - - // Collect live scopes from the scope chain. - collectLiveScopes(*DL.getScope()); - - // Tail-recurse through the inlined-at chain. - if (const DILocation *IA = DL.getInlinedAt()) - collectLiveScopes(*IA); -} - -void AggressiveDeadCodeElimination::markPhiLive(PHINode *PN) { - auto &Info = BlockInfo[PN->getParent()]; - // Only need to check this once per block. - if (Info.HasLivePhiNodes) - return; - Info.HasLivePhiNodes = true; - - // If a predecessor block is not live, mark it as control-flow live - // which will trigger marking live branches upon which - // that block is control dependent. - for (auto *PredBB : predecessors(Info.BB)) { - auto &Info = BlockInfo[PredBB]; - if (!Info.CFLive) { - Info.CFLive = true; - NewLiveBlocks.insert(PredBB); - } - } -} - -void AggressiveDeadCodeElimination::markLiveBranchesFromControlDependences() { - if (BlocksWithDeadTerminators.empty()) - return; - - LLVM_DEBUG({ - dbgs() << "new live blocks:\n"; - for (auto *BB : NewLiveBlocks) - dbgs() << "\t" << BB->getName() << '\n'; - dbgs() << "dead terminator blocks:\n"; - for (auto *BB : BlocksWithDeadTerminators) - dbgs() << "\t" << BB->getName() << '\n'; - }); - - // The dominance frontier of a live block X in the reverse - // control graph is the set of blocks upon which X is control - // dependent. The following sequence computes the set of blocks - // which currently have dead terminators that are control - // dependence sources of a block which is in NewLiveBlocks. - - const SmallPtrSet<BasicBlock *, 16> BWDT{ - BlocksWithDeadTerminators.begin(), - BlocksWithDeadTerminators.end() - }; - SmallVector<BasicBlock *, 32> IDFBlocks; - ReverseIDFCalculator IDFs(PDT); - IDFs.setDefiningBlocks(NewLiveBlocks); - IDFs.setLiveInBlocks(BWDT); - IDFs.calculate(IDFBlocks); - NewLiveBlocks.clear(); - - // Dead terminators which control live blocks are now marked live. - for (auto *BB : IDFBlocks) { - LLVM_DEBUG(dbgs() << "live control in: " << BB->getName() << '\n'); - markLive(BB->getTerminator()); - } -} - -//===----------------------------------------------------------------------===// -// -// Routines to update the CFG and SSA information before removing dead code. -// -//===----------------------------------------------------------------------===// -bool AggressiveDeadCodeElimination::removeDeadInstructions() { - // Updates control and dataflow around dead blocks - updateDeadRegions(); - - LLVM_DEBUG({ - for (Instruction &I : instructions(F)) { - // Check if the instruction is alive. - if (isLive(&I)) - continue; - - if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) { - // Check if the scope of this variable location is alive. - if (AliveScopes.count(DII->getDebugLoc()->getScope())) - continue; - - // If intrinsic is pointing at a live SSA value, there may be an - // earlier optimization bug: if we know the location of the variable, - // why isn't the scope of the location alive? - if (Value *V = DII->getVariableLocation()) - if (Instruction *II = dyn_cast<Instruction>(V)) - if (isLive(II)) - dbgs() << "Dropping debug info for " << *DII << "\n"; - } - } - }); - - // The inverse of the live set is the dead set. These are those instructions - // that have no side effects and do not influence the control flow or return - // value of the function, and may therefore be deleted safely. - // NOTE: We reuse the Worklist vector here for memory efficiency. - for (Instruction &I : instructions(F)) { - // Check if the instruction is alive. - if (isLive(&I)) - continue; - - if (auto *DII = dyn_cast<DbgInfoIntrinsic>(&I)) { - // Check if the scope of this variable location is alive. - if (AliveScopes.count(DII->getDebugLoc()->getScope())) - continue; - - // Fallthrough and drop the intrinsic. - } - - // Prepare to delete. - Worklist.push_back(&I); - I.dropAllReferences(); - } - - for (Instruction *&I : Worklist) { - ++NumRemoved; - I->eraseFromParent(); - } - - return !Worklist.empty(); -} - -// A dead region is the set of dead blocks with a common live post-dominator. -void AggressiveDeadCodeElimination::updateDeadRegions() { - LLVM_DEBUG({ - dbgs() << "final dead terminator blocks: " << '\n'; - for (auto *BB : BlocksWithDeadTerminators) - dbgs() << '\t' << BB->getName() - << (BlockInfo[BB].Live ? " LIVE\n" : "\n"); - }); - - // Don't compute the post ordering unless we needed it. - bool HavePostOrder = false; - - for (auto *BB : BlocksWithDeadTerminators) { - auto &Info = BlockInfo[BB]; - if (Info.UnconditionalBranch) { - InstInfo[Info.Terminator].Live = true; - continue; - } - - if (!HavePostOrder) { - computeReversePostOrder(); - HavePostOrder = true; - } - - // Add an unconditional branch to the successor closest to the - // end of the function which insures a path to the exit for each - // live edge. - BlockInfoType *PreferredSucc = nullptr; - for (auto *Succ : successors(BB)) { - auto *Info = &BlockInfo[Succ]; - if (!PreferredSucc || PreferredSucc->PostOrder < Info->PostOrder) - PreferredSucc = Info; - } - assert((PreferredSucc && PreferredSucc->PostOrder > 0) && - "Failed to find safe successor for dead branch"); - - // Collect removed successors to update the (Post)DominatorTrees. - SmallPtrSet<BasicBlock *, 4> RemovedSuccessors; - bool First = true; - for (auto *Succ : successors(BB)) { - if (!First || Succ != PreferredSucc->BB) { - Succ->removePredecessor(BB); - RemovedSuccessors.insert(Succ); - } else - First = false; - } - makeUnconditional(BB, PreferredSucc->BB); - - // Inform the dominators about the deleted CFG edges. - SmallVector<DominatorTree::UpdateType, 4> DeletedEdges; - for (auto *Succ : RemovedSuccessors) { - // It might have happened that the same successor appeared multiple times - // and the CFG edge wasn't really removed. - if (Succ != PreferredSucc->BB) { - LLVM_DEBUG(dbgs() << "ADCE: (Post)DomTree edge enqueued for deletion" - << BB->getName() << " -> " << Succ->getName() - << "\n"); - DeletedEdges.push_back({DominatorTree::Delete, BB, Succ}); - } - } - - DomTreeUpdater(DT, &PDT, DomTreeUpdater::UpdateStrategy::Eager) - .applyUpdates(DeletedEdges); - - NumBranchesRemoved += 1; - } -} - -// reverse top-sort order -void AggressiveDeadCodeElimination::computeReversePostOrder() { - // This provides a post-order numbering of the reverse control flow graph - // Note that it is incomplete in the presence of infinite loops but we don't - // need numbers blocks which don't reach the end of the functions since - // all branches in those blocks are forced live. - - // For each block without successors, extend the DFS from the block - // backward through the graph - SmallPtrSet<BasicBlock*, 16> Visited; - unsigned PostOrder = 0; - for (auto &BB : F) { - if (succ_begin(&BB) != succ_end(&BB)) - continue; - for (BasicBlock *Block : inverse_post_order_ext(&BB,Visited)) - BlockInfo[Block].PostOrder = PostOrder++; - } -} - -void AggressiveDeadCodeElimination::makeUnconditional(BasicBlock *BB, - BasicBlock *Target) { - Instruction *PredTerm = BB->getTerminator(); - // Collect the live debug info scopes attached to this instruction. - if (const DILocation *DL = PredTerm->getDebugLoc()) - collectLiveScopes(*DL); - - // Just mark live an existing unconditional branch - if (isUnconditionalBranch(PredTerm)) { - PredTerm->setSuccessor(0, Target); - InstInfo[PredTerm].Live = true; - return; - } - LLVM_DEBUG(dbgs() << "making unconditional " << BB->getName() << '\n'); - NumBranchesRemoved += 1; - IRBuilder<> Builder(PredTerm); - auto *NewTerm = Builder.CreateBr(Target); - InstInfo[NewTerm].Live = true; - if (const DILocation *DL = PredTerm->getDebugLoc()) - NewTerm->setDebugLoc(DL); - - InstInfo.erase(PredTerm); - PredTerm->eraseFromParent(); -} - -//===----------------------------------------------------------------------===// -// -// Pass Manager integration code -// -//===----------------------------------------------------------------------===// -PreservedAnalyses ADCEPass::run(Function &F, FunctionAnalysisManager &FAM) { - // ADCE does not need DominatorTree, but require DominatorTree here - // to update analysis if it is already available. - auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(F); - auto &PDT = FAM.getResult<PostDominatorTreeAnalysis>(F); - if (!AggressiveDeadCodeElimination(F, DT, PDT).performDeadCodeElimination()) - return PreservedAnalyses::all(); - - PreservedAnalyses PA; - PA.preserveSet<CFGAnalyses>(); - PA.preserve<GlobalsAA>(); - PA.preserve<DominatorTreeAnalysis>(); - PA.preserve<PostDominatorTreeAnalysis>(); - return PA; -} - -namespace { - -struct ADCELegacyPass : public FunctionPass { - static char ID; // Pass identification, replacement for typeid - - ADCELegacyPass() : FunctionPass(ID) { - initializeADCELegacyPassPass(*PassRegistry::getPassRegistry()); - } - - bool runOnFunction(Function &F) override { - if (skipFunction(F)) - return false; - - // ADCE does not need DominatorTree, but require DominatorTree here - // to update analysis if it is already available. - auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>(); - auto *DT = DTWP ? &DTWP->getDomTree() : nullptr; - auto &PDT = getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree(); - return AggressiveDeadCodeElimination(F, DT, PDT) - .performDeadCodeElimination(); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<PostDominatorTreeWrapperPass>(); - if (!RemoveControlFlowFlag) - AU.setPreservesCFG(); - else { - AU.addPreserved<DominatorTreeWrapperPass>(); - AU.addPreserved<PostDominatorTreeWrapperPass>(); - } - AU.addPreserved<GlobalsAAWrapperPass>(); - } -}; - -} // end anonymous namespace - -char ADCELegacyPass::ID = 0; - -INITIALIZE_PASS_BEGIN(ADCELegacyPass, "adce", - "Aggressive Dead Code Elimination", false, false) -INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass) -INITIALIZE_PASS_END(ADCELegacyPass, "adce", "Aggressive Dead Code Elimination", - false, false) - -FunctionPass *llvm::createAggressiveDCEPass() { return new ADCELegacyPass(); } |
