mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
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:
parent
1440ac5417
commit
663e441a75
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user