mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
Clean up StrongPHIElimination a bit, and add some more comments to the internal structures. There's
still more work to do on this front. llvm-svn: 45783
This commit is contained in:
parent
e97a9a373a
commit
62bb891e23
@ -39,13 +39,28 @@ namespace {
|
|||||||
static char ID; // Pass identification, replacement for typeid
|
static char ID; // Pass identification, replacement for typeid
|
||||||
StrongPHIElimination() : MachineFunctionPass((intptr_t)&ID) {}
|
StrongPHIElimination() : MachineFunctionPass((intptr_t)&ID) {}
|
||||||
|
|
||||||
|
// Waiting stores, for each MBB, the set of copies that need to
|
||||||
|
// be inserted into that MBB
|
||||||
DenseMap<MachineBasicBlock*,
|
DenseMap<MachineBasicBlock*,
|
||||||
std::map<unsigned, unsigned> > Waiting;
|
std::map<unsigned, unsigned> > Waiting;
|
||||||
|
|
||||||
|
// Stacks holds the renaming stack for each register
|
||||||
std::map<unsigned, std::vector<unsigned> > Stacks;
|
std::map<unsigned, std::vector<unsigned> > Stacks;
|
||||||
|
|
||||||
|
// Registers in UsedByAnother are PHI nodes that are themselves
|
||||||
|
// used as operands to another another PHI node
|
||||||
std::set<unsigned> UsedByAnother;
|
std::set<unsigned> UsedByAnother;
|
||||||
|
|
||||||
|
// RenameSets are the sets of operands to a PHI (the defining instruction
|
||||||
|
// of the key) that can be renamed without copies
|
||||||
std::map<unsigned, std::set<unsigned> > RenameSets;
|
std::map<unsigned, std::set<unsigned> > RenameSets;
|
||||||
|
|
||||||
|
// Store the DFS-in number of each block
|
||||||
|
DenseMap<MachineBasicBlock*, unsigned> preorder;
|
||||||
|
|
||||||
|
// Store the DFS-out number of each block
|
||||||
|
DenseMap<MachineBasicBlock*, unsigned> maxpreorder;
|
||||||
|
|
||||||
bool runOnMachineFunction(MachineFunction &Fn);
|
bool runOnMachineFunction(MachineFunction &Fn);
|
||||||
|
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
@ -59,19 +74,32 @@ namespace {
|
|||||||
maxpreorder.clear();
|
maxpreorder.clear();
|
||||||
|
|
||||||
Waiting.clear();
|
Waiting.clear();
|
||||||
|
Stacks.clear();
|
||||||
|
UsedByAnother.clear();
|
||||||
|
RenameSets.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/// DomForestNode - Represents a node in the "dominator forest". This is
|
||||||
|
/// a forest in which the nodes represent registers and the edges
|
||||||
|
/// represent a dominance relation in the block defining those registers.
|
||||||
struct DomForestNode {
|
struct DomForestNode {
|
||||||
private:
|
private:
|
||||||
|
// Store references to our children
|
||||||
std::vector<DomForestNode*> children;
|
std::vector<DomForestNode*> children;
|
||||||
|
// The register we represent
|
||||||
unsigned reg;
|
unsigned reg;
|
||||||
|
|
||||||
|
// Add another node as our child
|
||||||
void addChild(DomForestNode* DFN) { children.push_back(DFN); }
|
void addChild(DomForestNode* DFN) { children.push_back(DFN); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::vector<DomForestNode*>::iterator iterator;
|
typedef std::vector<DomForestNode*>::iterator iterator;
|
||||||
|
|
||||||
|
// Create a DomForestNode by providing the register it represents, and
|
||||||
|
// the node to be its parent. The virtual root node has register 0
|
||||||
|
// and a null parent.
|
||||||
DomForestNode(unsigned r, DomForestNode* parent) : reg(r) {
|
DomForestNode(unsigned r, DomForestNode* parent) : reg(r) {
|
||||||
if (parent)
|
if (parent)
|
||||||
parent->addChild(this);
|
parent->addChild(this);
|
||||||
@ -82,16 +110,14 @@ namespace {
|
|||||||
delete *I;
|
delete *I;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getReg - Return the regiser that this node represents
|
||||||
inline unsigned getReg() { return reg; }
|
inline unsigned getReg() { return reg; }
|
||||||
|
|
||||||
|
// Provide iterator access to our children
|
||||||
inline DomForestNode::iterator begin() { return children.begin(); }
|
inline DomForestNode::iterator begin() { return children.begin(); }
|
||||||
inline DomForestNode::iterator end() { return children.end(); }
|
inline DomForestNode::iterator end() { return children.end(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
DenseMap<MachineBasicBlock*, unsigned> preorder;
|
|
||||||
DenseMap<MachineBasicBlock*, unsigned> maxpreorder;
|
|
||||||
|
|
||||||
|
|
||||||
void computeDFS(MachineFunction& MF);
|
void computeDFS(MachineFunction& MF);
|
||||||
void processBlock(MachineBasicBlock* MBB);
|
void processBlock(MachineBasicBlock* MBB);
|
||||||
|
|
||||||
@ -188,22 +214,28 @@ std::vector<StrongPHIElimination::DomForestNode*>
|
|||||||
StrongPHIElimination::computeDomForest(std::set<unsigned>& regs) {
|
StrongPHIElimination::computeDomForest(std::set<unsigned>& regs) {
|
||||||
LiveVariables& LV = getAnalysis<LiveVariables>();
|
LiveVariables& LV = getAnalysis<LiveVariables>();
|
||||||
|
|
||||||
|
// Begin by creating a virtual root node, since the actual results
|
||||||
|
// may well be a forest. Assume this node has maximum DFS-out number.
|
||||||
DomForestNode* VirtualRoot = new DomForestNode(0, 0);
|
DomForestNode* VirtualRoot = new DomForestNode(0, 0);
|
||||||
maxpreorder.insert(std::make_pair((MachineBasicBlock*)0, ~0UL));
|
maxpreorder.insert(std::make_pair((MachineBasicBlock*)0, ~0UL));
|
||||||
|
|
||||||
|
// Populate a worklist with the registers
|
||||||
std::vector<unsigned> worklist;
|
std::vector<unsigned> worklist;
|
||||||
worklist.reserve(regs.size());
|
worklist.reserve(regs.size());
|
||||||
for (std::set<unsigned>::iterator I = regs.begin(), E = regs.end();
|
for (std::set<unsigned>::iterator I = regs.begin(), E = regs.end();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
worklist.push_back(*I);
|
worklist.push_back(*I);
|
||||||
|
|
||||||
|
// Sort the registers by the DFS-in number of their defining block
|
||||||
PreorderSorter PS(preorder, LV);
|
PreorderSorter PS(preorder, LV);
|
||||||
std::sort(worklist.begin(), worklist.end(), PS);
|
std::sort(worklist.begin(), worklist.end(), PS);
|
||||||
|
|
||||||
|
// Create a "current parent" stack, and put the virtual root on top of it
|
||||||
DomForestNode* CurrentParent = VirtualRoot;
|
DomForestNode* CurrentParent = VirtualRoot;
|
||||||
std::vector<DomForestNode*> stack;
|
std::vector<DomForestNode*> stack;
|
||||||
stack.push_back(VirtualRoot);
|
stack.push_back(VirtualRoot);
|
||||||
|
|
||||||
|
// Iterate over all the registers in the previously computed order
|
||||||
for (std::vector<unsigned>::iterator I = worklist.begin(), E = worklist.end();
|
for (std::vector<unsigned>::iterator I = worklist.begin(), E = worklist.end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
unsigned pre = preorder[LV.getVarInfo(*I).DefInst->getParent()];
|
unsigned pre = preorder[LV.getVarInfo(*I).DefInst->getParent()];
|
||||||
@ -211,6 +243,8 @@ StrongPHIElimination::computeDomForest(std::set<unsigned>& regs) {
|
|||||||
LV.getVarInfo(CurrentParent->getReg()).DefInst->getParent() :
|
LV.getVarInfo(CurrentParent->getReg()).DefInst->getParent() :
|
||||||
0;
|
0;
|
||||||
|
|
||||||
|
// If the DFS-in number of the register is greater than the DFS-out number
|
||||||
|
// of the current parent, repeatedly pop the parent stack until it isn't.
|
||||||
while (pre > maxpreorder[parentBlock]) {
|
while (pre > maxpreorder[parentBlock]) {
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
CurrentParent = stack.back();
|
CurrentParent = stack.back();
|
||||||
@ -220,11 +254,16 @@ StrongPHIElimination::computeDomForest(std::set<unsigned>& regs) {
|
|||||||
0;
|
0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now that we've found the appropriate parent, create a DomForestNode for
|
||||||
|
// this register and attach it to the forest
|
||||||
DomForestNode* child = new DomForestNode(*I, CurrentParent);
|
DomForestNode* child = new DomForestNode(*I, CurrentParent);
|
||||||
|
|
||||||
|
// Push this new node on the "current parent" stack
|
||||||
stack.push_back(child);
|
stack.push_back(child);
|
||||||
CurrentParent = child;
|
CurrentParent = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return a vector containing the children of the virtual root node
|
||||||
std::vector<DomForestNode*> ret;
|
std::vector<DomForestNode*> ret;
|
||||||
ret.insert(ret.end(), VirtualRoot->begin(), VirtualRoot->end());
|
ret.insert(ret.end(), VirtualRoot->begin(), VirtualRoot->end());
|
||||||
return ret;
|
return ret;
|
||||||
@ -269,7 +308,8 @@ static bool isKillInst(LiveVariables::VarInfo& V, MachineInstr* MI) {
|
|||||||
/// trick parameter is 'mode' which tells it the relationship of the two
|
/// trick parameter is 'mode' which tells it the relationship of the two
|
||||||
/// registers. 0 - defined in the same block, 1 - first properly dominates
|
/// registers. 0 - defined in the same block, 1 - first properly dominates
|
||||||
/// second, 2 - second properly dominates first
|
/// second, 2 - second properly dominates first
|
||||||
static bool interferes(LiveVariables::VarInfo& First, LiveVariables::VarInfo& Second,
|
static bool interferes(LiveVariables::VarInfo& First,
|
||||||
|
LiveVariables::VarInfo& Second,
|
||||||
MachineBasicBlock* scan, unsigned mode) {
|
MachineBasicBlock* scan, unsigned mode) {
|
||||||
MachineInstr* def = 0;
|
MachineInstr* def = 0;
|
||||||
MachineInstr* kill = 0;
|
MachineInstr* kill = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user