58#define DEBUG_TYPE "adce"
60STATISTIC(NumRemoved,
"Number of instructions removed");
61STATISTIC(NumBranchesRemoved,
"Number of branch instructions removed");
81 struct BlockInfoType *
Block =
nullptr;
90 bool UnconditionalBranch =
false;
93 bool HasLivePhiNodes =
false;
100 InstInfoType *TerminatorLiveInfo =
nullptr;
111 bool terminatorIsLive()
const {
return TerminatorLiveInfo->Live; }
115 bool ChangedAnything =
false;
116 bool ChangedNonDebugInstr =
false;
117 bool ChangedControlFlow =
false;
120class AggressiveDeadCodeElimination {
126 PostDominatorTree &PDT;
130 MapVector<BasicBlock *, BlockInfoType> BlockInfo;
131 bool isLive(BasicBlock *BB) {
return BlockInfo[BB].Live; }
134 DenseMap<Instruction *, InstInfoType> InstInfo;
135 bool isLive(Instruction *
I) {
return InstInfo[
I].Live; }
142 SmallPtrSet<const Metadata *, 32> AliveScopes;
145 SmallSetVector<BasicBlock *, 16> BlocksWithDeadTerminators;
150 SmallPtrSet<BasicBlock *, 16> NewLiveBlocks;
160 bool isInstrumentsConstant(Instruction &
I);
163 void markLiveInstructions();
166 void markLive(Instruction *
I);
169 void markLive(BlockInfoType &BB);
170 void markLive(BasicBlock *BB) { markLive(BlockInfo[BB]); }
173 void markPhiLive(PHINode *PN);
176 void collectLiveScopes(
const DILocalScope &LS);
177 void collectLiveScopes(
const DILocation &
DL);
182 void markLiveBranchesFromControlDependences();
186 ADCEChanged removeDeadInstructions();
190 bool updateDeadRegions();
194 void computeReversePostOrder();
197 void makeUnconditional(BasicBlock *BB, BasicBlock *Target);
200 AggressiveDeadCodeElimination(Function &F, DominatorTree *DT,
201 PostDominatorTree &PDT)
202 : F(F), DT(DT), PDT(PDT) {}
204 ADCEChanged performDeadCodeElimination();
209ADCEChanged AggressiveDeadCodeElimination::performDeadCodeElimination() {
211 markLiveInstructions();
212 return removeDeadInstructions();
215void AggressiveDeadCodeElimination::initialize() {
216 auto NumBlocks =
F.size();
220 BlockInfo.reserve(NumBlocks);
226 NumInsts += BB.size();
227 auto &
Info = BlockInfo[&BB];
229 Info.Terminator = BB.getTerminator();
234 InstInfo.reserve(NumInsts);
235 for (
auto &BBInfo : BlockInfo)
236 for (Instruction &
I : *BBInfo.second.BB)
237 InstInfo[&
I].Block = &BBInfo.second;
241 for (
auto &BBInfo : BlockInfo)
242 BBInfo.second.TerminatorLiveInfo = &InstInfo[BBInfo.second.Terminator];
257 using StatusMap = DenseMap<BasicBlock *, bool>;
259 class DFState :
public StatusMap {
261 std::pair<StatusMap::iterator, bool> insert(BasicBlock *BB) {
262 return StatusMap::insert(std::make_pair(BB,
true));
266 void completed(BasicBlock *BB) { (*this)[BB] =
false; }
270 bool onStack(BasicBlock *BB) {
271 auto Iter =
find(BB);
272 return Iter !=
end() && Iter->second;
276 State.reserve(
F.size());
286 if (State.onStack(Succ)) {
299 auto *BB = PDTChild->getBlock();
300 auto &
Info = BlockInfo[BB];
303 LLVM_DEBUG(
dbgs() <<
"post-dom root child is a return: " << BB->getName()
310 markLive(BlockInfo[DFNode->getBlock()].Terminator);
314 auto *BB = &
F.getEntryBlock();
315 auto &EntryInfo = BlockInfo[BB];
316 EntryInfo.Live =
true;
317 if (EntryInfo.UnconditionalBranch)
318 markLive(EntryInfo.Terminator);
321 for (
auto &BBInfo : BlockInfo)
322 if (!BBInfo.second.terminatorIsLive())
323 BlocksWithDeadTerminators.insert(BBInfo.second.BB);
326bool AggressiveDeadCodeElimination::isAlwaysLive(Instruction &
I) {
328 if (
I.isEHPad() ||
I.mayHaveSideEffects()) {
331 if (isInstrumentsConstant(
I))
335 if (!
I.isTerminator())
344bool AggressiveDeadCodeElimination::isInstrumentsConstant(Instruction &
I) {
347 if (Function *Callee = CI->getCalledFunction())
354void AggressiveDeadCodeElimination::markLiveInstructions() {
359 while (!Worklist.empty()) {
363 for (Use &OI : LiveInst->
operands())
373 markLiveBranchesFromControlDependences();
375 }
while (!Worklist.empty());
378void AggressiveDeadCodeElimination::markLive(Instruction *
I) {
379 auto &
Info = InstInfo[
I];
385 Worklist.push_back(
I);
388 if (
const DILocation *
DL =
I->getDebugLoc())
389 collectLiveScopes(*
DL);
392 auto &BBInfo = *
Info.Block;
393 if (BBInfo.Terminator ==
I) {
394 BlocksWithDeadTerminators.remove(BBInfo.BB);
397 if (!BBInfo.UnconditionalBranch)
404void AggressiveDeadCodeElimination::markLive(BlockInfoType &BBInfo) {
409 if (!BBInfo.CFLive) {
410 BBInfo.CFLive =
true;
411 NewLiveBlocks.insert(BBInfo.BB);
416 if (BBInfo.UnconditionalBranch)
417 markLive(BBInfo.Terminator);
420void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocalScope &LS) {
421 if (!AliveScopes.insert(&LS).second)
431void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocation &
DL) {
434 if (!AliveScopes.insert(&
DL).second)
438 collectLiveScopes(*
DL.getScope());
441 if (
const DILocation *IA =
DL.getInlinedAt())
442 collectLiveScopes(*IA);
445void AggressiveDeadCodeElimination::markPhiLive(PHINode *PN) {
448 if (
Info.HasLivePhiNodes)
450 Info.HasLivePhiNodes =
true;
456 auto &
Info = BlockInfo[PredBB];
459 NewLiveBlocks.insert(PredBB);
464void AggressiveDeadCodeElimination::markLiveBranchesFromControlDependences() {
465 if (BlocksWithDeadTerminators.empty())
469 dbgs() <<
"new live blocks:\n";
470 for (
auto *BB : NewLiveBlocks)
471 dbgs() <<
"\t" << BB->getName() <<
'\n';
472 dbgs() <<
"dead terminator blocks:\n";
473 for (
auto *BB : BlocksWithDeadTerminators)
474 dbgs() <<
"\t" << BB->getName() <<
'\n';
484 BlocksWithDeadTerminators);
487 IDFs.setDefiningBlocks(NewLiveBlocks);
488 IDFs.setLiveInBlocks(BWDT);
489 IDFs.calculate(IDFBlocks);
490 NewLiveBlocks.clear();
493 for (
auto *BB : IDFBlocks) {
494 LLVM_DEBUG(
dbgs() <<
"live control in: " << BB->getName() <<
'\n');
495 markLive(BB->getTerminator());
504ADCEChanged AggressiveDeadCodeElimination::removeDeadInstructions() {
507 Changed.ChangedControlFlow = updateDeadRegions();
517 if (AliveScopes.count(DII->getDebugLoc()->getScope()))
523 for (
Value *V : DII->location_ops()) {
526 dbgs() <<
"Dropping debug info for " << *DII <<
"\n";
548 DVR && DVR->isDbgAssign())
551 if (AliveScopes.count(DR.getDebugLoc()->getScope()))
553 I.dropOneDbgRecord(&DR);
560 Changed.ChangedNonDebugInstr =
true;
563 Worklist.push_back(&
I);
567 for (Instruction *&
I : Worklist)
568 I->dropAllReferences();
570 for (Instruction *&
I : Worklist) {
572 I->eraseFromParent();
575 Changed.ChangedAnything =
Changed.ChangedControlFlow || !Worklist.empty();
581bool AggressiveDeadCodeElimination::updateDeadRegions() {
583 dbgs() <<
"final dead terminator blocks: " <<
'\n';
584 for (
auto *BB : BlocksWithDeadTerminators)
585 dbgs() <<
'\t' << BB->getName()
586 << (BlockInfo[BB].Live ?
" LIVE\n" :
"\n");
590 bool HavePostOrder =
false;
594 for (
auto *BB : BlocksWithDeadTerminators) {
595 auto &
Info = BlockInfo[BB];
596 if (
Info.UnconditionalBranch) {
597 InstInfo[
Info.Terminator].Live =
true;
601 if (!HavePostOrder) {
602 computeReversePostOrder();
603 HavePostOrder =
true;
609 BlockInfoType *PreferredSucc =
nullptr;
611 auto *
Info = &BlockInfo[Succ];
612 if (!PreferredSucc || PreferredSucc->PostOrder <
Info->PostOrder)
613 PreferredSucc =
Info;
615 assert((PreferredSucc && PreferredSucc->PostOrder > 0) &&
616 "Failed to find safe successor for dead branch");
619 SmallPtrSet<BasicBlock *, 4> RemovedSuccessors;
622 if (!
First || Succ != PreferredSucc->BB) {
623 Succ->removePredecessor(BB);
624 RemovedSuccessors.
insert(Succ);
628 makeUnconditional(BB, PreferredSucc->BB);
631 for (
auto *Succ : RemovedSuccessors) {
634 if (Succ != PreferredSucc->BB) {
635 LLVM_DEBUG(
dbgs() <<
"ADCE: (Post)DomTree edge enqueued for deletion"
636 << BB->getName() <<
" -> " << Succ->getName()
638 DeletedEdges.
push_back({DominatorTree::Delete, BB, Succ});
642 NumBranchesRemoved += 1;
646 if (!DeletedEdges.
empty())
647 DomTreeUpdater(DT, &PDT, DomTreeUpdater::UpdateStrategy::Eager)
648 .applyUpdates(DeletedEdges);
654void AggressiveDeadCodeElimination::computeReversePostOrder() {
662 SmallPtrSet<BasicBlock*, 16> Visited;
663 unsigned PostOrder = 0;
668 BlockInfo[
Block].PostOrder = PostOrder++;
672void AggressiveDeadCodeElimination::makeUnconditional(BasicBlock *BB,
673 BasicBlock *Target) {
677 collectLiveScopes(*
DL);
681 BI->setSuccessor(Target);
682 InstInfo[PredTerm].Live =
true;
686 NumBranchesRemoved += 1;
688 auto *NewTerm = Builder.CreateBr(Target);
689 InstInfo[NewTerm].Live =
true;
691 NewTerm->setDebugLoc(
DL);
693 InstInfo.erase(PredTerm);
708 AggressiveDeadCodeElimination(
F, DT, PDT).performDeadCodeElimination();
713 if (!
Changed.ChangedControlFlow) {
715 if (!
Changed.ChangedNonDebugInstr) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< bool > RemoveLoops("adce-remove-loops", cl::init(false), cl::Hidden)
static cl::opt< bool > RemoveControlFlowFlag("adce-remove-control-flow", cl::init(true), cl::Hidden)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static bool isAlwaysLive(Instruction *I)
This file defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
This is the interface for a simple mod/ref and alias analysis over globals.
This file defines the little GraphTraits<X> template class that should be specialized by classes that...
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
This file implements a map that provides insertion order iteration.
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Represents analyses that only rely on functions' control flow.
Analysis pass which computes a DominatorTree.
DomTreeNodeBase< NodeT > * getRootNode()
getRootNode - This returns the entry node for the CFG of the function.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
An analysis that produces MemorySSA for a function.
Analysis pass which computes a PostDominatorTree.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void push_back(const T &Elt)
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void dump() const
Support for debugging, callable in GDB: V->dump()
const ParentTy * getParent() const
@ BasicBlock
Various leaf nodes.
LLVM_ABI AssignmentInstRange getAssignmentInsts(DIAssignID *ID)
Return a range of instructions (typically just one) that have ID as an attachment.
initializer< Ty > init(const Ty &Val)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< df_ext_iterator< T, SetTy > > depth_first_ext(const T &G, SetTy &S)
FunctionAddr VTableAddr Value
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool succ_empty(const Instruction *I)
iterator_range< ipo_ext_iterator< T, SetType > > inverse_post_order_ext(const T &G, SetType &S)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
auto successors(const MachineBasicBlock *BB)
constexpr from_range_t from_range
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
auto reverse(ContainerTy &&C)
IDFCalculator< true > ReverseIDFCalculator
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto predecessors(const MachineBasicBlock *BB)
StringRef getInstrProfValueProfFuncName()
Return the name profile runtime entry point to do value profiling for a given site.
iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &)