Improve V3List user interface (#4996)

This commit is contained in:
Geza Lore
2024-03-25 23:06:25 +00:00
committed by GitHub
parent 4df9e2e0e5
commit 98206a4f04
40 changed files with 2177 additions and 2158 deletions
+65 -82
View File
@@ -42,19 +42,15 @@ class GraphRemoveRedundant final : GraphAlg<> {
const bool m_sumWeights; ///< Sum, rather then maximize weights
private:
void main() {
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
vertexIterate(vertexp);
}
for (V3GraphVertex& vertex : m_graphp->vertices()) vertexIterate(&vertex);
}
void vertexIterate(V3GraphVertex* vertexp) {
// Clear marks
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
edgep->top()->userp(nullptr);
}
for (V3GraphEdge& edge : vertexp->outEdges()) edge.top()->userp(nullptr);
// Mark edges and detect duplications
for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
nextp = edgep->outNextp();
for (V3GraphEdge* const edgep : vertexp->outEdges().unlinkable()) {
if (followEdge(edgep)) {
V3GraphVertex* outVertexp = edgep->top();
V3GraphEdge* prevEdgep = static_cast<V3GraphEdge*>(outVertexp->userp());
@@ -112,15 +108,15 @@ public:
: GraphAlg<>(graphp, nullptr) {}
void go() {
GraphPathChecker checker{m_graphp};
for (V3GraphVertex* vxp = m_graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
for (V3GraphVertex& vtx : m_graphp->vertices()) {
V3GraphEdge* deletep = nullptr;
for (V3GraphEdge* edgep = vxp->outBeginp(); edgep; edgep = edgep->outNextp()) {
for (V3GraphEdge& edge : vtx.outEdges()) {
if (deletep) VL_DO_CLEAR(deletep->unlinkDelete(), deletep = nullptr);
// It should be safe to modify the graph, despite using
// the GraphPathChecker, as none of the modifications will
// change what can be reached from what, nor should they
// change the rank or CP of any node.
if (checker.isTransitiveEdge(edgep)) deletep = edgep;
if (checker.isTransitiveEdge(&edge)) deletep = &edge;
}
if (deletep) VL_DO_DANGLING(deletep->unlinkDelete(), deletep);
}
@@ -143,10 +139,9 @@ class GraphAlgWeakly final : GraphAlg<> {
m_graphp->clearColors();
// Color graph
uint32_t currentColor = 0;
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
for (V3GraphVertex& vertex : m_graphp->vertices()) {
currentColor++;
vertexIterate(vertexp, currentColor);
vertexIterate(&vertex, currentColor);
}
}
@@ -155,11 +150,11 @@ class GraphAlgWeakly final : GraphAlg<> {
// then visit each of its edges, giving them the same color
if (vertexp->color()) return; // Already colored it
vertexp->color(currentColor);
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
if (followEdge(edgep)) vertexIterate(edgep->top(), currentColor);
for (V3GraphEdge& edge : vertexp->outEdges()) {
if (followEdge(&edge)) vertexIterate(edge.top(), currentColor);
}
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
if (followEdge(edgep)) vertexIterate(edgep->fromp(), currentColor);
for (V3GraphEdge& edge : vertexp->inEdges()) {
if (followEdge(&edge)) vertexIterate(edge.fromp(), currentColor);
}
}
@@ -192,33 +187,30 @@ class GraphAlgStrongly final : GraphAlg<> {
// Vertex::color // Output subtree number (fully processed)
// Clear info
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
vertexp->color(0);
vertexp->user(0);
for (V3GraphVertex& vertex : m_graphp->vertices()) {
vertex.color(0);
vertex.user(0);
}
// Color graph
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
if (!vertexp->user()) {
for (V3GraphVertex& vertex : m_graphp->vertices()) {
if (!vertex.user()) {
m_currentDfs++;
vertexIterate(vertexp);
vertexIterate(&vertex);
}
}
// If there's a single vertex of a color, it doesn't need a subgraph
// This simplifies the consumer's code, and reduces graph debugging clutter
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
for (V3GraphVertex& vertex : m_graphp->vertices()) {
bool onecolor = true;
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
if (followEdge(edgep)) {
if (vertexp->color() == edgep->top()->color()) {
for (V3GraphEdge& edge : vertex.outEdges()) {
if (followEdge(&edge)) {
if (vertex.color() == edge.top()->color()) {
onecolor = false;
break;
}
}
}
if (onecolor) vertexp->color(0);
if (onecolor) vertex.color(0);
}
}
@@ -226,9 +218,9 @@ class GraphAlgStrongly final : GraphAlg<> {
const uint32_t thisDfsNum = m_currentDfs++;
vertexp->user(thisDfsNum);
vertexp->color(0);
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
if (followEdge(edgep)) {
V3GraphVertex* top = edgep->top();
for (V3GraphEdge& edge : vertexp->outEdges()) {
if (followEdge(&edge)) {
V3GraphVertex* top = edge.top();
if (!top->user()) { // Dest not computed yet
vertexIterate(top);
}
@@ -273,15 +265,13 @@ class GraphAlgRank final : GraphAlg<> {
// Rank each vertex, ignoring cutable edges
// Vertex::m_user begin: 1 indicates processing, 2 indicates completed
// Clear existing ranks
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
vertexp->rank(0);
vertexp->user(0);
for (V3GraphVertex& vertex : m_graphp->vertices()) {
vertex.rank(0);
vertex.user(0);
}
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
if (!vertexp->user()) { //
vertexIterate(vertexp, 1);
for (V3GraphVertex& vertex : m_graphp->vertices()) {
if (!vertex.user()) { //
vertexIterate(&vertex, 1);
}
}
}
@@ -298,10 +288,8 @@ class GraphAlgRank final : GraphAlg<> {
if (vertexp->rank() >= currentRank) return; // Already processed it
vertexp->user(1);
vertexp->rank(currentRank);
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
if (followEdge(edgep)) {
vertexIterate(edgep->top(), currentRank + vertexp->rankAdder());
}
for (V3GraphEdge& edge : vertexp->outEdges()) {
if (followEdge(&edge)) vertexIterate(edge.top(), currentRank + vertexp->rankAdder());
}
vertexp->user(2);
}
@@ -353,8 +341,8 @@ class GraphAlgRLoops final : GraphAlg<> {
}
if (vertexp->user() == 2) return; // Already processed it
vertexp->user(1);
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
if (followEdge(edgep)) vertexIterate(edgep->top(), currentRank);
for (V3GraphEdge& edge : vertexp->outEdges()) {
if (followEdge(&edge)) vertexIterate(edge.top(), currentRank);
}
vertexp->user(2);
}
@@ -387,13 +375,13 @@ class GraphAlgSubtrees final : GraphAlg<> {
newVertexp = vertexp->clone(m_loopGraphp);
vertexp->userp(newVertexp);
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
if (followEdge(edgep)) {
V3GraphEdge* newEdgep = static_cast<V3GraphEdge*>(edgep->userp());
for (V3GraphEdge& edge : vertexp->outEdges()) {
if (followEdge(&edge)) {
V3GraphEdge* newEdgep = static_cast<V3GraphEdge*>(edge.userp());
if (!newEdgep) {
V3GraphVertex* newTop = vertexIterateAll(edgep->top());
newEdgep = edgep->clone(m_loopGraphp, newVertexp, newTop);
edgep->userp(newEdgep);
V3GraphVertex* newTop = vertexIterateAll(edge.top());
newEdgep = edge.clone(m_loopGraphp, newVertexp, newTop);
edge.userp(newEdgep);
}
}
}
@@ -438,30 +426,25 @@ struct GraphSortEdgeCmp final {
void V3Graph::sortVertices() {
// Sort list of vertices by rank, then fanout
std::vector<V3GraphVertex*> vertices;
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) {
vertices.push_back(vertexp);
}
for (V3GraphVertex& vertex : m_vertices) vertices.push_back(&vertex);
std::stable_sort(vertices.begin(), vertices.end(), GraphSortVertexCmp());
this->verticesUnlink();
for (V3GraphVertex* ip : vertices) ip->verticesPushBack(this);
// Re-insert in sorted order
for (V3GraphVertex* const ip : vertices) {
m_vertices.unlink(ip);
m_vertices.linkBack(ip);
}
}
void V3Graph::sortEdges() {
// Sort edges by rank then fanout of node they point to
std::vector<V3GraphEdge*> edges;
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) {
for (V3GraphVertex& vertex : vertices()) {
// Make a vector
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
edges.push_back(edgep);
}
for (V3GraphEdge& edge : vertex.outEdges()) edges.push_back(&edge);
// Sort
std::stable_sort(edges.begin(), edges.end(), GraphSortEdgeCmp());
// Relink edges in specified order
// We know the vector contains all of the edges that were
// there originally (didn't delete or add)
vertexp->outUnlink();
for (V3GraphEdge* edgep : edges) edgep->outPushBack();
for (V3GraphEdge* const edgep : edges) edgep->relinkFromp(&vertex);
// Prep for next
edges.clear();
}
@@ -487,8 +470,8 @@ void V3Graph::orderPreRanked() {
// Compute fanouts
// Vertex::m_user begin: 1 indicates processing, 2 indicates completed
userClearVertices();
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) {
if (!vertexp->user()) orderDFSIterate(vertexp);
for (V3GraphVertex& vertex : vertices()) {
if (!vertex.user()) orderDFSIterate(&vertex);
}
// Sort list of vertices by rank, then fanout. Fanout is a bit of a
@@ -506,12 +489,12 @@ double V3Graph::orderDFSIterate(V3GraphVertex* vertexp) {
UASSERT_OBJ(vertexp->user() != 1, vertexp, "Loop found, backward edges should be dead");
vertexp->user(1);
double fanout = 0;
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
if (edgep->weight()) fanout += orderDFSIterate(edgep->m_top);
for (V3GraphEdge& edge : vertexp->outEdges()) {
if (edge.weight()) fanout += orderDFSIterate(edge.top());
}
// Just count inbound edges
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
if (edgep->weight()) ++fanout;
for (V3GraphEdge& edge : vertexp->inEdges()) {
if (edge.weight()) ++fanout;
}
vertexp->fanout(fanout);
vertexp->user(2);
@@ -524,12 +507,12 @@ double V3Graph::orderDFSIterate(V3GraphVertex* vertexp) {
class GraphAlgParallelismReport final {
// MEMBERS
const V3Graph& m_graph; // The graph
V3Graph& m_graph; // The graph
const std::function<uint64_t(const V3GraphVertex*)> m_vertexCost; // vertex cost function
V3Graph::ParallelismReport m_report; // The result report
// CONSTRUCTORS
explicit GraphAlgParallelismReport(const V3Graph& graph,
explicit GraphAlgParallelismReport(V3Graph& graph,
std::function<uint64_t(const V3GraphVertex*)> vertexCost)
: m_graph{graph}
, m_vertexCost{vertexCost} {
@@ -540,13 +523,13 @@ class GraphAlgParallelismReport final {
for (const V3GraphVertex* vertexp; (vertexp = serialize.nextp());) {
++m_report.m_vertexCount;
uint64_t cpCostToHere = 0;
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
for (const V3GraphEdge& edge : vertexp->inEdges()) {
++m_report.m_edgeCount;
// For each upstream item, add its critical path cost to
// the cost of this edge, to form a new candidate critical
// path cost to the current node. Whichever is largest is
// the critical path to reach the start of this node.
cpCostToHere = std::max(cpCostToHere, critPaths[edgep->fromp()]);
cpCostToHere = std::max(cpCostToHere, critPaths[edge.fromp()]);
}
// Include the cost of the current vertex in the critical
// path, so it represents the critical path to the end of
@@ -564,12 +547,12 @@ class GraphAlgParallelismReport final {
public:
static V3Graph::ParallelismReport
apply(const V3Graph& graph, std::function<uint32_t(const V3GraphVertex*)> vertexCost) {
apply(V3Graph& graph, std::function<uint32_t(const V3GraphVertex*)> vertexCost) {
return GraphAlgParallelismReport(graph, vertexCost).m_report;
}
};
V3Graph::ParallelismReport
V3Graph::parallelismReport(std::function<uint64_t(const V3GraphVertex*)> vertexCost) const {
V3Graph::parallelismReport(std::function<uint64_t(const V3GraphVertex*)> vertexCost) {
return GraphAlgParallelismReport::apply(*this, vertexCost);
}