56#define DEBUG_TYPE "adce"
58STATISTIC(NumRemoved,
"Number of instructions removed");
59STATISTIC(NumBranchesRemoved,
"Number of branch instructions removed");
69 bool HasLivePhiNodes =
false;
75 unsigned PostOrder = 0;
79 bool ChangedAnything =
false;
80 bool ChangedNonDebugInstr =
false;
81 bool ChangedControlFlow =
false;
84class AggressiveDeadCodeElimination {
85 const ScalarOptions &Opts;
91 PostDominatorTree &PDT;
97 SmallPtrSet<Instruction *, 32> LiveInst;
98 bool isLive(Instruction *
I) {
return LiveInst.contains(
I); }
105 SmallPtrSet<const Metadata *, 32> AliveScopes;
108 SmallSetVector<BasicBlock *, 16> BlocksWithDeadTerminators;
113 SmallPtrSet<BasicBlock *, 16> NewLiveBlocks;
119 BlockInfoType &getBlockInfo(BasicBlock *BB) {
127 bool isInstrumentsConstant(Instruction &
I);
130 void markLiveInstructions();
133 void markLive(Instruction *
I);
136 void markLive(BasicBlock *BB);
139 void markPhiLive(PHINode *PN);
142 void collectLiveScopes(
const DILocalScope &LS);
143 void collectLiveScopes(
const DILocation &
DL);
148 void markLiveBranchesFromControlDependences();
152 ADCEChanged removeDeadInstructions();
156 bool updateDeadRegions();
160 void computeReversePostOrder();
163 void makeUnconditional(BasicBlock *BB, BasicBlock *Target);
166 AggressiveDeadCodeElimination(
Function &F, DominatorTree *DT,
167 PostDominatorTree &PDT)
168 : Opts(ScalarOptions::
Global), F(F), DT(DT), PDT(PDT) {}
170 ADCEChanged performDeadCodeElimination();
175ADCEChanged AggressiveDeadCodeElimination::performDeadCodeElimination() {
177 markLiveInstructions();
178 return removeDeadInstructions();
181void AggressiveDeadCodeElimination::initialize() {
182 BlockInfo.
resize(
F.getMaxBlockNumber());
185 NumInsts += BB.size();
193 if (!Opts.adce_remove_control_flow)
196 if (!Opts.adce_remove_loops) {
200 for (
const auto &[Src, Dst] : Backedges)
201 markLive(
const_cast<Instruction *
>(Src->getTerminator()));
209 auto *BB = PDTChild->getBlock();
212 LLVM_DEBUG(
dbgs() <<
"post-dom root child is a return: " << BB->getName()
219 markLive(&DFNode->getBlock()->back());
223 auto *BB = &
F.getEntryBlock();
224 auto &EntryInfo = getBlockInfo(BB);
225 EntryInfo.Live =
true;
227 markLive(&BB->back());
231 if (!isLive(&BB.back()))
232 BlocksWithDeadTerminators.insert(&BB);
235bool AggressiveDeadCodeElimination::isAlwaysLive(Instruction &
I) {
237 if (
I.isEHPad() ||
I.mayHaveSideEffects()) {
240 if (isInstrumentsConstant(
I))
244 if (!
I.isTerminator())
246 if (Opts.adce_remove_control_flow &&
254bool AggressiveDeadCodeElimination::isInstrumentsConstant(Instruction &
I) {
257 if (
Function *Callee = CI->getCalledFunction())
264void AggressiveDeadCodeElimination::markLiveInstructions() {
269 while (!Worklist.empty()) {
273 for (Use &OI : LiveInst->
operands())
283 markLiveBranchesFromControlDependences();
285 }
while (!Worklist.empty());
288void AggressiveDeadCodeElimination::markLive(Instruction *
I) {
289 auto [It,
Inserted] = LiveInst.insert(
I);
294 Worklist.push_back(
I);
297 if (
const DILocation *
DL =
I->getDebugLoc())
298 collectLiveScopes(*
DL);
302 if (
I == &BB->
back()) {
303 BlocksWithDeadTerminators.remove(BB);
307 for (
auto *Succ :
I->successors())
313void AggressiveDeadCodeElimination::markLive(BasicBlock *BB) {
314 auto &BBInfo = BlockInfo[BB->
getNumber()];
319 if (!BBInfo.CFLive) {
320 BBInfo.CFLive =
true;
321 NewLiveBlocks.insert(BB);
327 markLive(&BB->
back());
330void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocalScope &LS) {
331 if (!AliveScopes.insert(&LS).second)
341void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocation &
DL) {
344 if (!AliveScopes.insert(&
DL).second)
348 collectLiveScopes(*
DL.getScope());
351 if (
const DILocation *IA =
DL.getInlinedAt())
352 collectLiveScopes(*IA);
355void AggressiveDeadCodeElimination::markPhiLive(PHINode *PN) {
358 if (
Info.HasLivePhiNodes)
360 Info.HasLivePhiNodes =
true;
366 auto &
Info = getBlockInfo(PredBB);
369 NewLiveBlocks.insert(PredBB);
374void AggressiveDeadCodeElimination::markLiveBranchesFromControlDependences() {
375 if (BlocksWithDeadTerminators.empty())
379 dbgs() <<
"new live blocks:\n";
380 for (
auto *BB : NewLiveBlocks)
382 dbgs() <<
"dead terminator blocks:\n";
383 for (
auto *BB : BlocksWithDeadTerminators)
394 BlocksWithDeadTerminators);
397 IDFs.setDefiningBlocks(NewLiveBlocks);
398 IDFs.setLiveInBlocks(BWDT);
399 IDFs.calculate(IDFBlocks);
400 NewLiveBlocks.clear();
403 for (
auto *BB : IDFBlocks) {
414ADCEChanged AggressiveDeadCodeElimination::removeDeadInstructions() {
417 Changed.ChangedControlFlow = updateDeadRegions();
432 DVR && DVR->isDbgAssign())
435 if (AliveScopes.count(DR.getDebugLoc()->getScope()))
437 I.dropOneDbgRecord(&DR);
444 Changed.ChangedNonDebugInstr =
true;
447 Worklist.push_back(&
I);
451 for (Instruction *&
I : Worklist)
452 I->dropAllReferences();
454 for (Instruction *&
I : Worklist) {
456 I->eraseFromParent();
459 Changed.ChangedAnything =
Changed.ChangedControlFlow || !Worklist.empty();
465bool AggressiveDeadCodeElimination::updateDeadRegions() {
467 dbgs() <<
"final dead terminator blocks: " <<
'\n';
468 for (
auto *BB : BlocksWithDeadTerminators)
470 << (getBlockInfo(BB).Live ?
" LIVE\n" :
"\n");
474 bool HavePostOrder =
false;
478 for (
auto *BB : BlocksWithDeadTerminators) {
480 LiveInst.insert(&BB->
back());
484 if (!HavePostOrder) {
485 computeReversePostOrder();
486 HavePostOrder =
true;
493 unsigned PreferredSuccPostOrder = 0;
495 unsigned SuccPostOrder = BlockInfo[Succ->getNumber()].PostOrder;
496 if (PreferredSuccPostOrder < SuccPostOrder) {
497 PreferredSucc = Succ;
498 PreferredSuccPostOrder = SuccPostOrder;
501 assert((PreferredSucc && PreferredSuccPostOrder > 0) &&
502 "Failed to find safe successor for dead branch");
505 SmallPtrSet<BasicBlock *, 4> RemovedSuccessors;
508 if (!
First || Succ != PreferredSucc) {
509 Succ->removePredecessor(BB);
510 RemovedSuccessors.
insert(Succ);
514 makeUnconditional(BB, PreferredSucc);
517 for (
auto *Succ : RemovedSuccessors) {
520 if (Succ != PreferredSucc) {
521 LLVM_DEBUG(
dbgs() <<
"ADCE: (Post)DomTree edge enqueued for deletion"
522 << BB->
getName() <<
" -> " << Succ->getName()
524 DeletedEdges.
push_back({DominatorTree::Delete, BB, Succ});
528 NumBranchesRemoved += 1;
532 if (!DeletedEdges.
empty())
533 DomTreeUpdater(DT, &PDT, DomTreeUpdater::UpdateStrategy::Eager)
534 .applyUpdates(DeletedEdges);
540void AggressiveDeadCodeElimination::computeReversePostOrder() {
548 SmallPtrSet<BasicBlock*, 16> Visited;
549 unsigned PostOrder = 0;
554 getBlockInfo(
Block).PostOrder = PostOrder++;
558void AggressiveDeadCodeElimination::makeUnconditional(BasicBlock *BB,
559 BasicBlock *Target) {
563 collectLiveScopes(*
DL);
567 BI->setSuccessor(Target);
568 LiveInst.insert(PredTerm);
572 NumBranchesRemoved += 1;
574 auto *NewTerm = Builder.CreateBr(Target);
575 LiveInst.insert(NewTerm);
592 AggressiveDeadCodeElimination(
F, DT, PDT).performDeadCodeElimination();
597 if (!
Changed.ChangedControlFlow) {
599 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...
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...
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 &)