39 #define DEBUG_TYPE "adce"
41 STATISTIC(NumRemoved,
"Number of instructions removed");
42 STATISTIC(NumBranchesRemoved,
"Number of branch instructions removed");
60 struct BlockInfoType *Block =
nullptr;
64 struct BlockInfoType {
68 bool UnconditionalBranch =
false;
70 bool HasLivePhiNodes =
false;
76 InstInfoType *TerminatorLiveInfo =
nullptr;
78 bool terminatorIsLive()
const {
return TerminatorLiveInfo->Live; }
90 class AggressiveDeadCodeElimination {
96 bool isLive(
BasicBlock *BB) {
return BlockInfo[BB].Live; }
125 void markLiveInstructions();
129 void markLive(BlockInfoType &BB);
130 void markLive(
BasicBlock *BB) { markLive(BlockInfo[BB]); }
142 void markLiveBranchesFromControlDependences();
146 bool removeDeadInstructions();
150 void updateDeadRegions();
154 void computeReversePostOrder();
162 bool performDeadCodeElimination();
166 bool AggressiveDeadCodeElimination::performDeadCodeElimination() {
168 markLiveInstructions();
169 return removeDeadInstructions();
174 return BR &&
BR->isUnconditional();
179 auto NumBlocks =
F.size();
183 BlockInfo.reserve(NumBlocks);
189 NumInsts += BB.size();
190 auto &Info = BlockInfo[&BB];
192 Info.Terminator = BB.getTerminator();
197 InstInfo.reserve(NumInsts);
198 for (
auto &BBInfo : BlockInfo)
200 InstInfo[&
I].Block = &BBInfo.second;
204 for (
auto &BBInfo : BlockInfo)
205 BBInfo.second.TerminatorLiveInfo = &InstInfo[BBInfo.second.Terminator];
221 class DFState :
public StatusMap {
223 std::pair<StatusMap::iterator, bool> insert(
BasicBlock *BB) {
224 return StatusMap::insert(std::make_pair(BB,
true));
228 void completed(
BasicBlock *BB) { (*this)[BB] =
false; }
233 auto Iter =
find(BB);
234 return Iter !=
end() && Iter->second;
238 State.reserve(F.size());
248 if (State.onStack(Succ)) {
259 for (
auto &BBInfoPair : BlockInfo) {
260 auto &BBInfo = BBInfoPair.second;
261 if (BBInfo.terminatorIsLive())
263 auto *BB = BBInfo.BB;
264 if (!PDT.getNode(BB)) {
265 markLive(BBInfo.Terminator);
269 if (!PDT.getNode(Succ)) {
270 markLive(BBInfo.Terminator);
278 for (
auto &BBInfoPair : BlockInfo) {
279 auto &BBInfo = BBInfoPair.second;
280 if (BBInfo.terminatorIsLive())
282 auto *BB = BBInfo.BB;
283 if (!PDT.getNode(BB)) {
284 DEBUG(
dbgs() <<
"Not post-dominated by return: " << BB->getName()
286 markLive(BBInfo.Terminator);
290 if (!PDT.getNode(Succ)) {
291 DEBUG(
dbgs() <<
"Successor not post-dominated by return: "
292 << BB->getName() <<
'\n';);
293 markLive(BBInfo.Terminator);
299 auto *BB = &F.getEntryBlock();
300 auto &EntryInfo = BlockInfo[BB];
301 EntryInfo.Live =
true;
302 if (EntryInfo.UnconditionalBranch)
303 markLive(EntryInfo.Terminator);
306 for (
auto &BBInfo : BlockInfo)
307 if (!BBInfo.second.terminatorIsLive())
308 BlocksWithDeadTerminators.insert(BBInfo.second.BB);
316 if (isInstrumentsConstant(I))
320 if (!isa<TerminatorInst>(I))
329 bool AggressiveDeadCodeElimination::isInstrumentsConstant(
Instruction &I) {
331 if (
CallInst *CI = dyn_cast<CallInst>(&I))
332 if (
Function *Callee = CI->getCalledFunction())
334 if (isa<Constant>(CI->getArgOperand(0)))
339 void AggressiveDeadCodeElimination::markLiveInstructions() {
345 while (!Worklist.empty()) {
353 if (
auto *PN = dyn_cast<PHINode>(LiveInst))
359 markLiveBranchesFromControlDependences();
361 }
while (!Worklist.empty());
364 void AggressiveDeadCodeElimination::markLive(
Instruction *I) {
366 auto &Info = InstInfo[
I];
372 Worklist.push_back(I);
376 collectLiveScopes(*DL);
379 auto &BBInfo = *Info.Block;
380 if (BBInfo.Terminator == I) {
381 BlocksWithDeadTerminators.erase(BBInfo.BB);
384 if (!BBInfo.UnconditionalBranch)
391 void AggressiveDeadCodeElimination::markLive(BlockInfoType &BBInfo) {
394 DEBUG(
dbgs() <<
"mark block live: " << BBInfo.BB->getName() <<
'\n');
396 if (!BBInfo.CFLive) {
397 BBInfo.CFLive =
true;
398 NewLiveBlocks.insert(BBInfo.BB);
403 if (BBInfo.UnconditionalBranch)
404 markLive(BBInfo.Terminator);
407 void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocalScope &
LS) {
408 if (!AliveScopes.insert(&LS).second)
411 if (isa<DISubprogram>(LS))
415 collectLiveScopes(cast<DILocalScope>(*LS.
getScope()));
418 void AggressiveDeadCodeElimination::collectLiveScopes(
const DILocation &DL) {
421 if (!AliveScopes.insert(&DL).second)
425 collectLiveScopes(*DL.getScope());
429 collectLiveScopes(*IA);
432 void AggressiveDeadCodeElimination::markPhiLive(
PHINode *PN) {
435 if (Info.HasLivePhiNodes)
437 Info.HasLivePhiNodes =
true;
443 auto &Info = BlockInfo[PredBB];
446 NewLiveBlocks.insert(PredBB);
451 void AggressiveDeadCodeElimination::markLiveBranchesFromControlDependences() {
453 if (BlocksWithDeadTerminators.empty())
457 dbgs() <<
"new live blocks:\n";
458 for (
auto *BB : NewLiveBlocks)
459 dbgs() <<
"\t" << BB->getName() <<
'\n';
460 dbgs() <<
"dead terminator blocks:\n";
461 for (
auto *BB : BlocksWithDeadTerminators)
462 dbgs() <<
"\t" << BB->getName() <<
'\n';
473 IDFs.setDefiningBlocks(NewLiveBlocks);
474 IDFs.setLiveInBlocks(BlocksWithDeadTerminators);
475 IDFs.calculate(IDFBlocks);
476 NewLiveBlocks.clear();
479 for (
auto *BB : IDFBlocks) {
480 DEBUG(
dbgs() <<
"live control in: " << BB->getName() <<
'\n');
481 markLive(BB->getTerminator());
490 bool AggressiveDeadCodeElimination::removeDeadInstructions() {
501 if (
auto *DII = dyn_cast<DbgInfoIntrinsic>(&I)) {
503 if (AliveScopes.count(DII->getDebugLoc()->getScope()))
509 if (
Value *V = DII->getVariableLocation())
512 dbgs() <<
"Dropping debug info for " << *DII <<
"\n";
526 if (
auto *DII = dyn_cast<DbgInfoIntrinsic>(&I)) {
528 if (AliveScopes.count(DII->getDebugLoc()->getScope()))
535 Worklist.push_back(&I);
544 return !Worklist.empty();
548 void AggressiveDeadCodeElimination::updateDeadRegions() {
551 dbgs() <<
"final dead terminator blocks: " <<
'\n';
552 for (
auto *BB : BlocksWithDeadTerminators)
553 dbgs() <<
'\t' << BB->getName()
554 << (BlockInfo[BB].Live ?
" LIVE\n" :
"\n");
558 bool HavePostOrder =
false;
560 for (
auto *BB : BlocksWithDeadTerminators) {
561 auto &Info = BlockInfo[BB];
562 if (Info.UnconditionalBranch) {
563 InstInfo[Info.Terminator].Live =
true;
567 if (!HavePostOrder) {
568 computeReversePostOrder();
569 HavePostOrder =
true;
575 BlockInfoType *PreferredSucc =
nullptr;
577 auto *Info = &BlockInfo[Succ];
578 if (!PreferredSucc || PreferredSucc->PostOrder < Info->PostOrder)
579 PreferredSucc = Info;
581 assert((PreferredSucc && PreferredSucc->PostOrder > 0) &&
582 "Failed to find safe successor for dead branc");
585 if (!First || Succ != PreferredSucc->BB)
586 Succ->removePredecessor(BB);
590 makeUnconditional(BB, PreferredSucc->BB);
591 NumBranchesRemoved += 1;
596 void AggressiveDeadCodeElimination::computeReversePostOrder() {
606 unsigned PostOrder = 0;
611 BlockInfo[
Block].PostOrder = PostOrder++;
615 void AggressiveDeadCodeElimination::makeUnconditional(
BasicBlock *BB,
620 collectLiveScopes(*DL);
625 InstInfo[PredTerm].Live =
true;
629 NumBranchesRemoved += 1;
631 auto *NewTerm = Builder.CreateBr(Target);
632 InstInfo[NewTerm].Live =
true;
634 NewTerm->setDebugLoc(DL);
644 if (!AggressiveDeadCodeElimination(F, PDT).performDeadCodeElimination())
660 bool runOnFunction(
Function &F)
override {
663 auto &PDT = getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
664 return AggressiveDeadCodeElimination(F, PDT).performDeadCodeElimination();
678 "Aggressive Dead Code Elimination",
false,
false)
Legacy wrapper pass to provide the GlobalsAAResult object.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
const_iterator end(StringRef path)
Get end iterator over path.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
void dropAllReferences()
Drop all references to operands.
Aggressive Dead Code Elimination
STATISTIC(NumFunctions,"Total number of functions")
This is the interface for a simple mod/ref and alias analysis over globals.
static cl::opt< bool > RemoveControlFlowFlag("adce-remove-control-flow", cl::init(true), cl::Hidden)
This class represents a function call, abstracting a target machine's calling convention.
bool mayHaveSideEffects() const
Return true if the instruction may have side effects.
static cl::opt< bool > RemoveLoops("adce-remove-loops", cl::init(false), cl::Hidden)
StringRef getName() const
Return a constant reference to the value's name.
Aggressive Dead Code false
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
void initializeADCELegacyPassPass(PassRegistry &)
static cl::opt< bool > Aggressive("aggressive-ext-opt", cl::Hidden, cl::desc("Aggressive extension optimization"))
A Use represents the edge between a Value definition and its users.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Interval::succ_iterator succ_begin(Interval *I)
succ_begin/succ_end - define methods so that Intervals may be used just like BasicBlocks can with the...
DIScopeRef getScope() const
void setSuccessor(unsigned idx, BasicBlock *B)
Update the specified successor to point at the provided block.
Interval::succ_iterator succ_end(Interval *I)
initializer< Ty > init(const Ty &Val)
Control flow instructions. These all have token chains.
Subclasses of this class are all able to terminate a basic block.
A set of analyses that are preserved following a run of a transformation pass.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs...ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
Conditional or Unconditional Branch instruction.
StringRef getInstrProfValueProfFuncName()
Return the name profile runtime entry point to do value profiling for a given site.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
iterator_range< df_ext_iterator< T, SetTy > > depth_first_ext(const T &G, SetTy &S)
Represent the analysis usage information of a pass.
Analysis pass providing a never-invalidated alias analysis result.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
FunctionPass class - This class is used to implement most global optimizations.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
void dump() const
Support for debugging, callable in GDB: V->dump()
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
auto find(R &&Range, const T &Val) -> decltype(std::begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Analysis pass which computes a PostDominatorTree.
pred_range predecessors(BasicBlock *BB)
void setPreservesCFG()
This function should be called by the pass, iff they do not:
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Target - Wrapper for Target specific information.
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringRef > StandardNames)
initialize - Initialize the set of available library functions based on the specified target triple...
static bool isUnconditionalBranch(TerminatorInst *Term)
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
iterator_range< ipo_ext_iterator< T, SetType > > inverse_post_order_ext(const T &G, SetType &S)
bool isEHPad() const
Return true if the instruction is a variety of EH-block.
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Determine the iterated dominance frontier, given a set of defining blocks, and optionally, a set of live-in blocks.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
succ_range successors(BasicBlock *BB)
static bool isAlwaysLive(Instruction *I)
INITIALIZE_PASS_BEGIN(ADCELegacyPass,"adce","Aggressive Dead Code Elimination", false, false) INITIALIZE_PASS_END(ADCELegacyPass
inst_range instructions(Function *F)
A container for analyses that lazily runs them and caches their results.
const BasicBlock * getParent() const
FunctionPass * createAggressiveDCEPass()