forked from github/verilator
Optimize modulus by power-of-two constants.
This commit is contained in:
parent
fcb733e8d0
commit
ce178ec987
2
Changes
2
Changes
@ -28,6 +28,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
**** Support quoted arguments in -f files, bug1535. [Yves Mathieu]
|
||||
|
||||
**** Optimize modulus by power-of-two constants.
|
||||
|
||||
**** Fix detecting missing reg types, bug1570. [Jacko Dirks]
|
||||
|
||||
**** Fix multithreaded yield behavior when no work. [Patrick Stewart]
|
||||
|
@ -880,6 +880,17 @@ private:
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
void replaceModAnd(AstModDiv* nodep) { // Mod, but not ModS as not simple shift
|
||||
UINFO(5,"MOD(b,2^n)->AND(b,2^n-1) "<<nodep<<endl);
|
||||
int amount = VN_CAST(nodep->rhsp(), Const)->num().mostSetBitP1()-1; // 2^n->n+1
|
||||
V3Number mask(nodep, nodep->width());
|
||||
mask.setMask(amount);
|
||||
AstNode* opp = nodep->lhsp()->unlinkFrBack();
|
||||
AstAnd* newp = new AstAnd(nodep->fileline(),
|
||||
opp, new AstConst(nodep->fileline(), mask));
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
void replaceShiftOp(AstNodeBiop* nodep) {
|
||||
UINFO(5,"SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) "<<nodep<<endl);
|
||||
AstNRelinker handle;
|
||||
@ -2257,6 +2268,7 @@ private:
|
||||
TREEOP ("AstDivS {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n
|
||||
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}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||
TREEOP ("AstSub {$lhsp.castAdd, operandSubAdd(nodep)}", "AstAdd{AstSub{$lhsp->castAdd()->lhsp(),$rhsp}, $lhsp->castAdd()->rhsp()}"); // ((a+x)-y) -> (a+(x-y))
|
||||
// Trinary ops
|
||||
|
@ -14,12 +14,20 @@ module t (/*AUTOARG*/
|
||||
reg [60:0] divisor;
|
||||
reg [60:0] qq;
|
||||
reg [60:0] rq;
|
||||
reg [60:0] qq4;
|
||||
reg [60:0] rq4;
|
||||
reg [60:0] qq5;
|
||||
reg [60:0] rq5;
|
||||
reg signed [60:0] qqs;
|
||||
reg signed [60:0] rqs;
|
||||
|
||||
always @* begin
|
||||
qq = a[60:0] / divisor;
|
||||
rq = a[60:0] % divisor;
|
||||
qq4 = a[60:0] / 4; // Check power-of-two constification
|
||||
rq4 = a[60:0] % 4;
|
||||
qq5 = a[60:0] / 5; // Non power-of-two
|
||||
rq5 = a[60:0] % 5;
|
||||
qqs = $signed(a[60:0]) / $signed(divisor);
|
||||
rqs = $signed(a[60:0]) % $signed(divisor);
|
||||
end
|
||||
@ -34,6 +42,10 @@ module t (/*AUTOARG*/
|
||||
divisor <= 61'h12371;
|
||||
a[60] <= 1'b0; divisor[60] <= 1'b0; // Unsigned
|
||||
end
|
||||
if (cyc > 1) begin
|
||||
if (qq4 != {2'b0, a[60:2]}) $stop;
|
||||
if (rq4 != {59'h0, a[1:0]}) $stop;
|
||||
end
|
||||
if (cyc==2) begin
|
||||
a <= 256'h0e17c88f3d5fe51a982646c8e2bd68c3e236ddfddddbdad20a48e039c9f395b8;
|
||||
divisor <= 61'h1238123771;
|
||||
@ -42,6 +54,8 @@ module t (/*AUTOARG*/
|
||||
if (rq!==61'h00000000000090ec) $stop;
|
||||
if (qqs!==61'h00000403ad81c0da) $stop;
|
||||
if (rqs!==61'h00000000000090ec) $stop;
|
||||
if (qq4 != 61'h01247cf6851f9fc9) $stop;
|
||||
if (rq4 != 61'h0000000000000002) $stop;
|
||||
end
|
||||
if (cyc==3) begin
|
||||
a <= 256'h0e17c88f00d5fe51a982646c8002bd68c3e236ddfd00ddbdad20a48e00f395b8;
|
||||
@ -51,6 +65,8 @@ module t (/*AUTOARG*/
|
||||
if (rq!==61'h0000000334becc6a) $stop;
|
||||
if (qqs!==61'h000000000090832e) $stop;
|
||||
if (rqs!==61'h0000000334becc6a) $stop;
|
||||
if (qq4 != 61'h0292380e727ce56e) $stop;
|
||||
if (rq4 != 61'h0000000000000000) $stop;
|
||||
end
|
||||
if (cyc==4) begin
|
||||
a[60] <= 1'b0; divisor[60] <= 1'b1; // Signed
|
||||
@ -58,6 +74,8 @@ module t (/*AUTOARG*/
|
||||
if (rq!==61'h0000000000000c40) $stop;
|
||||
if (qqs!==61'h1fffcf5187c76510) $stop;
|
||||
if (rqs!==61'h1ffffffffffffd08) $stop;
|
||||
if (qq4 != 61'h07482923803ce56e) $stop;
|
||||
if (rq4 != 61'h0000000000000000) $stop;
|
||||
end
|
||||
if (cyc==5) begin
|
||||
a[60] <= 1'b1; divisor[60] <= 1'b1; // Signed
|
||||
|
Loading…
Reference in New Issue
Block a user