forked from github/verilator
DFG: Remove topological sort
Cyclic components are now extracted separately, so there is no functional reason to have to do a topological sort (previously we used it to detect cyclic graphs). Removing it to gain some speed.
This commit is contained in:
parent
90447d54d1
commit
461f3c1004
@ -46,77 +46,6 @@ void DfgGraph::addGraph(DfgGraph& other) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DfgGraph::sortTopologically(bool reverse) {
|
|
||||||
// Vertices in reverse topological order
|
|
||||||
std::vector<DfgVertex*> order;
|
|
||||||
|
|
||||||
// Markings for algorithm
|
|
||||||
enum class Mark : uint8_t { Scheduled, OnPath, Finished };
|
|
||||||
std::unordered_map<DfgVertex*, Mark> marks;
|
|
||||||
|
|
||||||
// Stack of nodes in depth first search. The second element of the pair is true if the vertex
|
|
||||||
// is on the current DFS path, and false if it's only scheduled for visitation.
|
|
||||||
std::vector<std::pair<DfgVertex*, bool>> stack;
|
|
||||||
|
|
||||||
// Schedule vertex for visitation
|
|
||||||
const auto scheudle = [&](DfgVertex& vtx) {
|
|
||||||
// Nothing to do if already finished
|
|
||||||
if (marks.emplace(&vtx, Mark::Scheduled).first->second == Mark::Finished) return;
|
|
||||||
// Otherwise scheule for visitation
|
|
||||||
stack.emplace_back(&vtx, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// For each vertex (direct loop, so we can return early)
|
|
||||||
for (DfgVertex* vtxp = m_vertices.begin(); vtxp; vtxp = vtxp->m_verticesEnt.nextp()) {
|
|
||||||
// Initiate DFS from this vertex
|
|
||||||
scheudle(*vtxp);
|
|
||||||
while (!stack.empty()) {
|
|
||||||
// Pick up stack top
|
|
||||||
const auto pair = stack.back();
|
|
||||||
stack.pop_back();
|
|
||||||
DfgVertex* const currp = pair.first;
|
|
||||||
const bool onPath = pair.second;
|
|
||||||
Mark& mark = marks.at(currp);
|
|
||||||
|
|
||||||
if (onPath) { // Popped node on path
|
|
||||||
// Mark it as done
|
|
||||||
UASSERT_OBJ(mark == Mark::OnPath, currp, "DFS got lost");
|
|
||||||
mark = Mark::Finished;
|
|
||||||
// Add to order
|
|
||||||
order.push_back(currp);
|
|
||||||
} else { // Otherwise node was scheduled for visitation, so visit it
|
|
||||||
// If already finished, then nothing to do
|
|
||||||
if (mark == Mark::Finished) continue;
|
|
||||||
// If already on path, then not a DAG
|
|
||||||
if (mark == Mark::OnPath) return false;
|
|
||||||
// Push to path and mark as such
|
|
||||||
mark = Mark::OnPath;
|
|
||||||
stack.emplace_back(currp, true);
|
|
||||||
// Schedule children
|
|
||||||
currp->forEachSink(scheudle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move given vertex to end of vertex list
|
|
||||||
const auto reinsert = [this](DfgVertex& vtx) {
|
|
||||||
// Remove from current location
|
|
||||||
removeVertex(vtx);
|
|
||||||
// 'addVertex' appends to the end of the vertex list, so can do this in one loop
|
|
||||||
addVertex(vtx);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Remember 'order' is in reverse topological order
|
|
||||||
if (!reverse) {
|
|
||||||
for (DfgVertex* vtxp : vlstd::reverse_view(order)) reinsert(*vtxp);
|
|
||||||
} else {
|
|
||||||
for (DfgVertex* vtxp : order) reinsert(*vtxp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Done
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::unique_ptr<DfgGraph>> DfgGraph::splitIntoComponents(std::string label) {
|
std::vector<std::unique_ptr<DfgGraph>> DfgGraph::splitIntoComponents(std::string label) {
|
||||||
size_t componentNumber = 0;
|
size_t componentNumber = 0;
|
||||||
std::unordered_map<const DfgVertex*, unsigned> vertex2component;
|
std::unordered_map<const DfgVertex*, unsigned> vertex2component;
|
||||||
|
@ -179,12 +179,6 @@ public:
|
|||||||
// Add contents of other graph to this graph. Leaves other graph empty.
|
// Add contents of other graph to this graph. Leaves other graph empty.
|
||||||
void addGraph(DfgGraph& other);
|
void addGraph(DfgGraph& other);
|
||||||
|
|
||||||
// Topologically sort the list of vertices in this graph (such that 'forEachVertex' will
|
|
||||||
// iterate in topological order), or reverse topologically if the passed boolean argument is
|
|
||||||
// true. Returns true on success (the graph is acyclic and a topological order exists), false
|
|
||||||
// if the graph is cyclic. If the graph is cyclic, the vertex ordering is not modified.
|
|
||||||
bool sortTopologically(bool reverse = false);
|
|
||||||
|
|
||||||
// Split this graph into individual components (unique sub-graphs with no edges between them).
|
// Split this graph into individual components (unique sub-graphs with no edges between them).
|
||||||
// Leaves 'this' graph empty.
|
// Leaves 'this' graph empty.
|
||||||
std::vector<std::unique_ptr<DfgGraph>> splitIntoComponents(std::string label);
|
std::vector<std::unique_ptr<DfgGraph>> splitIntoComponents(std::string label);
|
||||||
|
@ -290,9 +290,6 @@ void V3DfgOptimizer::optimize(AstNetlist* netlistp, const string& label) {
|
|||||||
// For each acyclic component
|
// For each acyclic component
|
||||||
for (auto& component : acyclicComponents) {
|
for (auto& component : acyclicComponents) {
|
||||||
if (dumpDfg() >= 7) component->dumpDotFilePrefixed(ctx.prefix() + "source");
|
if (dumpDfg() >= 7) component->dumpDotFilePrefixed(ctx.prefix() + "source");
|
||||||
// Reverse topologically sort the component
|
|
||||||
const bool acyclic = component->sortTopologically(/* reverse: */ true);
|
|
||||||
UASSERT_OBJ(acyclic, nodep, "Supposedly acyclic graph is cyclic");
|
|
||||||
// Optimize the component
|
// Optimize the component
|
||||||
V3DfgPasses::optimize(*component, ctx);
|
V3DfgPasses::optimize(*component, ctx);
|
||||||
// Add back under the main DFG (we will convert everything back in one go)
|
// Add back under the main DFG (we will convert everything back in one go)
|
||||||
|
Loading…
Reference in New Issue
Block a user