Optimise out PUSHMARK/RETURN if return is the last statement in a sub.
authorMatthew Horsfall <WolfSage@gmail.com>
Wed, 11 Dec 2013 23:28:21 +0000 (18:28 -0500)
committerSteffen Mueller <smueller@cpan.org>
Fri, 13 Dec 2013 17:15:30 +0000 (18:15 +0100)
commit437e3a7dac994ebace1195549170c81f474d9c20
tree86a8fd6b0a36e0fb66683a245cfdb1d9deb43b78
parent4b76cb9db827e0f9f047de33ae98ca8b86be8260
Optimise out PUSHMARK/RETURN if return is the last statement in a sub.

This makes:

  sub baz { return $cat; }

Behave like:

  sub baz { $cat; }

Which is notably faster.

Unpatched:

  ./perl -Ilib/ ~/stuff/bench.pl
  Benchmark: timing 40000000 iterations of normal, ret...
    normal:  3 wallclock secs ( 1.60 usr +  0.01 sys =  1.61 CPU) @ 24844720.50/s (n=40000000)
       ret:  3 wallclock secs ( 2.08 usr +  0.00 sys =  2.08 CPU) @ 19230769.23/s (n=40000000)

Patched:

  ./perl -Ilib ~/stuff/bench.pl
  Benchmark: timing 40000000 iterations of aret, normal...
    normal:  2 wallclock secs ( 1.72 usr +  0.00 sys =  1.72 CPU) @ 23255813.95/s (n=40000000)
       ret:  2 wallclock secs ( 1.72 usr +  0.00 sys =  1.72 CPU) @ 23255813.95/s (n=40000000)

The difference in OP trees can be seen here:

Unpatched:

  $ perl  -MO=Concise,baz -e 'sub baz { return $cat }'
  main::baz:
  5  <1> leavesub[1 ref] K/REFC,1 ->(end)
  -     <@> lineseq KP ->5
  1        <;> nextstate(main 1 -e:1) v ->2
  4        <@> return K ->5
  2           <0> pushmark s ->3
  -           <1> ex-rv2sv sK/1 ->4
  3              <#> gvsv[*cat] s ->4
  -e syntax OK

Patched:

  $ ./perl -Ilib  -MO=Concise,baz -e 'sub baz { return $cat }'
  main::baz:
  3  <1> leavesub[1 ref] K/REFC,1 ->(end)
  -     <@> lineseq KP ->3
  1        <;> nextstate(main 1 -e:1) v ->2
  -        <@> return K ->-
  -           <0> pushmark s ->2
  -           <1> ex-rv2sv sK/1 ->-
  2              <$> gvsv(*cat) s ->3
  -e syntax OK

(Includes some modifications from Steffen)
ext/B/t/optree_samples.t
op.c
op.h