From 5dcd500a0f64c7b50ab6236f2e2f6654b8e73fdf Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Fri, 13 Feb 2026 14:25:06 +0000 Subject: [PATCH] Optimize additional Dfg peephole Shift and Concat patterns --- src/V3DfgPeephole.cpp | 75 +++++++++++++++++++++++++++++++++ src/V3DfgPeepholePatterns.h | 4 ++ test_regress/t/t_dfg_peephole.v | 6 +++ 3 files changed, 85 insertions(+) diff --git a/src/V3DfgPeephole.cpp b/src/V3DfgPeephole.cpp index 6ca05983a..afc9f628c 100644 --- a/src/V3DfgPeephole.cpp +++ b/src/V3DfgPeephole.cpp @@ -1306,6 +1306,44 @@ class V3DfgPeephole final : public DfgVisitor { } } + if (DfgConst* const lConstp = lhsp->cast()) { + if (DfgCond* const rCondp = rhsp->cast()) { + if (!rCondp->hasMultipleSinks()) { + DfgVertex* const rtVtxp = rCondp->thenp(); + DfgVertex* const reVtxp = rCondp->elsep(); + APPLYING(PUSH_CONCAT_THROUGH_COND_LHS) { + DfgConcat* const thenp + = make(rtVtxp->fileline(), vtxp->dtype(), lConstp, rtVtxp); + DfgConcat* const elsep + = make(reVtxp->fileline(), vtxp->dtype(), lConstp, reVtxp); + DfgCond* const replacementp + = make(vtxp, rCondp->condp(), thenp, elsep); + replace(vtxp, replacementp); + return; + } + } + } + } + + if (DfgConst* const rConstp = rhsp->cast()) { + if (DfgCond* const lCondp = lhsp->cast()) { + if (!lCondp->hasMultipleSinks()) { + DfgVertex* const ltVtxp = lCondp->thenp(); + DfgVertex* const leVtxp = lCondp->elsep(); + APPLYING(PUSH_CONCAT_THROUGH_COND_RHS) { + DfgConcat* const thenp + = make(ltVtxp->fileline(), vtxp->dtype(), ltVtxp, rConstp); + DfgConcat* const elsep + = make(leVtxp->fileline(), vtxp->dtype(), leVtxp, rConstp); + DfgCond* const replacementp + = make(vtxp, lCondp->condp(), thenp, elsep); + replace(vtxp, replacementp); + return; + } + } + } + } + // Attempt to narrow a concatenation that produces unused bits on the edges { const uint32_t vMsb = vtxp->width() - 1; // MSB of the concatenation @@ -1523,6 +1561,43 @@ class V3DfgPeephole final : public DfgVisitor { void visit(DfgShiftL* vtxp) override { if (foldBinary(vtxp)) return; if (optimizeShiftRHS(vtxp)) return; + + DfgVertex* const lhsp = vtxp->lhsp(); + DfgVertex* const rhsp = vtxp->rhsp(); + + if (DfgConst* const rConstp = rhsp->cast()) { + if (DfgConcat* const lConcatp = lhsp->cast()) { + if (!lConcatp->hasMultipleSinks() + && lConcatp->lhsp()->width() == rConstp->toU32()) { + APPLYING(REPLACE_SHIFTL_CAT) { + DfgConcat* const replacementp = make( + vtxp, lConcatp->rhsp(), + makeZero(lConcatp->fileline(), lConcatp->lhsp()->width())); + replace(vtxp, replacementp); + return; + } + } + } + + if (DfgShiftR* const lShiftRp = lhsp->cast()) { + if (!lShiftRp->hasMultipleSinks() && isSame(rConstp, lShiftRp->rhsp())) { + if (DfgConcat* const llConcatp = lShiftRp->lhsp()->cast()) { + const uint32_t shiftAmount = rConstp->toU32(); + if (!llConcatp->hasMultipleSinks() + && llConcatp->rhsp()->width() == shiftAmount) { + APPLYING(REPLACE_SHIFTRL_CAT) { + DfgConst* const zerop + = makeZero(llConcatp->fileline(), shiftAmount); + DfgConcat* const replacementp + = make(vtxp, llConcatp->lhsp(), zerop); + replace(vtxp, replacementp); + return; + } + } + } + } + } + } } void visit(DfgShiftR* vtxp) override { diff --git a/src/V3DfgPeepholePatterns.h b/src/V3DfgPeepholePatterns.h index a0d5ee059..cd234e1b5 100644 --- a/src/V3DfgPeepholePatterns.h +++ b/src/V3DfgPeepholePatterns.h @@ -40,6 +40,8 @@ _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_BITWISE_OP_THROUGH_CONCAT) \ _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_BITWISE_THROUGH_REDUCTION) \ _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_COMPARE_OP_THROUGH_CONCAT) \ + _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_CONCAT_THROUGH_COND_LHS) \ + _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_CONCAT_THROUGH_COND_RHS) \ _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_CONCAT_THROUGH_NOTS) \ _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_NOT_THROUGH_COND) \ _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, PUSH_REDUCTION_THROUGH_CONCAT) \ @@ -96,6 +98,8 @@ _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_OF_NOT_AND_NOT) \ _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_OR_WITH_ONES) \ _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_SEL_FROM_SEL) \ + _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_SHIFTL_CAT) \ + _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_SHIFTRL_CAT) \ _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_SUB_WITH_NOT) \ _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_TAUTOLOGICAL_OR) \ _FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION_APPLY(macro, REPLACE_TAUTOLOGICAL_OR_3) \ diff --git a/test_regress/t/t_dfg_peephole.v b/test_regress/t/t_dfg_peephole.v index c757612e9..0b182343b 100644 --- a/test_regress/t/t_dfg_peephole.v +++ b/test_regress/t/t_dfg_peephole.v @@ -245,6 +245,12 @@ module t ( end `signal(PUSH_SEL_THROUGH_SPLICE, sel_from_partial_tmp[1:0]); + `signal(PUSH_CONCAT_THROUGH_COND_LHS, {5'd0, rand_a[0] ? {rand_b[4], 1'b0} : {1'b0, rand_b[6]}}); + `signal(PUSH_CONCAT_THROUGH_COND_RHS, {rand_a[0] ? {rand_b[5], 1'b0} : {1'b0, rand_b[7]}, 5'd0}); + + `signal(REPLACE_SHIFTL_CAT, {31'd0, rand_a[42 +: 7]} << 31); + `signal(REPLACE_SHIFTRL_CAT, {rand_a[13 +: 7], rand_b[8 +: 27]} >> 27 << 27); + // Asscending ranges `signal(ASCENDNG_SEL, arand_a[0:4]); // verilator lint_off ASCRANGE