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 &)