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