From 2daa09a25540eeddf583d1dea8238633f54629a0 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Mon, 23 Jun 2025 22:58:26 +0100 Subject: [PATCH] Optimize constify within Expand and Subst (#6111) These passes blow up the Ast size on some designs, so delaying running V3Const until after the whole pass can notably increase peak memory usage. In this patch we apply V3Const per CFunc within these passes, which saves on memory. Added -fno-const-eager to disable the intra-pass V3Const application, for debugging. --- docs/guide/exe_verilator.rst | 2 ++ src/V3Expand.cpp | 10 ++++++++++ src/V3Options.cpp | 1 + src/V3Options.h | 2 ++ src/V3Subst.cpp | 7 +++++++ .../t/t_case_66bits_no_const_eager.py | 19 +++++++++++++++++++ 6 files changed, 41 insertions(+) create mode 100755 test_regress/t/t_case_66bits_no_const_eager.py diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index 938152af8..684d5646d 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -590,6 +590,8 @@ Summary: .. option:: -fno-const-bit-op-tree +.. option:: -fno-const-eager + .. option:: -fno-dedup .. option:: -fno-dfg diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index a0109d51e..952eb2d40 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -357,6 +357,16 @@ class ExpandVisitor final : public VNVisitor { } // VISITORS + void visit(AstCFunc* nodep) override { + iterateChildren(nodep); + + // Constant fold here, as Ast size can likely be reduced + if (v3Global.opt.fConstEager()) { + AstNode* const editedp = V3Const::constifyEditCpp(nodep); + UASSERT_OBJ(editedp == nodep, editedp, "Should not have replaced CFunc"); + } + } + void visit(AstExtend* nodep) override { if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 86a7c0c16..257b1c7fe 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1320,6 +1320,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, DECL_OPTION("-fconst", FOnOff, &m_fConst); DECL_OPTION("-fconst-before-dfg", FOnOff, &m_fConstBeforeDfg); DECL_OPTION("-fconst-bit-op-tree", FOnOff, &m_fConstBitOpTree); + DECL_OPTION("-fconst-eager", FOnOff, &m_fConstEager); DECL_OPTION("-fdead-assigns", FOnOff, &m_fDeadAssigns); DECL_OPTION("-fdead-cells", FOnOff, &m_fDeadCells); DECL_OPTION("-fdedup", FOnOff, &m_fDedupe); diff --git a/src/V3Options.h b/src/V3Options.h index 6c7fb6acd..8d5a2de1d 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -389,6 +389,7 @@ private: bool m_fConst; // main switch: -fno-const: constant folding bool m_fConstBeforeDfg = true; // main switch: -fno-const-before-dfg for testing only! bool m_fConstBitOpTree; // main switch: -fno-const-bit-op-tree constant bit op tree + bool m_fConstEager = true; // main switch: -fno-const-eagerly run V3Const during passes bool m_fDedupe; // main switch: -fno-dedupe: logic deduplication bool m_fDfgPeephole = true; // main switch: -fno-dfg-peephole bool m_fDfgPreInline; // main switch: -fno-dfg-pre-inline and -fno-dfg @@ -701,6 +702,7 @@ public: bool fConst() const { return m_fConst; } bool fConstBeforeDfg() const { return m_fConstBeforeDfg; } bool fConstBitOpTree() const { return m_fConstBitOpTree; } + bool fConstEager() const { return m_fConstEager; } bool fDedupe() const { return m_fDedupe; } bool fDfgPeephole() const { return m_fDfgPeephole; } bool fDfgPreInline() const { return m_fDfgPreInline; } diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index 19fd3d9d8..98ceea886 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -26,6 +26,7 @@ #include "V3Subst.h" +#include "V3Const.h" #include "V3Stats.h" #include @@ -361,6 +362,12 @@ class SubstVisitor final : public VNVisitor { iterateChildren(nodep); for (SubstVarEntry& ip : m_entries) ip.deleteUnusedAssign(); m_entries.clear(); + + // Constant fold here, as Ast size can likely be reduced + if (v3Global.opt.fConstEager()) { + AstNode* const editedp = V3Const::constifyEditCpp(nodep); + UASSERT_OBJ(editedp == nodep, editedp, "Should not have replaced CFunc"); + } } void visit(AstNode* nodep) override { diff --git a/test_regress/t/t_case_66bits_no_const_eager.py b/test_regress/t/t_case_66bits_no_const_eager.py new file mode 100755 index 000000000..2ce516e24 --- /dev/null +++ b/test_regress/t/t_case_66bits_no_const_eager.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') +test.top_filename = "t/t_case_66bits.v" + +test.compile(verilator_flags2=['-fno-const-eager']) + +test.execute() + +test.passes()