forked from github/verilator
Fix hang with large case statement optimization (#3405).
This commit is contained in:
parent
30783e6a79
commit
3d762282b9
1
Changes
1
Changes
@ -13,6 +13,7 @@ Verilator 4.223 devel
|
||||
|
||||
**Minor:**
|
||||
|
||||
* Fix hang with large case statement optimization (#3405). [Mike Urbach]
|
||||
|
||||
|
||||
Verilator 4.222 2022-05-02
|
||||
|
@ -769,6 +769,9 @@ public:
|
||||
|
||||
class ConstVisitor final : public VNVisitor {
|
||||
private:
|
||||
// CONSTANTS
|
||||
static constexpr unsigned CONCAT_MERGABLE_MAX_DEPTH = 10; // Limit alg recursion
|
||||
|
||||
// NODE STATE
|
||||
// ** only when m_warn/m_doExpensive is set. If state is needed other times,
|
||||
// ** must track down everywhere V3Const is called and make sure no overlaps.
|
||||
@ -1420,11 +1423,12 @@ private:
|
||||
if (rend == rfromp->width() && lstart->toSInt() == 0) return true;
|
||||
return false;
|
||||
}
|
||||
bool concatMergeable(const AstNode* lhsp, const AstNode* rhsp) {
|
||||
bool concatMergeable(const AstNode* lhsp, const AstNode* rhsp, unsigned depth) {
|
||||
// determine if {a OP b, c OP d} => {a, c} OP {b, d} is advantageous
|
||||
if (!v3Global.opt.oAssemble()) return false; // opt disabled
|
||||
if (lhsp->type() != rhsp->type()) return false;
|
||||
if (!ifConcatMergeableBiop(lhsp)) return false;
|
||||
if (depth > CONCAT_MERGABLE_MAX_DEPTH) return false; // As worse case O(n^2) algorithm
|
||||
|
||||
const AstNodeBiop* const lp = VN_CAST(lhsp, NodeBiop);
|
||||
const AstNodeBiop* const rp = VN_CAST(rhsp, NodeBiop);
|
||||
@ -1434,11 +1438,12 @@ private:
|
||||
const bool rad = ifMergeAdjacent(lp->rhsp(), rp->rhsp());
|
||||
if (lad && rad) return true;
|
||||
// {a[] & b[]&c[], a[] & b[]&c[]}
|
||||
if (lad && concatMergeable(lp->rhsp(), rp->rhsp())) return true;
|
||||
if (lad && concatMergeable(lp->rhsp(), rp->rhsp(), depth + 1)) return true;
|
||||
// {a[]&b[] & c[], a[]&b[] & c[]}
|
||||
if (rad && concatMergeable(lp->lhsp(), rp->lhsp())) return true;
|
||||
if (rad && concatMergeable(lp->lhsp(), rp->lhsp(), depth + 1)) return true;
|
||||
// {(a[]&b[])&(c[]&d[]), (a[]&b[])&(c[]&d[])}
|
||||
if (concatMergeable(lp->lhsp(), rp->lhsp()) && concatMergeable(lp->rhsp(), rp->rhsp())) {
|
||||
if (concatMergeable(lp->lhsp(), rp->lhsp(), depth + 1)
|
||||
&& concatMergeable(lp->rhsp(), rp->rhsp(), depth + 1)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1698,7 +1703,7 @@ private:
|
||||
AstNode* const lrp = lp->rhsp()->cloneTree(false);
|
||||
AstNode* const rlp = rp->lhsp()->cloneTree(false);
|
||||
AstNode* const rrp = rp->rhsp()->cloneTree(false);
|
||||
if (concatMergeable(lp, rp)) {
|
||||
if (concatMergeable(lp, rp, 0)) {
|
||||
AstConcat* const newlp = new AstConcat(rlp->fileline(), llp, rlp);
|
||||
AstConcat* const newrp = new AstConcat(rrp->fileline(), lrp, rrp);
|
||||
// use the lhs to replace the parent concat
|
||||
@ -3368,7 +3373,7 @@ private:
|
||||
TREEOPV("AstConcat{$lhsp.isZero, $rhsp}", "replaceExtend(nodep, nodep->rhsp())");
|
||||
// CONCAT(a[1],a[0]) -> a[1:0]
|
||||
TREEOPV("AstConcat{$lhsp.castSel, $rhsp.castSel, ifAdjacentSel(VN_AS($lhsp,,Sel),,VN_AS($rhsp,,Sel))}", "replaceConcatSel(nodep)");
|
||||
TREEOPV("AstConcat{ifConcatMergeableBiop($lhsp), concatMergeable($lhsp,,$rhsp)}", "replaceConcatMerge(nodep)");
|
||||
TREEOPV("AstConcat{ifConcatMergeableBiop($lhsp), concatMergeable($lhsp,,$rhsp,,0)}", "replaceConcatMerge(nodep)");
|
||||
// Common two-level operations that can be simplified
|
||||
TREEOP ("AstAnd {$lhsp.castConst,matchAndCond(nodep)}", "DONE");
|
||||
TREEOP ("AstAnd {$lhsp.castConst, $rhsp.castOr, matchMaskedOr(nodep)}", "DONE");
|
||||
|
18
test_regress/t/t_concat_or.pl
Executable file
18
test_regress/t/t_concat_or.pl
Executable file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2022 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
|
||||
|
||||
scenarios(linter => 1);
|
||||
|
||||
lint(
|
||||
verilator_flags2 => ["--lint-only"],
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
72
test_regress/t/t_concat_or.v
Normal file
72
test_regress/t/t_concat_or.v
Normal file
@ -0,0 +1,72 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2022 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t(/*AUTOARG*/
|
||||
// Outputs
|
||||
i299,
|
||||
// Inputs
|
||||
i190, i191, i192, i193, i194, i195, i196, i197, i198, i199, i200, i201, i202,
|
||||
i203, i204, i205, i182, i183, i184, i185, i186, i187, i188, i189, i206, i282,
|
||||
i284, i286, i287, i289, i290, i294, i34, i288, i31, i296, i37, i38
|
||||
);
|
||||
input [3:0] i190;
|
||||
input [3:0] i191;
|
||||
input [3:0] i192;
|
||||
input [3:0] i193;
|
||||
input [3:0] i194;
|
||||
input [3:0] i195;
|
||||
input [3:0] i196;
|
||||
input [3:0] i197;
|
||||
input [3:0] i198;
|
||||
input [3:0] i199;
|
||||
input [3:0] i200;
|
||||
input [3:0] i201;
|
||||
input [3:0] i202;
|
||||
input [3:0] i203;
|
||||
input [3:0] i204;
|
||||
input [3:0] i205;
|
||||
input [3:0] i182;
|
||||
input [3:0] i183;
|
||||
input [3:0] i184;
|
||||
input [3:0] i185;
|
||||
input [3:0] i186;
|
||||
input [3:0] i187;
|
||||
input [3:0] i188;
|
||||
input [3:0] i189;
|
||||
input [3:0] i206;
|
||||
input [3:0] i282;
|
||||
input [3:0] i284;
|
||||
input [3:0] i286;
|
||||
input [3:0] i287;
|
||||
input [3:0] i289;
|
||||
input [3:0] i290;
|
||||
input [3:0] i294;
|
||||
input [3:0] i34;
|
||||
input [3:0] i288;
|
||||
input [3:0] i31;
|
||||
input [3:0] i296;
|
||||
input [3:0] i37;
|
||||
input [3:0] i38;
|
||||
|
||||
output [3:0] i299;
|
||||
assign i299 = { i296[2:0] | i31[3:1] | i282[3:1] | i284[3:1] | i34[3:1]
|
||||
| i286[3:1] | i287[3:1] | i37[3:1] | i38[3:1]
|
||||
| i288[3:1] | i289[3:1] | i290[3:1] | i182[3:1]
|
||||
| i183[3:1] | i184[3:1] | i185[3:1] | i186[3:1]
|
||||
| i187[3:1] | i188[3:1] | i189[3:1] | i190[3:1]
|
||||
| i191[3:1] | i192[3:1] | i193[3:1] | i194[3:1]
|
||||
| i195[3:1] | i196[3:1] | i197[3:1] | i198[3:1]
|
||||
| i199[3:1] | i200[3:1] | i201[3:1] | i202[3:1]
|
||||
| i203[3:1] | i204[3:1] | i205[3:1] | i206[3:1]
|
||||
,
|
||||
i294[0] | i289[0] | i290[0] | i182[0] | i183[0]
|
||||
| i184[0] | i185[0] | i186[0] | i187[0] | i188[0]
|
||||
| i189[0] | i190[0] | i191[0] | i192[0] | i193[0]
|
||||
| i194[0] | i195[0] | i196[0] | i197[0] | i198[0]
|
||||
| i199[0] | i200[0] | i201[0] | i202[0] | i203[0]
|
||||
| i204[0] | i205[0] | i206[0] };
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user