Fix exponential expansion in V3Gate (#7550)
Unfortunate constellation of combinational assignments could be inlined by V3Gate yielding an exponential expansion (added test used to consume 4GB+ memory and generate 3GB+ code).
This commit is contained in:
parent
db8b6ce26d
commit
7c5069c7df
|
|
@ -693,7 +693,9 @@ class GateInline final {
|
|||
for (V3GraphEdge& edge : vVtxp->outEdges()) {
|
||||
const GateLogicVertex* const dstVtxp = edge.top()->as<GateLogicVertex>();
|
||||
// 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");
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue