[ADCE] Refactoring for new functionality (NFC)

Summary:
This is another refactoring to break up the one function into three logical components functions.
Another non-functional change before we start added in features.

Reviewers: nadav, mehdi_amini, majnemer

Subscribers: twoh, freik, llvm-commits

Differential Revision: https://reviews.llvm.org/D23102

llvm-svn: 277855
This commit is contained in:
David Callahan 2016-08-05 19:38:11 +00:00
parent 6fa08aafcc
commit 45e442ebaa
1 changed files with 84 additions and 46 deletions

View File

@ -37,54 +37,71 @@ using namespace llvm;
STATISTIC(NumRemoved, "Number of instructions removed");
namespace {
class AgggressiveDeadCodeElimination {
class AggressiveDeadCodeElimination {
Function &F;
// Instructions known to be live
/// Instructions known to be live.
SmallPtrSet<Instruction *, 32> Alive;
// Instructions known to be live where we need to mark
// reaching definitions as live
/// Instructions known to be live where we need to mark
/// reaching definitions as live.
SmallVector<Instruction *, 128> Worklist;
// Debug info scopes around a live instruction
/// Debug info scopes around a live instruction.
SmallPtrSet<const Metadata *, 32> AliveScopes;
void initialize();
/// True for operations which are always treated as live.
bool isAlwaysLive(Instruction &I);
/// True for instrumentation instructions for value profiling.
bool isInstrumentsConstant(Instruction &I);
/// Propagate liveness to reaching definitions.
void markLiveInstructions();
/// Mark an instruction as live.
void markLive(Instruction &I);
void collectLiveScopes(const DILocalScope &LS);
void collectLiveScopes(const DILocation &DL);
bool isInstrumentsConstant(Instruction &I);
/// Remove instructions not marked live, return if any any instruction
/// was removed.
bool removeDeadInstructions();
public:
AgggressiveDeadCodeElimination(Function &F) : F(F) {}
bool aggressiveDCE();
AggressiveDeadCodeElimination(Function &F) : F(F) {}
bool performDeadCodeElimination();
};
}
void AgggressiveDeadCodeElimination::collectLiveScopes(
const DILocalScope &LS) {
if (!AliveScopes.insert(&LS).second)
return;
if (isa<DISubprogram>(LS))
return;
// Tail-recurse through the scope chain.
collectLiveScopes(cast<DILocalScope>(*LS.getScope()));
bool AggressiveDeadCodeElimination::performDeadCodeElimination() {
initialize();
markLiveInstructions();
return removeDeadInstructions();
}
void AgggressiveDeadCodeElimination::collectLiveScopes(const DILocation &DL) {
// Even though DILocations are not scopes, shove them into AliveScopes so we
// don't revisit them.
if (!AliveScopes.insert(&DL).second)
return;
void AggressiveDeadCodeElimination::initialize() {
// Collect the set of "root" instructions that are known live.
for (Instruction &I : instructions(F))
if (isAlwaysLive(I))
markLive(I);
}
// Collect live scopes from the scope chain.
collectLiveScopes(*DL.getScope());
bool AggressiveDeadCodeElimination::isAlwaysLive(Instruction &I) {
// Tail-recurse through the inlined-at chain.
if (const DILocation *IA = DL.getInlinedAt())
collectLiveScopes(*IA);
// TODO -- use llvm::isInstructionTriviallyDead
if (isa<TerminatorInst>(I) || I.isEHPad() || I.mayHaveSideEffects()) {
// Skip any value profile instrumentation calls if they are
// instrumenting constants.
if (!isInstrumentsConstant(I))
return true;
}
return false;
}
// Check if this instruction is a runtime call for value profiling and
// if it's instrumenting a constant.
bool AgggressiveDeadCodeElimination::isInstrumentsConstant(Instruction &I) {
bool AggressiveDeadCodeElimination::isInstrumentsConstant(Instruction &I) {
// TODO -- move this test into llvm::isInstructionTriviallyDead
if (CallInst *CI = dyn_cast<CallInst>(&I))
if (Function *Callee = CI->getCalledFunction())
if (Callee->getName().equals(getInstrProfValueProfFuncName()))
@ -93,19 +110,7 @@ bool AgggressiveDeadCodeElimination::isInstrumentsConstant(Instruction &I) {
return false;
}
bool AgggressiveDeadCodeElimination::aggressiveDCE() {
// Collect the set of "root" instructions that are known live.
for (Instruction &I : instructions(F)) {
if (isa<TerminatorInst>(I) || I.isEHPad() || I.mayHaveSideEffects()) {
// Skip any value profile instrumentation calls if they are
// instrumenting constants.
if (isInstrumentsConstant(I))
continue;
Alive.insert(&I);
Worklist.push_back(&I);
}
}
void AggressiveDeadCodeElimination::markLiveInstructions() {
// Propagate liveness backwards to operands. Keep track of live debug info
// scopes.
@ -118,10 +123,43 @@ bool AgggressiveDeadCodeElimination::aggressiveDCE() {
for (Use &OI : Curr->operands()) {
if (Instruction *Inst = dyn_cast<Instruction>(OI))
if (Alive.insert(Inst).second)
Worklist.push_back(Inst);
markLive(*Inst);
}
}
}
void AggressiveDeadCodeElimination::collectLiveScopes(const DILocalScope &LS) {
if (!AliveScopes.insert(&LS).second)
return;
if (isa<DISubprogram>(LS))
return;
// Tail-recurse through the scope chain.
collectLiveScopes(cast<DILocalScope>(*LS.getScope()));
}
void AggressiveDeadCodeElimination::collectLiveScopes(const DILocation &DL) {
// Even though DILocations are not scopes, shove them into AliveScopes so we
// don't revisit them.
if (!AliveScopes.insert(&DL).second)
return;
// Collect live scopes from the scope chain.
collectLiveScopes(*DL.getScope());
// Tail-recurse through the inlined-at chain.
if (const DILocation *IA = DL.getInlinedAt())
collectLiveScopes(*IA);
}
void AggressiveDeadCodeElimination::markLive(Instruction &I) {
if (!Alive.insert(&I).second)
return;
Worklist.push_back(&I);
}
bool AggressiveDeadCodeElimination::removeDeadInstructions() {
// The inverse of the live set is the dead set. These are those instructions
// which have no side effects and do not influence the control flow or return
@ -163,7 +201,7 @@ bool AgggressiveDeadCodeElimination::aggressiveDCE() {
}
PreservedAnalyses ADCEPass::run(Function &F, FunctionAnalysisManager &) {
if (!AgggressiveDeadCodeElimination(F).aggressiveDCE())
if (!AggressiveDeadCodeElimination(F).performDeadCodeElimination())
return PreservedAnalyses::all();
// FIXME: This should also 'preserve the CFG'.
@ -182,7 +220,7 @@ struct ADCELegacyPass : public FunctionPass {
bool runOnFunction(Function &F) override {
if (skipFunction(F))
return false;
return AgggressiveDeadCodeElimination(F).aggressiveDCE();
return AggressiveDeadCodeElimination(F).performDeadCodeElimination();
}
void getAnalysisUsage(AnalysisUsage &AU) const override {