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();
217 return BR && BR->isUnconditional();
220void AggressiveDeadCodeElimination::initialize() {
221 auto NumBlocks =
F.size();
225 BlockInfo.reserve(NumBlocks);
231 NumInsts += BB.size();
232 auto &
Info = BlockInfo[&BB];
234 Info.Terminator = BB.getTerminator();
239 InstInfo.reserve(NumInsts);
240 for (
auto &BBInfo : BlockInfo)
241 for (Instruction &
I : *BBInfo.second.BB)
242 InstInfo[&
I].Block = &BBInfo.second;
246 for (
auto &BBInfo : BlockInfo)
247 BBInfo.second.TerminatorLiveInfo = &InstInfo[BBInfo.second.Terminator];
262 using StatusMap = DenseMap<BasicBlock *, bool>;
264 class DFState :
public StatusMap {
266 std::pair<StatusMap::iterator, bool> insert(BasicBlock *BB) {
267 return StatusMap::insert(std::make_pair(BB,
true));
271 void completed(BasicBlock *BB) { (*this)[BB] =
false; }
275 bool onStack(BasicBlock *BB) {
276 auto Iter =
find(BB);
277 return Iter !=
end() && Iter->second;
281 State.reserve(
F.size());
291 if (State.onStack(Succ)) {
304 auto *BB = PDTChild->getBlock();
305 auto &
Info = BlockInfo[BB];
308 LLVM_DEBUG(
dbgs() <<
"post-dom root child is a return: " << BB->getName()
315 markLive(BlockInfo[DFNode->getBlock()].Terminator);
319 auto *BB = &
F.getEntryBlock();
320 auto &EntryInfo = BlockInfo[BB];
321 EntryInfo.Live =
true;
322 if (EntryInfo.UnconditionalBranch)
323 markLive(EntryInfo.Terminator);
326 for (
auto &BBInfo : BlockInfo)
327 if (!BBInfo.second.terminatorIsLive())
328 BlocksWithDeadTerminators.insert(BBInfo.second.BB);
331bool AggressiveDeadCodeElimination::isAlwaysLive(Instruction &
I) {
333 if (
I.isEHPad() ||
I.mayHaveSideEffects()) {
336 if (isInstrumentsConstant(
I))
340 if (!
I.isTerminator())
349bool AggressiveDeadCodeElimination::isInstrumentsConstant(Instruction &
I) {
352 if (Function *Callee = CI->getCalledFunction())
359void AggressiveDeadCodeElimination::markLiveInstructions() {
364 while (!Worklist.empty()) {
368 for (Use &OI : LiveInst->
operands())
378 markLiveBranchesFromControlDependences();
380 }
while (!Worklist.empty());
383void AggressiveDeadCodeElimination::markLive(Instruction *
I) {
384 auto &
Info = InstInfo[
I];
390 Worklist.push_back(
I);
393 if (
const DILocation *
DL =
I->getDebugLoc())
394 collectLiveScopes(*
DL);
397 auto &BBInfo = *
Info.Block;
398 if (BBInfo.Terminator ==
I) {
399 BlocksWithDeadTerminators.remove(BBInfo.BB);
402 if (!BBInfo.UnconditionalBranch)
409void AggressiveDeadCodeElimination::markLive(BlockInfoType &BBInfo) {
414 if (!BBInfo.CFLive) {
415 BBInfo.CFLive =
true;
416 NewLiveBlocks.insert(BBInfo.BB);
421 if (BBInfo.UnconditionalBranch)
422 markLive(BBInfo.Terminator);
425void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocalScope &LS) {
426 if (!AliveScopes.insert(&LS).second)
436void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocation &
DL) {
439 if (!AliveScopes.insert(&
DL).second)
443 collectLiveScopes(*
DL.getScope());
446 if (
const DILocation *IA =
DL.getInlinedAt())
447 collectLiveScopes(*IA);
450void AggressiveDeadCodeElimination::markPhiLive(PHINode *PN) {
453 if (
Info.HasLivePhiNodes)
455 Info.HasLivePhiNodes =
true;
461 auto &
Info = BlockInfo[PredBB];
464 NewLiveBlocks.insert(PredBB);
469void AggressiveDeadCodeElimination::markLiveBranchesFromControlDependences() {
470 if (BlocksWithDeadTerminators.empty())
474 dbgs() <<
"new live blocks:\n";
475 for (
auto *BB : NewLiveBlocks)
476 dbgs() <<
"\t" << BB->getName() <<
'\n';
477 dbgs() <<
"dead terminator blocks:\n";
478 for (
auto *BB : BlocksWithDeadTerminators)
479 dbgs() <<
"\t" << BB->getName() <<
'\n';
489 BlocksWithDeadTerminators);
492 IDFs.setDefiningBlocks(NewLiveBlocks);
493 IDFs.setLiveInBlocks(BWDT);
494 IDFs.calculate(IDFBlocks);
495 NewLiveBlocks.clear();
498 for (
auto *BB : IDFBlocks) {
499 LLVM_DEBUG(
dbgs() <<
"live control in: " << BB->getName() <<
'\n');
500 markLive(BB->getTerminator());
509ADCEChanged AggressiveDeadCodeElimination::removeDeadInstructions() {
512 Changed.ChangedControlFlow = updateDeadRegions();
522 if (AliveScopes.count(DII->getDebugLoc()->getScope()))
528 for (
Value *V : DII->location_ops()) {
531 dbgs() <<
"Dropping debug info for " << *DII <<
"\n";
553 DVR && DVR->isDbgAssign())
556 if (AliveScopes.count(DR.getDebugLoc()->getScope()))
558 I.dropOneDbgRecord(&DR);
565 Changed.ChangedNonDebugInstr =
true;
568 Worklist.push_back(&
I);
572 for (Instruction *&
I : Worklist)
573 I->dropAllReferences();
575 for (Instruction *&
I : Worklist) {
577 I->eraseFromParent();
580 Changed.ChangedAnything =
Changed.ChangedControlFlow || !Worklist.empty();
586bool AggressiveDeadCodeElimination::updateDeadRegions() {
588 dbgs() <<
"final dead terminator blocks: " <<
'\n';
589 for (
auto *BB : BlocksWithDeadTerminators)
590 dbgs() <<
'\t' << BB->getName()
591 << (BlockInfo[BB].Live ?
" LIVE\n" :
"\n");
595 bool HavePostOrder =
false;
599 for (
auto *BB : BlocksWithDeadTerminators) {
600 auto &
Info = BlockInfo[BB];
601 if (
Info.UnconditionalBranch) {
602 InstInfo[
Info.Terminator].Live =
true;
606 if (!HavePostOrder) {
607 computeReversePostOrder();
608 HavePostOrder =
true;
614 BlockInfoType *PreferredSucc =
nullptr;
616 auto *
Info = &BlockInfo[Succ];
617 if (!PreferredSucc || PreferredSucc->PostOrder <
Info->PostOrder)
618 PreferredSucc =
Info;
620 assert((PreferredSucc && PreferredSucc->PostOrder > 0) &&
621 "Failed to find safe successor for dead branch");
624 SmallPtrSet<BasicBlock *, 4> RemovedSuccessors;
627 if (!
First || Succ != PreferredSucc->BB) {
628 Succ->removePredecessor(BB);
629 RemovedSuccessors.
insert(Succ);
633 makeUnconditional(BB, PreferredSucc->BB);
636 for (
auto *Succ : RemovedSuccessors) {
639 if (Succ != PreferredSucc->BB) {
640 LLVM_DEBUG(
dbgs() <<
"ADCE: (Post)DomTree edge enqueued for deletion"
641 << BB->getName() <<
" -> " << Succ->getName()
643 DeletedEdges.
push_back({DominatorTree::Delete, BB, Succ});
647 NumBranchesRemoved += 1;
651 if (!DeletedEdges.
empty())
652 DomTreeUpdater(DT, &PDT, DomTreeUpdater::UpdateStrategy::Eager)
653 .applyUpdates(DeletedEdges);
659void AggressiveDeadCodeElimination::computeReversePostOrder() {
667 SmallPtrSet<BasicBlock*, 16> Visited;
668 unsigned PostOrder = 0;
673 BlockInfo[
Block].PostOrder = PostOrder++;
677void AggressiveDeadCodeElimination::makeUnconditional(BasicBlock *BB,
678 BasicBlock *Target) {
682 collectLiveScopes(*
DL);
687 InstInfo[PredTerm].Live =
true;
691 NumBranchesRemoved += 1;
693 auto *NewTerm = Builder.CreateBr(Target);
694 InstInfo[NewTerm].Live =
true;
696 NewTerm->setDebugLoc(
DL);
698 InstInfo.erase(PredTerm);
713 AggressiveDeadCodeElimination(
F, DT, PDT).performDeadCodeElimination();
718 if (!
Changed.ChangedControlFlow) {
720 if (!
Changed.ChangedNonDebugInstr) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isUnconditionalBranch(Instruction *Term)
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
Analysis containing CSE Info
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, ArrayRef< StringLiteral > StandardNames)
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.
LLVM_ABI void setSuccessor(unsigned Idx, BasicBlock *BB)
Update the specified successor to point at the provided block.
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 &)