diff --git a/Changes b/Changes index 449b2ea99..3f5bf81e5 100644 --- a/Changes +++ b/Changes @@ -46,6 +46,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Fix -Wno-UNOPTFLAT change detection with 64-bits, bug762. [Clifford Wolf] +**** Fix shift-right optimization, bug763. [Clifford Wolf] + **** Fix Mac OS-X test issues. [Holger Waechtler] **** Fix C++-2011 warnings. diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 90a4e96c4..60222415d 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -728,9 +728,15 @@ private: AstNode* ap = lhsp->lhsp()->unlinkFrBack(); AstNode* shift1p = lhsp->rhsp()->unlinkFrBack(); AstNode* shift2p = nodep->rhsp()->unlinkFrBack(); + // Shift1p and shift2p may have different sizes, both are self-determined so sum with infinite width if (nodep->type()==lhsp->type()) { + int shift1 = shift1p->castConst()->toUInt(); + int shift2 = shift2p->castConst()->toUInt(); + int newshift = shift1+shift2; + shift1p->deleteTree(); shift1p=NULL; + shift2p->deleteTree(); shift2p=NULL; nodep->lhsp(ap); - nodep->rhsp(new AstAdd(nodep->fileline(), shift1p, shift2p)); + nodep->rhsp(new AstConst(nodep->fileline(), newshift)); nodep->accept(*this); // Further reduce, either node may have more reductions. } else { // We know shift amounts are constant, but might be a mixed left/right shift @@ -738,7 +744,7 @@ private: int shift2 = shift2p->castConst()->toUInt(); if (nodep->castShiftR()) shift2=-shift2; int newshift = shift1+shift2; shift1p->deleteTree(); shift1p=NULL; - shift2p->deleteTree(); shift1p=NULL; + shift2p->deleteTree(); shift2p=NULL; AstNode* newp; V3Number mask1 (nodep->fileline(), nodep->width()); V3Number ones (nodep->fileline(), nodep->width()); diff --git a/test_regress/t/t_math_signed5.v b/test_regress/t/t_math_signed5.v index 317a0baa7..ec90fd8ac 100644 --- a/test_regress/t/t_math_signed5.v +++ b/test_regress/t/t_math_signed5.v @@ -111,6 +111,11 @@ w4_u = |0 != (w5_s >>> w3_u); `checkh(w4_u, 4'b0000); + // bug763 + w3_u = 2; + w4_u = (w3_u >> 2'b11) >> 1; + `checkh(w4_u, 4'b0000); + if (fail) $stop; $write("*-* All Finished *-*\n"); $finish;