[Perl/perl5] 939d20: Add OP_REF_CMP to optimize (ref $x eq/ne 'SCALAR')...

[email protected] (Richard Leach via perl5-changes) Mon, 27 Jul 2026 03:05:59 -0700
Newsgroups perl.perl5.changes
Message-ID <Perl/perl5/push/refs/heads/blead/[email protected]>
  Branch: refs/heads/blead
  Home:   https://github.com/Perl/perl5
  Commit: 939d200deae641b5f24bb5cc2d5e3731cd30f3c0
      https://github.com/Perl/perl5/commit/939d200deae641b5f24bb5cc2d5e3731cd30f3c0
  Author: Richard Leach <[email protected]>
  Date:   2026-07-27 (Mon, 27 Jul 2026)

  Changed paths:
    M ext/B/t/b.t
    M ext/Opcode/Opcode.pm
    M lib/B/Deparse.pm
    M lib/B/Deparse.t
    M lib/B/Op_private.pm
    M op.c
    M opcode.h
    M opnames.h
    M peep.c
    M pp.c
    M pp_proto.h
    M regen/embed.pl
    M regen/op_private
    M regen/opcodes
    M sv.c
    M t/op/ref.t
    M t/perf/benchmarks
    M t/perf/opcount.t

  Log Message:
  -----------
  Add OP_REF_CMP to optimize (ref $x eq/ne 'SCALAR') patterns

Finding value of `ref`, comparing it to a specific one of Perl's
builtin types, and doing something with that boolean result is
currently a fair bit of work.

    if (ref $x eq 'SCALAR) { # do something }

or

    if (ref $x ne 'SCALAR) { # do something }

The type of `$x` has to be determined and the string value for it
pushed onto the stack, the value to compare it to is also pushed,
a string comparison is then performed, with `&PL_sv_yes` or
`&PL_sv_no` put on the stack to be consumed by a LOGOP in order to
determine the control flow.

The optree looks something like this:

    4     <;> nextstate(main 2 -e:1) v:{ ->5
    -     <1> null vK/1 ->d
    9        <|> and(other->a) vK/1 ->d
    8           <2> seq sKP/2 ->9
    6              <1> ref[t2] sK/1 ->7
    5                 <0> padsv[$x:1,2] s ->6
    7              <$> const[PV "SCALAR"] s/BARE ->8

This commit instead adds an OP_REF_CMP optimization, generating
an optree like this instead:

    4     <;> nextstate(main 2 -e:1) v:{ ->5
    -     <1> null vK/1 ->b
    7        <|> and(other->8) vK/1 ->b
    6           <1> ref_cmp sKP/SCALAR,SKIPLOGOP,AND ->7
    5              <0> padsv[$x:1,2] s ->6

OP_REF_CMP determines the type of the operand, more efficiently
compares it to the desired type (baked into the OP's flags),
and directly calls the `op_other` or `op_next` of the LOGOP.

The existing classname handling behaviour is preserved.

    $x = bless {}, "ARRAY";
    if (ref $x eq "ARRAY") {} # This *is* still true.

This commit also optimizes the same sort of patterns that use `reftype`
instead of `ref`. The behaviour differences between the two are
preserved.

As there were spare bits available, some additional common comparators
have also been baked in:
* `Regexp` - for the `qr//` case with `ref`
* `''` - the empty string


  Commit: f7504b2b932ed510a2d733413e7848d452cb840f
      https://github.com/Perl/perl5/commit/f7504b2b932ed510a2d733413e7848d452cb840f
  Author: Richard Leach <[email protected]>
  Date:   2026-07-27 (Mon, 27 Jul 2026)

  Changed paths:
    M embed.fnc
    M embed.h
    M ext/B/Makefile.PL
    M lib/B/Deparse.pm
    M lib/B/Op_private.pm
    M op.c
    M opcode.h
    M pp.c
    M proto.h
    M regen/embed.pl
    M regen/op_private
    M sv.c
    M sv.h

  Log Message:
  -----------
  Add PL_sv_reftype_lookup & Perl_sv_reftype_id

To avoid duplication of "what reference type is this?" logic across
`Perl_sv_reftype` and `pp_ref_cmp`, this commit:

* Renames `OPpREF_CMP_*` constants to `SVrt_*` equivalents
* Adds a `PL_sv_reftype_lookup` table ordered to match those constants
* Adds a `Perl_sv_reftype_id` function that takes the logic from
  `Perl_sv_reftype` but returns only an index ID value
* `Perl_sv_reftype` uses that new function and table to return strings
* `pp_ref_cmp` uses the function and compares to the expected ID value


  Commit: d97ad8ae554909fd88d9c2a84108c4aa446553f9
      https://github.com/Perl/perl5/commit/d97ad8ae554909fd88d9c2a84108c4aa446553f9
  Author: Richard Leach <[email protected]>
  Date:   2026-07-27 (Mon, 27 Jul 2026)

  Changed paths:
    M pod/perldelta.pod

  Log Message:
  -----------
  perldelta for OP_REF_CMP


Compare: https://github.com/Perl/perl5/compare/acdbee4511e9...d97ad8ae5549

To unsubscribe from these emails, change your notification settings at https://github.com/Perl/perl5/settings/notifications