void erase(Value* v);
unsigned size();
void setAliasAnalysis(AliasAnalysis* A) { AA = A; }
+ AliasAnalysis *getAliasAnalysis() const { return AA; }
void setMemDep(MemoryDependenceAnalysis* M) { MD = M; }
void setDomTree(DominatorTree* D) { DT = D; }
uint32_t getNextUnusedValueNumber() { return nextValueNumber; }
GVN() : FunctionPass(&ID) { }
private:
+ MemoryDependenceAnalysis *MD;
+ DominatorTree *DT;
+
ValueTable VN;
DenseMap<BasicBlock*, ValueNumberScope*> localAvail;
}
Value* GVN::CollapsePhi(PHINode* p) {
- DominatorTree &DT = getAnalysis<DominatorTree>();
Value* constVal = p->hasConstantValue();
-
if (!constVal) return 0;
Instruction* inst = dyn_cast<Instruction>(constVal);
if (!inst)
return constVal;
- if (DT.dominates(inst, p))
+ if (DT->dominates(inst, p))
if (isSafeReplacement(p, inst))
return inst;
return 0;
// If the block is unreachable, just return undef, since this path
// can't actually occur at runtime.
- if (!getAnalysis<DominatorTree>().isReachableFromEntry(BB))
+ if (!DT->isReachableFromEntry(BB))
return Phis[BB] = UndefValue::get(orig->getType());
BasicBlock* singlePred = BB->getSinglePredecessor();
PN->addIncoming(val, *PI);
}
- AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
- AA.copyValue(orig, PN);
+ VN.getAliasAnalysis()->copyValue(orig, PN);
// Attempt to collapse PHI nodes that are trivially redundant
Value* v = CollapsePhi(PN);
return PN;
}
- MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
-
- MD.removeInstruction(PN);
PN->replaceAllUsesWith(v);
for (DenseMap<BasicBlock*, Value*>::iterator I = Phis.begin(),
if (I->second == PN)
I->second = v;
+ DEBUG(cerr << "GVN removed: " << *PN);
+ MD->removeInstruction(PN);
PN->eraseFromParent();
Phis[BB] = v;
/// non-local by performing PHI construction.
bool GVN::processNonLocalLoad(LoadInst* L,
SmallVectorImpl<Instruction*> &toErase) {
- MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
-
// Find the non-local dependencies of the load
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
// dependencies, this load isn't worth worrying about. Optimizing
for (SmallPtrSet<Instruction*, 4>::iterator I = p.begin(), E = p.end();
I != E; ++I) {
if ((*I)->getParent() == L->getParent()) {
- MD.removeInstruction(L);
L->replaceAllUsesWith(*I);
toErase.push_back(L);
NumGVNLoad++;
repl.insert(std::make_pair((*I)->getParent(), *I));
}
-
+
+ DEBUG(cerr << "GVN REMOVING NONLOCAL LOAD: " << *L);
+
// Perform PHI construction
SmallPtrSet<BasicBlock*, 4> visited;
Value* v = GetValueForBlock(L->getParent(), L, repl, true);
-
- MD.removeInstruction(L);
L->replaceAllUsesWith(v);
toErase.push_back(L);
NumGVNLoad++;
-
return true;
}
LoadInst*& last = lastLoad[pointer];
// ... to a pointer that has been loaded from before...
- MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
bool removedNonLocal = false;
- MemDepResult dep = MD.getDependency(L);
+ MemDepResult dep = MD->getDependency(L);
if (dep.isNonLocal() &&
L->getParent() != &L->getParent()->getParent()->getEntryBlock()) {
removedNonLocal = processNonLocalLoad(L, toErase);
if (StoreInst* S = dyn_cast<StoreInst>(DepInst)) {
if (S->getPointerOperand() == pointer) {
// Remove it!
- MD.removeInstruction(L);
-
L->replaceAllUsesWith(S->getOperand(0));
toErase.push_back(L);
deletedLoad = true;
break;
} else if (DepInst == last) {
// Remove it!
- MD.removeInstruction(L);
-
L->replaceAllUsesWith(last);
toErase.push_back(L);
deletedLoad = true;
NumGVNLoad++;
break;
} else {
- dep = MD.getDependencyFrom(L, DepInst, DepInst->getParent());
+ dep = MD->getDependencyFrom(L, DepInst, DepInst->getParent());
}
}
// If this load depends directly on an allocation, there isn't
// anything stored there; therefore, we can optimize this load
// to undef.
- MD.removeInstruction(L);
L->replaceAllUsesWith(UndefValue::get(L->getType()));
toErase.push_back(L);
deletedLoad = true;
// Perform value-number based elimination
} else if (Value* repl = lookupNumber(I->getParent(), num)) {
// Remove it!
- MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
- MD.removeInstruction(I);
-
VN.erase(I);
I->replaceAllUsesWith(repl);
toErase.push_back(I);
// function.
//
bool GVN::runOnFunction(Function& F) {
+ MD = &getAnalysis<MemoryDependenceAnalysis>();
+ DT = &getAnalysis<DominatorTree>();
VN.setAliasAnalysis(&getAnalysis<AliasAnalysis>());
- VN.setMemDep(&getAnalysis<MemoryDependenceAnalysis>());
- VN.setDomTree(&getAnalysis<DominatorTree>());
+ VN.setMemDep(MD);
+ VN.setDomTree(DT);
bool changed = false;
bool shouldContinue = true;
bool GVN::processBlock(DomTreeNode* DTN) {
BasicBlock* BB = DTN->getBlock();
-
SmallVector<Instruction*, 8> toErase;
DenseMap<Value*, LoadInst*> lastSeenLoad;
bool changed_function = false;
--BI;
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();
+ }
if (AtStart)
BI = BB->begin();
Instruction* erase = BI;
BI++;
+ DEBUG(cerr << "GVN removed: " << *erase);
+ MD->removeInstruction(erase);
erase->eraseFromParent();
-
changed = true;
}
}
// iterateOnFunction - Executes one iteration of GVN
bool GVN::iterateOnFunction(Function &F) {
- DominatorTree &DT = getAnalysis<DominatorTree>();
-
cleanupGlobalSets();
// Top-down walk of the dominator tree
bool changed = false;
- for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()),
- DE = df_end(DT.getRootNode()); DI != DE; ++DI)
+ for (df_iterator<DomTreeNode*> DI = df_begin(DT->getRootNode()),
+ DE = df_end(DT->getRootNode()); DI != DE; ++DI)
changed |= processBlock(*DI);
return changed;