Change the PBQP graph adjacency list structure from std::set to std::vector.
authorLang Hames <lhames@gmail.com>
Wed, 26 Mar 2014 18:58:00 +0000 (18:58 +0000)
committerLang Hames <lhames@gmail.com>
Wed, 26 Mar 2014 18:58:00 +0000 (18:58 +0000)
The edge data structure (EdgeEntry) now holds the indices of its entries in the
adjacency lists of the nodes it connects. This trades a little ugliness for
faster insertion/removal, which is now O(1) with a cheap constant factor. All
of this is implementation detail within the PBQP graph, the external API remains
unchanged.

Individual register allocations are likely to change, since the adjacency lists
will now be ordered differently (or rather, will now be unordered). This
shouldn't affect the average quality of allocations however.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204841 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/PBQP/Graph.h

index 90e7e4f07421257043e0f448a73710a2d38244fe..a57a639bf7a69375516761127d0bb444ae2d02b4 100644 (file)
@@ -51,29 +51,115 @@ namespace PBQP {
 
     class NodeEntry {
     public:
-      typedef std::set<NodeId> AdjEdgeList;
+      typedef std::vector<EdgeId> AdjEdgeList;
+      typedef AdjEdgeList::size_type AdjEdgeIdx;
       typedef AdjEdgeList::const_iterator AdjEdgeItr;
+
+      static AdjEdgeIdx getInvalidAdjEdgeIdx() {
+        return std::numeric_limits<AdjEdgeIdx>::max();
+      }
+
       NodeEntry(VectorPtr Costs) : Costs(Costs) {}
 
+      AdjEdgeIdx addAdjEdgeId(EdgeId EId) {
+        AdjEdgeIdx Idx = AdjEdgeIds.size();
+        AdjEdgeIds.push_back(EId);
+        return Idx;
+      }
+
+      // If a swap is performed, returns the new EdgeId that must be
+      // updated, otherwise returns invalidEdgeId().
+      EdgeId removeAdjEdgeId(AdjEdgeIdx Idx) {
+        EdgeId EIdToUpdate = Graph::invalidEdgeId();
+        if (Idx < AdjEdgeIds.size() - 1) {
+          std::swap(AdjEdgeIds[Idx], AdjEdgeIds.back());
+          EIdToUpdate = AdjEdgeIds[Idx];
+        }
+        AdjEdgeIds.pop_back();
+        return EIdToUpdate;
+      }
+
+      const AdjEdgeList& getAdjEdgeIds() const { return AdjEdgeIds; }
+
       VectorPtr Costs;
       NodeMetadata Metadata;
+    private:
       AdjEdgeList AdjEdgeIds;
     };
 
     class EdgeEntry {
     public:
       EdgeEntry(NodeId N1Id, NodeId N2Id, MatrixPtr Costs)
-        : Costs(Costs), N1Id(N1Id), N2Id(N2Id) {}
+        : Costs(Costs) {
+        NIds[0] = N1Id;
+        NIds[1] = N2Id;
+        ThisEdgeAdjIdxs[0] = NodeEntry::getInvalidAdjEdgeIdx();
+        ThisEdgeAdjIdxs[1] = NodeEntry::getInvalidAdjEdgeIdx();
+      }
+
       void invalidate() {
-        N1Id = N2Id = Graph::invalidNodeId();
+        NIds[0] = NIds[1] = Graph::invalidNodeId();
+        ThisEdgeAdjIdxs[0] = ThisEdgeAdjIdxs[1] =
+          NodeEntry::getInvalidAdjEdgeIdx();
         Costs = nullptr;
       }
-      NodeId getN1Id() const { return N1Id; }
-      NodeId getN2Id() const { return N2Id; }
+
+      void connectToN(Graph &G, EdgeId ThisEdgeId, unsigned NIdx) {
+        assert(ThisEdgeAdjIdxs[NIdx] == NodeEntry::getInvalidAdjEdgeIdx() &&
+               "Edge already connected to NIds[NIdx].");
+        NodeEntry &N = G.getNode(NIds[NIdx]);
+        ThisEdgeAdjIdxs[NIdx] = N.addAdjEdgeId(ThisEdgeId);
+      }
+
+      void connectTo(Graph &G, EdgeId ThisEdgeId, NodeId NId) {
+        if (NId == NIds[0])
+          connectToN(G, ThisEdgeId, 0);
+        else {
+          assert(NId == NIds[1] && "Edge does not connect NId.");
+          connectToN(G, ThisEdgeId, 1);
+        }
+      }
+
+      void connect(Graph &G, EdgeId ThisEdgeId) {
+        connectToN(G, ThisEdgeId, 0);
+        connectToN(G, ThisEdgeId, 1);
+      }
+
+      void updateAdjEdgeIdx(NodeId NId, typename NodeEntry::AdjEdgeIdx NewIdx) {
+        if (NId == NIds[0])
+          ThisEdgeAdjIdxs[0] = NewIdx;
+        else {
+          assert(NId == NIds[1] && "Edge not connected to NId");
+          ThisEdgeAdjIdxs[1] = NewIdx;
+        }
+      }
+
+      void disconnectFromN(Graph &G, unsigned NIdx) {
+        assert(ThisEdgeAdjIdxs[NIdx] != NodeEntry::getInvalidAdjEdgeIdx() &&
+               "Edge not connected to NIds[NIdx].");
+        NodeEntry &N = G.getNode(NIds[NIdx]);
+        EdgeId EIdToUpdate = N.removeAdjEdgeId(ThisEdgeAdjIdxs[NIdx]);
+        if (EIdToUpdate != Graph::invalidEdgeId())
+          G.getEdge(EIdToUpdate).updateAdjEdgeIdx(NIds[NIdx], ThisEdgeAdjIdxs[NIdx]);
+        ThisEdgeAdjIdxs[NIdx] = NodeEntry::getInvalidAdjEdgeIdx();
+      }
+
+      void disconnectFrom(Graph &G, NodeId NId) {
+        if (NId == NIds[0])
+          disconnectFromN(G, 0);
+        else {
+          assert(NId == NIds[1] && "Edge does not connect NId");
+          disconnectFromN(G, 1);
+        }
+      }
+
+      NodeId getN1Id() const { return NIds[0]; }
+      NodeId getN2Id() const { return NIds[1]; }
       MatrixPtr Costs;
       EdgeMetadata Metadata;
     private:
-      NodeId N1Id, N2Id;
+      NodeId NIds[2];
+      typename NodeEntry::AdjEdgeIdx ThisEdgeAdjIdxs[2];
     };
 
     // ----- MEMBERS -----
@@ -134,8 +220,8 @@ namespace PBQP {
              (N2.Costs->getLength() == NE.Costs->getCols()) &&
              "Edge cost dimensions do not match node costs dimensions.");
 
-      N1.AdjEdgeIds.insert(EId);
-      N2.AdjEdgeIds.insert(EId);
+      // Add the edge to the adjacency sets of its nodes.
+      NE.connect(*this, EId);
       return EId;
     }
 
@@ -228,14 +314,14 @@ namespace PBQP {
     public:
       AdjEdgeIdSet(const NodeEntry &NE) : NE(NE) { }
       typename NodeEntry::AdjEdgeItr begin() const {
-        return NE.AdjEdgeIds.begin();
+        return NE.getAdjEdgeIds().begin();
       }
       typename NodeEntry::AdjEdgeItr end() const {
-        return NE.AdjEdgeIds.end();
+        return NE.getAdjEdgeIds().end();
       }
-      bool empty() const { return NE.AdjEdges.empty(); }
+      bool empty() const { return NE.getAdjEdgeIds().empty(); }
       typename NodeEntry::AdjEdgeList::size_type size() const {
-        return NE.AdjEdgeIds.size();
+        return NE.getAdjEdgeIds().size();
       }
     private:
       const NodeEntry &NE;
@@ -336,7 +422,7 @@ namespace PBQP {
     }
 
     typename NodeEntry::AdjEdgeList::size_type getNodeDegree(NodeId NId) const {
-      return getNode(NId).AdjEdgeIds.size();
+      return getNode(NId).getAdjEdgeIds().size();
     }
 
     /// \brief Set an edge's cost matrix.
@@ -459,8 +545,9 @@ namespace PBQP {
     void disconnectEdge(EdgeId EId, NodeId NId) {
       if (Solver)
         Solver->handleDisconnectEdge(EId, NId);
-      NodeEntry &N = getNode(NId);
-      N.AdjEdgeIds.erase(EId);
+
+      EdgeEntry &E = getEdge(EId);
+      E.disconnectFrom(*this, NId);
     }
 
     /// \brief Convenience method to disconnect all neighbours from the given
@@ -475,8 +562,8 @@ namespace PBQP {
     /// Adds an edge that had been previously disconnected back into the
     /// adjacency set of the nodes that the edge connects.
     void reconnectEdge(EdgeId EId, NodeId NId) {
-      NodeEntry &N = getNode(NId);
-      N.addAdjEdge(EId);
+      EdgeEntry &E = getEdge(EId);
+      E.connectTo(*this, EId, NId);
       if (Solver)
         Solver->handleReconnectEdge(EId, NId);
     }
@@ -487,10 +574,7 @@ namespace PBQP {
       if (Solver)
         Solver->handleRemoveEdge(EId);
       EdgeEntry &E = getEdge(EId);
-      NodeEntry &N1 = getNode(E.getNode1());
-      NodeEntry &N2 = getNode(E.getNode2());
-      N1.removeEdge(EId);
-      N2.removeEdge(EId);
+      E.disconnect();
       FreeEdgeIds.push_back(EId);
       Edges[EId].invalidate();
     }