| //===- ADCE.cpp - Code to perform dead code 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 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/SmallPtrSet.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/Statistic.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/IRBuilder.h" |
| #include "llvm/IR/Function.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(). |
| TerminatorInst *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. |
| SmallPtrSet<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(TerminatorInst *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)) { |
| TerminatorInst *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 (!isa<TerminatorInst>(I)) |
| 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.erase(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. |
| |
| SmallVector<BasicBlock *, 32> IDFBlocks; |
| ReverseIDFCalculator IDFs(PDT); |
| IDFs.setDefiningBlocks(NewLiveBlocks); |
| IDFs.setLiveInBlocks(BlocksWithDeadTerminators); |
| 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<DbgInfoIntrinsic>(&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}); |
| } |
| } |
| |
| DT.applyUpdates(DeletedEdges); |
| PDT.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) { |
| TerminatorInst *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) { |
| auto &DT = FAM.getResult<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; |
| |
| auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); |
| auto &PDT = getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree(); |
| return AggressiveDeadCodeElimination(F, DT, PDT) |
| .performDeadCodeElimination(); |
| } |
| |
| void getAnalysisUsage(AnalysisUsage &AU) const override { |
| // We require DominatorTree here only to update and thus preserve it. |
| AU.addRequired<DominatorTreeWrapperPass>(); |
| 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(DominatorTreeWrapperPass) |
| INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass) |
| INITIALIZE_PASS_END(ADCELegacyPass, "adce", "Aggressive Dead Code Elimination", |
| false, false) |
| |
| FunctionPass *llvm::createAggressiveDCEPass() { return new ADCELegacyPass(); } |