Fix constant pool recache after dead scope removal (#7845)
This commit is contained in:
parent
d023b3b075
commit
59b85f670b
|
|
@ -1000,8 +1000,8 @@ public:
|
|||
// this matters, the caller must handle the dtype difference as appropriate. If 'mergeDType' is
|
||||
// false, the returned VarScope will have _->dtypep()->sameTree(initp->dtypep()) return true.
|
||||
AstVarScope* findConst(AstConst* initp, bool mergeDType);
|
||||
// Rebuild hashes after potential removals
|
||||
void reCache();
|
||||
// Rebuild hashes and missing variable scopes after potential removals
|
||||
void rebuildVarScopesAndCache();
|
||||
};
|
||||
class AstConstraint final : public AstNode {
|
||||
// Constraint
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
// Routines for dumping dict fields (NOTE: due to leading ',' they can't be used for first field in
|
||||
|
|
@ -1779,14 +1780,28 @@ AstVarScope* AstConstPool::findConst(AstConst* initp, bool mergeDType) {
|
|||
return varScopep;
|
||||
}
|
||||
|
||||
void AstConstPool::reCache() {
|
||||
void AstConstPool::rebuildVarScopesAndCache() {
|
||||
m_tables.clear();
|
||||
m_consts.clear();
|
||||
std::unordered_map<const AstVar*, AstVarScope*> varScopeps;
|
||||
for (AstVarScope* vscp = m_scopep->varsp(); vscp; vscp = VN_CAST(vscp->nextp(), VarScope)) {
|
||||
AstNode* const valuep = vscp->varp()->valuep();
|
||||
const V3Hash hash = V3Hasher::uncachedHash(valuep);
|
||||
if (VN_IS(valuep, InitArray)) m_tables.emplace(hash.value(), vscp);
|
||||
if (VN_IS(valuep, Const)) m_consts.emplace(hash.value(), vscp);
|
||||
varScopeps.emplace(vscp->varp(), vscp);
|
||||
}
|
||||
for (AstNode* nodep = m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
AstVar* const varp = VN_CAST(nodep, Var);
|
||||
if (!varp) continue;
|
||||
AstNode* const valuep = varp->valuep();
|
||||
if (!valuep) continue;
|
||||
const bool isTable = VN_IS(valuep, InitArray);
|
||||
const AstConst* const constp = VN_CAST(valuep, Const);
|
||||
if (!isTable && !constp) continue;
|
||||
AstVarScope*& vscp = varScopeps[varp];
|
||||
if (!vscp) {
|
||||
vscp = new AstVarScope{varp->fileline(), m_scopep, varp};
|
||||
m_scopep->addVarsp(vscp);
|
||||
}
|
||||
if (isTable) m_tables.emplace(V3Hasher::uncachedHash(valuep).value(), vscp);
|
||||
if (constp) m_consts.emplace(constp->num().toHash().value(), vscp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -597,7 +597,7 @@ public:
|
|||
// We may have removed some datatypes, cleanup
|
||||
nodep->typeTablep()->repairCache();
|
||||
VIsCached::clearCacheTree(); // Removing assignments may affect isPure
|
||||
nodep->constPoolp()->reCache();
|
||||
nodep->constPoolp()->rebuildVarScopesAndCache();
|
||||
}
|
||||
~DeadVisitor() override {
|
||||
V3Stats::addStatSum("Optimizations, deadified FTasks", m_statFTasksDeadified);
|
||||
|
|
|
|||
|
|
@ -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=['--binary', '--stats'])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.file_grep(test.stats, r'Optimizations, Cases table normal\s+(\d+)', 1)
|
||||
test.file_grep(test.stats, r'ConstPool, Constants emitted\s+(\d+)', 1)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
// 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
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
module t;
|
||||
logic clk = 1'b0;
|
||||
always #5 clk = ~clk;
|
||||
|
||||
logic [31:0] cyc = 0;
|
||||
logic [3:0] idx;
|
||||
assign idx = cyc[3:0];
|
||||
|
||||
// V3Case lowers this to a 512-bit constant-pool lookup table before V3Dead
|
||||
// calls AstConstPool::rebuildVarScopesAndCache().
|
||||
logic [31:0] case_word;
|
||||
always_comb
|
||||
case (idx)
|
||||
4'h0: case_word = 32'h00000000;
|
||||
4'h1: case_word = 32'h00000001;
|
||||
4'h2: case_word = 32'h00000002;
|
||||
4'h3: case_word = 32'h00000003;
|
||||
4'h4: case_word = 32'h00000004;
|
||||
4'h5: case_word = 32'h00000005;
|
||||
4'h6: case_word = 32'h00000006;
|
||||
4'h7: case_word = 32'h00000007;
|
||||
4'h8: case_word = 32'h00000008;
|
||||
4'h9: case_word = 32'h00000009;
|
||||
4'ha: case_word = 32'h0000000a;
|
||||
4'hb: case_word = 32'h0000000b;
|
||||
4'hc: case_word = 32'h0000000c;
|
||||
4'hd: case_word = 32'h0000000d;
|
||||
4'he: case_word = 32'h0000000e;
|
||||
default: case_word = 32'h0000000f;
|
||||
endcase
|
||||
|
||||
localparam logic [511:0] TABLE = {
|
||||
32'h0000000f,
|
||||
32'h0000000e,
|
||||
32'h0000000d,
|
||||
32'h0000000c,
|
||||
32'h0000000b,
|
||||
32'h0000000a,
|
||||
32'h00000009,
|
||||
32'h00000008,
|
||||
32'h00000007,
|
||||
32'h00000006,
|
||||
32'h00000005,
|
||||
32'h00000004,
|
||||
32'h00000003,
|
||||
32'h00000002,
|
||||
32'h00000001,
|
||||
32'h00000000
|
||||
};
|
||||
|
||||
// V3Premit extracts this matching wide constant after V3Dead recached the
|
||||
// const-pool contents created by V3Case.
|
||||
logic [31:0] static_word;
|
||||
assign static_word = TABLE[{idx, 5'b0} +: 32];
|
||||
|
||||
always @(posedge clk) begin
|
||||
`checkh(case_word, static_word);
|
||||
cyc <= cyc + 32'd1;
|
||||
if (cyc == 32'd32) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue