Newer
Older
}
if (v == dep) {
// 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;
NumGVNLoad++;
}
}
Owen Anderson
committed
if (!deletedLoad)
last = L;
return deletedLoad;
}
Owen Anderson
committed
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;
}
Owen Anderson
committed
/// processInstruction - When calculating availability, handle an instruction
Owen Anderson
committed
/// by inserting it into the appropriate sets
bool GVN::processInstruction(Instruction *I,
Chris Lattner
committed
DenseMap<Value*, LoadInst*> &lastSeenLoad,
SmallVectorImpl<Instruction*> &toErase) {
Owen Anderson
committed
if (LoadInst* L = dyn_cast<LoadInst>(I)) {
bool changed = processLoad(L, lastSeenLoad, toErase);
if (!changed) {
unsigned num = VN.lookup_or_add(L);
Owen Anderson
committed
localAvail[I->getParent()]->table.insert(std::make_pair(num, L));
Owen Anderson
committed
}
return changed;
}
unsigned num = VN.lookup_or_add(I);
Chris Lattner
committed
Owen Anderson
committed
// Allocations are always uniquely numbered, so we can save time and memory
// by fast failing them.
Owen Anderson
committed
if (isa<AllocationInst>(I)) {
Owen Anderson
committed
localAvail[I->getParent()]->table.insert(std::make_pair(num, I));
Owen Anderson
committed
return false;
Owen Anderson
committed
}
Owen Anderson
committed
Owen Anderson
committed
if (PHINode* p = dyn_cast<PHINode>(I)) {
Value* constVal = CollapsePhi(p);
Owen Anderson
committed
if (constVal) {
for (PhiMapType::iterator PI = phiMap.begin(), PE = phiMap.end();
PI != PE; ++PI)
if (PI->second.count(p))
PI->second.erase(p);
Owen Anderson
committed
p->replaceAllUsesWith(constVal);
toErase.push_back(p);
Owen Anderson
committed
} else {
Owen Anderson
committed
localAvail[I->getParent()]->table.insert(std::make_pair(num, I));
Owen Anderson
committed
}
// Perform value-number based elimination
Owen Anderson
committed
} else if (Value* repl = lookupNumber(I->getParent(), num)) {
Owen Anderson
committed
// Remove it!
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
MD.removeInstruction(I);
Owen Anderson
committed
Owen Anderson
committed
I->replaceAllUsesWith(repl);
toErase.push_back(I);
return true;
} else if (!I->isTerminator()) {
Owen Anderson
committed
localAvail[I->getParent()]->table.insert(std::make_pair(num, I));
Owen Anderson
committed
}
return false;
}
// GVN::runOnFunction - This is the main transformation entry point for a
// function.
//
VN.setAliasAnalysis(&getAnalysis<AliasAnalysis>());
VN.setMemDep(&getAnalysis<MemoryDependenceAnalysis>());
VN.setDomTree(&getAnalysis<DominatorTree>());
bool changed = false;
bool shouldContinue = true;
while (shouldContinue) {
shouldContinue = iterateOnFunction(F);
changed |= shouldContinue;
}
return changed;
}
bool GVN::processBlock(DomTreeNode* DTN) {
BasicBlock* BB = DTN->getBlock();
SmallVector<Instruction*, 8> toErase;
DenseMap<Value*, LoadInst*> lastSeenLoad;
bool changed_function = false;
Owen Anderson
committed
if (DTN->getIDom())
Owen Anderson
committed
localAvail[BB] =
new ValueNumberScope(localAvail[DTN->getIDom()->getBlock()]);
else
localAvail[BB] = new ValueNumberScope(0);
Owen Anderson
committed
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
BI != BE;) {
changed_function |= processInstruction(BI, lastSeenLoad, toErase);
if (toErase.empty()) {
++BI;
continue;
}
// If we need some instructions deleted, do it now.
NumGVNInstr += toErase.size();
// Avoid iterator invalidation.
bool AtStart = BI == BB->begin();
if (!AtStart)
--BI;
for (SmallVector<Instruction*, 4>::iterator I = toErase.begin(),
E = toErase.end(); I != E; ++I)
(*I)->eraseFromParent();
if (AtStart)
BI = BB->begin();
else
++BI;
toErase.clear();
}
return changed_function;
}
Owen Anderson
committed
/// performPRE - Perform a purely local form of PRE that looks for diamond
/// control flow patterns and attempts to perform simple PRE at the join point.
bool GVN::performPRE(Function& F) {
bool changed = false;
SmallVector<std::pair<TerminatorInst*, unsigned>, 4> toSplit;
Owen Anderson
committed
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
for (df_iterator<BasicBlock*> DI = df_begin(&F.getEntryBlock()),
DE = df_end(&F.getEntryBlock()); DI != DE; ++DI) {
BasicBlock* CurrentBlock = *DI;
// Nothing to PRE in the entry block.
if (CurrentBlock == &F.getEntryBlock()) continue;
for (BasicBlock::iterator BI = CurrentBlock->begin(),
BE = CurrentBlock->end(); BI != BE; ) {
if (isa<AllocaInst>(BI) || isa<TerminatorInst>(BI) ||
isa<LoadInst>(BI) || isa<StoreInst>(BI) ||
isa<CallInst>(BI) || isa<PHINode>(BI)) {
BI++;
continue;
}
uint32_t valno = VN.lookup(BI);
// Look for the predecessors for PRE opportunities. We're
// only trying to solve the basic diamond case, where
// a value is computed in the successor and one predecessor,
// but not the other. We also explicitly disallow cases
// where the successor is its own predecessor, because they're
// more complicated to get right.
unsigned numWith = 0;
unsigned numWithout = 0;
BasicBlock* PREPred = 0;
Owen Anderson
committed
DenseMap<BasicBlock*, Value*> predMap;
Owen Anderson
committed
for (pred_iterator PI = pred_begin(CurrentBlock),
PE = pred_end(CurrentBlock); PI != PE; ++PI) {
// We're not interested in PRE where the block is its
Owen Anderson
committed
// own predecessor, on in blocks with predecessors
// that are not reachable.
if (*PI == CurrentBlock) {
Owen Anderson
committed
numWithout = 2;
Owen Anderson
committed
break;
} else if (!localAvail.count(*PI)) {
numWithout = 2;
break;
}
DenseMap<uint32_t, Value*>::iterator predV =
localAvail[*PI]->table.find(valno);
if (predV == localAvail[*PI]->table.end()) {
Owen Anderson
committed
PREPred = *PI;
numWithout++;
Owen Anderson
committed
} else if (predV->second == BI) {
Owen Anderson
committed
numWithout = 2;
} else {
Owen Anderson
committed
predMap[*PI] = predV->second;
Owen Anderson
committed
numWith++;
}
}
// Don't do PRE when it might increase code size, i.e. when
// we would need to insert instructions in more than one pred.
if (numWithout != 1 || numWith == 0) {
BI++;
continue;
}
// We can't do PRE safely on a critical edge, so instead we schedule
// the edge to be split and perform the PRE the next time we iterate
// on the function.
unsigned succNum = 0;
for (unsigned i = 0, e = PREPred->getTerminator()->getNumSuccessors();
i != e; ++i)
if (PREPred->getTerminator()->getSuccessor(i) == PREPred) {
succNum = i;
break;
}
if (isCriticalEdge(PREPred->getTerminator(), succNum)) {
toSplit.push_back(std::make_pair(PREPred->getTerminator(), succNum));
changed = true;
BI++;
continue;
}
Owen Anderson
committed
// Instantiate the expression the in predecessor that lacked it.
// Because we are going top-down through the block, all value numbers
// will be available in the predecessor by the time we need them. Any
// that weren't original present will have been instantiated earlier
// in this loop.
Instruction* PREInstr = BI->clone();
bool success = true;
for (unsigned i = 0; i < BI->getNumOperands(); ++i) {
Value* op = BI->getOperand(i);
if (isa<Argument>(op) || isa<Constant>(op) || isa<GlobalValue>(op))
PREInstr->setOperand(i, op);
Owen Anderson
committed
else if (!lookupNumber(PREPred, VN.lookup(op))) {
Owen Anderson
committed
success = false;
break;
} else
Owen Anderson
committed
PREInstr->setOperand(i, lookupNumber(PREPred, VN.lookup(op)));
Owen Anderson
committed
}
// Fail out if we encounter an operand that is not available in
// the PRE predecessor. This is typically because of loads which
// are not value numbered precisely.
if (!success) {
delete PREInstr;
BI++;
continue;
}
PREInstr->insertBefore(PREPred->getTerminator());
PREInstr->setName(BI->getName() + ".pre");
Owen Anderson
committed
predMap[PREPred] = PREInstr;
Owen Anderson
committed
VN.add(PREInstr, valno);
NumGVNPRE++;
// Update the availability map to include the new instruction.
Owen Anderson
committed
localAvail[PREPred]->table.insert(std::make_pair(valno, PREInstr));
Owen Anderson
committed
// Create a PHI to make the value available in this block.
PHINode* Phi = PHINode::Create(BI->getType(),
BI->getName() + ".pre-phi",
CurrentBlock->begin());
for (pred_iterator PI = pred_begin(CurrentBlock),
PE = pred_end(CurrentBlock); PI != PE; ++PI)
Owen Anderson
committed
Phi->addIncoming(predMap[*PI], *PI);
Owen Anderson
committed
VN.add(Phi, valno);
// The newly created PHI completely replaces the old instruction,
// so we need to update the maps to reflect this.
Owen Anderson
committed
DomTreeNode* DTN = getAnalysis<DominatorTree>()[CurrentBlock];
for (DomTreeNode::iterator UI = DTN->begin(), UE = DTN->end();
UI != UE; ++UI)
localAvail[(*UI)->getBlock()]->table[valno] = Phi;
localAvail[CurrentBlock]->table[valno] = Phi;
Owen Anderson
committed
BI->replaceAllUsesWith(Phi);
Owen Anderson
committed
VN.erase(BI);
Owen Anderson
committed
Instruction* erase = BI;
BI++;
erase->eraseFromParent();
changed = true;
}
}
for (SmallVector<std::pair<TerminatorInst*, unsigned>, 4>::iterator
I = toSplit.begin(), E = toSplit.end(); I != E; ++I)
SplitCriticalEdge(I->first, I->second, this);
Owen Anderson
committed
return changed;
}
// GVN::iterateOnFunction - Executes one iteration of GVN
bool GVN::iterateOnFunction(Function &F) {
Owen Anderson
committed
// Clean out global sets from any previous functions
VN.clear();
Owen Anderson
committed
Owen Anderson
committed
for (DenseMap<BasicBlock*, ValueNumberScope*>::iterator
I = localAvail.begin(), E = localAvail.end(); I != E; ++I)
delete I->second;
localAvail.clear();
DominatorTree &DT = getAnalysis<DominatorTree>();
Owen Anderson
committed
// Top-down walk of the dominator tree
Owen Anderson
committed
bool changed = false;
for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()),
DE = df_end(DT.getRootNode()); DI != DE; ++DI)
changed |= processBlock(*DI);
changed |= performPRE(F);
Owen Anderson
committed
return changed;