Newer
Older
Value* v = L->getOperand(0);
while (true) {
if (BitCastInst *BC = dyn_cast<BitCastInst>(v))
v = BC->getOperand(0);
else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(v))
v = GEP->getOperand(0);
else
break;
}
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) {
Owen Anderson
committed
DenseMap<BasicBlock*, ValueNumberScope*>::iterator I = localAvail.find(BB);
if (I == localAvail.end())
return 0;
ValueNumberScope* locals = I->second;
Owen Anderson
committed
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;
}
Owen Anderson
committed
uint32_t nextNum = VN.getNextUnusedValueNumber();
Owen Anderson
committed
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) || isa<TerminatorInst>(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
}
Owen Anderson
committed
// If the number we were assigned was a brand new VN, then we don't
// need to do a lookup to see if the number already exists
// somewhere in the domtree: it can't!
} else if (num == nextNum) {
localAvail[I->getParent()]->table.insert(std::make_pair(num, I));
// 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;
Owen Anderson
committed
} else {
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;
Owen Anderson
committed
// Merge unconditional branches, allowing PRE to catch more
// optimization opportunities.
for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ) {
BasicBlock* BB = FI;
++FI;
changed |= mergeBlockIntoPredecessor(BB);
}
while (shouldContinue) {
shouldContinue = iterateOnFunction(F);
changed |= shouldContinue;
}
Owen Anderson
committed
if (EnablePRE)
changed |= performPRE(F);
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
1156
1157
1158
1159
1160
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
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
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; ) {
Owen Anderson
committed
if (isa<AllocationInst>(BI) || isa<TerminatorInst>(BI) ||
isa<PHINode>(BI) || BI->mayReadFromMemory() ||
BI->mayWriteToMemory()) {
Owen Anderson
committed
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);
else {
Value* V = lookupNumber(PREPred, VN.lookup(op));
if (!V) {
success = false;
break;
} else
PREInstr->setOperand(i, V);
}
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);
Owen Anderson
committed
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;
}
Owen Anderson
committed
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
// mergeBlockIntoPredecessor - If this block is the only successor
// of its predecessor, and the edge is non-critical,
// fold it into that predecessor.
bool GVN::mergeBlockIntoPredecessor(BasicBlock* BB) {
// Can't merge the entry block.
if (pred_begin(BB) == pred_end(BB)) return false;
// Can't merge if there are multiple preds.
if (++pred_begin(BB) != pred_end(BB)) return false;
BasicBlock* PredBB = *pred_begin(BB);
// Can't merge if the edge is critical.
if (PredBB->getTerminator()->getNumSuccessors() != 1) return false;
// Begin by getting rid of unneeded PHIs.
while (PHINode *PN = dyn_cast<PHINode>(&BB->front())) {
PN->replaceAllUsesWith(PN->getIncomingValue(0));
BB->getInstList().pop_front(); // Delete the phi node...
}
// Delete the unconditional branch from the predecessor...
PredBB->getInstList().pop_back();
// Move all definitions in the successor to the predecessor...
PredBB->getInstList().splice(PredBB->end(), BB->getInstList());
// Make all PHI nodes that referred to BB now refer to Pred as their
// source...
BB->replaceAllUsesWith(PredBB);
// Finally, erase the old block and update dominator info.
DominatorTree& DT = getAnalysis<DominatorTree>();
DomTreeNode* DTN = DT[BB];
DomTreeNode* PredDTN = DT[PredBB];
if (DTN) {
SmallPtrSet<DomTreeNode*, 8> Children(DTN->begin(), DTN->end());
for (SmallPtrSet<DomTreeNode*, 8>::iterator DI = Children.begin(),
DE = Children.end(); DI != DE; ++DI)
DT.changeImmediateDominator(*DI, PredDTN);
DT.eraseNode(BB);
}
BB->eraseFromParent();
NumGVNBlocks++;
return true;
}
// iterateOnFunction - Executes one iteration of GVN
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);
Owen Anderson
committed
return changed;