Fix incorrect bit-op-tree NOT optimization (#4832) (#4847)

* Fix #4832. Bit-op-tree opt. should not touch a subtree under NOT in AND/OR tree.
This commit is contained in:
Yutetsu TAKATSUKASA 2024-01-21 21:25:24 +09:00 committed by GitHub
parent 3a5248a919
commit 50df902b54
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 32 additions and 2 deletions

View File

@ -541,6 +541,8 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
CONST_BITOP_RETURN_IF(m_failed, nodep->rhsp());
restorer.disableRestore(); // Now all checks passed
} else if (nodep->type() == m_rootp->type()) { // And, Or, Xor
// subtree under NOT can be optimized only in XOR tree.
CONST_BITOP_RETURN_IF(!m_polarity && !isXorTree(), nodep);
incrOps(nodep, __LINE__);
for (const bool right : {false, true}) {
VL_RESTORER(m_leafp);
@ -556,6 +558,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
// Reach past a cast then add to frozen nodes to be added to final reduction
if (const AstCCast* const castp = VN_CAST(opp, CCast)) opp = castp->lhsp();
const bool pol = isXorTree() || m_polarity; // Only AND/OR tree needs polarity
UASSERT(pol, "AND/OR tree expects m_polarity==true");
m_frozenNodes.emplace_back(opp, FrozenNodeInfo{pol, m_lsb});
m_failed = origFailed;
continue;

View File

@ -62,7 +62,7 @@ module t(/*AUTOARG*/
$write("[%0t] cyc==%0d crc=%x sum=%x\n", $time, cyc, crc, sum);
if (crc !== 64'hc77bb9b3784ea091) $stop;
// What checksum will we end up with (above print should match)
`define EXPECTED_SUM 64'hf5498264b93d4b48
`define EXPECTED_SUM 64'h7f4e4dade589ada1
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
@ -93,10 +93,11 @@ module Test(/*AUTOARG*/
logic bug3786_out;
logic bug3824_out;
logic bug4059_out;
logic bug4832_out;
output logic o;
logic [14:0] tmp;
logic [15:0] tmp;
assign o = ^tmp;
always_ff @(posedge clk) begin
@ -127,6 +128,7 @@ module Test(/*AUTOARG*/
tmp[12]<= bug3786_out;
tmp[13]<= bug3824_out;
tmp[14]<= bug4059_out;
tmp[15]<= bug4832_out;
end
bug3182 i_bug3182(.in(d[4:0]), .out(bug3182_out));
@ -138,6 +140,7 @@ module Test(/*AUTOARG*/
bug3786 i_bug3786(.clk(clk), .in(d), .out(bug3786_out));
bug3824 i_bug3824(.clk(clk), .in(d), .out(bug3824_out));
bug4059 i_bug4059(.clk(clk), .in(d), .out(bug4059_out));
bug4832 i_bug4832(.clk(clk), .in(d), .out(bug4832_out));
endmodule
@ -395,3 +398,27 @@ module bug4059(input wire clk, input wire [31:0] in, output wire out);
wire _013_ = ~(_009_ ^ _012_);
assign out = ~(_006_ ^ _013_);
endmodule
/// See issue #4832
// !(d[32 + 3] & in[3]) & d[32 + 22]
// was wrongly transformed to
// !d[32 + 3] & d[32 + 22] & !in[3]
// A subtree under NOT should be untouched, but was not.
// Testing OR subtree too.
module bug4832(input wire clk, input wire [31:0] in, output out);
logic [95:0] d;
always_ff @(posedge clk)
d <= {d[63:0], in};
logic [31:0] tmp_and;
logic [31:0] tmp_or;
logic result_and;
logic result_or;
assign tmp_and = (d[63:32] & in) >> 3;
assign tmp_or = (d[63:32] | in) >> 8;
always_ff @(posedge clk) begin
result_and <= !tmp_and[0] & d[32 + 22];
result_or <= !tmp_or[0] | d[32 + 21];
end
assign out = result_and ^ result_or;
endmodule