diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index dceab099e..bbe5f8c56 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -158,6 +158,7 @@ Martin Schmidt Martin Stadler Mateusz Gancarz Matthew Ballance +Max Wipfli Michael Bikovitsky Michael Killough Michal Czyz diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 690e70db2..31a8688a1 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1267,8 +1267,12 @@ class ConstVisitor final : public VNVisitor { && nodep->lhsp()->isPure()); } bool operandIsTwo(const AstNode* nodep) { - return (VN_IS(nodep, Const) && !VN_AS(nodep, Const)->num().isFourState() - && nodep->width() <= VL_QUADSIZE && VN_AS(nodep, Const)->toUQuad() == 2); + const AstConst* const constp = VN_CAST(nodep, Const); + if (!constp) return false; // not constant + if (constp->num().isFourState()) return false; // four-state + if (nodep->width() > VL_QUADSIZE) return false; // too wide + if (nodep->isSigned() && constp->num().isNegative()) return false; // signed and negative + return constp->toUQuad() == 2; } bool operandIsTwostate(const AstNode* nodep) { return (VN_IS(nodep, Const) && !VN_AS(nodep, Const)->num().isFourState()); @@ -3550,6 +3554,7 @@ class ConstVisitor final : public VNVisitor { TREEOP ("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n TREEOP ("AstModDiv{$lhsp, operandIsPowTwo($rhsp)}", "replaceModAnd(nodep)"); // a % 2^n -> a&(2^n-1) TREEOP ("AstPow {operandIsTwo($lhsp), !$rhsp.isZero}", "replacePowShift(nodep)"); // 2**a == 1<castAdd()->lhsp(),$rhsp}, $lhsp->castAdd()->rhsp()}"); // ((a+x)-y) -> (a+(x-y)) TREEOPC("AstAnd {$lhsp.isOne, matchRedundantClean(nodep)}", "DONE") // 1 & (a == b) -> (IData)(a == b) // Trinary ops diff --git a/test_regress/t/t_math_pow.v b/test_regress/t/t_math_pow.v index bf7236e89..286fe0546 100644 --- a/test_regress/t/t_math_pow.v +++ b/test_regress/t/t_math_pow.v @@ -37,7 +37,8 @@ module t (/*AUTOARG*/ wire signed [66:0] bsw = b[66:0]; // verilator lint_off WIDTH - wire [66:0] shifted = 2 ** b[20:0]; + wire [66:0] shifted = 32'd2 ** b[20:0]; + wire [66:0] shifted_signed = 32'sd2 ** b[20:0]; wire [15:0] uiii = aui ** bui; wire [15:0] uiiq = aui ** buq; @@ -358,5 +359,6 @@ module t (/*AUTOARG*/ 32'd09: `checkh(shifted, 67'h0000000000000000); default: ; endcase + `checkh(shifted_signed, shifted); end endmodule