57#define DEBUG_TYPE "adce"
59STATISTIC(NumRemoved,
"Number of instructions removed");
60STATISTIC(NumBranchesRemoved,
"Number of branch instructions removed");
80 bool HasLivePhiNodes =
false;
86 unsigned PostOrder = 0;
90 bool ChangedAnything =
false;
91 bool ChangedNonDebugInstr =
false;
92 bool ChangedControlFlow =
false;
95class AggressiveDeadCodeElimination {
101 PostDominatorTree &PDT;
107 SmallPtrSet<Instruction *, 32> LiveInst;
108 bool isLive(Instruction *
I) {
return LiveInst.contains(
I); }
115 SmallPtrSet<const Metadata *, 32> AliveScopes;
118 SmallSetVector<BasicBlock *, 16> BlocksWithDeadTerminators;
123 SmallPtrSet<BasicBlock *, 16> NewLiveBlocks;
129 BlockInfoType &getBlockInfo(BasicBlock *BB) {
137 bool isInstrumentsConstant(Instruction &
I);
140 void markLiveInstructions();
143 void markLive(Instruction *
I);
146 void markLive(BasicBlock *BB);
149 void markPhiLive(PHINode *PN);
152 void collectLiveScopes(
const DILocalScope &LS);
153 void collectLiveScopes(
const DILocation &
DL);
158 void markLiveBranchesFromControlDependences();
162 ADCEChanged removeDeadInstructions();
166 bool updateDeadRegions();
170 void computeReversePostOrder();
173 void makeUnconditional(BasicBlock *BB, BasicBlock *Target);
176 AggressiveDeadCodeElimination(
Function &F, DominatorTree *DT,
177 PostDominatorTree &PDT)
178 : F(F), DT(DT), PDT(PDT) {}
180 ADCEChanged performDeadCodeElimination();
185ADCEChanged AggressiveDeadCodeElimination::performDeadCodeElimination() {
187 markLiveInstructions();
188 return removeDeadInstructions();
191void AggressiveDeadCodeElimination::initialize() {
192 BlockInfo.
resize(
F.getMaxBlockNumber());
195 NumInsts += BB.size();
210 for (
const auto &[Src, Dst] : Backedges)
211 markLive(
const_cast<Instruction *
>(Src->getTerminator()));
219 auto *BB = PDTChild->getBlock();
222 LLVM_DEBUG(
dbgs() <<
"post-dom root child is a return: " << BB->getName()
229 markLive(&DFNode->getBlock()->back());
233 auto *BB = &
F.getEntryBlock();
234 auto &EntryInfo = getBlockInfo(BB);
235 EntryInfo.Live =
true;
237 markLive(&BB->back());
241 if (!isLive(&BB.back()))
242 BlocksWithDeadTerminators.insert(&BB);
245bool AggressiveDeadCodeElimination::isAlwaysLive(Instruction &
I) {
247 if (
I.isEHPad() ||
I.mayHaveSideEffects()) {
250 if (isInstrumentsConstant(
I))
254 if (!
I.isTerminator())
263bool AggressiveDeadCodeElimination::isInstrumentsConstant(Instruction &
I) {
266 if (
Function *Callee = CI->getCalledFunction())
273void AggressiveDeadCodeElimination::markLiveInstructions() {
278 while (!Worklist.empty()) {
282 for (Use &OI : LiveInst->
operands())
292 markLiveBranchesFromControlDependences();
294 }
while (!Worklist.empty());
297void AggressiveDeadCodeElimination::markLive(Instruction *
I) {
298 auto [It,
Inserted] = LiveInst.insert(
I);
303 Worklist.push_back(
I);
306 if (
const DILocation *
DL =
I->getDebugLoc())
307 collectLiveScopes(*
DL);
311 if (
I == &BB->
back()) {
312 BlocksWithDeadTerminators.remove(BB);
316 for (
auto *Succ :
I->successors())
322void AggressiveDeadCodeElimination::markLive(BasicBlock *BB) {
323 auto &BBInfo = BlockInfo[BB->
getNumber()];
328 if (!BBInfo.CFLive) {
329 BBInfo.CFLive =
true;
330 NewLiveBlocks.insert(BB);
336 markLive(&BB->
back());
339void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocalScope &LS) {
340 if (!AliveScopes.insert(&LS).second)
350void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocation &
DL) {
353 if (!AliveScopes.insert(&
DL).second)
357 collectLiveScopes(*
DL.getScope());
360 if (
const DILocation *IA =
DL.getInlinedAt())
361 collectLiveScopes(*IA);
364void AggressiveDeadCodeElimination::markPhiLive(PHINode *PN) {
367 if (
Info.HasLivePhiNodes)
369 Info.HasLivePhiNodes =
true;
375 auto &
Info = getBlockInfo(PredBB);
378 NewLiveBlocks.insert(PredBB);
383void AggressiveDeadCodeElimination::markLiveBranchesFromControlDependences() {
384 if (BlocksWithDeadTerminators.empty())
388 dbgs() <<
"new live blocks:\n";
389 for (
auto *BB : NewLiveBlocks)
391 dbgs() <<
"dead terminator blocks:\n";
392 for (
auto *BB : BlocksWithDeadTerminators)
403 BlocksWithDeadTerminators);
406 IDFs.setDefiningBlocks(NewLiveBlocks);
407 IDFs.setLiveInBlocks(BWDT);
408 IDFs.calculate(IDFBlocks);
409 NewLiveBlocks.clear();
412 for (
auto *BB : IDFBlocks) {
423ADCEChanged AggressiveDeadCodeElimination::removeDeadInstructions() {
426 Changed.ChangedControlFlow = updateDeadRegions();
436 if (AliveScopes.count(DII->getDebugLoc()->getScope()))
442 for (
Value *V : DII->location_ops()) {
445 dbgs() <<
"Dropping debug info for " << *DII <<
"\n";
467 DVR && DVR->isDbgAssign())
470 if (AliveScopes.count(DR.getDebugLoc()->getScope()))
472 I.dropOneDbgRecord(&DR);
479 Changed.ChangedNonDebugInstr =
true;
482 Worklist.push_back(&
I);
486 for (Instruction *&
I : Worklist)
487 I->dropAllReferences();
489 for (Instruction *&
I : Worklist) {
491 I->eraseFromParent();
494 Changed.ChangedAnything =
Changed.ChangedControlFlow || !Worklist.empty();
500bool AggressiveDeadCodeElimination::updateDeadRegions() {
502 dbgs() <<
"final dead terminator blocks: " <<
'\n';
503 for (
auto *BB : BlocksWithDeadTerminators)
505 << (getBlockInfo(BB).Live ?
" LIVE\n" :
"\n");
509 bool HavePostOrder =
false;
513 for (
auto *BB : BlocksWithDeadTerminators) {
515 LiveInst.insert(&BB->
back());
519 if (!HavePostOrder) {
520 computeReversePostOrder();
521 HavePostOrder =
true;
528 unsigned PreferredSuccPostOrder = 0;
530 unsigned SuccPostOrder = BlockInfo[Succ->getNumber()].PostOrder;
531 if (PreferredSuccPostOrder < SuccPostOrder) {
532 PreferredSucc = Succ;
533 PreferredSuccPostOrder = SuccPostOrder;
536 assert((PreferredSucc && PreferredSuccPostOrder > 0) &&
537 "Failed to find safe successor for dead branch");
540 SmallPtrSet<BasicBlock *, 4> RemovedSuccessors;
543 if (!
First || Succ != PreferredSucc) {
544 Succ->removePredecessor(BB);
545 RemovedSuccessors.
insert(Succ);
549 makeUnconditional(BB, PreferredSucc);
552 for (
auto *Succ : RemovedSuccessors) {
555 if (Succ != PreferredSucc) {
556 LLVM_DEBUG(
dbgs() <<
"ADCE: (Post)DomTree edge enqueued for deletion"
557 << BB->
getName() <<
" -> " << Succ->getName()
559 DeletedEdges.
push_back({DominatorTree::Delete, BB, Succ});
563 NumBranchesRemoved += 1;
567 if (!DeletedEdges.
empty())
568 DomTreeUpdater(DT, &PDT, DomTreeUpdater::UpdateStrategy::Eager)
569 .applyUpdates(DeletedEdges);
575void AggressiveDeadCodeElimination::computeReversePostOrder() {
583 SmallPtrSet<BasicBlock*, 16> Visited;
584 unsigned PostOrder = 0;
589 getBlockInfo(
Block).PostOrder = PostOrder++;
593void AggressiveDeadCodeElimination::makeUnconditional(BasicBlock *BB,
594 BasicBlock *Target) {
598 collectLiveScopes(*
DL);
602 BI->setSuccessor(Target);
603 LiveInst.insert(PredTerm);
607 NumBranchesRemoved += 1;
609 auto *NewTerm = Builder.CreateBr(Target);
610 LiveInst.insert(NewTerm);
627 AggressiveDeadCodeElimination(
F, DT, PDT).performDeadCodeElimination();
632 if (!
Changed.ChangedControlFlow) {
634 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 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.
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.
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.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &)