mirror of
https://github.com/verilator/verilator.git
synced 2026-09-06 08:57:23 +02:00
Add DFG 'regularize' pass, and improve variable removal (#4937)
This functionality used to be distributed in the removeVars pass and the final dfgToAst conversion. Instead added a new 'regularize' pass to convert DFGs into forms that can be trivially converted back to Ast, and a new 'eliminateVars' pass to remove/repalce redundant variables. This simplifies dfgToAst significantly and makes the code a bit easier to follow. The new 'regularize' pass will ensure that every sub-expression with multiple uses is assigned to a temporary (unless it's a trivial memory reference or constant), and will also eliminate or replace redundant variables. Overall it is a performance neutral change but it does enable some later improvements which required the graph to be in this form, and this also happens to be the form required for the dfgToAst conversion.
This commit is contained in:
+13
-35
@@ -25,8 +25,6 @@
|
||||
#include "V3AstUserAllocator.h"
|
||||
#include "V3Dfg.h"
|
||||
#include "V3DfgPasses.h"
|
||||
#include "V3DfgPatternStats.h"
|
||||
#include "V3File.h"
|
||||
#include "V3Graph.h"
|
||||
#include "V3UniqueNames.h"
|
||||
|
||||
@@ -242,7 +240,7 @@ void V3DfgOptimizer::optimize(AstNetlist* netlistp, const string& label) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
|
||||
// NODE STATE
|
||||
// AstVar::user1 -> Used by V3DfgPasses::astToDfg and DfgPassed::dfgToAst
|
||||
// AstVar::user1 -> Used by V3DfgPasses::astToDfg
|
||||
// AstVar::user2 -> bool: Flag indicating referenced by AstVarXRef (set just below)
|
||||
// AstVar::user3 -> bool: Flag indicating written by logic not representable as DFG
|
||||
// (set by V3DfgPasses::astToDfg)
|
||||
@@ -254,8 +252,6 @@ void V3DfgOptimizer::optimize(AstNetlist* netlistp, const string& label) {
|
||||
|
||||
V3DfgOptimizationContext ctx{label};
|
||||
|
||||
V3DfgPatternStats patternStats;
|
||||
|
||||
// Run the optimization phase
|
||||
for (AstNode* nodep = netlistp->modulesp(); nodep; nodep = nodep->nextp()) {
|
||||
// Only optimize proper modules
|
||||
@@ -282,14 +278,6 @@ void V3DfgOptimizer::optimize(AstNetlist* netlistp, const string& label) {
|
||||
// Quick sanity check
|
||||
UASSERT_OBJ(dfg->size() == 0, nodep, "DfgGraph should have become empty");
|
||||
|
||||
// For each cyclic component
|
||||
for (auto& component : cyclicComponents) {
|
||||
if (dumpDfgLevel() >= 7) component->dumpDotFilePrefixed(ctx.prefix() + "source");
|
||||
// TODO: Apply optimizations safe for cyclic graphs
|
||||
// Add back under the main DFG (we will convert everything back in one go)
|
||||
dfg->addGraph(*component);
|
||||
}
|
||||
|
||||
// For each acyclic component
|
||||
for (auto& component : acyclicComponents) {
|
||||
if (dumpDfgLevel() >= 7) component->dumpDotFilePrefixed(ctx.prefix() + "source");
|
||||
@@ -299,8 +287,18 @@ void V3DfgOptimizer::optimize(AstNetlist* netlistp, const string& label) {
|
||||
dfg->addGraph(*component);
|
||||
}
|
||||
|
||||
// Accumulate patterns from the optimized graph for reporting
|
||||
if (v3Global.opt.stats()) patternStats.accumulate(*dfg);
|
||||
// Eliminate redundant variables. Run this on the whole acyclic DFG. It needs to traverse
|
||||
// the module to perform variable substitutions. Doing this by component would do
|
||||
// redundant traversals and can be extremely slow in large modules with many components.
|
||||
V3DfgPasses::eliminateVars(*dfg, ctx.m_eliminateVarsContext);
|
||||
|
||||
// For each cyclic component
|
||||
for (auto& component : cyclicComponents) {
|
||||
if (dumpDfgLevel() >= 7) component->dumpDotFilePrefixed(ctx.prefix() + "source");
|
||||
// TODO: Apply optimizations safe for cyclic graphs
|
||||
// Add back under the main DFG (we will convert everything back in one go)
|
||||
dfg->addGraph(*component);
|
||||
}
|
||||
|
||||
// Convert back to Ast
|
||||
if (dumpDfgLevel() >= 8) dfg->dumpDotFilePrefixed(ctx.prefix() + "whole-optimized");
|
||||
@@ -308,25 +306,5 @@ void V3DfgOptimizer::optimize(AstNetlist* netlistp, const string& label) {
|
||||
UASSERT_OBJ(resultModp == modp, modp, "Should be the same module");
|
||||
}
|
||||
|
||||
// Print the collected patterns
|
||||
if (v3Global.opt.stats()) {
|
||||
// Label to lowercase, without spaces
|
||||
std::string ident = label;
|
||||
std::transform(ident.begin(), ident.end(), ident.begin(), [](unsigned char c) { //
|
||||
return c == ' ' ? '_' : std::tolower(c);
|
||||
});
|
||||
|
||||
// File to dump to
|
||||
const std::string filename = v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix()
|
||||
+ "__stats_dfg_patterns__" + ident + ".txt";
|
||||
|
||||
// Open, write, close
|
||||
std::ofstream* const ofp = V3File::new_ofstream(filename);
|
||||
if (ofp->fail()) v3fatal("Can't write " << filename);
|
||||
patternStats.dump(label, *ofp);
|
||||
ofp->close();
|
||||
VL_DO_DANGLING(delete ofp, ofp);
|
||||
}
|
||||
|
||||
V3Global::dumpCheckGlobalTree("dfg-optimize", 0, dumpTreeEitherLevel() >= 3);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user