Cache analyses in ivars and add some useful DEBUG output.

This speeds up GVN from 4.0386s to 3.9376s.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60310 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2008-12-01 00:40:32 +00:00
parent 1440ac5417
commit 663e441a75

View File

@ -166,6 +166,7 @@ namespace {
void erase(Value* v); void erase(Value* v);
unsigned size(); unsigned size();
void setAliasAnalysis(AliasAnalysis* A) { AA = A; } void setAliasAnalysis(AliasAnalysis* A) { AA = A; }
AliasAnalysis *getAliasAnalysis() const { return AA; }
void setMemDep(MemoryDependenceAnalysis* M) { MD = M; } void setMemDep(MemoryDependenceAnalysis* M) { MD = M; }
void setDomTree(DominatorTree* D) { DT = D; } void setDomTree(DominatorTree* D) { DT = D; }
uint32_t getNextUnusedValueNumber() { return nextValueNumber; } uint32_t getNextUnusedValueNumber() { return nextValueNumber; }
@ -710,6 +711,9 @@ namespace {
GVN() : FunctionPass(&ID) { } GVN() : FunctionPass(&ID) { }
private: private:
MemoryDependenceAnalysis *MD;
DominatorTree *DT;
ValueTable VN; ValueTable VN;
DenseMap<BasicBlock*, ValueNumberScope*> localAvail; DenseMap<BasicBlock*, ValueNumberScope*> localAvail;
@ -771,16 +775,14 @@ void GVN::dump(DenseMap<uint32_t, Value*>& d) {
} }
Value* GVN::CollapsePhi(PHINode* p) { Value* GVN::CollapsePhi(PHINode* p) {
DominatorTree &DT = getAnalysis<DominatorTree>();
Value* constVal = p->hasConstantValue(); Value* constVal = p->hasConstantValue();
if (!constVal) return 0; if (!constVal) return 0;
Instruction* inst = dyn_cast<Instruction>(constVal); Instruction* inst = dyn_cast<Instruction>(constVal);
if (!inst) if (!inst)
return constVal; return constVal;
if (DT.dominates(inst, p)) if (DT->dominates(inst, p))
if (isSafeReplacement(p, inst)) if (isSafeReplacement(p, inst))
return inst; return inst;
return 0; return 0;
@ -811,7 +813,7 @@ Value *GVN::GetValueForBlock(BasicBlock *BB, LoadInst* orig,
// If the block is unreachable, just return undef, since this path // If the block is unreachable, just return undef, since this path
// can't actually occur at runtime. // can't actually occur at runtime.
if (!getAnalysis<DominatorTree>().isReachableFromEntry(BB)) if (!DT->isReachableFromEntry(BB))
return Phis[BB] = UndefValue::get(orig->getType()); return Phis[BB] = UndefValue::get(orig->getType());
BasicBlock* singlePred = BB->getSinglePredecessor(); BasicBlock* singlePred = BB->getSinglePredecessor();
@ -836,8 +838,7 @@ Value *GVN::GetValueForBlock(BasicBlock *BB, LoadInst* orig,
PN->addIncoming(val, *PI); PN->addIncoming(val, *PI);
} }
AliasAnalysis& AA = getAnalysis<AliasAnalysis>(); VN.getAliasAnalysis()->copyValue(orig, PN);
AA.copyValue(orig, PN);
// Attempt to collapse PHI nodes that are trivially redundant // Attempt to collapse PHI nodes that are trivially redundant
Value* v = CollapsePhi(PN); Value* v = CollapsePhi(PN);
@ -847,9 +848,6 @@ Value *GVN::GetValueForBlock(BasicBlock *BB, LoadInst* orig,
return PN; return PN;
} }
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
MD.removeInstruction(PN);
PN->replaceAllUsesWith(v); PN->replaceAllUsesWith(v);
for (DenseMap<BasicBlock*, Value*>::iterator I = Phis.begin(), for (DenseMap<BasicBlock*, Value*>::iterator I = Phis.begin(),
@ -857,6 +855,8 @@ Value *GVN::GetValueForBlock(BasicBlock *BB, LoadInst* orig,
if (I->second == PN) if (I->second == PN)
I->second = v; I->second = v;
DEBUG(cerr << "GVN removed: " << *PN);
MD->removeInstruction(PN);
PN->eraseFromParent(); PN->eraseFromParent();
Phis[BB] = v; Phis[BB] = v;
@ -867,11 +867,12 @@ Value *GVN::GetValueForBlock(BasicBlock *BB, LoadInst* orig,
/// non-local by performing PHI construction. /// non-local by performing PHI construction.
bool GVN::processNonLocalLoad(LoadInst* L, bool GVN::processNonLocalLoad(LoadInst* L,
SmallVectorImpl<Instruction*> &toErase) { SmallVectorImpl<Instruction*> &toErase) {
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
// Find the non-local dependencies of the load // Find the non-local dependencies of the load
SmallVector<std::pair<BasicBlock*, MemDepResult>, 32> deps; SmallVector<std::pair<BasicBlock*, MemDepResult>, 32> deps;
MD.getNonLocalDependency(L, deps); MD->getNonLocalDependency(L, deps);
DEBUG(cerr << "INVESTIGATING NONLOCAL LOAD: " << deps.size() << *L);
// If we had to process more than one hundred blocks to find the // If we had to process more than one hundred blocks to find the
// dependencies, this load isn't worth worrying about. Optimizing // dependencies, this load isn't worth worrying about. Optimizing
@ -919,7 +920,6 @@ bool GVN::processNonLocalLoad(LoadInst* L,
for (SmallPtrSet<Instruction*, 4>::iterator I = p.begin(), E = p.end(); for (SmallPtrSet<Instruction*, 4>::iterator I = p.begin(), E = p.end();
I != E; ++I) { I != E; ++I) {
if ((*I)->getParent() == L->getParent()) { if ((*I)->getParent() == L->getParent()) {
MD.removeInstruction(L);
L->replaceAllUsesWith(*I); L->replaceAllUsesWith(*I);
toErase.push_back(L); toErase.push_back(L);
NumGVNLoad++; NumGVNLoad++;
@ -928,16 +928,15 @@ bool GVN::processNonLocalLoad(LoadInst* L,
repl.insert(std::make_pair((*I)->getParent(), *I)); repl.insert(std::make_pair((*I)->getParent(), *I));
} }
DEBUG(cerr << "GVN REMOVING NONLOCAL LOAD: " << *L);
// Perform PHI construction // Perform PHI construction
SmallPtrSet<BasicBlock*, 4> visited; SmallPtrSet<BasicBlock*, 4> visited;
Value* v = GetValueForBlock(L->getParent(), L, repl, true); Value* v = GetValueForBlock(L->getParent(), L, repl, true);
MD.removeInstruction(L);
L->replaceAllUsesWith(v); L->replaceAllUsesWith(v);
toErase.push_back(L); toErase.push_back(L);
NumGVNLoad++; NumGVNLoad++;
return true; return true;
} }
@ -954,9 +953,8 @@ bool GVN::processLoad(LoadInst *L, DenseMap<Value*, LoadInst*> &lastLoad,
LoadInst*& last = lastLoad[pointer]; LoadInst*& last = lastLoad[pointer];
// ... to a pointer that has been loaded from before... // ... to a pointer that has been loaded from before...
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
bool removedNonLocal = false; bool removedNonLocal = false;
MemDepResult dep = MD.getDependency(L); MemDepResult dep = MD->getDependency(L);
if (dep.isNonLocal() && if (dep.isNonLocal() &&
L->getParent() != &L->getParent()->getParent()->getEntryBlock()) { L->getParent() != &L->getParent()->getParent()->getEntryBlock()) {
removedNonLocal = processNonLocalLoad(L, toErase); removedNonLocal = processNonLocalLoad(L, toErase);
@ -977,8 +975,6 @@ bool GVN::processLoad(LoadInst *L, DenseMap<Value*, LoadInst*> &lastLoad,
if (StoreInst* S = dyn_cast<StoreInst>(DepInst)) { if (StoreInst* S = dyn_cast<StoreInst>(DepInst)) {
if (S->getPointerOperand() == pointer) { if (S->getPointerOperand() == pointer) {
// Remove it! // Remove it!
MD.removeInstruction(L);
L->replaceAllUsesWith(S->getOperand(0)); L->replaceAllUsesWith(S->getOperand(0));
toErase.push_back(L); toErase.push_back(L);
deletedLoad = true; deletedLoad = true;
@ -997,15 +993,13 @@ bool GVN::processLoad(LoadInst *L, DenseMap<Value*, LoadInst*> &lastLoad,
break; break;
} else if (DepInst == last) { } else if (DepInst == last) {
// Remove it! // Remove it!
MD.removeInstruction(L);
L->replaceAllUsesWith(last); L->replaceAllUsesWith(last);
toErase.push_back(L); toErase.push_back(L);
deletedLoad = true; deletedLoad = true;
NumGVNLoad++; NumGVNLoad++;
break; break;
} else { } else {
dep = MD.getDependencyFrom(L, DepInst, DepInst->getParent()); dep = MD->getDependencyFrom(L, DepInst, DepInst->getParent());
} }
} }
@ -1016,7 +1010,6 @@ bool GVN::processLoad(LoadInst *L, DenseMap<Value*, LoadInst*> &lastLoad,
// If this load depends directly on an allocation, there isn't // If this load depends directly on an allocation, there isn't
// anything stored there; therefore, we can optimize this load // anything stored there; therefore, we can optimize this load
// to undef. // to undef.
MD.removeInstruction(L);
L->replaceAllUsesWith(UndefValue::get(L->getType())); L->replaceAllUsesWith(UndefValue::get(L->getType()));
toErase.push_back(L); toErase.push_back(L);
deletedLoad = true; deletedLoad = true;
@ -1098,9 +1091,6 @@ bool GVN::processInstruction(Instruction *I,
// Perform value-number based elimination // Perform value-number based elimination
} else if (Value* repl = lookupNumber(I->getParent(), num)) { } else if (Value* repl = lookupNumber(I->getParent(), num)) {
// Remove it! // Remove it!
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
MD.removeInstruction(I);
VN.erase(I); VN.erase(I);
I->replaceAllUsesWith(repl); I->replaceAllUsesWith(repl);
toErase.push_back(I); toErase.push_back(I);
@ -1116,9 +1106,11 @@ bool GVN::processInstruction(Instruction *I,
// function. // function.
// //
bool GVN::runOnFunction(Function& F) { bool GVN::runOnFunction(Function& F) {
MD = &getAnalysis<MemoryDependenceAnalysis>();
DT = &getAnalysis<DominatorTree>();
VN.setAliasAnalysis(&getAnalysis<AliasAnalysis>()); VN.setAliasAnalysis(&getAnalysis<AliasAnalysis>());
VN.setMemDep(&getAnalysis<MemoryDependenceAnalysis>()); VN.setMemDep(MD);
VN.setDomTree(&getAnalysis<DominatorTree>()); VN.setDomTree(DT);
bool changed = false; bool changed = false;
bool shouldContinue = true; bool shouldContinue = true;
@ -1155,7 +1147,6 @@ bool GVN::runOnFunction(Function& F) {
bool GVN::processBlock(DomTreeNode* DTN) { bool GVN::processBlock(DomTreeNode* DTN) {
BasicBlock* BB = DTN->getBlock(); BasicBlock* BB = DTN->getBlock();
SmallVector<Instruction*, 8> toErase; SmallVector<Instruction*, 8> toErase;
DenseMap<Value*, LoadInst*> lastSeenLoad; DenseMap<Value*, LoadInst*> lastSeenLoad;
bool changed_function = false; bool changed_function = false;
@ -1183,8 +1174,11 @@ bool GVN::processBlock(DomTreeNode* DTN) {
--BI; --BI;
for (SmallVector<Instruction*, 4>::iterator I = toErase.begin(), for (SmallVector<Instruction*, 4>::iterator I = toErase.begin(),
E = toErase.end(); I != E; ++I) E = toErase.end(); I != E; ++I) {
DEBUG(cerr << "GVN removed: " << **I);
MD->removeInstruction(*I);
(*I)->eraseFromParent(); (*I)->eraseFromParent();
}
if (AtStart) if (AtStart)
BI = BB->begin(); BI = BB->begin();
@ -1336,8 +1330,9 @@ bool GVN::performPRE(Function& F) {
Instruction* erase = BI; Instruction* erase = BI;
BI++; BI++;
DEBUG(cerr << "GVN removed: " << *erase);
MD->removeInstruction(erase);
erase->eraseFromParent(); erase->eraseFromParent();
changed = true; changed = true;
} }
} }
@ -1351,14 +1346,12 @@ bool GVN::performPRE(Function& F) {
// iterateOnFunction - Executes one iteration of GVN // iterateOnFunction - Executes one iteration of GVN
bool GVN::iterateOnFunction(Function &F) { bool GVN::iterateOnFunction(Function &F) {
DominatorTree &DT = getAnalysis<DominatorTree>();
cleanupGlobalSets(); cleanupGlobalSets();
// Top-down walk of the dominator tree // Top-down walk of the dominator tree
bool changed = false; bool changed = false;
for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()), for (df_iterator<DomTreeNode*> DI = df_begin(DT->getRootNode()),
DE = df_end(DT.getRootNode()); DI != DE; ++DI) DE = df_end(DT->getRootNode()); DI != DE; ++DI)
changed |= processBlock(*DI); changed |= processBlock(*DI);
return changed; return changed;