diff options
| author | Lang Hames <lhames@gmail.com> | 2014-10-27 17:44:25 +0000 |
|---|---|---|
| committer | Lang Hames <lhames@gmail.com> | 2014-10-27 17:44:25 +0000 |
| commit | 5fe30ca56fd5f4276c0f4d5de721210bbb0514bd (patch) | |
| tree | 80f5366e1d2f0290cb737e74369a8fd50d230320 /llvm/lib/CodeGen | |
| parent | d71825c3cbdb173274c2e3afcef2c66552400648 (diff) | |
| download | bcm5719-llvm-5fe30ca56fd5f4276c0f4d5de721210bbb0514bd.tar.gz bcm5719-llvm-5fe30ca56fd5f4276c0f4d5de721210bbb0514bd.zip | |
[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%.
llvm-svn: 220688
Diffstat (limited to 'llvm/lib/CodeGen')
| -rw-r--r-- | llvm/lib/CodeGen/RegAllocPBQP.cpp | 79 |
1 files changed, 50 insertions, 29 deletions
diff --git a/llvm/lib/CodeGen/RegAllocPBQP.cpp b/llvm/lib/CodeGen/RegAllocPBQP.cpp index 5bd33743db0..768e650a952 100644 --- a/llvm/lib/CodeGen/RegAllocPBQP.cpp +++ b/llvm/lib/CodeGen/RegAllocPBQP.cpp @@ -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 { |

