xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Scalar/DCE.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- DCE.cpp - Code to perform dead code elimination --------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements dead inst elimination and dead code elimination.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric // Dead Inst Elimination performs a single pass over the function removing
120b57cec5SDimitry Andric // instructions that are obviously dead.  Dead Code Elimination is similar, but
130b57cec5SDimitry Andric // it rechecks instructions that were used by removed instructions to see if
140b57cec5SDimitry Andric // they are newly dead.
150b57cec5SDimitry Andric //
160b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/DCE.h"
190b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
200b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
210b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
220b57cec5SDimitry Andric #include "llvm/IR/InstIterator.h"
230b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
24480093f4SDimitry Andric #include "llvm/InitializePasses.h"
250b57cec5SDimitry Andric #include "llvm/Pass.h"
260b57cec5SDimitry Andric #include "llvm/Support/DebugCounter.h"
270b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h"
285ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
29480093f4SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
30480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
310b57cec5SDimitry Andric using namespace llvm;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric #define DEBUG_TYPE "dce"
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric STATISTIC(DCEEliminated, "Number of insts removed");
360b57cec5SDimitry Andric DEBUG_COUNTER(DCECounter, "dce-transform",
370b57cec5SDimitry Andric               "Controls which instructions are eliminated");
380b57cec5SDimitry Andric 
39e8d8bef9SDimitry Andric PreservedAnalyses
run(Function & F,FunctionAnalysisManager & AM)40e8d8bef9SDimitry Andric RedundantDbgInstEliminationPass::run(Function &F, FunctionAnalysisManager &AM) {
41e8d8bef9SDimitry Andric   bool Changed = false;
42e8d8bef9SDimitry Andric   for (auto &BB : F)
43e8d8bef9SDimitry Andric     Changed |= RemoveRedundantDbgInstrs(&BB);
44e8d8bef9SDimitry Andric   if (!Changed)
45e8d8bef9SDimitry Andric     return PreservedAnalyses::all();
46e8d8bef9SDimitry Andric   PreservedAnalyses PA;
47e8d8bef9SDimitry Andric   PA.preserveSet<CFGAnalyses>();
48e8d8bef9SDimitry Andric   return PA;
49e8d8bef9SDimitry Andric }
50e8d8bef9SDimitry Andric 
51480093f4SDimitry Andric //===--------------------------------------------------------------------===//
52480093f4SDimitry Andric // DeadCodeElimination pass implementation
53480093f4SDimitry Andric //
54480093f4SDimitry Andric 
DCEInstruction(Instruction * I,SmallSetVector<Instruction *,16> & WorkList,const TargetLibraryInfo * TLI)550b57cec5SDimitry Andric static bool DCEInstruction(Instruction *I,
560b57cec5SDimitry Andric                            SmallSetVector<Instruction *, 16> &WorkList,
570b57cec5SDimitry Andric                            const TargetLibraryInfo *TLI) {
580b57cec5SDimitry Andric   if (isInstructionTriviallyDead(I, TLI)) {
590b57cec5SDimitry Andric     if (!DebugCounter::shouldExecute(DCECounter))
600b57cec5SDimitry Andric       return false;
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric     salvageDebugInfo(*I);
635ffd83dbSDimitry Andric     salvageKnowledge(I);
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric     // Null out all of the instruction's operands to see if any operand becomes
660b57cec5SDimitry Andric     // dead as we go.
670b57cec5SDimitry Andric     for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
680b57cec5SDimitry Andric       Value *OpV = I->getOperand(i);
690b57cec5SDimitry Andric       I->setOperand(i, nullptr);
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric       if (!OpV->use_empty() || I == OpV)
720b57cec5SDimitry Andric         continue;
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric       // If the operand is an instruction that became dead as we nulled out the
750b57cec5SDimitry Andric       // operand, and if it is 'trivially' dead, delete it in a future loop
760b57cec5SDimitry Andric       // iteration.
770b57cec5SDimitry Andric       if (Instruction *OpI = dyn_cast<Instruction>(OpV))
780b57cec5SDimitry Andric         if (isInstructionTriviallyDead(OpI, TLI))
790b57cec5SDimitry Andric           WorkList.insert(OpI);
800b57cec5SDimitry Andric     }
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric     I->eraseFromParent();
830b57cec5SDimitry Andric     ++DCEEliminated;
840b57cec5SDimitry Andric     return true;
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric   return false;
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric 
eliminateDeadCode(Function & F,TargetLibraryInfo * TLI)890b57cec5SDimitry Andric static bool eliminateDeadCode(Function &F, TargetLibraryInfo *TLI) {
900b57cec5SDimitry Andric   bool MadeChange = false;
910b57cec5SDimitry Andric   SmallSetVector<Instruction *, 16> WorkList;
920b57cec5SDimitry Andric   // Iterate over the original function, only adding insts to the worklist
930b57cec5SDimitry Andric   // if they actually need to be revisited. This avoids having to pre-init
940b57cec5SDimitry Andric   // the worklist with the entire function's worth of instructions.
95*fe6060f1SDimitry Andric   for (Instruction &I : llvm::make_early_inc_range(instructions(F))) {
960b57cec5SDimitry Andric     // We're visiting this instruction now, so make sure it's not in the
970b57cec5SDimitry Andric     // worklist from an earlier visit.
98*fe6060f1SDimitry Andric     if (!WorkList.count(&I))
99*fe6060f1SDimitry Andric       MadeChange |= DCEInstruction(&I, WorkList, TLI);
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   while (!WorkList.empty()) {
1030b57cec5SDimitry Andric     Instruction *I = WorkList.pop_back_val();
1040b57cec5SDimitry Andric     MadeChange |= DCEInstruction(I, WorkList, TLI);
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric   return MadeChange;
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
run(Function & F,FunctionAnalysisManager & AM)1090b57cec5SDimitry Andric PreservedAnalyses DCEPass::run(Function &F, FunctionAnalysisManager &AM) {
110e8d8bef9SDimitry Andric   if (!eliminateDeadCode(F, &AM.getResult<TargetLibraryAnalysis>(F)))
1110b57cec5SDimitry Andric     return PreservedAnalyses::all();
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   PreservedAnalyses PA;
1140b57cec5SDimitry Andric   PA.preserveSet<CFGAnalyses>();
1150b57cec5SDimitry Andric   return PA;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric namespace {
1190b57cec5SDimitry Andric struct DCELegacyPass : public FunctionPass {
1200b57cec5SDimitry Andric   static char ID; // Pass identification, replacement for typeid
DCELegacyPass__anoncaca06510111::DCELegacyPass1210b57cec5SDimitry Andric   DCELegacyPass() : FunctionPass(ID) {
1220b57cec5SDimitry Andric     initializeDCELegacyPassPass(*PassRegistry::getPassRegistry());
1230b57cec5SDimitry Andric   }
1240b57cec5SDimitry Andric 
runOnFunction__anoncaca06510111::DCELegacyPass1250b57cec5SDimitry Andric   bool runOnFunction(Function &F) override {
1260b57cec5SDimitry Andric     if (skipFunction(F))
1270b57cec5SDimitry Andric       return false;
1280b57cec5SDimitry Andric 
129e8d8bef9SDimitry Andric     TargetLibraryInfo *TLI =
130e8d8bef9SDimitry Andric         &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric     return eliminateDeadCode(F, TLI);
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric 
getAnalysisUsage__anoncaca06510111::DCELegacyPass1350b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
136e8d8bef9SDimitry Andric     AU.addRequired<TargetLibraryInfoWrapperPass>();
1370b57cec5SDimitry Andric     AU.setPreservesCFG();
1380b57cec5SDimitry Andric   }
1390b57cec5SDimitry Andric };
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric char DCELegacyPass::ID = 0;
1430b57cec5SDimitry Andric INITIALIZE_PASS(DCELegacyPass, "dce", "Dead Code Elimination", false, false)
1440b57cec5SDimitry Andric 
createDeadCodeEliminationPass()1450b57cec5SDimitry Andric FunctionPass *llvm::createDeadCodeEliminationPass() {
1460b57cec5SDimitry Andric   return new DCELegacyPass();
1470b57cec5SDimitry Andric }
148