57#define DEBUG_TYPE "adce"
59STATISTIC(NumRemoved,
"Number of instructions removed");
60STATISTIC(NumBranchesRemoved,
"Number of branch instructions removed");
70 bool HasLivePhiNodes =
false;
76 unsigned PostOrder = 0;
80 bool ChangedAnything =
false;
81 bool ChangedNonDebugInstr =
false;
82 bool ChangedControlFlow =
false;
85class AggressiveDeadCodeElimination {
86 const ScalarOptions &Opts;
92 PostDominatorTree &PDT;
98 SmallPtrSet<Instruction *, 32> LiveInst;
99 bool isLive(Instruction *
I) {
return LiveInst.contains(
I); }
106 SmallPtrSet<const Metadata *, 32> AliveScopes;
109 SmallSetVector<BasicBlock *, 16> BlocksWithDeadTerminators;
114 SmallPtrSet<BasicBlock *, 16> NewLiveBlocks;
120 BlockInfoType &getBlockInfo(BasicBlock *BB) {
128 bool isInstrumentsConstant(Instruction &
I);
131 void markLiveInstructions();
134 void markLive(Instruction *
I);
137 void markLive(BasicBlock *BB);
140 void markPhiLive(PHINode *PN);
143 void collectLiveScopes(
const DILocalScope &LS);
144 void collectLiveScopes(
const DILocation &
DL);
149 void markLiveBranchesFromControlDependences();
153 ADCEChanged removeDeadInstructions();
157 bool updateDeadRegions();
161 void computeReversePostOrder();
164 void makeUnconditional(BasicBlock *BB, BasicBlock *Target);
167 AggressiveDeadCodeElimination(
Function &F, DominatorTree *DT,
168 PostDominatorTree &PDT)
169 : Opts(ScalarOptions::
Global), F(F), DT(DT), PDT(PDT) {}
171 ADCEChanged performDeadCodeElimination();
176ADCEChanged AggressiveDeadCodeElimination::performDeadCodeElimination() {
178 markLiveInstructions();
179 return removeDeadInstructions();
182void AggressiveDeadCodeElimination::initialize() {
183 BlockInfo.
resize(
F.getMaxBlockNumber());
186 NumInsts += BB.size();
194 if (!Opts.adce_remove_control_flow)
197 if (!Opts.adce_remove_loops) {
201 for (
const auto &[Src, Dst] : Backedges)
202 markLive(
const_cast<Instruction *
>(Src->getTerminator()));
210 auto *BB = PDTChild->getBlock();
213 LLVM_DEBUG(
dbgs() <<
"post-dom root child is a return: " << BB->getName()
220 markLive(&DFNode->getBlock()->back());
224 auto *BB = &
F.getEntryBlock();
225 auto &EntryInfo = getBlockInfo(BB);
226 EntryInfo.Live =
true;
228 markLive(&BB->back());
232 if (!isLive(&BB.back()))
233 BlocksWithDeadTerminators.insert(&BB);
236bool AggressiveDeadCodeElimination::isAlwaysLive(Instruction &
I) {
238 if (
I.isEHPad() ||
I.mayHaveSideEffects()) {
241 if (isInstrumentsConstant(
I))
245 if (!
I.isTerminator())
247 if (Opts.adce_remove_control_flow &&
255bool AggressiveDeadCodeElimination::isInstrumentsConstant(Instruction &
I) {
258 if (
Function *Callee = CI->getCalledFunction())
265void AggressiveDeadCodeElimination::markLiveInstructions() {
270 while (!Worklist.empty()) {
274 for (Use &OI : LiveInst->
operands())
284 markLiveBranchesFromControlDependences();
286 }
while (!Worklist.empty());
289void AggressiveDeadCodeElimination::markLive(Instruction *
I) {
290 auto [It,
Inserted] = LiveInst.insert(
I);
295 Worklist.push_back(
I);
298 if (
const DILocation *
DL =
I->getDebugLoc())
299 collectLiveScopes(*
DL);
303 if (
I == &BB->
back()) {
304 BlocksWithDeadTerminators.remove(BB);
308 for (
auto *Succ :
I->successors())
314void AggressiveDeadCodeElimination::markLive(BasicBlock *BB) {
315 auto &BBInfo = BlockInfo[BB->
getNumber()];
320 if (!BBInfo.CFLive) {
321 BBInfo.CFLive =
true;
322 NewLiveBlocks.insert(BB);
328 markLive(&BB->
back());
331void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocalScope &LS) {
332 if (!AliveScopes.insert(&LS).second)
342void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocation &
DL) {
345 if (!AliveScopes.insert(&
DL).second)
349 collectLiveScopes(*
DL.getScope());
352 if (
const DILocation *IA =
DL.getInlinedAt())
353 collectLiveScopes(*IA);
356void AggressiveDeadCodeElimination::markPhiLive(PHINode *PN) {
359 if (
Info.HasLivePhiNodes)
361 Info.HasLivePhiNodes =
true;
367 auto &
Info = getBlockInfo(PredBB);
370 NewLiveBlocks.insert(PredBB);
375void AggressiveDeadCodeElimination::markLiveBranchesFromControlDependences() {
376 if (BlocksWithDeadTerminators.empty())
380 dbgs() <<
"new live blocks:\n";
381 for (
auto *BB : NewLiveBlocks)
383 dbgs() <<
"dead terminator blocks:\n";
384 for (
auto *BB : BlocksWithDeadTerminators)
395 BlocksWithDeadTerminators);
398 IDFs.setDefiningBlocks(NewLiveBlocks);
399 IDFs.setLiveInBlocks(BWDT);
400 IDFs.calculate(IDFBlocks);
401 NewLiveBlocks.clear();
404 for (
auto *BB : IDFBlocks) {
415ADCEChanged AggressiveDeadCodeElimination::removeDeadInstructions() {
418 Changed.ChangedControlFlow = updateDeadRegions();
428 if (AliveScopes.count(DII->getDebugLoc()->getScope()))
434 for (
Value *V : DII->location_ops()) {
437 dbgs() <<
"Dropping debug info for " << *DII <<
"\n";
459 DVR && DVR->isDbgAssign())
462 if (AliveScopes.count(DR.getDebugLoc()->getScope()))
464 I.dropOneDbgRecord(&DR);
471 Changed.ChangedNonDebugInstr =
true;
474 Worklist.push_back(&
I);
478 for (Instruction *&
I : Worklist)
479 I->dropAllReferences();
481 for (Instruction *&
I : Worklist) {
483 I->eraseFromParent();
486 Changed.ChangedAnything =
Changed.ChangedControlFlow || !Worklist.empty();
492bool AggressiveDeadCodeElimination::updateDeadRegions() {
494 dbgs() <<
"final dead terminator blocks: " <<
'\n';
495 for (
auto *BB : BlocksWithDeadTerminators)
497 << (getBlockInfo(BB).Live ?
" LIVE\n" :
"\n");
501 bool HavePostOrder =
false;
505 for (
auto *BB : BlocksWithDeadTerminators) {
507 LiveInst.insert(&BB->
back());
511 if (!HavePostOrder) {
512 computeReversePostOrder();
513 HavePostOrder =
true;
520 unsigned PreferredSuccPostOrder = 0;
522 unsigned SuccPostOrder = BlockInfo[Succ->getNumber()].PostOrder;
523 if (PreferredSuccPostOrder < SuccPostOrder) {
524 PreferredSucc = Succ;
525 PreferredSuccPostOrder = SuccPostOrder;
528 assert((PreferredSucc && PreferredSuccPostOrder > 0) &&
529 "Failed to find safe successor for dead branch");
532 SmallPtrSet<BasicBlock *, 4> RemovedSuccessors;
535 if (!
First || Succ != PreferredSucc) {
536 Succ->removePredecessor(BB);
537 RemovedSuccessors.
insert(Succ);
541 makeUnconditional(BB, PreferredSucc);
544 for (
auto *Succ : RemovedSuccessors) {
547 if (Succ != PreferredSucc) {
548 LLVM_DEBUG(
dbgs() <<
"ADCE: (Post)DomTree edge enqueued for deletion"
549 << BB->
getName() <<
" -> " << Succ->getName()
551 DeletedEdges.
push_back({DominatorTree::Delete, BB, Succ});
555 NumBranchesRemoved += 1;
559 if (!DeletedEdges.
empty())
560 DomTreeUpdater(DT, &PDT, DomTreeUpdater::UpdateStrategy::Eager)
561 .applyUpdates(DeletedEdges);
567void AggressiveDeadCodeElimination::computeReversePostOrder() {
575 SmallPtrSet<BasicBlock*, 16> Visited;
576 unsigned PostOrder = 0;
581 getBlockInfo(
Block).PostOrder = PostOrder++;
585void AggressiveDeadCodeElimination::makeUnconditional(BasicBlock *BB,
586 BasicBlock *Target) {
590 collectLiveScopes(*
DL);
594 BI->setSuccessor(Target);
595 LiveInst.insert(PredTerm);
599 NumBranchesRemoved += 1;
601 auto *NewTerm = Builder.CreateBr(Target);
602 LiveInst.insert(NewTerm);
619 AggressiveDeadCodeElimination(
F, DT, PDT).performDeadCodeElimination();
624 if (!
Changed.ChangedControlFlow) {
626 if (!
Changed.ChangedNonDebugInstr) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static bool isAlwaysLive(Instruction *I)
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 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.
unsigned getNumber() const
const Instruction & back() const
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
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.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
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.
void reserve(size_type NewNumEntries)
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.
AssignmentInstRange getAssignmentInsts(DIAssignID *ID)
Return a range of instructions (typically just one) that have ID as an attachment.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
bool succ_empty(const Instruction *I)
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...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto inverse_post_order_ext(const T &G, SetType &S)
auto reverse(ContainerTy &&C)
IDFCalculator< true > ReverseIDFCalculator
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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...
@ Global
Append to llvm.global_dtors.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
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.
LLVM_ABI void FindFunctionBackedges(const Function &F, SmallVectorImpl< std::pair< const BasicBlock *, const BasicBlock * > > &Result)
Analyze the specified function to find all of the loop backedges in the function and return them.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &)