Optimize Ast read references in Dfg directly (#7354)

Introduce a new DfgAstRd vertex, which holds an AstNodeExpr that is a
reference to a variable. This enables tracking all read references in
Dfg, which both enables more optimization, and allows inlining of
expressions in place of the reference more intelligently (e.g, when the
expression is only used once, and is not in a loop). This can get rid of
20-30% of temporary variables introduced in Dfg in some designs. Note
V3Gate later got rid of a lot of those, this is a step towards making
V3Gate redundant. The more intelligent expression inlining is worth ~10%
runtime speed on some designs.
This commit is contained in:
Geza Lore
2026-04-01 10:52:56 +01:00
committed by GitHub
parent dbd4823323
commit b4a0ca8ba6
23 changed files with 610 additions and 224 deletions
+22 -9
View File
@@ -492,9 +492,12 @@ public:
return false;
}
// For now, only direct array assignment is supported (e.g. a = b, but not a = _ ? b : c)
if (rDtypep->isArray() && !VN_IS(rhsp, VarRef)) {
++m_ctx.m_conv.nonRepDType;
return false;
if (rDtypep->isArray()) {
if (!VN_IS(rhsp, VarRef)
|| !lhsp->dtypep()->skipRefp()->sameTree(rhsp->dtypep()->skipRefp())) {
++m_ctx.m_conv.nonRepDType;
return false;
}
}
// Widths should match at this point
UASSERT_OBJ(lhsp->width() == rhsp->width(), nodep, "Mismatched width reached DFG");
@@ -1746,11 +1749,16 @@ class AstToDfgSynthesize final {
if (logicp->selectedForSynthesis()) continue;
// There should be no sinks left for unselected DfgLogic, delete them here
UASSERT_OBJ(!logicp->hasSinks(), vtxp, "Unselected 'DfgLogic' with sinks remaining");
// Input variables will be read in Ast code, mark as such
// Input variables will be read in Ast code, add Ast reference vertices
// AstVar/AstVarScope::user4p() -> corresponding DfgVertexVar* in the graph
const VNUser4InUse m_user4InUse;
logicp->foreachSource([](DfgVertex& src) {
src.as<DfgVertexVar>()->setHasModRdRefs();
src.as<DfgVertexVar>()->nodep()->user4p(&src);
return false;
});
V3DfgPasses::addAstRefs(m_dfg, logicp->nodep(), [](AstNode* varp) { //
return varp->user4u().to<DfgVertexVar*>();
});
VL_DO_DANGLING(logicp->unlinkDelete(m_dfg), logicp);
}
debugDump("synth-selected");
@@ -1856,12 +1864,17 @@ class AstToDfgSynthesize final {
// If synthesized, delete the corresponding AstNode. It is now in Dfg.
logicp->nodep()->unlinkFrBack()->deleteTree();
} else {
// Not synthesized. Logic stays in Ast. Mark source variables
//as read in module. Outputs already marked by revertTransivelyAndRemove.
logicp->foreachSource([](DfgVertex& src) { //
src.as<DfgVertexVar>()->setHasModRdRefs();
// Not synthesized. Logic stays in Ast. Add Ast reference vertices.
// Outputs already marked by revertTransivelyAndRemove.
// AstVar/AstVarScope::user4p() -> corresponding DfgVertexVar* in the graph
const VNUser4InUse m_user4InUse;
logicp->foreachSource([](DfgVertex& src) {
src.as<DfgVertexVar>()->nodep()->user4p(&src);
return false;
});
V3DfgPasses::addAstRefs(m_dfg, logicp->nodep(), [](AstNode* varp) { //
return varp->user4u().to<DfgVertexVar*>();
});
}
// Delete this DfgLogic