Newer
Older
bool PREChanged = true;
while (PREChanged) {
PREChanged = performPRE(F);
Owen Anderson
committed
}
// FIXME: Should perform GVN again after PRE does something. PRE can move
// computations into blocks where they become fully redundant. Note that
// we can't do this until PRE's critical edge splitting updates memdep.
// Actually, when this happens, we should just fully integrate PRE into GVN.
cleanupGlobalSets();
bool GVN::processBlock(BasicBlock *BB) {
// FIXME: Kill off InstrsToErase by doing erasing eagerly in a helper function
// (and incrementing BI before processing an instruction).
assert(InstrsToErase.empty() &&
"We expect InstrsToErase to be empty across iterations");
bool ChangedFunction = false;
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
BI != BE;) {
ChangedFunction |= processInstruction(BI);
if (InstrsToErase.empty()) {
// If we need some instructions deleted, do it now.
NumGVNInstr += InstrsToErase.size();
// Avoid iterator invalidation.
bool AtStart = BI == BB->begin();
if (!AtStart)
--BI;
for (SmallVector<Instruction*, 4>::iterator I = InstrsToErase.begin(),
E = InstrsToErase.end(); I != E; ++I) {
DEBUG(dbgs() << "GVN removed: " << **I << '\n');
if (MD) MD->removeInstruction(*I);
if (AtStart)
BI = BB->begin();
else
++BI;
}
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) {
Chris Lattner
committed
bool Changed = false;
DenseMap<BasicBlock*, Value*> predMap;
Owen Anderson
committed
for (df_iterator<BasicBlock*> DI = df_begin(&F.getEntryBlock()),
DE = df_end(&F.getEntryBlock()); DI != DE; ++DI) {
BasicBlock *CurrentBlock = *DI;
Owen Anderson
committed
// Nothing to PRE in the entry block.
if (CurrentBlock == &F.getEntryBlock()) continue;
Owen Anderson
committed
for (BasicBlock::iterator BI = CurrentBlock->begin(),
BE = CurrentBlock->end(); BI != BE; ) {
Chris Lattner
committed
Instruction *CurInst = BI++;
Victor Hernandez
committed
if (isa<AllocaInst>(CurInst) ||
Victor Hernandez
committed
isa<TerminatorInst>(CurInst) || isa<PHINode>(CurInst) ||
CurInst->mayReadFromMemory() || CurInst->mayHaveSideEffects() ||
isa<DbgInfoIntrinsic>(CurInst))
Owen Anderson
committed
continue;
Owen Anderson
committed
// We don't currently value number ANY inline asm calls.
if (CallInst *CallI = dyn_cast<CallInst>(CurInst))
if (CallI->isInlineAsm())
continue;
uint32_t ValNo = VN.lookup(CurInst);
Owen Anderson
committed
// 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;
predMap.clear();
Owen Anderson
committed
for (pred_iterator PI = pred_begin(CurrentBlock),
PE = pred_end(CurrentBlock); PI != PE; ++PI) {
Owen Anderson
committed
// We're not interested in PRE where the block is its
// own predecessor, or in blocks with predecessors
Owen Anderson
committed
// that are not reachable.
Owen Anderson
committed
break;
Owen Anderson
committed
} else if (!DT->dominates(&F.getEntryBlock(), P)) {
Owen Anderson
committed
break;
}
Owen Anderson
committed
Value* predV = findLeader(P, ValNo);
Owen Anderson
committed
if (predV == 0) {
++NumWithout;
Owen Anderson
committed
} else if (predV == CurInst) {
Owen Anderson
committed
} else {
Owen Anderson
committed
predMap[P] = predV;
++NumWith;
Owen Anderson
committed
}
}
Owen Anderson
committed
// 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)
Owen Anderson
committed
continue;
// Don't do PRE across indirect branch.
if (isa<IndirectBrInst>(PREPred->getTerminator()))
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 = GetSuccessorNumber(PREPred, CurrentBlock);
if (isCriticalEdge(PREPred->getTerminator(), SuccNum)) {
toSplit.push_back(std::make_pair(PREPred->getTerminator(), SuccNum));
// Instantiate the expression in the predecessor that lacked it.
Owen Anderson
committed
// 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 originally present will have been instantiated earlier
Owen Anderson
committed
// in this loop.
Instruction *PREInstr = CurInst->clone();
Owen Anderson
committed
bool success = true;
Chris Lattner
committed
for (unsigned i = 0, e = CurInst->getNumOperands(); i != e; ++i) {
Value *Op = PREInstr->getOperand(i);
if (isa<Argument>(Op) || isa<Constant>(Op) || isa<GlobalValue>(Op))
continue;
Owen Anderson
committed
if (Value *V = findLeader(PREPred, VN.lookup(Op))) {
Chris Lattner
committed
PREInstr->setOperand(i, V);
} else {
success = false;
break;
Owen Anderson
committed
}
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
Owen Anderson
committed
// are not value numbered precisely.
if (!success) {
delete PREInstr;
DEBUG(verifyRemoved(PREInstr));
Owen Anderson
committed
continue;
}
Owen Anderson
committed
PREInstr->insertBefore(PREPred->getTerminator());
Chris Lattner
committed
PREInstr->setName(CurInst->getName() + ".pre");
PREInstr->setDebugLoc(CurInst->getDebugLoc());
Owen Anderson
committed
predMap[PREPred] = PREInstr;
++NumGVNPRE;
Owen Anderson
committed
// Update the availability map to include the new instruction.
Owen Anderson
committed
addToLeaderTable(ValNo, PREInstr, PREPred);
Owen Anderson
committed
// Create a PHI to make the value available in this block.
pred_iterator PB = pred_begin(CurrentBlock), PE = pred_end(CurrentBlock);
PHINode* Phi = PHINode::Create(CurInst->getType(), std::distance(PB, PE),
Chris Lattner
committed
CurInst->getName() + ".pre-phi",
Owen Anderson
committed
CurrentBlock->begin());
for (pred_iterator PI = PB; PI != PE; ++PI) {
BasicBlock *P = *PI;
Phi->addIncoming(predMap[P], P);
}
Owen Anderson
committed
addToLeaderTable(ValNo, Phi, CurrentBlock);
Phi->setDebugLoc(CurInst->getDebugLoc());
Chris Lattner
committed
CurInst->replaceAllUsesWith(Phi);
Owen Anderson
committed
if (Phi->getType()->isPointerTy()) {
// Because we have added a PHI-use of the pointer value, it has now
// "escaped" from alias analysis' perspective. We need to inform
// AA of this.
for (unsigned ii = 0, ee = Phi->getNumIncomingValues(); ii != ee;
++ii) {
unsigned jj = PHINode::getOperandNumForIncomingValue(ii);
VN.getAliasAnalysis()->addEscapingUse(Phi->getOperandUse(jj));
}
Owen Anderson
committed
if (MD)
MD->invalidateCachedPointerInfo(Phi);
}
Chris Lattner
committed
VN.erase(CurInst);
Owen Anderson
committed
removeFromLeaderTable(ValNo, CurInst, CurrentBlock);
DEBUG(dbgs() << "GVN PRE removed: " << *CurInst << '\n');
if (MD) MD->removeInstruction(CurInst);
Chris Lattner
committed
CurInst->eraseFromParent();
Chris Lattner
committed
Changed = true;
Owen Anderson
committed
}
}
if (splitCriticalEdges())
Changed = true;
return Changed;
}
/// splitCriticalEdges - Split critical edges found during the previous
/// iteration that may enable further optimization.
bool GVN::splitCriticalEdges() {
if (toSplit.empty())
return false;
do {
std::pair<TerminatorInst*, unsigned> Edge = toSplit.pop_back_val();
SplitCriticalEdge(Edge.first, Edge.second, this);
} while (!toSplit.empty());
if (MD) MD->invalidateCachedPredecessors();
Owen Anderson
committed
}
/// iterateOnFunction - Executes one iteration of GVN
Owen Anderson
committed
Owen Anderson
committed
// Top-down walk of the dominator tree
#if 0
// Needed for value numbering with phi construction to work.
Owen Anderson
committed
ReversePostOrderTraversal<Function*> RPOT(&F);
for (ReversePostOrderTraversal<Function*>::rpo_iterator RI = RPOT.begin(),
RE = RPOT.end(); RI != RE; ++RI)
Changed |= processBlock(*RI);
#else
for (df_iterator<DomTreeNode*> DI = df_begin(DT->getRootNode()),
DE = df_end(DT->getRootNode()); DI != DE; ++DI)
Changed |= processBlock(DI->getBlock());
#endif
Owen Anderson
committed
}
void GVN::cleanupGlobalSets() {
VN.clear();
Owen Anderson
committed
TableAllocator.Reset();
Bill Wendling
committed
/// verifyRemoved - Verify that the specified instruction does not occur in our
/// internal data structures.
void GVN::verifyRemoved(const Instruction *Inst) const {
VN.verifyRemoved(Inst);
// Walk through the value number scope to make sure the instruction isn't
// ferreted away in it.
Owen Anderson
committed
for (DenseMap<uint32_t, LeaderTableEntry>::const_iterator
I = LeaderTable.begin(), E = LeaderTable.end(); I != E; ++I) {
Owen Anderson
committed
const LeaderTableEntry *Node = &I->second;
Owen Anderson
committed
assert(Node->Val != Inst && "Inst still in value numbering scope!");
Owen Anderson
committed
Owen Anderson
committed
while (Node->Next) {
Node = Node->Next;
assert(Node->Val != Inst && "Inst still in value numbering scope!");
}
}