Change around the data structures used to store availability sets, resulting in a GVN+PRE that is faster that GVN alone was before.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52521 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Owen Anderson 2008-06-20 01:15:47 +00:00
parent c4b65ea56b
commit 6fafe847b2

View File

@ -692,6 +692,15 @@ namespace llvm {
}; };
} }
namespace {
struct VISIBILITY_HIDDEN ValueNumberScope {
ValueNumberScope* parent;
DenseMap<uint32_t, Value*> table;
ValueNumberScope(ValueNumberScope* p) : parent(p) { }
};
}
namespace { namespace {
class VISIBILITY_HIDDEN GVN : public FunctionPass { class VISIBILITY_HIDDEN GVN : public FunctionPass {
@ -702,7 +711,7 @@ namespace {
private: private:
ValueTable VN; ValueTable VN;
DenseMap<BasicBlock*, DenseMap<uint32_t, Value*> > localAvail; DenseMap<BasicBlock*, ValueNumberScope*> localAvail;
typedef DenseMap<Value*, SmallPtrSet<Instruction*, 4> > PhiMapType; typedef DenseMap<Value*, SmallPtrSet<Instruction*, 4> > PhiMapType;
PhiMapType phiMap; PhiMapType phiMap;
@ -737,6 +746,7 @@ namespace {
Value* CollapsePhi(PHINode* p); Value* CollapsePhi(PHINode* p);
bool isSafeReplacement(PHINode* p, Instruction* inst); bool isSafeReplacement(PHINode* p, Instruction* inst);
bool performPRE(Function& F); bool performPRE(Function& F);
Value* lookupNumber(BasicBlock* BB, uint32_t num);
}; };
char GVN::ID = 0; char GVN::ID = 0;
@ -1008,6 +1018,20 @@ bool GVN::processLoad(LoadInst *L, DenseMap<Value*, LoadInst*> &lastLoad,
return deletedLoad; return deletedLoad;
} }
Value* GVN::lookupNumber(BasicBlock* BB, uint32_t num) {
ValueNumberScope* locals = localAvail[BB];
while (locals) {
DenseMap<uint32_t, Value*>::iterator I = locals->table.find(num);
if (I != locals->table.end())
return I->second;
else
locals = locals->parent;
}
return 0;
}
/// processInstruction - When calculating availability, handle an instruction /// processInstruction - When calculating availability, handle an instruction
/// by inserting it into the appropriate sets /// by inserting it into the appropriate sets
bool GVN::processInstruction(Instruction *I, bool GVN::processInstruction(Instruction *I,
@ -1018,7 +1042,7 @@ bool GVN::processInstruction(Instruction *I,
if (!changed) { if (!changed) {
unsigned num = VN.lookup_or_add(L); unsigned num = VN.lookup_or_add(L);
localAvail[I->getParent()].insert(std::make_pair(num, L)); localAvail[I->getParent()]->table.insert(std::make_pair(num, L));
} }
return changed; return changed;
@ -1029,7 +1053,7 @@ bool GVN::processInstruction(Instruction *I,
// Allocations are always uniquely numbered, so we can save time and memory // Allocations are always uniquely numbered, so we can save time and memory
// by fast failing them. // by fast failing them.
if (isa<AllocationInst>(I)) { if (isa<AllocationInst>(I)) {
localAvail[I->getParent()].insert(std::make_pair(num, I)); localAvail[I->getParent()]->table.insert(std::make_pair(num, I));
return false; return false;
} }
@ -1046,12 +1070,10 @@ bool GVN::processInstruction(Instruction *I,
p->replaceAllUsesWith(constVal); p->replaceAllUsesWith(constVal);
toErase.push_back(p); toErase.push_back(p);
} else { } else {
localAvail[I->getParent()].insert(std::make_pair(num, I)); localAvail[I->getParent()]->table.insert(std::make_pair(num, I));
} }
// Perform value-number based elimination // Perform value-number based elimination
} else if (localAvail[I->getParent()].count(num)) { } else if (Value* repl = lookupNumber(I->getParent(), num)) {
Value* repl = localAvail[I->getParent()][num];
// Remove it! // Remove it!
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>(); MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
MD.removeInstruction(I); MD.removeInstruction(I);
@ -1061,7 +1083,7 @@ bool GVN::processInstruction(Instruction *I,
toErase.push_back(I); toErase.push_back(I);
return true; return true;
} else if (!I->isTerminator()) { } else if (!I->isTerminator()) {
localAvail[I->getParent()].insert(std::make_pair(num, I)); localAvail[I->getParent()]->table.insert(std::make_pair(num, I));
} }
return false; return false;
@ -1095,8 +1117,10 @@ bool GVN::processBlock(DomTreeNode* DTN) {
bool changed_function = false; bool changed_function = false;
if (DTN->getIDom()) if (DTN->getIDom())
localAvail.insert(std::make_pair(BB, localAvail[BB] =
localAvail[DTN->getIDom()->getBlock()])); new ValueNumberScope(localAvail[DTN->getIDom()->getBlock()]);
else
localAvail[BB] = new ValueNumberScope(0);
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
BI != BE;) { BI != BE;) {
@ -1161,19 +1185,29 @@ bool GVN::performPRE(Function& F) {
unsigned numWith = 0; unsigned numWith = 0;
unsigned numWithout = 0; unsigned numWithout = 0;
BasicBlock* PREPred = 0; BasicBlock* PREPred = 0;
DenseMap<BasicBlock*, Value*> predMap;
for (pred_iterator PI = pred_begin(CurrentBlock), for (pred_iterator PI = pred_begin(CurrentBlock),
PE = pred_end(CurrentBlock); PI != PE; ++PI) { PE = pred_end(CurrentBlock); PI != PE; ++PI) {
// We're not interested in PRE where the block is its // We're not interested in PRE where the block is its
// own predecessor. // own predecessor, on in blocks with predecessors
if (*PI == CurrentBlock) // that are not reachable.
if (*PI == CurrentBlock) {
numWithout = 2; numWithout = 2;
break;
} else if (!localAvail.count(*PI)) {
numWithout = 2;
break;
}
if (!localAvail[*PI].count(valno)) { DenseMap<uint32_t, Value*>::iterator predV =
localAvail[*PI]->table.find(valno);
if (predV == localAvail[*PI]->table.end()) {
PREPred = *PI; PREPred = *PI;
numWithout++; numWithout++;
} else if (localAvail[*PI][valno] == BI) { } else if (predV->second == BI) {
numWithout = 2; numWithout = 2;
} else { } else {
predMap[*PI] = predV->second;
numWith++; numWith++;
} }
} }
@ -1214,11 +1248,11 @@ bool GVN::performPRE(Function& F) {
Value* op = BI->getOperand(i); Value* op = BI->getOperand(i);
if (isa<Argument>(op) || isa<Constant>(op) || isa<GlobalValue>(op)) if (isa<Argument>(op) || isa<Constant>(op) || isa<GlobalValue>(op))
PREInstr->setOperand(i, op); PREInstr->setOperand(i, op);
else if (!localAvail[PREPred].count(VN.lookup(op))) { else if (!lookupNumber(PREPred, VN.lookup(op))) {
success = false; success = false;
break; break;
} else } else
PREInstr->setOperand(i, localAvail[PREPred][VN.lookup(op)]); PREInstr->setOperand(i, lookupNumber(PREPred, VN.lookup(op)));
} }
// Fail out if we encounter an operand that is not available in // Fail out if we encounter an operand that is not available in
@ -1232,11 +1266,12 @@ bool GVN::performPRE(Function& F) {
PREInstr->insertBefore(PREPred->getTerminator()); PREInstr->insertBefore(PREPred->getTerminator());
PREInstr->setName(BI->getName() + ".pre"); PREInstr->setName(BI->getName() + ".pre");
predMap[PREPred] = PREInstr;
VN.add(PREInstr, valno); VN.add(PREInstr, valno);
NumGVNPRE++; NumGVNPRE++;
// Update the availability map to include the new instruction. // Update the availability map to include the new instruction.
localAvail[PREPred].insert(std::make_pair(valno, PREInstr)); localAvail[PREPred]->table.insert(std::make_pair(valno, PREInstr));
// Create a PHI to make the value available in this block. // Create a PHI to make the value available in this block.
PHINode* Phi = PHINode::Create(BI->getType(), PHINode* Phi = PHINode::Create(BI->getType(),
@ -1244,18 +1279,17 @@ bool GVN::performPRE(Function& F) {
CurrentBlock->begin()); CurrentBlock->begin());
for (pred_iterator PI = pred_begin(CurrentBlock), for (pred_iterator PI = pred_begin(CurrentBlock),
PE = pred_end(CurrentBlock); PI != PE; ++PI) PE = pred_end(CurrentBlock); PI != PE; ++PI)
Phi->addIncoming(localAvail[*PI][valno], *PI); Phi->addIncoming(predMap[*PI], *PI);
VN.add(Phi, valno); VN.add(Phi, valno);
// The newly created PHI completely replaces the old instruction, // The newly created PHI completely replaces the old instruction,
// so we need to update the maps to reflect this. // so we need to update the maps to reflect this.
for (DenseMap<BasicBlock*, DenseMap<uint32_t, Value*> >::iterator DomTreeNode* DTN = getAnalysis<DominatorTree>()[CurrentBlock];
UI = localAvail.begin(), UE = localAvail.end(); UI != UE; ++UI) for (DomTreeNode::iterator UI = DTN->begin(), UE = DTN->end();
for (DenseMap<uint32_t, Value*>::iterator UUI = UI->second.begin(), UI != UE; ++UI)
UUE = UI->second.end(); UUI != UUE; ++UUI) localAvail[(*UI)->getBlock()]->table[valno] = Phi;
if (UUI->second == BI) localAvail[CurrentBlock]->table[valno] = Phi;
UUI->second = Phi;
BI->replaceAllUsesWith(Phi); BI->replaceAllUsesWith(Phi);
VN.erase(BI); VN.erase(BI);
@ -1279,9 +1313,13 @@ bool GVN::performPRE(Function& F) {
bool GVN::iterateOnFunction(Function &F) { bool GVN::iterateOnFunction(Function &F) {
// Clean out global sets from any previous functions // Clean out global sets from any previous functions
VN.clear(); VN.clear();
localAvail.clear();
phiMap.clear(); phiMap.clear();
for (DenseMap<BasicBlock*, ValueNumberScope*>::iterator
I = localAvail.begin(), E = localAvail.end(); I != E; ++I)
delete I->second;
localAvail.clear();
DominatorTree &DT = getAnalysis<DominatorTree>(); DominatorTree &DT = getAnalysis<DominatorTree>();
// Top-down walk of the dominator tree // Top-down walk of the dominator tree