[PBQP] Unique allowed-sets for nodes in the PBQP graph and use pairs of these

sets as keys into a cache of interference matrice values in the Interference
constraint adder.

Creating interference matrices was one of the large remaining time-sinks in
PBQP. Caching them reduces the total compile time (when using PBQP) on the
nightly test suite by ~10%.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220688 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Lang Hames
2014-10-27 17:44:25 +00:00
parent 86ec9c4081
commit 57902cc070
5 changed files with 247 additions and 86 deletions
+50 -29
View File
@@ -166,6 +166,12 @@ public:
class Interference : public PBQPRAConstraint {
private:
private:
typedef const PBQP::RegAlloc::AllowedRegVector* AllowedRegVecPtr;
typedef std::pair<AllowedRegVecPtr, AllowedRegVecPtr> IMatrixKey;
typedef DenseMap<IMatrixKey, PBQPRAGraph::MatrixPtr> IMatrixCache;
// Holds (Interval, CurrentSegmentID, and NodeId). The first two are required
// for the fast interference graph construction algorithm. The last is there
// to save us from looking up node ids via the VRegToNode map in the graph
@@ -226,8 +232,11 @@ public:
// number of registers, but rather the size of the largest clique in the
// graph. Still, we expect this to be better than N^2.
LiveIntervals &LIS = G.getMetadata().LIS;
const TargetRegisterInfo &TRI =
*G.getMetadata().MF.getTarget().getSubtargetImpl()->getRegisterInfo();
// Interferenc matrices are incredibly regular - they're only a function of
// the allowed sets, so we cache them to avoid the overhead of constructing
// and uniquing them.
IMatrixCache C;
typedef std::set<IntervalInfo, decltype(&lowestEndPoint)> IntervalSet;
typedef std::priority_queue<IntervalInfo, std::vector<IntervalInfo>,
@@ -275,13 +284,11 @@ public:
// Check that we haven't already added this edge
// FIXME: findEdge is expensive in the worst case (O(max_clique(G))).
// It might be better to replace this with a local bit-matrix.
if (G.findEdge(NId, MId) != PBQP::GraphBase::invalidEdgeId())
if (G.findEdge(NId, MId) != PBQPRAGraph::invalidEdgeId())
continue;
// This is a new edge - add it to the graph.
const auto &NOpts = G.getNodeMetadata(NId).getOptionRegs();
const auto &MOpts = G.getNodeMetadata(MId).getOptionRegs();
G.addEdge(NId, MId, createInterferenceMatrix(TRI, NOpts, MOpts));
createInterferenceEdge(G, NId, MId, C);
}
// Finally, add Cur to the Active set.
@@ -291,21 +298,35 @@ public:
private:
PBQPRAGraph::RawMatrix createInterferenceMatrix(
const TargetRegisterInfo &TRI,
const PBQPRAGraph::NodeMetadata::OptionToRegMap &NOpts,
const PBQPRAGraph::NodeMetadata::OptionToRegMap &MOpts) {
PBQPRAGraph::RawMatrix M(NOpts.size() + 1, MOpts.size() + 1, 0);
for (unsigned I = 0; I != NOpts.size(); ++I) {
unsigned PRegN = NOpts[I];
for (unsigned J = 0; J != MOpts.size(); ++J) {
unsigned PRegM = MOpts[J];
void createInterferenceEdge(PBQPRAGraph &G, PBQPRAGraph::NodeId NId,
PBQPRAGraph::NodeId MId, IMatrixCache &C) {
const TargetRegisterInfo &TRI =
*G.getMetadata().MF.getTarget().getSubtargetImpl()->getRegisterInfo();
const auto &NRegs = G.getNodeMetadata(NId).getAllowedRegs();
const auto &MRegs = G.getNodeMetadata(MId).getAllowedRegs();
// Try looking the edge costs up in the IMatrixCache first.
IMatrixKey K(&NRegs, &MRegs);
IMatrixCache::iterator I = C.find(K);
if (I != C.end()) {
G.addEdgeBypassingCostAllocator(NId, MId, I->second);
return;
}
PBQPRAGraph::RawMatrix M(NRegs.size() + 1, MRegs.size() + 1, 0);
for (unsigned I = 0; I != NRegs.size(); ++I) {
unsigned PRegN = NRegs[I];
for (unsigned J = 0; J != MRegs.size(); ++J) {
unsigned PRegM = MRegs[J];
if (TRI.regsOverlap(PRegN, PRegM))
M[I + 1][J + 1] = std::numeric_limits<PBQP::PBQPNum>::infinity();
}
}
return M;
PBQPRAGraph::EdgeId EId = G.addEdge(NId, MId, std::move(M));
C[K] = G.getEdgeCostsPtr(EId);
}
};
@@ -341,8 +362,8 @@ public:
PBQPRAGraph::NodeId NId = G.getMetadata().getNodeIdForVReg(SrcReg);
const PBQPRAGraph::NodeMetadata::OptionToRegMap &Allowed =
G.getNodeMetadata(NId).getOptionRegs();
const PBQPRAGraph::NodeMetadata::AllowedRegVector &Allowed =
G.getNodeMetadata(NId).getAllowedRegs();
unsigned PRegOpt = 0;
while (PRegOpt < Allowed.size() && Allowed[PRegOpt] != DstReg)
@@ -356,10 +377,10 @@ public:
} else {
PBQPRAGraph::NodeId N1Id = G.getMetadata().getNodeIdForVReg(DstReg);
PBQPRAGraph::NodeId N2Id = G.getMetadata().getNodeIdForVReg(SrcReg);
const PBQPRAGraph::NodeMetadata::OptionToRegMap *Allowed1 =
&G.getNodeMetadata(N1Id).getOptionRegs();
const PBQPRAGraph::NodeMetadata::OptionToRegMap *Allowed2 =
&G.getNodeMetadata(N2Id).getOptionRegs();
const PBQPRAGraph::NodeMetadata::AllowedRegVector *Allowed1 =
&G.getNodeMetadata(N1Id).getAllowedRegs();
const PBQPRAGraph::NodeMetadata::AllowedRegVector *Allowed2 =
&G.getNodeMetadata(N2Id).getAllowedRegs();
PBQPRAGraph::EdgeId EId = G.findEdge(N1Id, N2Id);
if (EId == G.invalidEdgeId()) {
@@ -384,10 +405,10 @@ public:
private:
void addVirtRegCoalesce(
PBQPRAGraph::RawMatrix &CostMat,
const PBQPRAGraph::NodeMetadata::OptionToRegMap &Allowed1,
const PBQPRAGraph::NodeMetadata::OptionToRegMap &Allowed2,
PBQP::PBQPNum Benefit) {
PBQPRAGraph::RawMatrix &CostMat,
const PBQPRAGraph::NodeMetadata::AllowedRegVector &Allowed1,
const PBQPRAGraph::NodeMetadata::AllowedRegVector &Allowed2,
PBQP::PBQPNum Benefit) {
assert(CostMat.getRows() == Allowed1.size() + 1 && "Size mismatch.");
assert(CostMat.getCols() == Allowed2.size() + 1 && "Size mismatch.");
for (unsigned I = 0; I != Allowed1.size(); ++I) {
@@ -501,7 +522,8 @@ void RegAllocPBQP::initializeGraph(PBQPRAGraph &G) {
PBQPRAGraph::RawVector NodeCosts(VRegAllowed.size() + 1, 0);
PBQPRAGraph::NodeId NId = G.addNode(std::move(NodeCosts));
G.getNodeMetadata(NId).setVReg(VReg);
G.getNodeMetadata(NId).setOptionRegs(std::move(VRegAllowed));
G.getNodeMetadata(NId).setAllowedRegs(
G.getMetadata().getAllowedRegs(std::move(VRegAllowed)));
G.getMetadata().setNodeIdForVReg(VReg, NId);
}
}
@@ -529,7 +551,7 @@ bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAGraph &G,
unsigned AllocOption = Solution.getSelection(NId);
if (AllocOption != PBQP::RegAlloc::getSpillOptionIdx()) {
unsigned PReg = G.getNodeMetadata(NId).getOptionRegs()[AllocOption - 1];
unsigned PReg = G.getNodeMetadata(NId).getAllowedRegs()[AllocOption - 1];
DEBUG(dbgs() << "VREG " << PrintReg(VReg, &TRI) << " -> "
<< TRI.getName(PReg) << "\n");
assert(PReg != 0 && "Invalid preg selected.");
@@ -563,7 +585,6 @@ bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAGraph &G,
return !AnotherRoundNeeded;
}
void RegAllocPBQP::finalizeAlloc(MachineFunction &MF,
LiveIntervals &LIS,
VirtRegMap &VRM) const {