Optimize 2 ** X to 1 << X if base is signed
This commit is contained in:
parent
f535a73ea7
commit
4f59b4acfe
|
@ -158,6 +158,7 @@ Martin Schmidt
|
|||
Martin Stadler
|
||||
Mateusz Gancarz
|
||||
Matthew Ballance
|
||||
Max Wipfli
|
||||
Michael Bikovitsky
|
||||
Michael Killough
|
||||
Michal Czyz
|
||||
|
|
|
@ -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<<a
|
||||
TREEOP ("AstPowSU {operandIsTwo($lhsp), !$rhsp.isZero}", "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))
|
||||
TREEOPC("AstAnd {$lhsp.isOne, matchRedundantClean(nodep)}", "DONE") // 1 & (a == b) -> (IData)(a == b)
|
||||
// Trinary ops
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue