58#define DEBUG_TYPE "adce"
60STATISTIC(NumRemoved,
"Number of instructions removed");
61STATISTIC(NumBranchesRemoved,
"Number of branch instructions removed");
81 bool HasLivePhiNodes =
false;
87 unsigned PostOrder = 0;
91 bool ChangedAnything =
false;
92 bool ChangedNonDebugInstr =
false;
93 bool ChangedControlFlow =
false;
96class AggressiveDeadCodeElimination {
102 PostDominatorTree &PDT;
108 SmallPtrSet<Instruction *, 32> LiveInst;
109 bool isLive(Instruction *
I) {
return LiveInst.contains(
I); }
116 SmallPtrSet<const Metadata *, 32> AliveScopes;
119 SmallSetVector<BasicBlock *, 16> BlocksWithDeadTerminators;
124 SmallPtrSet<BasicBlock *, 16> NewLiveBlocks;
130 BlockInfoType &getBlockInfo(BasicBlock *BB) {
138 bool isInstrumentsConstant(Instruction &
I);
141 void markLiveInstructions();
144 void markLive(Instruction *
I);
147 void markLive(BasicBlock *BB);
150 void markPhiLive(PHINode *PN);
153 void collectLiveScopes(
const DILocalScope &LS);
154 void collectLiveScopes(
const DILocation &
DL);
159 void markLiveBranchesFromControlDependences();
163 ADCEChanged removeDeadInstructions();
167 bool updateDeadRegions();
171 void computeReversePostOrder();
174 void makeUnconditional(BasicBlock *BB, BasicBlock *Target);
177 AggressiveDeadCodeElimination(Function &F, DominatorTree *DT,
178 PostDominatorTree &PDT)
179 : F(F), DT(DT), PDT(PDT) {}
181 ADCEChanged performDeadCodeElimination();
186ADCEChanged AggressiveDeadCodeElimination::performDeadCodeElimination() {
188 markLiveInstructions();
189 return removeDeadInstructions();
192void AggressiveDeadCodeElimination::initialize() {
193 BlockInfo.
resize(
F.getMaxBlockNumber());
196 NumInsts += BB.size();
211 for (
const auto &[Src, Dst] : Backedges)
212 markLive(
const_cast<Instruction *
>(Src->getTerminator()));
220 auto *BB = PDTChild->getBlock();
223 LLVM_DEBUG(
dbgs() <<
"post-dom root child is a return: " << BB->getName()
230 markLive(&DFNode->getBlock()->back());
234 auto *BB = &
F.getEntryBlock();
235 auto &EntryInfo = getBlockInfo(BB);
236 EntryInfo.Live =
true;
238 markLive(&BB->back());
242 if (!isLive(&BB.back()))
243 BlocksWithDeadTerminators.insert(&BB);
246bool AggressiveDeadCodeElimination::isAlwaysLive(Instruction &
I) {
248 if (
I.isEHPad() ||
I.mayHaveSideEffects()) {
251 if (isInstrumentsConstant(
I))
255 if (!
I.isTerminator())
264bool AggressiveDeadCodeElimination::isInstrumentsConstant(Instruction &
I) {
267 if (Function *Callee = CI->getCalledFunction())
274void AggressiveDeadCodeElimination::markLiveInstructions() {
279 while (!Worklist.empty()) {
283 for (Use &OI : LiveInst->
operands())
293 markLiveBranchesFromControlDependences();
295 }
while (!Worklist.empty());
298void AggressiveDeadCodeElimination::markLive(Instruction *
I) {
299 auto [It,
Inserted] = LiveInst.insert(
I);
304 Worklist.push_back(
I);
307 if (
const DILocation *
DL =
I->getDebugLoc())
308 collectLiveScopes(*
DL);
312 if (
I == &BB->
back()) {
313 BlocksWithDeadTerminators.remove(BB);
317 for (
auto *Succ :
I->successors())
323void AggressiveDeadCodeElimination::markLive(BasicBlock *BB) {
324 auto &BBInfo = BlockInfo[BB->
getNumber()];
329 if (!BBInfo.CFLive) {
330 BBInfo.CFLive =
true;
331 NewLiveBlocks.insert(BB);
337 markLive(&BB->
back());
340void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocalScope &LS) {
341 if (!AliveScopes.insert(&LS).second)
351void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocation &
DL) {
354 if (!AliveScopes.insert(&
DL).second)
358 collectLiveScopes(*
DL.getScope());
361 if (
const DILocation *IA =
DL.getInlinedAt())
362 collectLiveScopes(*IA);
365void AggressiveDeadCodeElimination::markPhiLive(PHINode *PN) {
368 if (
Info.HasLivePhiNodes)
370 Info.HasLivePhiNodes =
true;
376 auto &
Info = getBlockInfo(PredBB);
379 NewLiveBlocks.insert(PredBB);
384void AggressiveDeadCodeElimination::markLiveBranchesFromControlDependences() {
385 if (BlocksWithDeadTerminators.empty())
389 dbgs() <<
"new live blocks:\n";
390 for (
auto *BB : NewLiveBlocks)
392 dbgs() <<
"dead terminator blocks:\n";
393 for (
auto *BB : BlocksWithDeadTerminators)
404 BlocksWithDeadTerminators);
407 IDFs.setDefiningBlocks(NewLiveBlocks);
408 IDFs.setLiveInBlocks(BWDT);
409 IDFs.calculate(IDFBlocks);
410 NewLiveBlocks.clear();
413 for (
auto *BB : IDFBlocks) {
424ADCEChanged AggressiveDeadCodeElimination::removeDeadInstructions() {
427 Changed.ChangedControlFlow = updateDeadRegions();
437 if (AliveScopes.count(DII->getDebugLoc()->getScope()))
443 for (
Value *V : DII->location_ops()) {
446 dbgs() <<
"Dropping debug info for " << *DII <<
"\n";
468 DVR && DVR->isDbgAssign())
471 if (AliveScopes.count(DR.getDebugLoc()->getScope()))
473 I.dropOneDbgRecord(&DR);
480 Changed.ChangedNonDebugInstr =
true;
483 Worklist.push_back(&
I);
487 for (Instruction *&
I : Worklist)
488 I->dropAllReferences();
490 for (Instruction *&
I : Worklist) {
492 I->eraseFromParent();
495 Changed.ChangedAnything =
Changed.ChangedControlFlow || !Worklist.empty();
501bool AggressiveDeadCodeElimination::updateDeadRegions() {
503 dbgs() <<
"final dead terminator blocks: " <<
'\n';
504 for (
auto *BB : BlocksWithDeadTerminators)
506 << (getBlockInfo(BB).Live ?
" LIVE\n" :
"\n");
510 bool HavePostOrder =
false;
514 for (
auto *BB : BlocksWithDeadTerminators) {
516 LiveInst.insert(&BB->
back());
520 if (!HavePostOrder) {
521 computeReversePostOrder();
522 HavePostOrder =
true;
529 unsigned PreferredSuccPostOrder = 0;
531 unsigned SuccPostOrder = BlockInfo[Succ->getNumber()].PostOrder;
532 if (PreferredSuccPostOrder < SuccPostOrder) {
533 PreferredSucc = Succ;
534 PreferredSuccPostOrder = SuccPostOrder;
537 assert((PreferredSucc && PreferredSuccPostOrder > 0) &&
538 "Failed to find safe successor for dead branch");
541 SmallPtrSet<BasicBlock *, 4> RemovedSuccessors;
544 if (!
First || Succ != PreferredSucc) {
545 Succ->removePredecessor(BB);
546 RemovedSuccessors.
insert(Succ);
550 makeUnconditional(BB, PreferredSucc);
553 for (
auto *Succ : RemovedSuccessors) {
556 if (Succ != PreferredSucc) {
557 LLVM_DEBUG(
dbgs() <<
"ADCE: (Post)DomTree edge enqueued for deletion"
558 << BB->
getName() <<
" -> " << Succ->getName()
560 DeletedEdges.
push_back({DominatorTree::Delete, BB, Succ});
564 NumBranchesRemoved += 1;
568 if (!DeletedEdges.
empty())
569 DomTreeUpdater(DT, &PDT, DomTreeUpdater::UpdateStrategy::Eager)
570 .applyUpdates(DeletedEdges);
576void AggressiveDeadCodeElimination::computeReversePostOrder() {
584 SmallPtrSet<BasicBlock*, 16> Visited;
585 unsigned PostOrder = 0;
590 getBlockInfo(
Block).PostOrder = PostOrder++;
594void AggressiveDeadCodeElimination::makeUnconditional(BasicBlock *BB,
595 BasicBlock *Target) {
599 collectLiveScopes(*
DL);
603 BI->setSuccessor(Target);
604 LiveInst.insert(PredTerm);
608 NumBranchesRemoved += 1;
610 auto *NewTerm = Builder.CreateBr(Target);
611 LiveInst.insert(NewTerm);
628 AggressiveDeadCodeElimination(
F, DT, PDT).performDeadCodeElimination();
633 if (!
Changed.ChangedControlFlow) {
635 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 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.
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.
FunctionAddr VTableAddr Value
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.
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.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &)