mirror of
https://github.com/verilator/verilator.git
synced 2026-10-07 18:42:58 +02:00
Optimize circular logic in Dfg (#7902)
Introduce a new DfgPrev vertex, representing the value of a variable before any in-graph assignments. This can be used to break all remaining cycles in the graph, so all Dfgs become acyclic after V3DfgBreakCycles. The circular dataflow is still represented, and is taken care of by the scheduler, it is just the DfgGraph that represents the logic that becomes acyclic. This makes V3DfgBreakCycles a mandatory transform, so drop the disabling -fno-dfg-break-cycles option (still parsed, but has no effect). Note the effect of this is small, as most cycles can be fixed up by driver tracing, which is unchanged, but this is required for some upcoming work.
This commit is contained in:
+6
-16
@@ -56,16 +56,6 @@ class DfgRegularize final {
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<const DfgVertexVar*> gatherCyclicVariables() {
|
||||
DfgUserMap<uint64_t> vtx2Scc = m_dfg.makeUserMap<uint64_t>();
|
||||
V3DfgPasses::colorStronglyConnectedComponents(m_dfg, vtx2Scc);
|
||||
std::unordered_set<const DfgVertexVar*> circularVariables;
|
||||
for (const DfgVertexVar& vtx : m_dfg.varVertices()) {
|
||||
if (vtx2Scc[vtx]) circularVariables.emplace(&vtx);
|
||||
}
|
||||
return circularVariables;
|
||||
}
|
||||
|
||||
static bool isUnused(const DfgVertex& vtx) {
|
||||
if (vtx.hasSinks()) return false;
|
||||
if (const DfgVertexVar* const varp = vtx.cast<DfgVertexVar>()) {
|
||||
@@ -73,6 +63,7 @@ class DfgRegularize final {
|
||||
UASSERT_OBJ(!varp->hasDfgRefs(), varp, "Should not have refs in other DfgGraph");
|
||||
if (varp->hasModWrRefs()) return false;
|
||||
if (varp->hasExtRefs()) return false;
|
||||
if (varp->hasPrev()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -87,6 +78,9 @@ class DfgRegularize final {
|
||||
&aVtx, "Mismatched vertices");
|
||||
UASSERT_OBJ(!aVtx.is<DfgVertexVar>(), &aVtx, "Should be an operation vertex");
|
||||
|
||||
// Prev is just a variable reference
|
||||
if (aVtx.is<DfgPrev>()) return false;
|
||||
|
||||
if (bVtx.hasMultipleSinks()) {
|
||||
// Add a temporary if it's cheaper to store and load from memory than recompute
|
||||
if (!aVtx.isCheaperThanLoad()) return true;
|
||||
@@ -119,10 +113,6 @@ class DfgRegularize final {
|
||||
}
|
||||
|
||||
void eliminateVars() {
|
||||
// Although we could eliminate some circular variables, doing so would
|
||||
// make UNOPTFLAT traces fairly usesless, so we will not do so.
|
||||
const std::unordered_set<const DfgVertexVar*> circularVariables = gatherCyclicVariables();
|
||||
|
||||
// Worklist based algoritm
|
||||
DfgWorklist workList{m_dfg};
|
||||
|
||||
@@ -141,7 +131,7 @@ class DfgRegularize final {
|
||||
});
|
||||
// Delete corresponsing Ast variable at the end
|
||||
if (const DfgVertexVar* const varp = vtx.cast<DfgVertexVar>()) {
|
||||
m_ctx.m_deleteps.push_back(varp->vscp());
|
||||
if (!varp->hasPrev()) m_ctx.m_deleteps.push_back(varp->vscp());
|
||||
}
|
||||
// Remove the unused vertex
|
||||
vtx.unlinkDelete(m_dfg);
|
||||
@@ -173,7 +163,7 @@ class DfgRegularize final {
|
||||
UASSERT_OBJ(!varp->hasDfgRefs(), varp, "Should not have refs in other DfgGraph");
|
||||
|
||||
// Do not eliminate circular variables - need to preserve UNOPTFLAT traces
|
||||
if (circularVariables.count(varp)) return;
|
||||
if (varp->hasPrev()) return;
|
||||
|
||||
// Do not inline if partially driven (the partial driver network can't be fed into
|
||||
// arbitrary logic. TODO: we should peeophole these away entirely)
|
||||
|
||||
Reference in New Issue
Block a user