From ff49f797e5ec201343bddfd5c317e7fec437cd8b Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Sat, 8 Oct 2022 12:05:30 +0100 Subject: [PATCH] Speed up DfgGraph::addGraph Append whole lists in one go, rather than going item by item. --- src/V3Dfg.cpp | 20 ++++++++++++++++---- src/V3Dfg.h | 2 ++ src/V3List.h | 17 +++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/V3Dfg.cpp b/src/V3Dfg.cpp index 4fd2f7a93..39983cd5c 100644 --- a/src/V3Dfg.cpp +++ b/src/V3Dfg.cpp @@ -40,10 +40,22 @@ DfgGraph::~DfgGraph() { } void DfgGraph::addGraph(DfgGraph& other) { - other.forEachVertex([&](DfgVertex& vtx) { - other.removeVertex(vtx); - this->addVertex(vtx); - }); + m_size += other.m_size; + other.m_size = 0; + + const auto moveVertexList = [this](V3List& src, V3List& dst) { + if (DfgVertex* vtxp = src.begin()) { + vtxp->m_verticesEnt.moveAppend(src, dst, vtxp); + do { + vtxp->m_graphp = this; + vtxp = vtxp->verticesNext(); + } while (vtxp); + } + }; + + moveVertexList(other.m_varVertices, m_varVertices); + moveVertexList(other.m_constVertices, m_constVertices); + moveVertexList(other.m_opVertices, m_opVertices); } std::vector> DfgGraph::splitIntoComponents(std::string label) { diff --git a/src/V3Dfg.h b/src/V3Dfg.h index 5f5928c6c..3720e09e4 100644 --- a/src/V3Dfg.h +++ b/src/V3Dfg.h @@ -536,6 +536,7 @@ public: //------------------------------------------------------------------------------ void DfgGraph::addVertex(DfgVertex& vtx) { + // Note: changes here need to be replicated in DfgGraph::addGraph ++m_size; if (vtx.is()) { vtx.m_verticesEnt.pushBack(m_constVertices, &vtx); @@ -548,6 +549,7 @@ void DfgGraph::addVertex(DfgVertex& vtx) { } void DfgGraph::removeVertex(DfgVertex& vtx) { + // Note: changes here need to be replicated in DfgGraph::addGraph --m_size; if (vtx.is()) { vtx.m_verticesEnt.unlink(m_constVertices, &vtx); diff --git a/src/V3List.h b/src/V3List.h index 83ef4de17..e7e524c6e 100644 --- a/src/V3List.h +++ b/src/V3List.h @@ -119,6 +119,23 @@ public: } m_prevp = m_nextp = nullptr; } + // Remove all nodes from 'oldListr', append them to 'newListr'. 'this' must be a member of the + // object at 'selfp', and 'selfp' must be the head of the list in 'oldListr'. + void moveAppend(V3List& oldListr, V3List& newListr, T selfp) { + UASSERT(selfp == oldListr.m_headp, "Must be head of list to use 'moveAppend'"); + const size_t offset = (size_t)(uint8_t*)(this) - (size_t)(uint8_t*)(selfp); + const T headp = selfp; + const T tailp = oldListr.m_tailp; + oldListr.reset(); + if (newListr.empty()) { + newListr.m_headp = headp; + newListr.m_tailp = tailp; + } else { + baseToListEnt(newListr.m_tailp, offset)->m_nextp = headp; + m_prevp = newListr.m_tailp; + newListr.m_tailp = tailp; + } + } }; //============================================================================