diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 6bd46d81e..30747a1e8 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -586,6 +586,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst { } else if ((isAndTree() && VN_IS(nodep, Eq)) || (isOrTree() && VN_IS(nodep, Neq))) { Restorer restorer{*this}; CONST_BITOP_RETURN_IF(!m_polarity, nodep); + CONST_BITOP_RETURN_IF(m_lsb, nodep); // the result of EQ/NE is 1 bit width const AstNode* lhsp = nodep->lhsp(); if (const AstCCast* const castp = VN_CAST(lhsp, CCast)) lhsp = castp->lhsp(); const AstConst* const constp = VN_CAST(lhsp, Const); diff --git a/test_regress/t/t_const_opt.pl b/test_regress/t/t_const_opt.pl index c01b55613..0fdd9fb02 100755 --- a/test_regress/t/t_const_opt.pl +++ b/test_regress/t/t_const_opt.pl @@ -20,7 +20,7 @@ execute( ); if ($Self->{vlt}) { - file_grep($Self->{stats}, qr/Optimizations, Const bit op reduction\s+(\d+)/i, 39); + file_grep($Self->{stats}, qr/Optimizations, Const bit op reduction\s+(\d+)/i, 40); } ok(1); 1; diff --git a/test_regress/t/t_const_opt.v b/test_regress/t/t_const_opt.v index 33be8914e..b60aa75fa 100644 --- a/test_regress/t/t_const_opt.v +++ b/test_regress/t/t_const_opt.v @@ -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'h5a76f060ff8aba3e +`define EXPECTED_SUM 64'h4c5aa8d19cd13750 if (sum !== `EXPECTED_SUM) $stop; $write("*-* All Finished *-*\n"); @@ -96,10 +96,11 @@ module Test(/*AUTOARG*/ logic bug4832_out; logic bug4837_out; logic bug4857_out; + logic bug4864_out; output logic o; - logic [17:0] tmp; + logic [18:0] tmp; assign o = ^tmp; always_ff @(posedge clk) begin @@ -133,6 +134,7 @@ module Test(/*AUTOARG*/ tmp[15]<= bug4832_out; tmp[16]<= bug4837_out; tmp[17]<= bug4857_out; + tmp[18]<= bug4864_out; end bug3182 i_bug3182(.in(d[4:0]), .out(bug3182_out)); @@ -147,6 +149,7 @@ module Test(/*AUTOARG*/ bug4832 i_bug4832(.clk(clk), .in(d), .out(bug4832_out)); bug4837 i_bug4837(.clk(clk), .in(d), .out(bug4837_out)); bug4857 i_bug4857(.clk(clk), .in(d), .out(bug4857_out)); + bug4864 i_bug4864(.clk(clk), .in(d), .out(bug4864_out)); endmodule @@ -489,3 +492,54 @@ module bug4857(input wire clk, input wire [31:0] in, output out); result <= out_data[32]; assign out = result; endmodule + + +// See issue #4864 +// (((in_data[32*1] & 32'h3000000 != 0) | (in_data[32*2 + 25])| (sig_b != 9'b0)) >> 4) | sig_b[2] +// was wrongly optimized as below. +// ((in_data[32] & 32'h30000000) != 0 >> 0) | (in_data[32*2 + 29])|((sig_b & 9'h1f4) != 0) +// The result of EQ/NE is just 1 bit width, so EQ/NE under SHFITR cannot be treated as a multi-bit term +// such as AND/OR. +module bug4864(input wire clk, input wire [31:0] in, output wire out); + logic [159:0] clkin_data = '0; + logic [95:0] in_data = '0; + int cycle = 0; + always @(posedge clk) begin + if (in[0]) begin + cycle <= cycle + 1; + if (cycle == 0) begin + clkin_data <= 160'hFFFFFFFF_00000000_00000000_00000000_00000000; + end else if (cycle == 1) begin + in_data <= 96'h00000000_FFFFFFFF_00000000; + end else begin + clkin_data <= 160'hFFFFFFFF_00000000_00000000_00000000_FFFFFFFF; + end + end + end + + wire moveme; + wire sig_a; + reg [8:0] sig_b; + wire sig_c; + wire [20:0] sig_d; + reg sig_e; + + logic myfirst, mysecond; + assign myfirst = 1'b0; + assign mysecond = 1'b0; + + always_ff @(posedge clkin_data[0], posedge myfirst, posedge mysecond) + if (myfirst) sig_e <= 1'b0; + else if (mysecond) sig_e <= 1'b1; + else if (clkin_data[128]) sig_e <= sig_d[7]; + + always_ff @(posedge clkin_data[128]) + sig_b <= '0; + + assign sig_a = in_data[89]; // 1'b0; + assign sig_c = | { in_data[61:60], sig_b, sig_a }; + assign sig_d = ~ { moveme, 6'b0, sig_b, 1'b0, sig_c, 3'b0 }; + assign moveme = 1'b1; + + assign out = sig_e; +endmodule diff --git a/test_regress/t/t_const_opt_dfg.pl b/test_regress/t/t_const_opt_dfg.pl index ef7ce89ed..c93977609 100755 --- a/test_regress/t/t_const_opt_dfg.pl +++ b/test_regress/t/t_const_opt_dfg.pl @@ -21,7 +21,7 @@ execute( ); if ($Self->{vlt}) { - file_grep($Self->{stats}, qr/Optimizations, Const bit op reduction\s+(\d+)/i, 34); + file_grep($Self->{stats}, qr/Optimizations, Const bit op reduction\s+(\d+)/i, 35); } ok(1); 1;