mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Narrow NBA shadow copies for partial writes (#8266)
Signed-off-by: Artur Bieniek <[email protected]>
This commit is contained in:
+44
-1
@@ -56,6 +56,10 @@
|
||||
//
|
||||
// Constraint 3 should always hold with V3Delayed, will check assert it.
|
||||
//
|
||||
// If old-value reads prevent elimination, constant partial writes can still narrow both
|
||||
// copies to the words containing those writes. Other shadow bits are never read. The
|
||||
// assignments keep their original positions, so evaluation order and scheduling are unchanged.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT
|
||||
@@ -124,6 +128,7 @@ class LifePostDlyVisitor final : public VNVisitorConst {
|
||||
const AstExecGraph* m_execGraphp = nullptr; // Current AstExecGraph being processed (or null)
|
||||
const ExecMTask* m_execMTaskp = nullptr; // Current ExecMTask being processed (or null)
|
||||
VDouble0 m_statAssnDel; // Statistic tracking
|
||||
VDouble0 m_statWordsSaved; // Words removed from NBA shadow copies
|
||||
// Maps from Varscope to all their reads and writes
|
||||
using LocMap = std::unordered_map<const AstVarScope*, std::vector<Location<AstVarRef>>>;
|
||||
LocMap m_reads; // VarScope read locations
|
||||
@@ -134,6 +139,40 @@ class LifePostDlyVisitor final : public VNVisitorConst {
|
||||
bool m_inEvalNba = false; // Traversing under the 'nba' region entry point
|
||||
|
||||
// METHODS
|
||||
void narrowCopies(AstNodeAssign* postp, AstVarScope* dVscp,
|
||||
const std::vector<Location<AstVarRef>>& writes) {
|
||||
if (!dVscp->isWide()) return;
|
||||
AstNodeAssign* const prep = VN_AS(writes[0].nodep()->backp(), NodeAssign);
|
||||
UASSERT_OBJ(VN_AS(prep->lhsp(), VarRef)->varScopep()
|
||||
== VN_AS(postp->rhsp(), VarRef)->varScopep()
|
||||
&& VN_AS(prep->rhsp(), VarRef)->varScopep()
|
||||
== VN_AS(postp->lhsp(), VarRef)->varScopep(),
|
||||
prep, "NBA shadow pre/post assignments are not reverse copies");
|
||||
|
||||
int lsb = dVscp->width();
|
||||
int end = 0;
|
||||
for (size_t i = 1; i < writes.size(); ++i) {
|
||||
const AstSel* const selp = VN_CAST(writes[i].nodep()->backp(), Sel);
|
||||
if (!selp || !VN_IS(selp->lsbp(), Const)) return;
|
||||
const int start = selp->lsbConst();
|
||||
if (start > dVscp->width() - selp->width()) return;
|
||||
lsb = std::min(lsb, start);
|
||||
end = std::max(end, start + selp->width());
|
||||
}
|
||||
// Copy one word-aligned range enclosing all writes, including any gaps.
|
||||
lsb = VL_BITWORD_E(lsb) * VL_EDATASIZE;
|
||||
end = std::min(VL_WORDS_I(end) * VL_EDATASIZE, dVscp->width());
|
||||
const int width = end - lsb;
|
||||
if (width == dVscp->width()) return;
|
||||
for (AstNodeAssign* const assignp : {prep, postp}) {
|
||||
FileLine* const flp = assignp->fileline();
|
||||
assignp->lhsp(new AstSel{flp, assignp->lhsp()->unlinkFrBack(), lsb, width});
|
||||
assignp->rhsp(new AstSel{flp, assignp->rhsp()->unlinkFrBack(), lsb, width});
|
||||
assignp->dtypeFrom(assignp->lhsp());
|
||||
}
|
||||
m_statWordsSaved += 2 * (dVscp->widthWords() - VL_WORDS_I(width));
|
||||
}
|
||||
|
||||
void squashAssignposts() {
|
||||
for (const Location<AstNodeAssign>& assign : m_assigns) {
|
||||
AstVarScope* const dVscp = VN_AS(assign.nodep()->rhsp(), VarRef)->varScopep();
|
||||
@@ -172,7 +211,10 @@ class LifePostDlyVisitor final : public VNVisitorConst {
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
if (!qRdOK) continue;
|
||||
if (!qRdOK) {
|
||||
narrowCopies(assign.nodep(), dVscp, dWrites);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark variable for replacement
|
||||
@@ -308,6 +350,7 @@ public:
|
||||
}
|
||||
~LifePostDlyVisitor() override {
|
||||
V3Stats::addStat("Optimizations, Lifetime postassign deletions", m_statAssnDel);
|
||||
V3Stats::addStat("Optimizations, Lifetime NBA copy words removed", m_statWordsSaved);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user