Perl 5.20 optimizes return at the end of a subroutine

Want to save 10 nanoseconds? Perl v5.20 optimizes a return at the end of a subroutine to use two fewer ops in the optimized version. During compilation, a subroutine like this one:


sub some_sub { ...; return $foo }

turns into a subroutine like this one, without the return

sub some_sub { ...; $foo }

You can see the difference in the output from the B::Concise module (which you can use through the O frontend). Prior to v5.20, there are five steps to return the first argument:

$ perl5.18.0 -MO=Concise,baz,-exec -e 'sub baz { return $_[0] }'
main::baz:
1  <;> nextstate(main 1 -e:1) v
2  <0> pushmark s
3  <$> aelemfast(*_) s
4  <@> return K
5  <1> leavesub[1 ref] K/REFC,1
-e syntax OK

But, prior to v5.20, if you didn’t use the return keyword, there are only three steps after the PUSHMARK isn’t there:

$ perl5.18.0 -MO=Concise,baz,-exec -e 'sub baz { $_[0] }'
main::baz:
1  <;> nextstate(main 1 -e:1) v
2  <$> aelemfast(*_) s
3  <1> leavesub[1 ref] K/REFC,1
-e syntax OK

You can read about PUSHMARK in the perlcall documentation. It’s a signal to perl to remember where the current stack pointer is.

With v5.20, perl optimizes the return version to have the same steps:

$ perl5.20.0 -MO=Concise,baz,-exec -e 'sub baz { return $_[0] }'
main::baz:
1  <;> nextstate(main 1 -e:1) v
2  <$> aelemfast(*_) s
3  <1> leavesub[1 ref] K/REFC,1
-e syntax OK

$ perl5.20.0 -MO=Concise,baz,-exec -e 'sub baz { $_[0] }'
main::baz:
1  <;> nextstate(main 1 -e:1) v
2  <$> aelemfast(*_) s
3  <1> leavesub[1 ref] K/REFC,1
-e syntax OK

This will be happy news to people who stick to Perl Best Practices, which recommends that you always use an explicit return. Damian’s recommendation is to denote intent, but now you don’t suffer if it’s the last statement in the subroutine.