Speed up DfgPeephole in various ways

This commit is contained in:
Geza Lore 2022-10-06 12:02:46 +01:00
parent 4f0158b5e0
commit 6fa14bf029
2 changed files with 87 additions and 60 deletions

View File

@ -365,8 +365,8 @@ public:
// Width of result // Width of result
uint32_t width() const { uint32_t width() const {
// Everything supported is packed now, so we can just do this: // This is a hot enough function that this is an expensive check, so in debug build only.
UASSERT_OBJ(VN_IS(dtypep(), BasicDType), this, "'width()' called on unpacked value"); UDEBUGONLY(UASSERT_OBJ(VN_IS(dtypep(), BasicDType), this, "non-packed has no 'width()'"););
return dtypep()->width(); return dtypep()->width();
} }

View File

@ -356,14 +356,15 @@ class V3DfgPeephole final : public DfgVisitor {
// Bitwise operation with one side Const, and the other side a Concat // Bitwise operation with one side Const, and the other side a Concat
template <typename Vertex> template <typename Vertex>
bool tryPushBitwiseOpThroughConcat(Vertex* vtxp, DfgConst* constp, DfgConcat* concatp) { bool tryPushBitwiseOpThroughConcat(Vertex* vtxp, DfgConst* constp, DfgConcat* concatp) {
UASSERT_OBJ(constp->width() == concatp->width(), vtxp, "Mismatched widths"); UASSERT_OBJ(constp->dtypep() == concatp->dtypep(), vtxp, "Mismatched widths");
FileLine* const flp = vtxp->fileline(); FileLine* const flp = vtxp->fileline();
// If at least one of the sides of the Concat constant, or width 1 (i.e.: can be // If at least one of the sides of the Concat constant, or width 1 (i.e.: can be
// further simplified), then push the Vertex past the Concat // further simplified), then push the Vertex past the Concat
if (concatp->lhsp()->is<DfgConst>() || concatp->rhsp()->is<DfgConst>() // if (concatp->lhsp()->is<DfgConst>() || concatp->rhsp()->is<DfgConst>() //
|| concatp->lhsp()->width() == 1 || concatp->rhsp()->width() == 1) { || concatp->lhsp()->dtypep() == m_bitDType
|| concatp->rhsp()->dtypep() == m_bitDType) {
APPLYING(PUSH_BITWISE_OP_THROUGH_CONCAT) { APPLYING(PUSH_BITWISE_OP_THROUGH_CONCAT) {
const uint32_t width = concatp->width(); const uint32_t width = concatp->width();
AstNodeDType* const lDtypep = concatp->lhsp()->dtypep(); AstNodeDType* const lDtypep = concatp->lhsp()->dtypep();
@ -401,7 +402,7 @@ class V3DfgPeephole final : public DfgVisitor {
template <typename Vertex> template <typename Vertex>
bool tryPushCompareOpThroughConcat(Vertex* vtxp, DfgConst* constp, DfgConcat* concatp) { bool tryPushCompareOpThroughConcat(Vertex* vtxp, DfgConst* constp, DfgConcat* concatp) {
UASSERT_OBJ(constp->width() == concatp->width(), vtxp, "Mismatched widths"); UASSERT_OBJ(constp->dtypep() == concatp->dtypep(), vtxp, "Mismatched widths");
FileLine* const flp = vtxp->fileline(); FileLine* const flp = vtxp->fileline();
@ -483,7 +484,7 @@ class V3DfgPeephole final : public DfgVisitor {
FileLine* const flp = vtxp->fileline(); FileLine* const flp = vtxp->fileline();
// Reduction of 1-bit value // Reduction of 1-bit value
if (srcp->width() == 1) { if (srcp->dtypep() == m_bitDType) {
APPLYING(REMOVE_WIDTH_ONE_REDUCTION) { APPLYING(REMOVE_WIDTH_ONE_REDUCTION) {
vtxp->replaceWith(srcp); vtxp->replaceWith(srcp);
return; return;
@ -589,19 +590,19 @@ class V3DfgPeephole final : public DfgVisitor {
} }
void visit(DfgLogNot* vtxp) override { void visit(DfgLogNot* vtxp) override {
UASSERT_OBJ(vtxp->width() == 1, vtxp, "Incorrect width"); UASSERT_OBJ(vtxp->dtypep() == m_bitDType, vtxp, "Incorrect width");
if (foldUnary(vtxp)) return; if (foldUnary(vtxp)) return;
} }
void visit(DfgNegate* vtxp) override { void visit(DfgNegate* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->srcp()->width(), vtxp, "Mismatched width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->srcp()->dtypep(), vtxp, "Mismatched width");
if (foldUnary(vtxp)) return; if (foldUnary(vtxp)) return;
} }
void visit(DfgNot* vtxp) override { void visit(DfgNot* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->srcp()->width(), vtxp, "Mismatched width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->srcp()->dtypep(), vtxp, "Mismatched width");
if (foldUnary(vtxp)) return; if (foldUnary(vtxp)) return;
@ -634,7 +635,7 @@ class V3DfgPeephole final : public DfgVisitor {
// Not of Not // Not of Not
if (DfgNot* const notp = vtxp->srcp()->cast<DfgNot>()) { if (DfgNot* const notp = vtxp->srcp()->cast<DfgNot>()) {
UASSERT_OBJ(vtxp->width() == notp->srcp()->width(), vtxp, "Width mismatch"); UASSERT_OBJ(vtxp->dtypep() == notp->srcp()->dtypep(), vtxp, "Width mismatch");
APPLYING(REMOVE_NOT_NOT) { APPLYING(REMOVE_NOT_NOT) {
vtxp->replaceWith(notp->srcp()); vtxp->replaceWith(notp->srcp());
return; return;
@ -686,8 +687,8 @@ class V3DfgPeephole final : public DfgVisitor {
//========================================================================= //=========================================================================
void visit(DfgAnd* vtxp) override { void visit(DfgAnd* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width(), vtxp, "Mismatched LHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->width() == vtxp->rhsp()->width(), vtxp, "Mismatched RHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->rhsp()->dtypep(), vtxp, "Mismatched RHS width");
if (associativeBinary(vtxp)) return; if (associativeBinary(vtxp)) return;
@ -763,8 +764,8 @@ class V3DfgPeephole final : public DfgVisitor {
} }
void visit(DfgOr* vtxp) override { void visit(DfgOr* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width(), vtxp, "Mismatched LHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->width() == vtxp->rhsp()->width(), vtxp, "Mismatched RHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->rhsp()->dtypep(), vtxp, "Mismatched RHS width");
if (associativeBinary(vtxp)) return; if (associativeBinary(vtxp)) return;
@ -807,7 +808,7 @@ class V3DfgPeephole final : public DfgVisitor {
if (DfgConcat* const lhsConcatp = lhsp->cast<DfgConcat>()) { if (DfgConcat* const lhsConcatp = lhsp->cast<DfgConcat>()) {
if (DfgConcat* const rhsConcatp = rhsp->cast<DfgConcat>()) { if (DfgConcat* const rhsConcatp = rhsp->cast<DfgConcat>()) {
if (lhsConcatp->lhsp()->width() == rhsConcatp->lhsp()->width()) { if (lhsConcatp->lhsp()->dtypep() == rhsConcatp->lhsp()->dtypep()) {
if (lhsConcatp->lhsp()->isZero() && rhsConcatp->rhsp()->isZero()) { if (lhsConcatp->lhsp()->isZero() && rhsConcatp->rhsp()->isZero()) {
APPLYING(REPLACE_OR_OF_CONCAT_ZERO_LHS_AND_CONCAT_RHS_ZERO) { APPLYING(REPLACE_OR_OF_CONCAT_ZERO_LHS_AND_CONCAT_RHS_ZERO) {
DfgConcat* const replacementp DfgConcat* const replacementp
@ -868,8 +869,8 @@ class V3DfgPeephole final : public DfgVisitor {
} }
void visit(DfgXor* vtxp) override { void visit(DfgXor* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width(), vtxp, "Mismatched LHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->width() == vtxp->rhsp()->width(), vtxp, "Mismatched RHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->rhsp()->dtypep(), vtxp, "Mismatched RHS width");
if (associativeBinary(vtxp)) return; if (associativeBinary(vtxp)) return;
@ -908,8 +909,8 @@ class V3DfgPeephole final : public DfgVisitor {
//========================================================================= //=========================================================================
void visit(DfgAdd* vtxp) override { void visit(DfgAdd* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width(), vtxp, "Mismatched LHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->width() == vtxp->rhsp()->width(), vtxp, "Mismatched RHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->rhsp()->dtypep(), vtxp, "Mismatched RHS width");
if (associativeBinary(vtxp)) return; if (associativeBinary(vtxp)) return;
@ -931,11 +932,11 @@ class V3DfgPeephole final : public DfgVisitor {
} }
void visit(DfgConcat* vtxp) override { void visit(DfgConcat* vtxp) override {
if (associativeBinary(vtxp)) return;
UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width() + vtxp->rhsp()->width(), vtxp, UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width() + vtxp->rhsp()->width(), vtxp,
"Inconsistent Concat"); "Inconsistent Concat");
if (associativeBinary(vtxp)) return;
DfgVertex* const lhsp = vtxp->lhsp(); DfgVertex* const lhsp = vtxp->lhsp();
DfgVertex* const rhsp = vtxp->rhsp(); DfgVertex* const rhsp = vtxp->rhsp();
@ -945,7 +946,7 @@ class V3DfgPeephole final : public DfgVisitor {
DfgConst* const lConstp = lhsp->as<DfgConst>(); DfgConst* const lConstp = lhsp->as<DfgConst>();
if (DfgSel* const rSelp = rhsp->cast<DfgSel>()) { if (DfgSel* const rSelp = rhsp->cast<DfgSel>()) {
if (DfgConst* const rSelLsbConstp = rSelp->lsbp()->cast<DfgConst>()) { if (DfgConst* const rSelLsbConstp = rSelp->lsbp()->cast<DfgConst>()) {
if (vtxp->width() == rSelp->fromp()->width() if (vtxp->dtypep() == rSelp->fromp()->dtypep()
&& rSelLsbConstp->toU32() == lConstp->width()) { && rSelLsbConstp->toU32() == lConstp->width()) {
const uint32_t rSelWidth = rSelp->widthp()->as<DfgConst>()->toU32(); const uint32_t rSelWidth = rSelp->widthp()->as<DfgConst>()->toU32();
UASSERT_OBJ(lConstp->width() + rSelWidth == vtxp->width(), vtxp, UASSERT_OBJ(lConstp->width() + rSelWidth == vtxp->width(), vtxp,
@ -967,7 +968,8 @@ class V3DfgPeephole final : public DfgVisitor {
DfgConst* const rConstp = rhsp->as<DfgConst>(); DfgConst* const rConstp = rhsp->as<DfgConst>();
if (DfgSel* const lSelp = lhsp->cast<DfgSel>()) { if (DfgSel* const lSelp = lhsp->cast<DfgSel>()) {
if (DfgConst* const lSelLsbConstp = lSelp->lsbp()->cast<DfgConst>()) { if (DfgConst* const lSelLsbConstp = lSelp->lsbp()->cast<DfgConst>()) {
if (vtxp->width() == lSelp->fromp()->width() && lSelLsbConstp->toU32() == 0) { if (vtxp->dtypep() == lSelp->fromp()->dtypep()
&& lSelLsbConstp->toU32() == 0) {
const uint32_t lSelWidth = lSelp->widthp()->as<DfgConst>()->toU32(); const uint32_t lSelWidth = lSelp->widthp()->as<DfgConst>()->toU32();
UASSERT_OBJ(lSelWidth + rConstp->width() == vtxp->width(), vtxp, UASSERT_OBJ(lSelWidth + rConstp->width() == vtxp->width(), vtxp,
"Inconsistent"); "Inconsistent");
@ -1147,8 +1149,8 @@ class V3DfgPeephole final : public DfgVisitor {
} }
void visit(DfgMul* vtxp) override { void visit(DfgMul* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width(), vtxp, "Mismatched LHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->width() == vtxp->rhsp()->width(), vtxp, "Mismatched RHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->rhsp()->dtypep(), vtxp, "Mismatched RHS width");
if (associativeBinary(vtxp)) return; if (associativeBinary(vtxp)) return;
@ -1156,8 +1158,8 @@ class V3DfgPeephole final : public DfgVisitor {
} }
void visit(DfgMulS* vtxp) override { void visit(DfgMulS* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width(), vtxp, "Mismatched LHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->width() == vtxp->rhsp()->width(), vtxp, "Mismatched RHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->rhsp()->dtypep(), vtxp, "Mismatched RHS width");
if (associativeBinary(vtxp)) return; if (associativeBinary(vtxp)) return;
@ -1185,7 +1187,7 @@ class V3DfgPeephole final : public DfgVisitor {
} }
void visit(DfgReplicate* vtxp) override { void visit(DfgReplicate* vtxp) override {
if (vtxp->width() == vtxp->srcp()->width()) { if (vtxp->dtypep() == vtxp->srcp()->dtypep()) {
APPLYING(REMOVE_REPLICATE_ONCE) { APPLYING(REMOVE_REPLICATE_ONCE) {
vtxp->replaceWith(vtxp->srcp()); vtxp->replaceWith(vtxp->srcp());
return; return;
@ -1196,7 +1198,7 @@ class V3DfgPeephole final : public DfgVisitor {
} }
void visit(DfgShiftL* vtxp) override { void visit(DfgShiftL* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width(), vtxp, "Mismatched width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched width");
if (foldBinary(vtxp)) return; if (foldBinary(vtxp)) return;
@ -1204,7 +1206,7 @@ class V3DfgPeephole final : public DfgVisitor {
} }
void visit(DfgShiftR* vtxp) override { void visit(DfgShiftR* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width(), vtxp, "Mismatched width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched width");
if (foldBinary(vtxp)) return; if (foldBinary(vtxp)) return;
@ -1212,7 +1214,7 @@ class V3DfgPeephole final : public DfgVisitor {
} }
void visit(DfgShiftRS* vtxp) override { void visit(DfgShiftRS* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width(), vtxp, "Mismatched width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched width");
if (foldBinary(vtxp)) return; if (foldBinary(vtxp)) return;
@ -1220,8 +1222,8 @@ class V3DfgPeephole final : public DfgVisitor {
} }
void visit(DfgSub* vtxp) override { void visit(DfgSub* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->lhsp()->width(), vtxp, "Mismatched LHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched LHS width");
UASSERT_OBJ(vtxp->width() == vtxp->rhsp()->width(), vtxp, "Mismatched RHS width"); UASSERT_OBJ(vtxp->dtypep() == vtxp->rhsp()->dtypep(), vtxp, "Mismatched RHS width");
if (foldBinary(vtxp)) return; if (foldBinary(vtxp)) return;
@ -1235,7 +1237,7 @@ class V3DfgPeephole final : public DfgVisitor {
return; return;
} }
} }
if (vtxp->width() == 1 && rConstp->toU32() == 1) { if (vtxp->dtypep() == m_bitDType && rConstp->toU32() == 1) {
APPLYING(REPLACE_SUB_WITH_NOT) { APPLYING(REPLACE_SUB_WITH_NOT) {
DfgNot* const replacementp = new DfgNot{m_dfg, vtxp->fileline(), m_bitDType}; DfgNot* const replacementp = new DfgNot{m_dfg, vtxp->fileline(), m_bitDType};
replacementp->srcp(lhsp); replacementp->srcp(lhsp);
@ -1354,7 +1356,7 @@ class V3DfgPeephole final : public DfgVisitor {
if (DfgNot* const notp = fromp->cast<DfgNot>()) { if (DfgNot* const notp = fromp->cast<DfgNot>()) {
// Replace "Sel from Not" with "Not of Sel" // Replace "Sel from Not" with "Not of Sel"
if (!notp->hasMultipleSinks()) { if (!notp->hasMultipleSinks()) {
UASSERT_OBJ(notp->srcp()->width() == notp->width(), notp, "Mismatched widths"); UASSERT_OBJ(notp->srcp()->dtypep() == notp->dtypep(), notp, "Mismatched widths");
APPLYING(PUSH_SEL_THROUGH_NOT) { APPLYING(PUSH_SEL_THROUGH_NOT) {
// Make Sel select from source of Not // Make Sel select from source of Not
vtxp->fromp(notp->srcp()); vtxp->fromp(notp->srcp());
@ -1432,15 +1434,15 @@ class V3DfgPeephole final : public DfgVisitor {
} }
void visit(DfgCond* vtxp) override { void visit(DfgCond* vtxp) override {
UASSERT_OBJ(vtxp->width() == vtxp->thenp()->width(), vtxp, "Width mismatch"); UASSERT_OBJ(vtxp->dtypep() == vtxp->thenp()->dtypep(), vtxp, "Width mismatch");
UASSERT_OBJ(vtxp->width() == vtxp->elsep()->width(), vtxp, "Width mismatch"); UASSERT_OBJ(vtxp->dtypep() == vtxp->elsep()->dtypep(), vtxp, "Width mismatch");
DfgVertex* const condp = vtxp->condp(); DfgVertex* const condp = vtxp->condp();
DfgVertex* const thenp = vtxp->thenp(); DfgVertex* const thenp = vtxp->thenp();
DfgVertex* const elsep = vtxp->elsep(); DfgVertex* const elsep = vtxp->elsep();
FileLine* const flp = vtxp->fileline(); FileLine* const flp = vtxp->fileline();
if (condp->width() != 1) return; if (condp->dtypep() != m_bitDType) return;
if (condp->isOnes()) { if (condp->isOnes()) {
APPLYING(REMOVE_COND_WITH_TRUE_CONDITION) { APPLYING(REMOVE_COND_WITH_TRUE_CONDITION) {
@ -1462,7 +1464,6 @@ class V3DfgPeephole final : public DfgVisitor {
vtxp->condp(condNotp->srcp()); vtxp->condp(condNotp->srcp());
vtxp->thenp(elsep); vtxp->thenp(elsep);
vtxp->elsep(thenp); vtxp->elsep(thenp);
visit(vtxp);
return; return;
} }
} }
@ -1477,7 +1478,6 @@ class V3DfgPeephole final : public DfgVisitor {
vtxp->condp(newCondp); vtxp->condp(newCondp);
vtxp->thenp(elsep); vtxp->thenp(elsep);
vtxp->elsep(thenp); vtxp->elsep(thenp);
visit(vtxp);
return; return;
} }
} }
@ -1543,7 +1543,7 @@ class V3DfgPeephole final : public DfgVisitor {
} }
} }
if (vtxp->width() == 1) { if (vtxp->dtypep() == m_bitDType) {
AstNodeDType* const dtypep = vtxp->dtypep(); AstNodeDType* const dtypep = vtxp->dtypep();
if (thenp->isZero()) { // a ? 0 : b becomes ~a & b if (thenp->isZero()) { // a ? 0 : b becomes ~a & b
APPLYING(REPLACE_COND_WITH_THEN_BRANCH_ZERO) { APPLYING(REPLACE_COND_WITH_THEN_BRANCH_ZERO) {
@ -1606,44 +1606,71 @@ class V3DfgPeephole final : public DfgVisitor {
#undef APPLYING #undef APPLYING
// Process one vertex. Return true if graph changed // Process one vertex. Return true if graph changed
bool processVertex(DfgVertex& vtx) { void processVertex(DfgVertex* vtxp) {
// Keep DfgVertexVar vertices in this pass. We will remove them later if they become // Keep DfgVertexVar vertices in this pass. We will remove them later if they become
// redundant. We want to keep the original variables for non-var vertices that drive // redundant. We want to keep the original variables for non-var vertices that drive
// multiple sinks (otherwise we would need to introduce a temporary, but it is better for // multiple sinks (otherwise we would need to introduce a temporary, but it is better for
// debugging to keep the original variable name, if one is available), so we can't remove // debugging to keep the original variable name, if one is available), so we can't remove
// redundant variables here. // redundant variables here.
const bool keep = vtx.is<DfgVertexVar>(); const bool keep = vtxp->is<DfgVertexVar>();
// If it has no sinks (unused), we can remove it // If it has no sinks (unused), we can remove it
if (!keep && !vtx.hasSinks()) { if (!keep && !vtxp->hasSinks()) {
vtx.unlinkDelete(m_dfg); vtxp->unlinkDelete(m_dfg);
return true; m_changed = true;
return;
} }
// Transform node // Transform node
m_changed = false; iterate(vtxp);
iterate(&vtx);
// If it became unused, we can remove it // If it became unused, we can remove it
if (!keep && !vtx.hasSinks()) { if (!keep && !vtxp->hasSinks()) {
UASSERT_OBJ(m_changed, &vtx, "'m_changed' must be set if node became unused"); UASSERT_OBJ(m_changed, vtxp, "'m_changed' must be set if node became unused");
vtx.unlinkDelete(m_dfg); vtxp->unlinkDelete(m_dfg);
return true;
} }
// Return the changed status
return m_changed;
} }
V3DfgPeephole(DfgGraph& dfg, V3DfgPeepholeContext& ctx) V3DfgPeephole(DfgGraph& dfg, V3DfgPeepholeContext& ctx)
: m_dfg{dfg} : m_dfg{dfg}
, m_ctx{ctx} {} , m_ctx{ctx} {
while (true) {
// Do one pass over the graph in the forward direction.
m_changed = false;
for (DfgVertex *vtxp = m_dfg.verticesBegin(), *nextp; vtxp; vtxp = nextp) {
nextp = vtxp->verticesNext();
if (VL_LIKELY(nextp)) VL_PREFETCH_RW(nextp);
// Special case DfgConst as it's common and the is nothing we can do about them.
// No need to set 'm_changed' when deleting it as it influences nothing else.
if (vtxp->is<DfgConst>()) {
if (!vtxp->hasSinks()) vtxp->unlinkDelete(m_dfg);
continue;
}
processVertex(vtxp);
}
if (!m_changed) break;
// Do another pass in the opposite direction. Alternating directions reduces
// the pathological complexity with left/right leaning trees.
m_changed = false;
for (DfgVertex *vtxp = m_dfg.verticesRbegin(), *nextp; vtxp; vtxp = nextp) {
nextp = vtxp->verticesPrev();
if (VL_LIKELY(nextp)) VL_PREFETCH_RW(nextp);
// Special case DfgConst as it's common and the is nothing we can do about them.
// No need to set 'm_changed' when deleting it as it influences nothing else.
if (vtxp->is<DfgConst>()) {
if (!vtxp->hasSinks()) vtxp->unlinkDelete(m_dfg);
continue;
}
processVertex(vtxp);
}
if (!m_changed) break;
}
}
public: public:
static void apply(DfgGraph& dfg, V3DfgPeepholeContext& ctx) { static void apply(DfgGraph& dfg, V3DfgPeepholeContext& ctx) { V3DfgPeephole{dfg, ctx}; }
V3DfgPeephole visitor{dfg, ctx};
dfg.runToFixedPoint([&](DfgVertex& vtx) { return visitor.processVertex(vtx); });
}
}; };
void V3DfgPasses::peephole(DfgGraph& dfg, V3DfgPeepholeContext& ctx) { void V3DfgPasses::peephole(DfgGraph& dfg, V3DfgPeepholeContext& ctx) {