From 2287d420ee78bb76be9fe5c1abdf6aa1e8018cea Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 24 Jul 2025 01:47:16 -0400 Subject: [PATCH] Optimize to return memory when using -build (#6192) (#6226). --- Changes | 2 +- configure.ac | 3 +++ src/V3AstNodeOther.h | 1 + src/V3AstNodes.cpp | 19 +++++++++++++++++++ src/V3Os.cpp | 13 +++++++++++++ src/V3Os.h | 3 +++ src/Verilator.cpp | 6 ++++++ src/config_package.h.in | 3 +++ 8 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index a6eee82ae..0a9ca458b 100644 --- a/Changes +++ b/Changes @@ -24,6 +24,7 @@ Verilator 5.039 devel * Support multiple variables on RHS of a `force` assignment (#6163). [Artur Bieniek, Antmicro Ltd.]] * Support covergroup extends, etc., as unsupported (#6160). [Artur Bieniek, Antmicro Ltd.] * Change control file `public_flat_*` and other signal attributes to support __ in names (#6140). +* Optimize to return memory when using -build (#6192) (#6226). [Michael B. Taylor] * Fix constructor parameters in inheritance hierarchies (#6036) (#6070). [Petr Nohavica] * Fix replicate of negative giving 'REPLICATE has no expected width' internal error (#6048). * Fix cmake `-Wno` compiler flag testing (#6145). [Martin Stadler] @@ -39,7 +40,6 @@ Verilator 5.039 devel * Fix VPI signal range order (#6189) (#6200). [Ibrahim Burak Yorulmaz] * Fix structure select causing 'Wide Op' error (#6191). [Danny Oler] - Verilator 5.038 2025-07-08 ========================== diff --git a/configure.ac b/configure.ac index 05757edbb..c72b048e8 100644 --- a/configure.ac +++ b/configure.ac @@ -68,6 +68,7 @@ AC_ARG_ENABLE([tcmalloc], *) AC_MSG_ERROR([bad value '${enableval}' for --enable-tcmalloc]) ;; esac], [CFG_WITH_TCMALLOC=check;]) +AC_SUBST(CFG_WITH_TCMALLOC) AC_MSG_RESULT($CFG_WITH_TCMALLOC) # Flag to enable coverage build @@ -546,10 +547,12 @@ _MY_LDLIBS_CHECK_IFELSE( _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-builtin-calloc) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-builtin-realloc) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-builtin-free) + AC_DEFINE([HAVE_TCMALLOC],[1],[Defined if have tcmalloc]) fi], [if test "$CFG_WITH_TCMALLOC" = "yes"; then AC_MSG_ERROR([--enable-tcmalloc was given but test for ${LTCMALLOC} failed]) fi]) +AC_SUBST(HAVE_TCMALLOC) AC_SUBST(CFG_LIBS) # Need C++14 at least diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 549e304eb..b819ee829 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -1406,6 +1406,7 @@ class AstNetlist final : public AstNode { public: AstNetlist(); ASTGEN_MEMBERS_AstNetlist; + void deleteContents(); void cloneRelink() override { V3ERROR_NA; } string name() const override VL_MT_STABLE { return "$root"; } void dump(std::ostream& str) const override; diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 7cfc48210..0caf0d379 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -2296,6 +2296,25 @@ void AstNetlist::dumpJson(std::ostream& str) const { dumpJsonStr(str, "timeprecision", timeprecision().ascii()); dumpJsonGen(str); } +void AstNetlist::deleteContents() { + // Delete all netlist memory. Only for use by Verilator.cpp + m_typeTablep = nullptr; + m_constPoolp = nullptr; + m_dollarUnitPkgp = nullptr; + m_stdPackagep = nullptr; + m_evalp = nullptr; + m_evalNbap = nullptr; + m_dpiExportTriggerp = nullptr; + m_delaySchedulerp = nullptr; + m_nbaEventp = nullptr; + m_nbaEventTriggerp = nullptr; + m_topScopep = nullptr; + if (op1p()) op1p()->unlinkFrBackWithNext()->deleteTree(); + if (op2p()) op2p()->unlinkFrBackWithNext()->deleteTree(); + if (op3p()) op3p()->unlinkFrBackWithNext()->deleteTree(); + if (op4p()) op4p()->unlinkFrBackWithNext()->deleteTree(); +#undef VN_DELETE_ONE +} AstPackage* AstNetlist::dollarUnitPkgAddp() { if (!m_dollarUnitPkgp) { m_dollarUnitPkgp = new AstPackage{fileline(), AstPackage::dollarUnitName(), "work"}; diff --git a/src/V3Os.cpp b/src/V3Os.cpp index 5b6eea6f7..13be637a4 100644 --- a/src/V3Os.cpp +++ b/src/V3Os.cpp @@ -54,6 +54,10 @@ VL_DEFINE_DEBUG_FUNCTIONS; #include #include +#ifdef HAVE_TCMALLOC +#include +#endif + // clang-format off #if defined(_WIN32) || defined(__MINGW32__) # include // LONG for bcrypt.h on MINGW @@ -402,6 +406,15 @@ void V3Os::unlinkRegexp(const string& dir, const string& regexp) { #endif } +//###################################################################### +// METHODS (memory) + +void V3Os::releaseMemory() { +#ifdef HAVE_TCMALLOC + MallocExtension::instance()->ReleaseFreeMemory(); +#endif +} + //###################################################################### // METHODS (random) diff --git a/src/V3Os.h b/src/V3Os.h index 79714136d..8a2e66e1a 100644 --- a/src/V3Os.h +++ b/src/V3Os.h @@ -71,6 +71,9 @@ public: static void filesystemFlushBuildDir(const string& dirname); static void unlinkRegexp(const string& dir, const string& regexp); + // METHODS (memory) + static void releaseMemory(); + // METHODS (random) static uint64_t rand64(std::array& stater); static string trueRandom(size_t size) VL_MT_SAFE; diff --git a/src/Verilator.cpp b/src/Verilator.cpp index 61cc3b9b5..3ef409ebc 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -773,6 +773,12 @@ static void verilate(const string& argString) { // Final writing shouldn't throw warnings, but... V3Error::abortIfWarnings(); + + // Free memory so compiler has more for --build + UINFO(1, "Releasing netlist memory"); + v3Global.rootp()->deleteContents(); + V3Os::releaseMemory(); + if (v3Global.opt.stats()) V3Stats::statsStage("released"); } static string buildMakeCmd(const string& makefile, const string& target) { diff --git a/src/config_package.h.in b/src/config_package.h.in index 7a7088a82..f8c02101a 100644 --- a/src/config_package.h.in +++ b/src/config_package.h.in @@ -41,6 +41,9 @@ PACKAGE_VERSION_STRING_CHAR // Define if coroutines are supported on this platform #undef HAVE_COROUTINES +// Define if compiled with tcmalloc +#undef HAVE_TCMALLOC + //********************************************************************** //**** This file sometimes gets truncated, so check in consumers #define HAVE_CONFIG_PACKAGE