forked from OSchip/llvm-project
Improve performance of SimplifyInstructionsInBlock
1. Use a worklist, not a recursive approach, to avoid needless revisitation and being repeatedly forced to jump back to the start of the BB if a handle is invalidated. 2. Only insert operands to the worklist if they become unused after a dead instruction is removed, so we don’t have to visit them again in most cases. 3. Use a SmallSetVector to track the worklist. 4. Instead of pre-initting the SmallSetVector like in DeadCodeEliminationPass, only put things into the worklist if they have to be revisited after the first run-through. This minimizes how much the actual SmallSetVector gets used, which saves a lot of time. llvm-svn: 248727
This commit is contained in:
parent
dfc7200b18
commit
f74cc40e34
|
@ -17,6 +17,7 @@
|
|||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
|
@ -419,6 +420,49 @@ bool llvm::RecursivelyDeleteDeadPHINode(PHINode *PN,
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
simplifyAndDCEInstruction(Instruction *I,
|
||||
SmallSetVector<Instruction *, 16> &WorkList,
|
||||
const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
if (isInstructionTriviallyDead(I, TLI)) {
|
||||
// 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();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Value *SimpleV = SimplifyInstruction(I, DL)) {
|
||||
// Add the users to the worklist. CAREFUL: an instruction can use itself,
|
||||
// in the case of a phi node.
|
||||
for (User *U : I->users())
|
||||
if (U != I)
|
||||
WorkList.insert(cast<Instruction>(U));
|
||||
|
||||
// Replace the instruction with its simplified value.
|
||||
I->replaceAllUsesWith(SimpleV);
|
||||
I->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// SimplifyInstructionsInBlock - Scan the specified basic block and try to
|
||||
/// simplify any instructions in it and recursively delete dead instructions.
|
||||
///
|
||||
|
@ -427,6 +471,7 @@ bool llvm::RecursivelyDeleteDeadPHINode(PHINode *PN,
|
|||
bool llvm::SimplifyInstructionsInBlock(BasicBlock *BB,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
bool MadeChange = false;
|
||||
const DataLayout &DL = BB->getModule()->getDataLayout();
|
||||
|
||||
#ifndef NDEBUG
|
||||
// In debug builds, ensure that the terminator of the block is never replaced
|
||||
|
@ -436,21 +481,24 @@ bool llvm::SimplifyInstructionsInBlock(BasicBlock *BB,
|
|||
AssertingVH<Instruction> TerminatorVH(--BB->end());
|
||||
#endif
|
||||
|
||||
for (BasicBlock::iterator BI = BB->begin(), E = --BB->end(); BI != E; ) {
|
||||
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 (BasicBlock::iterator BI = BB->begin(), E = std::prev(BB->end()); BI != E;) {
|
||||
assert(!BI->isTerminator());
|
||||
Instruction *Inst = BI++;
|
||||
Instruction *I = &*BI;
|
||||
++BI;
|
||||
|
||||
WeakVH BIHandle(BI);
|
||||
if (recursivelySimplifyInstruction(Inst, TLI)) {
|
||||
MadeChange = true;
|
||||
if (BIHandle != BI)
|
||||
BI = BB->begin();
|
||||
continue;
|
||||
}
|
||||
// We're visiting this instruction now, so make sure it's not in the
|
||||
// worklist from an earlier visit.
|
||||
if (!WorkList.count(I))
|
||||
MadeChange |= simplifyAndDCEInstruction(I, WorkList, DL, TLI);
|
||||
}
|
||||
|
||||
MadeChange |= RecursivelyDeleteTriviallyDeadInstructions(Inst, TLI);
|
||||
if (BIHandle != BI)
|
||||
BI = BB->begin();
|
||||
while (!WorkList.empty()) {
|
||||
Instruction *I = WorkList.pop_back_val();
|
||||
MadeChange |= simplifyAndDCEInstruction(I, WorkList, DL, TLI);
|
||||
}
|
||||
return MadeChange;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue