12f7c9635SChris Lattner //===- DCE.cpp - Code to perform dead code elimination --------------------===//
22f7c9635SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6482202a6SJohn Criswell //
7482202a6SJohn Criswell //===----------------------------------------------------------------------===//
8482202a6SJohn Criswell //
987e8806fSChris Lattner // This file implements dead inst elimination and dead code elimination.
102f7c9635SChris Lattner //
1187e8806fSChris Lattner // Dead Inst Elimination performs a single pass over the function removing
1287e8806fSChris Lattner // instructions that are obviously dead.  Dead Code Elimination is similar, but
1387e8806fSChris Lattner // it rechecks instructions that were used by removed instructions to see if
1487e8806fSChris Lattner // they are newly dead.
155ba5f88cSChris Lattner //
162f7c9635SChris Lattner //===----------------------------------------------------------------------===//
172f7c9635SChris Lattner 
18395c2127SJustin Bogner #include "llvm/Transforms/Scalar/DCE.h"
19b0c6d917SFiona Glaser #include "llvm/ADT/SetVector.h"
20ed0881b2SChandler Carruth #include "llvm/ADT/Statistic.h"
216bda14b3SChandler Carruth #include "llvm/Analysis/TargetLibraryInfo.h"
228394857fSChandler Carruth #include "llvm/IR/InstIterator.h"
239fb823bbSChandler Carruth #include "llvm/IR/Instruction.h"
2405da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
2504805fa2SChris Lattner #include "llvm/Pass.h"
267a8dc3daSGeorge Burgess IV #include "llvm/Support/DebugCounter.h"
27395c2127SJustin Bogner #include "llvm/Transforms/Scalar.h"
283bdfa966STyker #include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
291c49553cSBjorn Pettersson #include "llvm/Transforms/Utils/BasicBlockUtils.h"
3005da2fe5SReid Kleckner #include "llvm/Transforms/Utils/Local.h"
3149525f8cSChris Lattner using namespace llvm;
32960707c3SBrian Gaeke 
33964daaafSChandler Carruth #define DEBUG_TYPE "dce"
34964daaafSChandler Carruth 
3579a42ac9SChris Lattner STATISTIC(DCEEliminated, "Number of insts removed");
367a8dc3daSGeorge Burgess IV DEBUG_COUNTER(DCECounter, "dce-transform",
377a8dc3daSGeorge Burgess IV               "Controls which instructions are eliminated");
380b18c1d6SChris Lattner 
391c49553cSBjorn Pettersson //===--------------------------------------------------------------------===//
401c49553cSBjorn Pettersson // RedundantDbgInstElimination pass implementation
411c49553cSBjorn Pettersson //
421c49553cSBjorn Pettersson 
431c49553cSBjorn Pettersson namespace {
441c49553cSBjorn Pettersson struct RedundantDbgInstElimination : public FunctionPass {
451c49553cSBjorn Pettersson   static char ID; // Pass identification, replacement for typeid
RedundantDbgInstElimination__anona134866f0111::RedundantDbgInstElimination461c49553cSBjorn Pettersson   RedundantDbgInstElimination() : FunctionPass(ID) {
471c49553cSBjorn Pettersson     initializeRedundantDbgInstEliminationPass(*PassRegistry::getPassRegistry());
481c49553cSBjorn Pettersson   }
runOnFunction__anona134866f0111::RedundantDbgInstElimination491c49553cSBjorn Pettersson   bool runOnFunction(Function &F) override {
501c49553cSBjorn Pettersson     if (skipFunction(F))
511c49553cSBjorn Pettersson       return false;
521c49553cSBjorn Pettersson     bool Changed = false;
531c49553cSBjorn Pettersson     for (auto &BB : F)
541c49553cSBjorn Pettersson       Changed |= RemoveRedundantDbgInstrs(&BB);
551c49553cSBjorn Pettersson     return Changed;
561c49553cSBjorn Pettersson   }
571c49553cSBjorn Pettersson 
getAnalysisUsage__anona134866f0111::RedundantDbgInstElimination581c49553cSBjorn Pettersson   void getAnalysisUsage(AnalysisUsage &AU) const override {
591c49553cSBjorn Pettersson     AU.setPreservesCFG();
601c49553cSBjorn Pettersson   }
611c49553cSBjorn Pettersson };
621c49553cSBjorn Pettersson }
631c49553cSBjorn Pettersson 
641c49553cSBjorn Pettersson char RedundantDbgInstElimination::ID = 0;
651c49553cSBjorn Pettersson INITIALIZE_PASS(RedundantDbgInstElimination, "redundant-dbg-inst-elim",
661c49553cSBjorn Pettersson                 "Redundant Dbg Instruction Elimination", false, false)
671c49553cSBjorn Pettersson 
createRedundantDbgInstEliminationPass()681c49553cSBjorn Pettersson Pass *llvm::createRedundantDbgInstEliminationPass() {
691c49553cSBjorn Pettersson   return new RedundantDbgInstElimination();
701c49553cSBjorn Pettersson }
711c49553cSBjorn Pettersson 
726e04da0aSArthur Eubanks PreservedAnalyses
run(Function & F,FunctionAnalysisManager & AM)736e04da0aSArthur Eubanks RedundantDbgInstEliminationPass::run(Function &F, FunctionAnalysisManager &AM) {
746e04da0aSArthur Eubanks   bool Changed = false;
756e04da0aSArthur Eubanks   for (auto &BB : F)
766e04da0aSArthur Eubanks     Changed |= RemoveRedundantDbgInstrs(&BB);
776e04da0aSArthur Eubanks   if (!Changed)
786e04da0aSArthur Eubanks     return PreservedAnalyses::all();
796e04da0aSArthur Eubanks   PreservedAnalyses PA;
806e04da0aSArthur Eubanks   PA.preserveSet<CFGAnalyses>();
816e04da0aSArthur Eubanks   return PA;
826e04da0aSArthur Eubanks }
836e04da0aSArthur Eubanks 
841c49553cSBjorn Pettersson //===--------------------------------------------------------------------===//
851c49553cSBjorn Pettersson // DeadCodeElimination pass implementation
861c49553cSBjorn Pettersson //
871c49553cSBjorn Pettersson 
DCEInstruction(Instruction * I,SmallSetVector<Instruction *,16> & WorkList,const TargetLibraryInfo * TLI)88b0c6d917SFiona Glaser static bool DCEInstruction(Instruction *I,
89b0c6d917SFiona Glaser                            SmallSetVector<Instruction *, 16> &WorkList,
90b0c6d917SFiona Glaser                            const TargetLibraryInfo *TLI) {
91b0c6d917SFiona Glaser   if (isInstructionTriviallyDead(I, TLI)) {
927a8dc3daSGeorge Burgess IV     if (!DebugCounter::shouldExecute(DCECounter))
937a8dc3daSGeorge Burgess IV       return false;
947a8dc3daSGeorge Burgess IV 
951df820ecSVedant Kumar     salvageDebugInfo(*I);
963bdfa966STyker     salvageKnowledge(I);
971df820ecSVedant Kumar 
98b0c6d917SFiona Glaser     // Null out all of the instruction's operands to see if any operand becomes
99b0c6d917SFiona Glaser     // dead as we go.
100b0c6d917SFiona Glaser     for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
101b0c6d917SFiona Glaser       Value *OpV = I->getOperand(i);
102b0c6d917SFiona Glaser       I->setOperand(i, nullptr);
103b0c6d917SFiona Glaser 
104b0c6d917SFiona Glaser       if (!OpV->use_empty() || I == OpV)
105b0c6d917SFiona Glaser         continue;
106b0c6d917SFiona Glaser 
107b0c6d917SFiona Glaser       // If the operand is an instruction that became dead as we nulled out the
108b0c6d917SFiona Glaser       // operand, and if it is 'trivially' dead, delete it in a future loop
109b0c6d917SFiona Glaser       // iteration.
110b0c6d917SFiona Glaser       if (Instruction *OpI = dyn_cast<Instruction>(OpV))
111b0c6d917SFiona Glaser         if (isInstructionTriviallyDead(OpI, TLI))
112b0c6d917SFiona Glaser           WorkList.insert(OpI);
113b0c6d917SFiona Glaser     }
114b0c6d917SFiona Glaser 
115b0c6d917SFiona Glaser     I->eraseFromParent();
116b0c6d917SFiona Glaser     ++DCEEliminated;
117b0c6d917SFiona Glaser     return true;
118b0c6d917SFiona Glaser   }
119b0c6d917SFiona Glaser   return false;
120b0c6d917SFiona Glaser }
121b0c6d917SFiona Glaser 
eliminateDeadCode(Function & F,TargetLibraryInfo * TLI)122a65b610bSBenjamin Kramer static bool eliminateDeadCode(Function &F, TargetLibraryInfo *TLI) {
1234922118dSChris Lattner   bool MadeChange = false;
124b0c6d917SFiona Glaser   SmallSetVector<Instruction *, 16> WorkList;
125b0c6d917SFiona Glaser   // Iterate over the original function, only adding insts to the worklist
126b0c6d917SFiona Glaser   // if they actually need to be revisited. This avoids having to pre-init
127b0c6d917SFiona Glaser   // the worklist with the entire function's worth of instructions.
128*5fc9e309SKazu Hirata   for (Instruction &I : llvm::make_early_inc_range(instructions(F))) {
129b0c6d917SFiona Glaser     // We're visiting this instruction now, so make sure it's not in the
130b0c6d917SFiona Glaser     // worklist from an earlier visit.
131*5fc9e309SKazu Hirata     if (!WorkList.count(&I))
132*5fc9e309SKazu Hirata       MadeChange |= DCEInstruction(&I, WorkList, TLI);
13387e8806fSChris Lattner   }
134b0c6d917SFiona Glaser 
135b0c6d917SFiona Glaser   while (!WorkList.empty()) {
136b0c6d917SFiona Glaser     Instruction *I = WorkList.pop_back_val();
137b0c6d917SFiona Glaser     MadeChange |= DCEInstruction(I, WorkList, TLI);
1384922118dSChris Lattner   }
1394922118dSChris Lattner   return MadeChange;
14087e8806fSChris Lattner }
14187e8806fSChris Lattner 
run(Function & F,FunctionAnalysisManager & AM)14236e0d01eSSean Silva PreservedAnalyses DCEPass::run(Function &F, FunctionAnalysisManager &AM) {
143ee7d315cSArthur Eubanks   if (!eliminateDeadCode(F, &AM.getResult<TargetLibraryAnalysis>(F)))
144395c2127SJustin Bogner     return PreservedAnalyses::all();
145ca68a3ecSChandler Carruth 
146ca68a3ecSChandler Carruth   PreservedAnalyses PA;
147ca68a3ecSChandler Carruth   PA.preserveSet<CFGAnalyses>();
148ca68a3ecSChandler Carruth   return PA;
14904805fa2SChris Lattner }
150960707c3SBrian Gaeke 
151395c2127SJustin Bogner namespace {
152395c2127SJustin Bogner struct DCELegacyPass : public FunctionPass {
153395c2127SJustin Bogner   static char ID; // Pass identification, replacement for typeid
DCELegacyPass__anona134866f0211::DCELegacyPass154395c2127SJustin Bogner   DCELegacyPass() : FunctionPass(ID) {
155395c2127SJustin Bogner     initializeDCELegacyPassPass(*PassRegistry::getPassRegistry());
156395c2127SJustin Bogner   }
157395c2127SJustin Bogner 
runOnFunction__anona134866f0211::DCELegacyPass158395c2127SJustin Bogner   bool runOnFunction(Function &F) override {
159aa641a51SAndrew Kaylor     if (skipFunction(F))
160395c2127SJustin Bogner       return false;
161395c2127SJustin Bogner 
162ee7d315cSArthur Eubanks     TargetLibraryInfo *TLI =
163ee7d315cSArthur Eubanks         &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
164395c2127SJustin Bogner 
165395c2127SJustin Bogner     return eliminateDeadCode(F, TLI);
166395c2127SJustin Bogner   }
167395c2127SJustin Bogner 
getAnalysisUsage__anona134866f0211::DCELegacyPass168395c2127SJustin Bogner   void getAnalysisUsage(AnalysisUsage &AU) const override {
169ee7d315cSArthur Eubanks     AU.addRequired<TargetLibraryInfoWrapperPass>();
170395c2127SJustin Bogner     AU.setPreservesCFG();
171395c2127SJustin Bogner   }
172395c2127SJustin Bogner };
173395c2127SJustin Bogner }
174395c2127SJustin Bogner 
175395c2127SJustin Bogner char DCELegacyPass::ID = 0;
176395c2127SJustin Bogner INITIALIZE_PASS(DCELegacyPass, "dce", "Dead Code Elimination", false, false)
177395c2127SJustin Bogner 
createDeadCodeEliminationPass()178395c2127SJustin Bogner FunctionPass *llvm::createDeadCodeEliminationPass() {
179395c2127SJustin Bogner   return new DCELegacyPass();
180395c2127SJustin Bogner }
181