From c74a928a43322c574522f122a3f3a29262f90613 Mon Sep 17 00:00:00 2001 From: Richard Leach Date: Sun, 7 Aug 2022 23:34:42 +0000 Subject: Add OPpTARGET_MY optimization to OP_UNDEF This allows the existing `undef` OP to act on a pad SV. The following two cases are optimized: `undef my $x`, currently implemented as: 4 <1> undef vK/1 ->5 3 <0> padsv[$x:1,2] sRM/LVINTRO ->4 `my $a = undef`, currently implemented as: 5 <2> sassign vKS/2 ->6 3 <0> undef s ->4 4 <0> padsv[$x:1,2] sRM*/LVINTRO ->5 These are now just represented as: 3 <1> undef[$x:1,2] vK/SOMEFLAGS ->4 Note: The two cases are not quite functionally identical, as `$x = undef` clears the SV flags but preserves any PV allocation for later reuse, whereas `undef $x` does free any PV allocation. This behaviour difference is preserved through use of the OPpUNDEF_KEEP_PV flag. --- peep.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'peep.c') diff --git a/peep.c b/peep.c index d7e618d0c0..41bb46d7e7 100644 --- a/peep.c +++ b/peep.c @@ -3775,6 +3775,58 @@ Perl_rpeep(pTHX_ OP *o) break; } + case OP_UNDEF: + if ((o->op_flags & OPf_KIDS) && + (cUNOPx(o)->op_first->op_type == OP_PADSV)) { + + /* Convert: + * undef + * padsv[$x] + * to: + * undef[$x] + */ + + OP * padsv = cUNOPx(o)->op_first; + o->op_private = OPpTARGET_MY | + (padsv->op_private & (OPpLVAL_INTRO|OPpPAD_STATE)); + o->op_targ = padsv->op_targ; padsv->op_targ = 0; + op_null(padsv); + /* Optimizer does NOT seem to fix up the padsv op_next ptr */ + if (oldoldop) + oldoldop->op_next = o; + oldop = oldoldop; + oldoldop = NULL; + + } else if (o->op_next->op_type == OP_PADSV) { + OP * padsv = o->op_next; + OP * sassign = (padsv->op_next && + padsv->op_next->op_type == OP_SASSIGN) ? + padsv->op_next : NULL; + if (sassign && cBINOPx(sassign)->op_first == o) { + /* Convert: + * sassign + * undef + * padsv[$x] + * to: + * undef[$x] + * NOTE: undef does not have the "T" flag set in + * regen/opcodes, as this would cause + * S_maybe_targlex to do the optimization. + * Seems easier to keep it all here, rather + * than have an undef-specific branch in + * S_maybe_targlex just to add the + * OPpUNDEF_KEEP_PV flag. + */ + o->op_private = OPpTARGET_MY | OPpUNDEF_KEEP_PV | + (padsv->op_private & (OPpLVAL_INTRO|OPpPAD_STATE)); + o->op_targ = padsv->op_targ; padsv->op_targ = 0; + op_null(padsv); + op_null(sassign); + /* Optimizer DOES seems to fix up the op_next ptrs */ + } + } + break; + case OP_QR: case OP_MATCH: if (!(cPMOP->op_pmflags & PMf_ONCE)) { -- cgit v1.2.1