From f23f3ca90773f0e791607fd4969baa7e1975374e Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Tue, 4 Oct 2022 18:26:53 +0100 Subject: [PATCH] Try to ensure DFG peephole patterns don't grow the graph Some optimizations are only a net win if they help us remove a graph node (or at least ensure they don't grow the graph), or yields otherwise special logic, so try to apply them only in these cases. --- src/V3DfgPeephole.cpp | 230 +++++++++++++++++--------------- test_regress/t/t_dfg_peephole.v | 23 ++-- 2 files changed, 135 insertions(+), 118 deletions(-) diff --git a/src/V3DfgPeephole.cpp b/src/V3DfgPeephole.cpp index e02671d64..9e8a761ed 100644 --- a/src/V3DfgPeephole.cpp +++ b/src/V3DfgPeephole.cpp @@ -268,7 +268,8 @@ class V3DfgPeephole final : public DfgVisitor { if (Reduction* const rRedp = vtxp->rhsp()->template cast()) { DfgVertex* const lSrcp = lRedp->srcp(); DfgVertex* const rSrcp = rRedp->srcp(); - if (lSrcp->dtypep() == rSrcp->dtypep()) { + if (lSrcp->dtypep() == rSrcp->dtypep() && lSrcp->width() <= 64 + && !lSrcp->hasMultipleSinks() && !rSrcp->hasMultipleSinks()) { APPLYING(PUSH_BITWISE_THROUGH_REDUCTION) { FileLine* const flp = vtxp->fileline(); Bitwise* const bwp = new Bitwise{m_dfg, flp, lSrcp->dtypep()}; @@ -326,23 +327,25 @@ class V3DfgPeephole final : public DfgVisitor { } if (DfgConcat* const concatp = srcp->cast()) { - APPLYING(PUSH_REDUCTION_THROUGH_CONCAT) { - // Reduce the parts of the concatenation - Reduction* const lReducep = new Reduction{m_dfg, concatp->fileline(), m_bitDType}; - lReducep->srcp(concatp->lhsp()); - Reduction* const rReducep = new Reduction{m_dfg, concatp->fileline(), m_bitDType}; - rReducep->srcp(concatp->rhsp()); + if (!concatp->hasMultipleSinks()) { + APPLYING(PUSH_REDUCTION_THROUGH_CONCAT) { + // Reduce the parts of the concatenation + Reduction* const lRedp = new Reduction{m_dfg, srcp->fileline(), m_bitDType}; + lRedp->srcp(concatp->lhsp()); + Reduction* const rRedp = new Reduction{m_dfg, srcp->fileline(), m_bitDType}; + rRedp->srcp(concatp->rhsp()); - // Bitwise reduce the results - Bitwise* const replacementp = new Bitwise{m_dfg, flp, m_bitDType}; - replacementp->lhsp(lReducep); - replacementp->rhsp(rReducep); - vtxp->replaceWith(replacementp); + // Bitwise reduce the results + Bitwise* const replacementp = new Bitwise{m_dfg, flp, m_bitDType}; + replacementp->lhsp(lRedp); + replacementp->rhsp(rRedp); + vtxp->replaceWith(replacementp); - // Optimize the new reductions - optimizeReduction(lReducep); - optimizeReduction(rReducep); - return; + // Optimize the new reductions + optimizeReduction(lRedp); + optimizeReduction(rRedp); + return; + } } } @@ -433,25 +436,28 @@ class V3DfgPeephole final : public DfgVisitor { } } - // Not of Eq - if (DfgEq* const eqp = vtxp->srcp()->cast()) { - APPLYING(REPLACE_NOT_EQ) { - DfgNeq* const replacementp = new DfgNeq{m_dfg, eqp->fileline(), vtxp->dtypep()}; - replacementp->lhsp(eqp->lhsp()); - replacementp->rhsp(eqp->rhsp()); - vtxp->replaceWith(replacementp); - return; + if (!vtxp->srcp()->hasMultipleSinks()) { + // Not of Eq + if (DfgEq* const eqp = vtxp->srcp()->cast()) { + APPLYING(REPLACE_NOT_EQ) { + DfgNeq* const replacementp + = new DfgNeq{m_dfg, eqp->fileline(), vtxp->dtypep()}; + replacementp->lhsp(eqp->lhsp()); + replacementp->rhsp(eqp->rhsp()); + vtxp->replaceWith(replacementp); + return; + } } - } - // Not of Neq - if (DfgNeq* const neqp = vtxp->srcp()->cast()) { - APPLYING(REPLACE_NOT_NEQ) { - DfgEq* const replacementp = new DfgEq{m_dfg, neqp->fileline(), vtxp->dtypep()}; - replacementp->lhsp(neqp->lhsp()); - replacementp->rhsp(neqp->rhsp()); - vtxp->replaceWith(replacementp); - return; + // Not of Neq + if (DfgNeq* const neqp = vtxp->srcp()->cast()) { + APPLYING(REPLACE_NOT_NEQ) { + DfgEq* const replacementp = new DfgEq{m_dfg, neqp->fileline(), vtxp->dtypep()}; + replacementp->lhsp(neqp->lhsp()); + replacementp->rhsp(neqp->rhsp()); + vtxp->replaceWith(replacementp); + return; + } } } @@ -478,30 +484,32 @@ class V3DfgPeephole final : public DfgVisitor { FileLine* const flp = vtxp->fileline(); // Bubble pushing - if (DfgNot* const lhsNotp = lhsp->cast()) { - if (DfgNot* const rhsNotp = rhsp->cast()) { - APPLYING(REPLACE_AND_OF_NOT_AND_NOT) { - DfgOr* const orp = new DfgOr{m_dfg, flp, vtxp->dtypep()}; - orp->lhsp(lhsNotp->srcp()); - orp->rhsp(rhsNotp->srcp()); - DfgNot* const notp = new DfgNot{m_dfg, flp, vtxp->dtypep()}; - notp->srcp(orp); - vtxp->replaceWith(notp); - return; + if (!vtxp->hasMultipleSinks() && !lhsp->hasMultipleSinks() && !rhsp->hasMultipleSinks()) { + if (DfgNot* const lhsNotp = lhsp->cast()) { + if (DfgNot* const rhsNotp = rhsp->cast()) { + APPLYING(REPLACE_AND_OF_NOT_AND_NOT) { + DfgOr* const orp = new DfgOr{m_dfg, flp, vtxp->dtypep()}; + orp->lhsp(lhsNotp->srcp()); + orp->rhsp(rhsNotp->srcp()); + DfgNot* const notp = new DfgNot{m_dfg, flp, vtxp->dtypep()}; + notp->srcp(orp); + vtxp->replaceWith(notp); + return; + } } - } - if (DfgNeq* const rhsNeqp = rhsp->cast()) { - APPLYING(REPLACE_AND_OF_NOT_AND_NEQ) { - DfgOr* const orp = new DfgOr{m_dfg, flp, vtxp->dtypep()}; - orp->lhsp(lhsNotp->srcp()); - DfgEq* const newRhsp = new DfgEq{m_dfg, rhsp->fileline(), rhsp->dtypep()}; - newRhsp->lhsp(rhsNeqp->lhsp()); - newRhsp->rhsp(rhsNeqp->rhsp()); - orp->rhsp(newRhsp); - DfgNot* const notp = new DfgNot{m_dfg, flp, vtxp->dtypep()}; - notp->srcp(orp); - vtxp->replaceWith(notp); - return; + if (DfgNeq* const rhsNeqp = rhsp->cast()) { + APPLYING(REPLACE_AND_OF_NOT_AND_NEQ) { + DfgOr* const orp = new DfgOr{m_dfg, flp, vtxp->dtypep()}; + orp->lhsp(lhsNotp->srcp()); + DfgEq* const newRhsp = new DfgEq{m_dfg, rhsp->fileline(), rhsp->dtypep()}; + newRhsp->lhsp(rhsNeqp->lhsp()); + newRhsp->rhsp(rhsNeqp->rhsp()); + orp->rhsp(newRhsp); + DfgNot* const notp = new DfgNot{m_dfg, flp, vtxp->dtypep()}; + notp->srcp(orp); + vtxp->replaceWith(notp); + return; + } } } } @@ -561,30 +569,32 @@ class V3DfgPeephole final : public DfgVisitor { FileLine* const flp = vtxp->fileline(); // Bubble pushing - if (DfgNot* const lhsNotp = lhsp->cast()) { - if (DfgNot* const rhsNotp = rhsp->cast()) { - APPLYING(REPLACE_OR_OF_NOT_AND_NOT) { - DfgAnd* const andp = new DfgAnd{m_dfg, flp, vtxp->dtypep()}; - andp->lhsp(lhsNotp->srcp()); - andp->rhsp(rhsNotp->srcp()); - DfgNot* const notp = new DfgNot{m_dfg, flp, vtxp->dtypep()}; - notp->srcp(andp); - vtxp->replaceWith(notp); - return; + if (!vtxp->hasMultipleSinks() && !lhsp->hasMultipleSinks() && !rhsp->hasMultipleSinks()) { + if (DfgNot* const lhsNotp = lhsp->cast()) { + if (DfgNot* const rhsNotp = rhsp->cast()) { + APPLYING(REPLACE_OR_OF_NOT_AND_NOT) { + DfgAnd* const andp = new DfgAnd{m_dfg, flp, vtxp->dtypep()}; + andp->lhsp(lhsNotp->srcp()); + andp->rhsp(rhsNotp->srcp()); + DfgNot* const notp = new DfgNot{m_dfg, flp, vtxp->dtypep()}; + notp->srcp(andp); + vtxp->replaceWith(notp); + return; + } } - } - if (DfgNeq* const rhsNeqp = rhsp->cast()) { - APPLYING(REPLACE_OR_OF_NOT_AND_NEQ) { - DfgAnd* const andp = new DfgAnd{m_dfg, flp, vtxp->dtypep()}; - andp->lhsp(lhsNotp->srcp()); - DfgEq* const newRhsp = new DfgEq{m_dfg, rhsp->fileline(), rhsp->dtypep()}; - newRhsp->lhsp(rhsNeqp->lhsp()); - newRhsp->rhsp(rhsNeqp->rhsp()); - andp->rhsp(newRhsp); - DfgNot* const notp = new DfgNot{m_dfg, flp, vtxp->dtypep()}; - notp->srcp(andp); - vtxp->replaceWith(notp); - return; + if (DfgNeq* const rhsNeqp = rhsp->cast()) { + APPLYING(REPLACE_OR_OF_NOT_AND_NEQ) { + DfgAnd* const andp = new DfgAnd{m_dfg, flp, vtxp->dtypep()}; + andp->lhsp(lhsNotp->srcp()); + DfgEq* const newRhsp = new DfgEq{m_dfg, rhsp->fileline(), rhsp->dtypep()}; + newRhsp->lhsp(rhsNeqp->lhsp()); + newRhsp->rhsp(rhsNeqp->rhsp()); + andp->rhsp(newRhsp); + DfgNot* const notp = new DfgNot{m_dfg, flp, vtxp->dtypep()}; + notp->srcp(andp); + vtxp->replaceWith(notp); + return; + } } } } @@ -802,10 +812,11 @@ class V3DfgPeephole final : public DfgVisitor { vtxp->lsbp(makeI32(flp, lsb - rhsp->width())); } } else if (lsb == 0 || msb == concatp->width() - 1 // - || lhsp->is() || rhsp->is()) { + || lhsp->is() || rhsp->is() // + || !concatp->hasMultipleSinks()) { // If the select straddles both sides, but at least one of the sides is wholly - // selected, or at least one of the sides is a Const, then push the Sel past - // the Concat + // selected, or at least one of the sides is a Const, or this concat has no other + // use, then push the Sel past the Concat APPLYING(PUSH_SEL_THROUGH_CONCAT) { const uint32_t rSelWidth = rhsp->width() - lsb; const uint32_t lSelWidth = width - rSelWidth; @@ -1071,7 +1082,7 @@ class V3DfgPeephole final : public DfgVisitor { { DfgNot* const lNot = lhsp->cast(); DfgNot* const rNot = rhsp->cast(); - if (lNot && rNot) { + if (lNot && rNot && !lNot->hasMultipleSinks() && !rNot->hasMultipleSinks()) { APPLYING(PUSH_CONCAT_THROUGH_NOTS) { vtxp->lhsp(lNot->srcp()); vtxp->rhsp(rNot->srcp()); @@ -1177,38 +1188,45 @@ class V3DfgPeephole final : public DfgVisitor { } if (DfgNot* const condNotp = condp->cast()) { - APPLYING(SWAP_COND_WITH_NOT_CONDITION) { - vtxp->condp(condNotp->srcp()); - vtxp->thenp(elsep); - vtxp->elsep(thenp); - visit(vtxp); - return; + if (!condp->hasMultipleSinks() || condNotp->hasMultipleSinks()) { + APPLYING(SWAP_COND_WITH_NOT_CONDITION) { + vtxp->condp(condNotp->srcp()); + vtxp->thenp(elsep); + vtxp->elsep(thenp); + visit(vtxp); + return; + } } } if (DfgNeq* const condNeqp = condp->cast()) { - APPLYING(SWAP_COND_WITH_NEQ_CONDITION) { - DfgEq* const newCondp = new DfgEq{m_dfg, condp->fileline(), condp->dtypep()}; - newCondp->lhsp(condNeqp->lhsp()); - newCondp->rhsp(condNeqp->rhsp()); - vtxp->condp(newCondp); - vtxp->thenp(elsep); - vtxp->elsep(thenp); - visit(vtxp); - return; + if (!condp->hasMultipleSinks()) { + APPLYING(SWAP_COND_WITH_NEQ_CONDITION) { + DfgEq* const newCondp = new DfgEq{m_dfg, condp->fileline(), condp->dtypep()}; + newCondp->lhsp(condNeqp->lhsp()); + newCondp->rhsp(condNeqp->rhsp()); + vtxp->condp(newCondp); + vtxp->thenp(elsep); + vtxp->elsep(thenp); + visit(vtxp); + return; + } } } if (DfgNot* const thenNotp = thenp->cast()) { if (DfgNot* const elseNotp = elsep->cast()) { - APPLYING(PULL_NOTS_THROUGH_COND) { - DfgNot* const replacementp - = new DfgNot{m_dfg, thenp->fileline(), vtxp->dtypep()}; - vtxp->thenp(thenNotp->srcp()); - vtxp->elsep(elseNotp->srcp()); - vtxp->replaceWith(replacementp); - replacementp->srcp(vtxp); - return; + if ((!thenp->hasMultipleSinks() || thenNotp->hasMultipleSinks()) + && (!elsep->hasMultipleSinks() || elsep->hasMultipleSinks())) { + APPLYING(PULL_NOTS_THROUGH_COND) { + DfgNot* const replacementp + = new DfgNot{m_dfg, thenp->fileline(), vtxp->dtypep()}; + vtxp->thenp(thenNotp->srcp()); + vtxp->elsep(elseNotp->srcp()); + vtxp->replaceWith(replacementp); + replacementp->srcp(vtxp); + return; + } } } } diff --git a/test_regress/t/t_dfg_peephole.v b/test_regress/t/t_dfg_peephole.v index f7defa9b4..bc8251345 100644 --- a/test_regress/t/t_dfg_peephole.v +++ b/test_regress/t/t_dfg_peephole.v @@ -40,7 +40,6 @@ module t ( `signal(PUSH_BITWISE_OP_THROUGH_CONCAT, 32'h12345678 ^ {8'h0, rand_a[23:0]}); `signal(PUSH_BITWISE_OP_THROUGH_CONCAT_2, 32'h12345678 ^ {rand_b[7:0], rand_a[23:0]}); `signal(PUSH_COMPARE_OP_THROUGH_CONCAT, 4'b1011 == {2'b10, rand_a[1:0]}); - `signal(REMOVE_WIDTH_ONE_REDUCTION, &`DFG(rand_a[0])); `signal(PUSH_REDUCTION_THROUGH_COND_WITH_CONST_BRANCH, |(rand_a[32] ? rand_a[3:0] : 4'h0)); `signal(REPLACE_REDUCTION_OF_CONST_AND, &const_a); `signal(REPLACE_REDUCTION_OF_CONST_OR, |const_a); @@ -51,14 +50,14 @@ module t ( `signal(REPLACE_NOT_NEQ, ~`DFG(rand_a != rand_b)); `signal(REPLACE_NOT_EQ, ~`DFG(rand_a == rand_b)); `signal(REPLACE_NOT_OF_CONST, ~4'd0); - `signal(REPLACE_AND_OF_NOT_AND_NOT, ~rand_a[0] & ~rand_b[0]); - `signal(REPLACE_AND_OF_NOT_AND_NEQ, ~rand_a[0] & (rand_b != 64'd2)); + `signal(REPLACE_AND_OF_NOT_AND_NOT, ~rand_a[1] & ~rand_b[1]); + `signal(REPLACE_AND_OF_NOT_AND_NEQ, ~rand_a[2] & (rand_b != 64'd2)); `signal(REPLACE_AND_OF_CONST_AND_CONST, const_a & const_b); `signal(REPLACE_AND_WITH_ZERO, `ZERO & rand_a); `signal(REMOVE_AND_WITH_ONES, `ONES & rand_a); `signal(REPLACE_CONTRADICTORY_AND, rand_a & ~rand_a); - `signal(REPLACE_OR_OF_NOT_AND_NOT, ~rand_a[0] | ~rand_b[0]); - `signal(REPLACE_OR_OF_NOT_AND_NEQ, ~rand_a[0] | (rand_b != 64'd2)); + `signal(REPLACE_OR_OF_NOT_AND_NOT, ~rand_a[3] | ~rand_b[3]); + `signal(REPLACE_OR_OF_NOT_AND_NEQ, ~rand_a[4] | (rand_b != 64'd3)); `signal(REPLACE_OR_OF_CONCAT_ZERO_LHS_AND_CONCAT_RHS_ZERO, {2'd0, rand_a[1:0]} | {rand_b[1:0], 2'd0}); `signal(REPLACE_OR_OF_CONCAT_LHS_ZERO_AND_CONCAT_ZERO_RHS, {rand_a[1:0], 2'd0} | {2'd0, rand_b[1:0]}); `signal(REPLACE_OR_OF_CONST_AND_CONST, const_a | const_b); @@ -80,7 +79,7 @@ module t ( `signal(REPLACE_NESTED_CONCAT_OF_CONSTS_ON_LHS, {const_a, `DFG({const_b, rand_a})}); `signal(REPLACE_CONCAT_ZERO_AND_SEL_TOP_WITH_SHIFTR, {62'd0, rand_a[63:62]}); `signal(REPLACE_CONCAT_SEL_BOTTOM_AND_ZERO_WITH_SHIFTL, {rand_a[1:0], 62'd0}); - `signal(PUSH_CONCAT_THROUGH_NOTS, {~rand_a, ~rand_b} ); + `signal(PUSH_CONCAT_THROUGH_NOTS, {~(rand_a+64'd101), ~(rand_b+64'd101)} ); `signal(REMOVE_CONCAT_OF_ADJOINING_SELS, {`DFG(rand_a[10:3]), `DFG(rand_a[2:1])}); `signal(REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_LHS, {rand_a[10:3], {rand_a[2:1], rand_b}}); `signal(REPLACE_NESTED_CONCAT_OF_ADJOINING_SELS_ON_RHS, {`DFG({rand_b, rand_a[10:3]}), rand_a[2:1]}); @@ -97,12 +96,12 @@ module t ( `signal(PUSH_BITWISE_THROUGH_REDUCTION_AND, (&rand_a) & (&rand_b)); `signal(PUSH_BITWISE_THROUGH_REDUCTION_OR, (|rand_a) | (|rand_b)); `signal(PUSH_BITWISE_THROUGH_REDUCTION_XOR, (^rand_a) ^ (^rand_b)); - `signal(PUSH_REDUCTION_THROUGH_CONCAT_AND, &`DFG({rand_a, rand_b})); - `signal(PUSH_REDUCTION_THROUGH_CONCAT_OR, |`DFG({rand_a, rand_b})); - `signal(PUSH_REDUCTION_THROUGH_CONCAT_XOR, ^`DFG({rand_a, rand_b})); - `signal(REMOVE_WIDTH_ONE_REDUCTION_AND, &`DFG({randbit_a, rand_b})); - `signal(REMOVE_WIDTH_ONE_REDUCTION_OR, |`DFG({randbit_a, rand_b})); - `signal(REMOVE_WIDTH_ONE_REDUCTION_XOR, ^`DFG({randbit_a, rand_b})); + `signal(PUSH_REDUCTION_THROUGH_CONCAT_AND, &`DFG({(rand_a + 64'd102), rand_b})); + `signal(PUSH_REDUCTION_THROUGH_CONCAT_OR, |`DFG({(rand_a + 64'd103), rand_b})); + `signal(PUSH_REDUCTION_THROUGH_CONCAT_XOR, ^`DFG({(rand_a + 64'd104), rand_b})); + `signal(REMOVE_WIDTH_ONE_REDUCTION_AND, &`DFG({randbit_a ^ rand_a[0], rand_b})); + `signal(REMOVE_WIDTH_ONE_REDUCTION_OR, |`DFG({randbit_a ^ rand_a[1], rand_b})); + `signal(REMOVE_WIDTH_ONE_REDUCTION_XOR, ^`DFG({randbit_a ^ rand_a[2], rand_b})); `signal(REMOVE_XOR_WITH_ZERO, `ZERO ^ rand_a); `signal(REMOVE_XOR_WITH_ONES, `ONES ^ rand_a); `signal(REPLACE_COND_DEC, randbit_a ? rand_b - 64'b1 : rand_b);