diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index e24fd54ef..e6f3c295f 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -693,7 +693,9 @@ class GateInline final { for (V3GraphEdge& edge : vVtxp->outEdges()) { const GateLogicVertex* const dstVtxp = edge.top()->as(); // Ignore slow code, or if the destination is not used - if (!dstVtxp->slow() && !dstVtxp->outEmpty()) n += edge.weight(); + if (dstVtxp->slow()) continue; + if (dstVtxp->outEmpty() && !dstVtxp->consumed()) continue; + n += edge.weight(); if (n > 1) break; } if (n > 1) continue; @@ -1308,6 +1310,10 @@ void V3Gate::gateAll(AstNetlist* netlistp) { graphp->removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue); if (dumpGraphLevel() >= 6) graphp->dumpDotFilePrefixed("gate_simp"); + // Remove unused logic + GateUnused::apply(*graphp); + if (dumpGraphLevel() >= 3) graphp->dumpDotFilePrefixed("gate_unused"); + // Inline variables GateInline::apply(*graphp); if (dumpGraphLevel() >= 6) graphp->dumpDotFilePrefixed("gate_inline"); diff --git a/test_regress/t/t_gate_chained.py b/test_regress/t/t_gate_chained.py index b164183a5..7fa18e3a3 100755 --- a/test_regress/t/t_gate_chained.py +++ b/test_regress/t/t_gate_chained.py @@ -48,6 +48,6 @@ test.compile( test.execute() # Must be <<9000 above to prove this worked -test.file_grep(test.stats, r'Optimizations, Gate sigs deleted\s+(\d+)', 8554) +test.file_grep(test.stats, r'Optimizations, Gate sigs deleted\s+(\d+)', 8550) test.passes() diff --git a/test_regress/t/t_lint_unusedloop_removed_bad.out b/test_regress/t/t_lint_unusedloop_removed_bad.out index febd5756d..792568e78 100644 --- a/test_regress/t/t_lint_unusedloop_removed_bad.out +++ b/test_regress/t/t_lint_unusedloop_removed_bad.out @@ -12,14 +12,17 @@ : ... note: In instance 't.non_parametrized_initial' 158 | do ; while(0); | ^~ -%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:114:5: Loop condition is always false - 114 | while(always_zero < 0) begin +%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:136:5: Loop is not used and will be optimized out + 136 | while(param_unused_while < always_zero) begin | ^~~~~ -%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:156:5: Loop condition is always false +%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:156:5: Loop is not used and will be optimized out 156 | while(always_false); | ^~~~~ -%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:157:5: Loop condition is always false - 157 | while(always_zero < 0); +%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:280:5: Loop is not used and will be optimized out + 280 | while (m_2_ticked); + | ^~~~~ +%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:114:5: Loop condition is always false + 114 | while(always_zero < 0) begin | ^~~~~ %Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:171:5: Loop condition is always false 171 | while(always_false) begin @@ -33,10 +36,4 @@ %Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:190:5: Loop condition is always false 190 | for (int i = 0; i < always_zero; i++) | ^~~ -%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:136:5: Loop is not used and will be optimized out - 136 | while(param_unused_while < always_zero) begin - | ^~~~~ -%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:280:5: Loop is not used and will be optimized out - 280 | while (m_2_ticked); - | ^~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_opt_gate_blow_up.py b/test_regress/t/t_opt_gate_blow_up.py new file mode 100755 index 000000000..6e6d77fd3 --- /dev/null +++ b/test_regress/t/t_opt_gate_blow_up.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# 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-FileCopyrightText: 2026 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=["--stats"]) + +memUsageMB = int(test.file_grep(test.stats, r'Peak Memory Usage \(MB\) +(\d+)')[0]) + +if memUsageMB > 128 and not test.have_dev_asan: + test.error("Consumed over 128MB memory") + +test.passes() diff --git a/test_regress/t/t_opt_gate_blow_up.v b/test_regress/t/t_opt_gate_blow_up.v new file mode 100644 index 000000000..451ad8d73 --- /dev/null +++ b/test_regress/t/t_opt_gate_blow_up.v @@ -0,0 +1,43 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Wilson Snyder +// SPDX-License-Identifier: CC0-1.0 + +module top( + input wire [31:0] a +); + + wire [31:0] w00, w01, w02, w03, w04, w05, w06, w07, w08, w09; + wire [31:0] w10, w11, w12, w13, w14, w15, w16, w17, w18, w19; + + // V3Gate used to inline all the continuous assignments into + // the always_comb block, resultingin an exponential increase + // in AST size. + + always_comb begin + $display(w19); + end + + assign w19 = w18 + (w18 >> 1); + assign w18 = w17 + (w17 >> 1); + assign w17 = w16 + (w16 >> 1); + assign w16 = w15 + (w15 >> 1); + assign w15 = w14 + (w14 >> 1); + assign w14 = w13 + (w13 >> 1); + assign w13 = w12 + (w12 >> 1); + assign w12 = w11 + (w11 >> 1); + assign w11 = w10 + (w10 >> 1); + assign w10 = w09 + (w09 >> 1); + assign w09 = w08 + (w08 >> 1); + assign w08 = w07 + (w07 >> 1); + assign w07 = w06 + (w06 >> 1); + assign w06 = w05 + (w05 >> 1); + assign w05 = w04 + (w04 >> 1); + assign w04 = w03 + (w03 >> 1); + assign w03 = w02 + (w02 >> 1); + assign w02 = w01 + (w01 >> 1); + assign w01 = w00 + (w00 >> 1); + assign w00 = a + (a >> 1); + +endmodule