Optimize always blocks using local temporary variables in Dfg (#7085)

Enable synthesis of blocks that use a variable only within certain
branches, if that variable is not externally observable.
This commit is contained in:
Geza Lore 2026-02-17 20:00:55 +00:00 committed by GitHub
parent 5d0352ab46
commit 7176bdcff6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 9 deletions

View File

@ -1034,20 +1034,20 @@ class AstToDfgSynthesize final {
// Merge 'thenSymTab' into 'elseSymTab' using the given predicate to join values
bool joinSymbolTables(SymTab& elseSymTab, DfgVertexVar* predicatep, const SymTab& thenSymTab) {
// Give up if something is not assigned on all paths ... Latch?
if (thenSymTab.size() != elseSymTab.size()) {
++m_ctx.m_synt.nonSynLatch;
return false;
}
// Any variable that does not have a binding on both paths will be removed. These might be
// temporaries, loop vars, etc used only in one branch. Conversion will fail if the
// variable is actually referenced later.
std::vector<Variable*> toRemove;
// Join each symbol
for (std::pair<Variable* const, DfgVertexVar*>& pair : elseSymTab) {
Variable* const varp = pair.first;
// Find same variable on the else path
auto it = thenSymTab.find(varp);
// Give up if something is not assigned on all paths ... Latch?
const auto it = thenSymTab.find(varp);
// Record for removal if not assigned on both paths
if (it == thenSymTab.end()) {
++m_ctx.m_synt.nonSynLatch;
return false;
toRemove.emplace_back(varp);
continue;
}
// Join paths with the predicate
DfgVertexVar* const thenp = it->second;
@ -1056,6 +1056,10 @@ class AstToDfgSynthesize final {
if (!newp) return false;
pair.second = newp;
}
// Remove variables not assigned on both paths
for (Variable* const varp : toRemove) elseSymTab.erase(varp);
// Done
return true;
}

View File

@ -502,4 +502,26 @@ module t (
end
`signal(BOTH_BREAK, both_break);
logic [1:0] uses_tmp;
always_comb begin
uses_tmp = 2'd0;
if (rand_a[0]) begin
automatic logic [1:0] tmp;
tmp = rand_b[1:0];
uses_tmp = tmp ^ rand_b[3:2];
end
end
`signal(USES_TMP, uses_tmp);
logic [3:0] uses_loop_var;
always_comb begin
uses_loop_var = 4'd0;
if (rand_a[0]) begin
for (int i = 0; i < 4; ++i) begin
uses_loop_var[i] = rand_b[2*i];
end
end
end
`signal(USES_LOOP_VAR, uses_loop_var);
endmodule