Optimize wide word shifts by multiple of word size (#6970)
V3Expand wide SHIFTL and SHIFTR if the shift amount is know and is a multiple of VL_EDATA_SIZE. This case results in each word requiring a simple copy from the original, or store of a constant zero, which subsequent V3Subst can then eliminate.
This commit is contained in:
parent
cea4c88e12
commit
bef709a235
|
|
@ -373,6 +373,47 @@ class ExpandVisitor final : public VNVisitor {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
bool expandWideShift(AstNodeAssign* nodep, AstNodeBiop* rhsp, bool isLeftShift) {
|
||||
if (!doExpandWide(nodep)) return false;
|
||||
|
||||
// Simplify the shift amount, in case it becomes a constant
|
||||
V3Const::constifyEditCpp(rhsp->rhsp());
|
||||
|
||||
// If it's a constant shift by whole words, expand it so V3Subst can substitute it
|
||||
if (const AstConst* const rhsConstp = VN_CAST(rhsp->rhsp(), Const)) {
|
||||
const uint32_t shiftBits = rhsConstp->toUInt();
|
||||
if (VL_BITBIT_E(shiftBits) == 0) {
|
||||
const int widthWords = nodep->widthWords();
|
||||
const int shiftWords = std::min<int>(VL_BITWORD_E(shiftBits), widthWords);
|
||||
FileLine* const flp = rhsp->fileline();
|
||||
if (isLeftShift) {
|
||||
UINFO(8, " Wordize ASSIGN(SHIFTL,words) " << nodep);
|
||||
// Low words of the result are zero
|
||||
for (int w = 0; w < shiftWords; ++w) {
|
||||
addWordAssign(nodep, w, new AstConst{flp, AstConst::SizedEData{}, 0});
|
||||
}
|
||||
// High words of the result are copied from higher words of the source
|
||||
for (int w = shiftWords; w < widthWords; ++w) {
|
||||
addWordAssign(nodep, w, newAstWordSelClone(rhsp->lhsp(), w - shiftWords));
|
||||
}
|
||||
} else {
|
||||
UINFO(8, " Wordize ASSIGN(SHIFTR,words) " << nodep);
|
||||
// Low words of the result are copied from higher words of the source
|
||||
for (int w = 0; w < widthWords - shiftWords; ++w) {
|
||||
addWordAssign(nodep, w, newAstWordSelClone(rhsp->lhsp(), w + shiftWords));
|
||||
}
|
||||
// High words of the result are zero
|
||||
for (int w = widthWords - shiftWords; w < widthWords; ++w) {
|
||||
addWordAssign(nodep, w, new AstConst{flp, AstConst::SizedEData{}, 0});
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------- Triops
|
||||
bool expandWide(AstNodeAssign* nodep, AstCond* rhsp) {
|
||||
UINFO(8, " Wordize ASSIGN(COND) " << nodep);
|
||||
|
|
@ -1026,7 +1067,7 @@ class ExpandVisitor final : public VNVisitor {
|
|||
m_stmtp = nodep;
|
||||
iterateChildren(nodep);
|
||||
bool did = false;
|
||||
if (nodep->isWide() && ((VN_IS(nodep->lhsp(), VarRef) || VN_IS(nodep->lhsp(), ArraySel)))
|
||||
if (nodep->isWide() //
|
||||
&& ((VN_IS(nodep->lhsp(), VarRef) || VN_IS(nodep->lhsp(), ArraySel)))
|
||||
&& !AstVar::scVarRecurse(nodep->lhsp()) // Need special function for SC
|
||||
&& !AstVar::scVarRecurse(nodep->rhsp())) {
|
||||
|
|
@ -1052,6 +1093,10 @@ class ExpandVisitor final : public VNVisitor {
|
|||
did = expandWide(nodep, rhsp);
|
||||
} else if (AstXor* const rhsp = VN_CAST(nodep->rhsp(), Xor)) {
|
||||
did = expandWide(nodep, rhsp);
|
||||
} else if (AstShiftL* const rhsp = VN_CAST(nodep->rhsp(), ShiftL)) {
|
||||
did = expandWideShift(nodep, rhsp, /* isLeftShift: */ true);
|
||||
} else if (AstShiftR* const rhsp = VN_CAST(nodep->rhsp(), ShiftR)) {
|
||||
did = expandWideShift(nodep, rhsp, /* isLeftShift: */ false);
|
||||
} else if (AstCond* const rhsp = VN_CAST(nodep->rhsp(), Cond)) {
|
||||
did = expandWide(nodep, rhsp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
ign, ign2, ign3, ign4, ign4s,
|
||||
ign, ign2, ign3, c_wright_32, c_wleft_32, ign4, ign4s,
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
|
@ -59,6 +59,12 @@ module t (/*AUTOARG*/
|
|||
reg [63:0] qamt;
|
||||
reg [95:0] wamt;
|
||||
|
||||
output reg [95:0] c_wright_32;
|
||||
output reg [95:0] c_wleft_32;
|
||||
|
||||
reg [63:0] crc = 64'h5aef0c8d_d70a4497;
|
||||
wire [95:0] rand_96 = {crc[63:32] | crc[31:0], crc};
|
||||
|
||||
assign ign = {31'h0, clk} >>> 4'bx; // bug760
|
||||
assign ign2 = {iamt[1:0] >> {22{iamt[5:2]}}, iamt[1:0] << (0 <<< iamt[5:2])}; // bug1174
|
||||
assign ign3 = {iamt[1:0] >> {22{iamt[5:2]}},
|
||||
|
|
@ -104,12 +110,16 @@ module t (/*AUTOARG*/
|
|||
w_wright = 96'hf784bf8f_12734089_190abe48 >> wamt;
|
||||
w_wrights = 96'shf784bf8f_12734089_190abe48 >>> signed'(wamt);
|
||||
w_wleft = 96'hf784bf8f_12734089_190abe48 << wamt;
|
||||
|
||||
c_wright_32 = rand_96 >> 32;
|
||||
c_wleft_32 = rand_96 << 32;
|
||||
end
|
||||
|
||||
integer cyc; initial cyc=1;
|
||||
always @ (posedge clk) begin
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63] ^ crc[2] ^ crc[0]};
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("%d %x %x %x %x %x %x\n", cyc, ileft, iright, qleft, qright, wleft, wright);
|
||||
`endif
|
||||
|
|
@ -233,6 +243,9 @@ module t (/*AUTOARG*/
|
|||
if (wleft != w_wleft) $stop;
|
||||
if (wright != w_wright) $stop;
|
||||
if (wrights != w_wrights) $stop;
|
||||
|
||||
if (c_wright_32 << 32 != {rand_96[95:32], 32'd0}) $stop;
|
||||
if (c_wleft_32 >> 32 != {32'd0, rand_96[63:0]}) $stop;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue