Optimize multiplexers in Dfg synthesis (#6331)

The previous algorithm was designed to handle the general case where a
full control flow path predicate is required to select which value to
use when synthesizing control flow join point in an always block.

Here we add a better algorithm that tries to use the predicate of
the closest dominating branch if the branch paths dominate the joining
paths. This is almost universally true in synthesizable logic (RTLMeter
has no exceptions), however there are cases where this is not
applicable, for which we fall back on the previous generic algorithm.

Overall this significantly simplifies the synthesized Dfg graphs and
enables further optimization.
This commit is contained in:
Geza Lore
2025-08-25 13:47:45 +01:00
committed by GitHub
parent c2cac8a7fd
commit 02e64f0795
12 changed files with 1269 additions and 407 deletions
+3 -3
View File
@@ -57,7 +57,7 @@ class AstToDfgVisitor final : public VNVisitor {
}
}
std::unique_ptr<std::vector<Variable*>> getLiveVariables(const ControlFlowGraph& cfg) {
std::unique_ptr<std::vector<Variable*>> getLiveVariables(const CfgGraph& cfg) {
// TODO: remove the useless reinterpret_casts when C++17 'if constexpr' actually works
if VL_CONSTEXPR_CXX17 (T_Scoped) {
std::unique_ptr<std::vector<AstVarScope*>> result = V3Cfg::liveVarScopes(cfg);
@@ -139,7 +139,7 @@ class AstToDfgVisitor final : public VNVisitor {
// Gather variables live in to the given CFG.
// Return nullptr if any are not supported.
std::unique_ptr<std::vector<DfgVertexVar*>> gatherLive(const ControlFlowGraph& cfg) {
std::unique_ptr<std::vector<DfgVertexVar*>> gatherLive(const CfgGraph& cfg) {
// Run analysis
std::unique_ptr<std::vector<Variable*>> varps = getLiveVariables(cfg);
if (!varps) {
@@ -206,7 +206,7 @@ class AstToDfgVisitor final : public VNVisitor {
// Potentially convertible block
++m_ctx.m_inputs;
// Attempt to build CFG of AstAlways, give up if failed
std::unique_ptr<const ControlFlowGraph> cfgp = V3Cfg::build(nodep);
std::unique_ptr<CfgGraph> cfgp = CfgGraph::build(nodep->stmtsp());
if (!cfgp) {
++m_ctx.m_nonRepCfg;
return false;