mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-25 00:29:20 +00:00
can be used by both the new pass manager and the old. This removes it from any of the virtual mess of the pass interfaces and lets it derive cleanly from the DominatorTreeBase<> template. In turn, tons of boilerplate interface can be nuked and it turns into a very straightforward extension of the base DominatorTree interface. The old analysis pass is now a simple wrapper. The names and style of this split should match the split between CallGraph and CallGraphWrapperPass. All of the users of DominatorTree have been updated to match using many of the same tricks as with CallGraph. The goal is that the common type remains the resulting DominatorTree rather than the pass. This will make subsequent work toward the new pass manager significantly easier. Also in numerous places things became cleaner because I switched from re-running the pass (!!! mid way through some other passes run!!!) to directly recomputing the domtree. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199104 91177308-0d34-0410-b5e6-96231b3b80d8
141 lines
4.4 KiB
C++
141 lines
4.4 KiB
C++
//===- DominanceFrontier.cpp - Dominance Frontier Calculation -------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Analysis/DominanceFrontier.h"
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
using namespace llvm;
|
|
|
|
char DominanceFrontier::ID = 0;
|
|
INITIALIZE_PASS_BEGIN(DominanceFrontier, "domfrontier",
|
|
"Dominance Frontier Construction", true, true)
|
|
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
|
INITIALIZE_PASS_END(DominanceFrontier, "domfrontier",
|
|
"Dominance Frontier Construction", true, true)
|
|
|
|
namespace {
|
|
class DFCalculateWorkObject {
|
|
public:
|
|
DFCalculateWorkObject(BasicBlock *B, BasicBlock *P,
|
|
const DomTreeNode *N,
|
|
const DomTreeNode *PN)
|
|
: currentBB(B), parentBB(P), Node(N), parentNode(PN) {}
|
|
BasicBlock *currentBB;
|
|
BasicBlock *parentBB;
|
|
const DomTreeNode *Node;
|
|
const DomTreeNode *parentNode;
|
|
};
|
|
}
|
|
|
|
void DominanceFrontier::anchor() { }
|
|
|
|
const DominanceFrontier::DomSetType &
|
|
DominanceFrontier::calculate(const DominatorTree &DT,
|
|
const DomTreeNode *Node) {
|
|
BasicBlock *BB = Node->getBlock();
|
|
DomSetType *Result = NULL;
|
|
|
|
std::vector<DFCalculateWorkObject> workList;
|
|
SmallPtrSet<BasicBlock *, 32> visited;
|
|
|
|
workList.push_back(DFCalculateWorkObject(BB, NULL, Node, NULL));
|
|
do {
|
|
DFCalculateWorkObject *currentW = &workList.back();
|
|
assert (currentW && "Missing work object.");
|
|
|
|
BasicBlock *currentBB = currentW->currentBB;
|
|
BasicBlock *parentBB = currentW->parentBB;
|
|
const DomTreeNode *currentNode = currentW->Node;
|
|
const DomTreeNode *parentNode = currentW->parentNode;
|
|
assert (currentBB && "Invalid work object. Missing current Basic Block");
|
|
assert (currentNode && "Invalid work object. Missing current Node");
|
|
DomSetType &S = Frontiers[currentBB];
|
|
|
|
// Visit each block only once.
|
|
if (visited.count(currentBB) == 0) {
|
|
visited.insert(currentBB);
|
|
|
|
// Loop over CFG successors to calculate DFlocal[currentNode]
|
|
for (succ_iterator SI = succ_begin(currentBB), SE = succ_end(currentBB);
|
|
SI != SE; ++SI) {
|
|
// Does Node immediately dominate this successor?
|
|
if (DT[*SI]->getIDom() != currentNode)
|
|
S.insert(*SI);
|
|
}
|
|
}
|
|
|
|
// At this point, S is DFlocal. Now we union in DFup's of our children...
|
|
// Loop through and visit the nodes that Node immediately dominates (Node's
|
|
// children in the IDomTree)
|
|
bool visitChild = false;
|
|
for (DomTreeNode::const_iterator NI = currentNode->begin(),
|
|
NE = currentNode->end(); NI != NE; ++NI) {
|
|
DomTreeNode *IDominee = *NI;
|
|
BasicBlock *childBB = IDominee->getBlock();
|
|
if (visited.count(childBB) == 0) {
|
|
workList.push_back(DFCalculateWorkObject(childBB, currentBB,
|
|
IDominee, currentNode));
|
|
visitChild = true;
|
|
}
|
|
}
|
|
|
|
// If all children are visited or there is any child then pop this block
|
|
// from the workList.
|
|
if (!visitChild) {
|
|
|
|
if (!parentBB) {
|
|
Result = &S;
|
|
break;
|
|
}
|
|
|
|
DomSetType::const_iterator CDFI = S.begin(), CDFE = S.end();
|
|
DomSetType &parentSet = Frontiers[parentBB];
|
|
for (; CDFI != CDFE; ++CDFI) {
|
|
if (!DT.properlyDominates(parentNode, DT[*CDFI]))
|
|
parentSet.insert(*CDFI);
|
|
}
|
|
workList.pop_back();
|
|
}
|
|
|
|
} while (!workList.empty());
|
|
|
|
return *Result;
|
|
}
|
|
|
|
void DominanceFrontierBase::print(raw_ostream &OS, const Module* ) const {
|
|
for (const_iterator I = begin(), E = end(); I != E; ++I) {
|
|
OS << " DomFrontier for BB ";
|
|
if (I->first)
|
|
I->first->printAsOperand(OS, false);
|
|
else
|
|
OS << " <<exit node>>";
|
|
OS << " is:\t";
|
|
|
|
const std::set<BasicBlock*> &BBs = I->second;
|
|
|
|
for (std::set<BasicBlock*>::const_iterator I = BBs.begin(), E = BBs.end();
|
|
I != E; ++I) {
|
|
OS << ' ';
|
|
if (*I)
|
|
(*I)->printAsOperand(OS, false);
|
|
else
|
|
OS << "<<exit node>>";
|
|
}
|
|
OS << "\n";
|
|
}
|
|
}
|
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
void DominanceFrontierBase::dump() const {
|
|
print(dbgs());
|
|
}
|
|
#endif
|
|
|