xref: /aosp_15_r20/external/llvm/lib/Transforms/Scalar/ADCE.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- ADCE.cpp - Code to perform dead code elimination -------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the Aggressive Dead Code Elimination pass.  This pass
11*9880d681SAndroid Build Coastguard Worker // optimistically assumes that all instructions are dead until proven otherwise,
12*9880d681SAndroid Build Coastguard Worker // allowing it to eliminate dead computations that other DCE passes do not
13*9880d681SAndroid Build Coastguard Worker // catch, particularly involving loop computations.
14*9880d681SAndroid Build Coastguard Worker //
15*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
16*9880d681SAndroid Build Coastguard Worker 
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Scalar/ADCE.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DepthFirstIterator.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallPtrSet.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/GlobalsModRef.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/BasicBlock.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/CFG.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DebugInfoMetadata.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/InstIterator.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IntrinsicInst.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/ProfileData/InstrProf.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Scalar.h"
32*9880d681SAndroid Build Coastguard Worker using namespace llvm;
33*9880d681SAndroid Build Coastguard Worker 
34*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "adce"
35*9880d681SAndroid Build Coastguard Worker 
36*9880d681SAndroid Build Coastguard Worker STATISTIC(NumRemoved, "Number of instructions removed");
37*9880d681SAndroid Build Coastguard Worker 
collectLiveScopes(const DILocalScope & LS,SmallPtrSetImpl<const Metadata * > & AliveScopes)38*9880d681SAndroid Build Coastguard Worker static void collectLiveScopes(const DILocalScope &LS,
39*9880d681SAndroid Build Coastguard Worker                               SmallPtrSetImpl<const Metadata *> &AliveScopes) {
40*9880d681SAndroid Build Coastguard Worker   if (!AliveScopes.insert(&LS).second)
41*9880d681SAndroid Build Coastguard Worker     return;
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker   if (isa<DISubprogram>(LS))
44*9880d681SAndroid Build Coastguard Worker     return;
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker   // Tail-recurse through the scope chain.
47*9880d681SAndroid Build Coastguard Worker   collectLiveScopes(cast<DILocalScope>(*LS.getScope()), AliveScopes);
48*9880d681SAndroid Build Coastguard Worker }
49*9880d681SAndroid Build Coastguard Worker 
collectLiveScopes(const DILocation & DL,SmallPtrSetImpl<const Metadata * > & AliveScopes)50*9880d681SAndroid Build Coastguard Worker static void collectLiveScopes(const DILocation &DL,
51*9880d681SAndroid Build Coastguard Worker                               SmallPtrSetImpl<const Metadata *> &AliveScopes) {
52*9880d681SAndroid Build Coastguard Worker   // Even though DILocations are not scopes, shove them into AliveScopes so we
53*9880d681SAndroid Build Coastguard Worker   // don't revisit them.
54*9880d681SAndroid Build Coastguard Worker   if (!AliveScopes.insert(&DL).second)
55*9880d681SAndroid Build Coastguard Worker     return;
56*9880d681SAndroid Build Coastguard Worker 
57*9880d681SAndroid Build Coastguard Worker   // Collect live scopes from the scope chain.
58*9880d681SAndroid Build Coastguard Worker   collectLiveScopes(*DL.getScope(), AliveScopes);
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker   // Tail-recurse through the inlined-at chain.
61*9880d681SAndroid Build Coastguard Worker   if (const DILocation *IA = DL.getInlinedAt())
62*9880d681SAndroid Build Coastguard Worker     collectLiveScopes(*IA, AliveScopes);
63*9880d681SAndroid Build Coastguard Worker }
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker // Check if this instruction is a runtime call for value profiling and
66*9880d681SAndroid Build Coastguard Worker // if it's instrumenting a constant.
isInstrumentsConstant(Instruction & I)67*9880d681SAndroid Build Coastguard Worker static bool isInstrumentsConstant(Instruction &I) {
68*9880d681SAndroid Build Coastguard Worker   if (CallInst *CI = dyn_cast<CallInst>(&I))
69*9880d681SAndroid Build Coastguard Worker     if (Function *Callee = CI->getCalledFunction())
70*9880d681SAndroid Build Coastguard Worker       if (Callee->getName().equals(getInstrProfValueProfFuncName()))
71*9880d681SAndroid Build Coastguard Worker         if (isa<Constant>(CI->getArgOperand(0)))
72*9880d681SAndroid Build Coastguard Worker           return true;
73*9880d681SAndroid Build Coastguard Worker   return false;
74*9880d681SAndroid Build Coastguard Worker }
75*9880d681SAndroid Build Coastguard Worker 
aggressiveDCE(Function & F)76*9880d681SAndroid Build Coastguard Worker static bool aggressiveDCE(Function& F) {
77*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<Instruction*, 32> Alive;
78*9880d681SAndroid Build Coastguard Worker   SmallVector<Instruction*, 128> Worklist;
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker   // Collect the set of "root" instructions that are known live.
81*9880d681SAndroid Build Coastguard Worker   for (Instruction &I : instructions(F)) {
82*9880d681SAndroid Build Coastguard Worker     if (isa<TerminatorInst>(I) || I.isEHPad() || I.mayHaveSideEffects()) {
83*9880d681SAndroid Build Coastguard Worker       // Skip any value profile instrumentation calls if they are
84*9880d681SAndroid Build Coastguard Worker       // instrumenting constants.
85*9880d681SAndroid Build Coastguard Worker       if (isInstrumentsConstant(I))
86*9880d681SAndroid Build Coastguard Worker         continue;
87*9880d681SAndroid Build Coastguard Worker       Alive.insert(&I);
88*9880d681SAndroid Build Coastguard Worker       Worklist.push_back(&I);
89*9880d681SAndroid Build Coastguard Worker     }
90*9880d681SAndroid Build Coastguard Worker   }
91*9880d681SAndroid Build Coastguard Worker 
92*9880d681SAndroid Build Coastguard Worker   // Propagate liveness backwards to operands.  Keep track of live debug info
93*9880d681SAndroid Build Coastguard Worker   // scopes.
94*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<const Metadata *, 32> AliveScopes;
95*9880d681SAndroid Build Coastguard Worker   while (!Worklist.empty()) {
96*9880d681SAndroid Build Coastguard Worker     Instruction *Curr = Worklist.pop_back_val();
97*9880d681SAndroid Build Coastguard Worker 
98*9880d681SAndroid Build Coastguard Worker     // Collect the live debug info scopes attached to this instruction.
99*9880d681SAndroid Build Coastguard Worker     if (const DILocation *DL = Curr->getDebugLoc())
100*9880d681SAndroid Build Coastguard Worker       collectLiveScopes(*DL, AliveScopes);
101*9880d681SAndroid Build Coastguard Worker 
102*9880d681SAndroid Build Coastguard Worker     for (Use &OI : Curr->operands()) {
103*9880d681SAndroid Build Coastguard Worker       if (Instruction *Inst = dyn_cast<Instruction>(OI))
104*9880d681SAndroid Build Coastguard Worker         if (Alive.insert(Inst).second)
105*9880d681SAndroid Build Coastguard Worker           Worklist.push_back(Inst);
106*9880d681SAndroid Build Coastguard Worker     }
107*9880d681SAndroid Build Coastguard Worker   }
108*9880d681SAndroid Build Coastguard Worker 
109*9880d681SAndroid Build Coastguard Worker   // The inverse of the live set is the dead set.  These are those instructions
110*9880d681SAndroid Build Coastguard Worker   // which have no side effects and do not influence the control flow or return
111*9880d681SAndroid Build Coastguard Worker   // value of the function, and may therefore be deleted safely.
112*9880d681SAndroid Build Coastguard Worker   // NOTE: We reuse the Worklist vector here for memory efficiency.
113*9880d681SAndroid Build Coastguard Worker   for (Instruction &I : instructions(F)) {
114*9880d681SAndroid Build Coastguard Worker     // Check if the instruction is alive.
115*9880d681SAndroid Build Coastguard Worker     if (Alive.count(&I))
116*9880d681SAndroid Build Coastguard Worker       continue;
117*9880d681SAndroid Build Coastguard Worker 
118*9880d681SAndroid Build Coastguard Worker     if (auto *DII = dyn_cast<DbgInfoIntrinsic>(&I)) {
119*9880d681SAndroid Build Coastguard Worker       // Check if the scope of this variable location is alive.
120*9880d681SAndroid Build Coastguard Worker       if (AliveScopes.count(DII->getDebugLoc()->getScope()))
121*9880d681SAndroid Build Coastguard Worker         continue;
122*9880d681SAndroid Build Coastguard Worker 
123*9880d681SAndroid Build Coastguard Worker       // Fallthrough and drop the intrinsic.
124*9880d681SAndroid Build Coastguard Worker       DEBUG({
125*9880d681SAndroid Build Coastguard Worker         // If intrinsic is pointing at a live SSA value, there may be an
126*9880d681SAndroid Build Coastguard Worker         // earlier optimization bug: if we know the location of the variable,
127*9880d681SAndroid Build Coastguard Worker         // why isn't the scope of the location alive?
128*9880d681SAndroid Build Coastguard Worker         if (Value *V = DII->getVariableLocation())
129*9880d681SAndroid Build Coastguard Worker           if (Instruction *II = dyn_cast<Instruction>(V))
130*9880d681SAndroid Build Coastguard Worker             if (Alive.count(II))
131*9880d681SAndroid Build Coastguard Worker               dbgs() << "Dropping debug info for " << *DII << "\n";
132*9880d681SAndroid Build Coastguard Worker       });
133*9880d681SAndroid Build Coastguard Worker     }
134*9880d681SAndroid Build Coastguard Worker 
135*9880d681SAndroid Build Coastguard Worker     // Prepare to delete.
136*9880d681SAndroid Build Coastguard Worker     Worklist.push_back(&I);
137*9880d681SAndroid Build Coastguard Worker     I.dropAllReferences();
138*9880d681SAndroid Build Coastguard Worker   }
139*9880d681SAndroid Build Coastguard Worker 
140*9880d681SAndroid Build Coastguard Worker   for (Instruction *&I : Worklist) {
141*9880d681SAndroid Build Coastguard Worker     ++NumRemoved;
142*9880d681SAndroid Build Coastguard Worker     I->eraseFromParent();
143*9880d681SAndroid Build Coastguard Worker   }
144*9880d681SAndroid Build Coastguard Worker 
145*9880d681SAndroid Build Coastguard Worker   return !Worklist.empty();
146*9880d681SAndroid Build Coastguard Worker }
147*9880d681SAndroid Build Coastguard Worker 
run(Function & F,FunctionAnalysisManager &)148*9880d681SAndroid Build Coastguard Worker PreservedAnalyses ADCEPass::run(Function &F, FunctionAnalysisManager &) {
149*9880d681SAndroid Build Coastguard Worker   if (!aggressiveDCE(F))
150*9880d681SAndroid Build Coastguard Worker     return PreservedAnalyses::all();
151*9880d681SAndroid Build Coastguard Worker 
152*9880d681SAndroid Build Coastguard Worker   // FIXME: This should also 'preserve the CFG'.
153*9880d681SAndroid Build Coastguard Worker   auto PA = PreservedAnalyses();
154*9880d681SAndroid Build Coastguard Worker   PA.preserve<GlobalsAA>();
155*9880d681SAndroid Build Coastguard Worker   return PA;
156*9880d681SAndroid Build Coastguard Worker }
157*9880d681SAndroid Build Coastguard Worker 
158*9880d681SAndroid Build Coastguard Worker namespace {
159*9880d681SAndroid Build Coastguard Worker struct ADCELegacyPass : public FunctionPass {
160*9880d681SAndroid Build Coastguard Worker   static char ID; // Pass identification, replacement for typeid
ADCELegacyPass__anond73cf7380111::ADCELegacyPass161*9880d681SAndroid Build Coastguard Worker   ADCELegacyPass() : FunctionPass(ID) {
162*9880d681SAndroid Build Coastguard Worker     initializeADCELegacyPassPass(*PassRegistry::getPassRegistry());
163*9880d681SAndroid Build Coastguard Worker   }
164*9880d681SAndroid Build Coastguard Worker 
runOnFunction__anond73cf7380111::ADCELegacyPass165*9880d681SAndroid Build Coastguard Worker   bool runOnFunction(Function& F) override {
166*9880d681SAndroid Build Coastguard Worker     if (skipFunction(F))
167*9880d681SAndroid Build Coastguard Worker       return false;
168*9880d681SAndroid Build Coastguard Worker     return aggressiveDCE(F);
169*9880d681SAndroid Build Coastguard Worker   }
170*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage__anond73cf7380111::ADCELegacyPass171*9880d681SAndroid Build Coastguard Worker   void getAnalysisUsage(AnalysisUsage& AU) const override {
172*9880d681SAndroid Build Coastguard Worker     AU.setPreservesCFG();
173*9880d681SAndroid Build Coastguard Worker     AU.addPreserved<GlobalsAAWrapperPass>();
174*9880d681SAndroid Build Coastguard Worker   }
175*9880d681SAndroid Build Coastguard Worker };
176*9880d681SAndroid Build Coastguard Worker }
177*9880d681SAndroid Build Coastguard Worker 
178*9880d681SAndroid Build Coastguard Worker char ADCELegacyPass::ID = 0;
179*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(ADCELegacyPass, "adce", "Aggressive Dead Code Elimination",
180*9880d681SAndroid Build Coastguard Worker                 false, false)
181*9880d681SAndroid Build Coastguard Worker 
createAggressiveDCEPass()182*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createAggressiveDCEPass() { return new ADCELegacyPass(); }
183