forked from OSchip/llvm-project
384 lines
12 KiB
C++
384 lines
12 KiB
C++
//===-- Briggs.h --- Briggs Heuristic for PBQP -----------------*- C++ --*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This class implements the Briggs test for "allocability" of nodes in a
|
|
// PBQP graph representing a register allocation problem. Nodes which can be
|
|
// proven allocable (by a safe and relatively accurate test) are removed from
|
|
// the PBQP graph first. If no provably allocable node is present in the graph
|
|
// then the node with the minimal spill-cost to degree ratio is removed.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H
|
|
#define LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H
|
|
|
|
#include "../HeuristicSolver.h"
|
|
|
|
#include <set>
|
|
|
|
namespace PBQP {
|
|
namespace Heuristics {
|
|
|
|
class Briggs {
|
|
public:
|
|
|
|
class NodeData;
|
|
class EdgeData;
|
|
|
|
private:
|
|
|
|
typedef HeuristicSolverImpl<Briggs> Solver;
|
|
typedef HSITypes<NodeData, EdgeData> HSIT;
|
|
typedef HSIT::SolverGraph SolverGraph;
|
|
typedef HSIT::GraphNodeIterator GraphNodeIterator;
|
|
typedef HSIT::GraphEdgeIterator GraphEdgeIterator;
|
|
|
|
class LinkDegreeComparator {
|
|
public:
|
|
LinkDegreeComparator() : g(0) {}
|
|
LinkDegreeComparator(SolverGraph *g) : g(g) {}
|
|
|
|
bool operator()(const GraphNodeIterator &node1Itr,
|
|
const GraphNodeIterator &node2Itr) const {
|
|
assert((g != 0) && "Graph object not set, cannot access node data.");
|
|
unsigned n1Degree = g->getNodeData(node1Itr).getLinkDegree(),
|
|
n2Degree = g->getNodeData(node2Itr).getLinkDegree();
|
|
if (n1Degree > n2Degree) {
|
|
return true;
|
|
}
|
|
else if (n1Degree < n2Degree) {
|
|
return false;
|
|
}
|
|
// else they're "equal" by degree, differentiate based on ID.
|
|
return g->getNodeID(node1Itr) < g->getNodeID(node2Itr);
|
|
}
|
|
|
|
private:
|
|
SolverGraph *g;
|
|
};
|
|
|
|
class SpillPriorityComparator {
|
|
public:
|
|
SpillPriorityComparator() : g(0) {}
|
|
SpillPriorityComparator(SolverGraph *g) : g(g) {}
|
|
|
|
bool operator()(const GraphNodeIterator &node1Itr,
|
|
const GraphNodeIterator &node2Itr) const {
|
|
assert((g != 0) && "Graph object not set, cannot access node data.");
|
|
PBQPNum cost1 =
|
|
g->getNodeCosts(node1Itr)[0] /
|
|
g->getNodeData(node1Itr).getLinkDegree(),
|
|
cost2 =
|
|
g->getNodeCosts(node2Itr)[0] /
|
|
g->getNodeData(node2Itr).getLinkDegree();
|
|
|
|
if (cost1 < cost2) {
|
|
return true;
|
|
}
|
|
else if (cost1 > cost2) {
|
|
return false;
|
|
}
|
|
// else they'er "equal" again, differentiate based on address again.
|
|
return g->getNodeID(node1Itr) < g->getNodeID(node2Itr);
|
|
}
|
|
|
|
private:
|
|
SolverGraph *g;
|
|
};
|
|
|
|
typedef std::set<GraphNodeIterator, LinkDegreeComparator>
|
|
RNAllocableNodeList;
|
|
typedef RNAllocableNodeList::iterator RNAllocableNodeListIterator;
|
|
|
|
typedef std::set<GraphNodeIterator, SpillPriorityComparator>
|
|
RNUnallocableNodeList;
|
|
typedef RNUnallocableNodeList::iterator RNUnallocableNodeListIterator;
|
|
|
|
public:
|
|
|
|
class NodeData {
|
|
private:
|
|
RNAllocableNodeListIterator rNAllocableNodeListItr;
|
|
RNUnallocableNodeListIterator rNUnallocableNodeListItr;
|
|
unsigned numRegOptions, numDenied, numSafe;
|
|
std::vector<unsigned> unsafeDegrees;
|
|
bool allocable;
|
|
|
|
void addRemoveLink(SolverGraph &g, const GraphNodeIterator &nodeItr,
|
|
const GraphEdgeIterator &edgeItr, bool add) {
|
|
|
|
//assume we're adding...
|
|
unsigned udTarget = 0, dir = 1;
|
|
|
|
if (!add) {
|
|
udTarget = 1;
|
|
dir = ~0;
|
|
}
|
|
|
|
EdgeData &linkEdgeData = g.getEdgeData(edgeItr).getHeuristicData();
|
|
|
|
EdgeData::ConstUnsafeIterator edgeUnsafeBegin, edgeUnsafeEnd;
|
|
|
|
if (nodeItr == g.getEdgeNode1Itr(edgeItr)) {
|
|
numDenied += (dir * linkEdgeData.getWorstDegree());
|
|
edgeUnsafeBegin = linkEdgeData.unsafeBegin();
|
|
edgeUnsafeEnd = linkEdgeData.unsafeEnd();
|
|
}
|
|
else {
|
|
numDenied += (dir * linkEdgeData.getReverseWorstDegree());
|
|
edgeUnsafeBegin = linkEdgeData.reverseUnsafeBegin();
|
|
edgeUnsafeEnd = linkEdgeData.reverseUnsafeEnd();
|
|
}
|
|
|
|
assert((unsafeDegrees.size() ==
|
|
static_cast<unsigned>(
|
|
std::distance(edgeUnsafeBegin, edgeUnsafeEnd)))
|
|
&& "Unsafe array size mismatch.");
|
|
|
|
std::vector<unsigned>::iterator unsafeDegreesItr =
|
|
unsafeDegrees.begin();
|
|
|
|
for (EdgeData::ConstUnsafeIterator edgeUnsafeItr = edgeUnsafeBegin;
|
|
edgeUnsafeItr != edgeUnsafeEnd;
|
|
++edgeUnsafeItr, ++unsafeDegreesItr) {
|
|
|
|
if ((*edgeUnsafeItr == 1) && (*unsafeDegreesItr == udTarget)) {
|
|
numSafe -= dir;
|
|
}
|
|
*unsafeDegreesItr += (dir * (*edgeUnsafeItr));
|
|
}
|
|
|
|
allocable = (numDenied < numRegOptions) || (numSafe > 0);
|
|
}
|
|
|
|
public:
|
|
|
|
void setup(SolverGraph &g, const GraphNodeIterator &nodeItr) {
|
|
|
|
numRegOptions = g.getNodeCosts(nodeItr).getLength() - 1;
|
|
|
|
numSafe = numRegOptions; // Optimistic, correct below.
|
|
numDenied = 0; // Also optimistic.
|
|
unsafeDegrees.resize(numRegOptions, 0);
|
|
|
|
HSIT::NodeData &nodeData = g.getNodeData(nodeItr);
|
|
|
|
for (HSIT::NodeData::AdjLinkIterator
|
|
adjLinkItr = nodeData.adjLinksBegin(),
|
|
adjLinkEnd = nodeData.adjLinksEnd();
|
|
adjLinkItr != adjLinkEnd; ++adjLinkItr) {
|
|
|
|
addRemoveLink(g, nodeItr, *adjLinkItr, true);
|
|
}
|
|
}
|
|
|
|
bool isAllocable() const { return allocable; }
|
|
|
|
void handleAddLink(SolverGraph &g, const GraphNodeIterator &nodeItr,
|
|
const GraphEdgeIterator &adjEdge) {
|
|
addRemoveLink(g, nodeItr, adjEdge, true);
|
|
}
|
|
|
|
void handleRemoveLink(SolverGraph &g, const GraphNodeIterator &nodeItr,
|
|
const GraphEdgeIterator &adjEdge) {
|
|
addRemoveLink(g, nodeItr, adjEdge, false);
|
|
}
|
|
|
|
void setRNAllocableNodeListItr(
|
|
const RNAllocableNodeListIterator &rNAllocableNodeListItr) {
|
|
|
|
this->rNAllocableNodeListItr = rNAllocableNodeListItr;
|
|
}
|
|
|
|
RNAllocableNodeListIterator getRNAllocableNodeListItr() const {
|
|
return rNAllocableNodeListItr;
|
|
}
|
|
|
|
void setRNUnallocableNodeListItr(
|
|
const RNUnallocableNodeListIterator &rNUnallocableNodeListItr) {
|
|
|
|
this->rNUnallocableNodeListItr = rNUnallocableNodeListItr;
|
|
}
|
|
|
|
RNUnallocableNodeListIterator getRNUnallocableNodeListItr() const {
|
|
return rNUnallocableNodeListItr;
|
|
}
|
|
|
|
|
|
};
|
|
|
|
class EdgeData {
|
|
private:
|
|
|
|
typedef std::vector<unsigned> UnsafeArray;
|
|
|
|
unsigned worstDegree,
|
|
reverseWorstDegree;
|
|
UnsafeArray unsafe, reverseUnsafe;
|
|
|
|
public:
|
|
|
|
EdgeData() : worstDegree(0), reverseWorstDegree(0) {}
|
|
|
|
typedef UnsafeArray::const_iterator ConstUnsafeIterator;
|
|
|
|
void setup(SolverGraph &g, const GraphEdgeIterator &edgeItr) {
|
|
const Matrix &edgeCosts = g.getEdgeCosts(edgeItr);
|
|
unsigned numRegs = edgeCosts.getRows() - 1,
|
|
numReverseRegs = edgeCosts.getCols() - 1;
|
|
|
|
unsafe.resize(numRegs, 0);
|
|
reverseUnsafe.resize(numReverseRegs, 0);
|
|
|
|
std::vector<unsigned> rowInfCounts(numRegs, 0),
|
|
colInfCounts(numReverseRegs, 0);
|
|
|
|
for (unsigned i = 0; i < numRegs; ++i) {
|
|
for (unsigned j = 0; j < numReverseRegs; ++j) {
|
|
if (edgeCosts[i + 1][j + 1] ==
|
|
std::numeric_limits<PBQPNum>::infinity()) {
|
|
unsafe[i] = 1;
|
|
reverseUnsafe[j] = 1;
|
|
++rowInfCounts[i];
|
|
++colInfCounts[j];
|
|
|
|
if (colInfCounts[j] > worstDegree) {
|
|
worstDegree = colInfCounts[j];
|
|
}
|
|
|
|
if (rowInfCounts[i] > reverseWorstDegree) {
|
|
reverseWorstDegree = rowInfCounts[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned getWorstDegree() const { return worstDegree; }
|
|
unsigned getReverseWorstDegree() const { return reverseWorstDegree; }
|
|
ConstUnsafeIterator unsafeBegin() const { return unsafe.begin(); }
|
|
ConstUnsafeIterator unsafeEnd() const { return unsafe.end(); }
|
|
ConstUnsafeIterator reverseUnsafeBegin() const {
|
|
return reverseUnsafe.begin();
|
|
}
|
|
ConstUnsafeIterator reverseUnsafeEnd() const {
|
|
return reverseUnsafe.end();
|
|
}
|
|
};
|
|
|
|
void initialise(Solver &solver) {
|
|
this->s = &solver;
|
|
g = &s->getGraph();
|
|
rNAllocableBucket = RNAllocableNodeList(LinkDegreeComparator(g));
|
|
rNUnallocableBucket =
|
|
RNUnallocableNodeList(SpillPriorityComparator(g));
|
|
|
|
for (GraphEdgeIterator
|
|
edgeItr = g->edgesBegin(), edgeEnd = g->edgesEnd();
|
|
edgeItr != edgeEnd; ++edgeItr) {
|
|
|
|
g->getEdgeData(edgeItr).getHeuristicData().setup(*g, edgeItr);
|
|
}
|
|
|
|
for (GraphNodeIterator
|
|
nodeItr = g->nodesBegin(), nodeEnd = g->nodesEnd();
|
|
nodeItr != nodeEnd; ++nodeItr) {
|
|
|
|
g->getNodeData(nodeItr).getHeuristicData().setup(*g, nodeItr);
|
|
}
|
|
}
|
|
|
|
void addToRNBucket(const GraphNodeIterator &nodeItr) {
|
|
NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData();
|
|
|
|
if (nodeData.isAllocable()) {
|
|
nodeData.setRNAllocableNodeListItr(
|
|
rNAllocableBucket.insert(rNAllocableBucket.begin(), nodeItr));
|
|
}
|
|
else {
|
|
nodeData.setRNUnallocableNodeListItr(
|
|
rNUnallocableBucket.insert(rNUnallocableBucket.begin(), nodeItr));
|
|
}
|
|
}
|
|
|
|
void removeFromRNBucket(const GraphNodeIterator &nodeItr) {
|
|
NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData();
|
|
|
|
if (nodeData.isAllocable()) {
|
|
rNAllocableBucket.erase(nodeData.getRNAllocableNodeListItr());
|
|
}
|
|
else {
|
|
rNUnallocableBucket.erase(nodeData.getRNUnallocableNodeListItr());
|
|
}
|
|
}
|
|
|
|
void handleAddLink(const GraphEdgeIterator &edgeItr) {
|
|
// We assume that if we got here this edge is attached to at least
|
|
// one high degree node.
|
|
g->getEdgeData(edgeItr).getHeuristicData().setup(*g, edgeItr);
|
|
|
|
GraphNodeIterator n1Itr = g->getEdgeNode1Itr(edgeItr),
|
|
n2Itr = g->getEdgeNode2Itr(edgeItr);
|
|
|
|
HSIT::NodeData &n1Data = g->getNodeData(n1Itr),
|
|
&n2Data = g->getNodeData(n2Itr);
|
|
|
|
if (n1Data.getLinkDegree() > 2) {
|
|
n1Data.getHeuristicData().handleAddLink(*g, n1Itr, edgeItr);
|
|
}
|
|
if (n2Data.getLinkDegree() > 2) {
|
|
n2Data.getHeuristicData().handleAddLink(*g, n2Itr, edgeItr);
|
|
}
|
|
}
|
|
|
|
void handleRemoveLink(const GraphEdgeIterator &edgeItr,
|
|
const GraphNodeIterator &nodeItr) {
|
|
NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData();
|
|
nodeData.handleRemoveLink(*g, nodeItr, edgeItr);
|
|
}
|
|
|
|
void processRN() {
|
|
|
|
if (!rNAllocableBucket.empty()) {
|
|
GraphNodeIterator selectedNodeItr = *rNAllocableBucket.begin();
|
|
//std::cerr << "RN safely pushing " << g->getNodeID(selectedNodeItr) << "\n";
|
|
rNAllocableBucket.erase(rNAllocableBucket.begin());
|
|
s->pushStack(selectedNodeItr);
|
|
s->unlinkNode(selectedNodeItr);
|
|
}
|
|
else {
|
|
GraphNodeIterator selectedNodeItr = *rNUnallocableBucket.begin();
|
|
//std::cerr << "RN optimistically pushing " << g->getNodeID(selectedNodeItr) << "\n";
|
|
rNUnallocableBucket.erase(rNUnallocableBucket.begin());
|
|
s->pushStack(selectedNodeItr);
|
|
s->unlinkNode(selectedNodeItr);
|
|
}
|
|
|
|
}
|
|
|
|
bool rNBucketEmpty() const {
|
|
return (rNAllocableBucket.empty() && rNUnallocableBucket.empty());
|
|
}
|
|
|
|
private:
|
|
|
|
Solver *s;
|
|
SolverGraph *g;
|
|
RNAllocableNodeList rNAllocableBucket;
|
|
RNUnallocableNodeList rNUnallocableBucket;
|
|
};
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
#endif // LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H
|