1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
//===- DCE.cpp - Code to perform dead code elimination --------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements dead inst elimination and dead code elimination.
//
// Dead Inst Elimination performs a single pass over the function removing
// instructions that are obviously dead. Dead Code Elimination is similar, but
// it rechecks instructions that were used by removed instructions to see if
// they are newly dead.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Scalar/DCE.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instruction.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/DebugCounter.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
using namespace llvm;
#define DEBUG_TYPE "dce"
STATISTIC(DCEEliminated, "Number of insts removed");
DEBUG_COUNTER(DCECounter, "dce-transform",
"Controls which instructions are eliminated");
//===--------------------------------------------------------------------===//
// RedundantDbgInstElimination pass implementation
//
namespace {
struct RedundantDbgInstElimination : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
RedundantDbgInstElimination() : FunctionPass(ID) {
initializeRedundantDbgInstEliminationPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override {
if (skipFunction(F))
return false;
bool Changed = false;
for (auto &BB : F)
Changed |= RemoveRedundantDbgInstrs(&BB);
return Changed;
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
}
};
}
char RedundantDbgInstElimination::ID = 0;
INITIALIZE_PASS(RedundantDbgInstElimination, "redundant-dbg-inst-elim",
"Redundant Dbg Instruction Elimination", false, false)
Pass *llvm::createRedundantDbgInstEliminationPass() {
return new RedundantDbgInstElimination();
}
PreservedAnalyses
RedundantDbgInstEliminationPass::run(Function &F, FunctionAnalysisManager &AM) {
bool Changed = false;
for (auto &BB : F)
Changed |= RemoveRedundantDbgInstrs(&BB);
if (!Changed)
return PreservedAnalyses::all();
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
return PA;
}
//===--------------------------------------------------------------------===//
// DeadCodeElimination pass implementation
//
static bool DCEInstruction(Instruction *I,
SmallSetVector<Instruction *, 16> &WorkList,
const TargetLibraryInfo *TLI) {
if (isInstructionTriviallyDead(I, TLI)) {
if (!DebugCounter::shouldExecute(DCECounter))
return false;
salvageDebugInfo(*I);
salvageKnowledge(I);
// Null out all of the instruction's operands to see if any operand becomes
// dead as we go.
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
Value *OpV = I->getOperand(i);
I->setOperand(i, nullptr);
if (!OpV->use_empty() || I == OpV)
continue;
// If the operand is an instruction that became dead as we nulled out the
// operand, and if it is 'trivially' dead, delete it in a future loop
// iteration.
if (Instruction *OpI = dyn_cast<Instruction>(OpV))
if (isInstructionTriviallyDead(OpI, TLI))
WorkList.insert(OpI);
}
I->eraseFromParent();
++DCEEliminated;
return true;
}
return false;
}
static bool eliminateDeadCode(Function &F, TargetLibraryInfo *TLI) {
bool MadeChange = false;
SmallSetVector<Instruction *, 16> WorkList;
// Iterate over the original function, only adding insts to the worklist
// if they actually need to be revisited. This avoids having to pre-init
// the worklist with the entire function's worth of instructions.
for (Instruction &I : llvm::make_early_inc_range(instructions(F))) {
// We're visiting this instruction now, so make sure it's not in the
// worklist from an earlier visit.
if (!WorkList.count(&I))
MadeChange |= DCEInstruction(&I, WorkList, TLI);
}
while (!WorkList.empty()) {
Instruction *I = WorkList.pop_back_val();
MadeChange |= DCEInstruction(I, WorkList, TLI);
}
return MadeChange;
}
PreservedAnalyses DCEPass::run(Function &F, FunctionAnalysisManager &AM) {
if (!eliminateDeadCode(F, &AM.getResult<TargetLibraryAnalysis>(F)))
return PreservedAnalyses::all();
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
return PA;
}
namespace {
struct DCELegacyPass : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
DCELegacyPass() : FunctionPass(ID) {
initializeDCELegacyPassPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override {
if (skipFunction(F))
return false;
TargetLibraryInfo *TLI =
&getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
return eliminateDeadCode(F, TLI);
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<TargetLibraryInfoWrapperPass>();
AU.setPreservesCFG();
}
};
}
char DCELegacyPass::ID = 0;
INITIALIZE_PASS(DCELegacyPass, "dce", "Dead Code Elimination", false, false)
FunctionPass *llvm::createDeadCodeEliminationPass() {
return new DCELegacyPass();
}
|