ikegami has asked for the wisdom of the Perl Monks concerning the following question:

When return is the last op of a function, is there a reason it isn't removed from the tree such that
>perl -MO=Concise,f -e"sub f { return $x }" main::f: 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[*x] s ->4 -e syntax OK

looks like

main::f: 3 <1> leavesub[1 ref] K/REFC,1 ->(end) - <@> lineseq KP ->5 1 <;> nextstate(main 1 -e:1) v ->2 - <@> ex-return K ->- - <0> ex-pushmark s ->- - <1> ex-rv2sv sK/1 ->- 2 <#> gvsv[*x] s ->3 -e syntax OK

which would be equivalent to

>perl -MO=Concise,f -e"sub f { $x }" main::f: 3 <1> leavesub[1 ref] K/REFC,1 ->(end) - <@> lineseq KP ->3 1 <;> nextstate(main 1 -e:1) v ->2 - <1> ex-rv2sv sK/1 ->- 2 <#> gvsv[*x] s ->3 -e syntax OK

Just curious. There's no speed penalty to leaving it in

5.8.8: Rate implicit explicit implicit 980/ms -- -0% explicit 984/ms 0% -- 5.10.0: Rate explicit implicit explicit 1000/ms -- -0% implicit 1004/ms 0% --

Benchmark code

Replies are listed 'Best First'.
Re: Why isn't return removed from optree?
by chromatic (Archbishop) on Dec 29, 2008 at 08:29 UTC

    Reading through pp_return confirmed my initial guess that the return opcode checks the calling context and performs the appropriate stack manipulations. I don't think you can avoid that, but I'm not completely certain.

      I don't think you can avoid that, but I'm not completely certain.

      You might have to remove the pushmark along with the return. When you do that, you get exactly the same opcode tree as if you hadn't used the return keyword, so it's obviously safe.

        Ah-ha! I found a situation where return can't simply be omitted.

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

        That gives me something to look at.

Re: Why isn't return removed from optree?
by ccn (Vicar) on Dec 29, 2008 at 06:45 UTC
    What is the reason to make an optimization if there is no speed nor memory gain in result?

      Don't know, but it wouldn't be the only one. For example, list is a no-op in list context

      PP(pp_list) { dVAR; dSP; dMARK; if (GIMME != G_ARRAY) { if (++MARK <= SP) *MARK = *SP; /* unwanted list, return last item */ else *MARK = &PL_sv_undef; SP = MARK; } RETURN; }

      so why is it optimized away for being used in list context?

      >perl -MO=Concise -e"$x = (1,2)" 8 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v ->3 7 <2> sassign vKS/2 ->8 5 <@> list sKP ->6 3 <0> pushmark v ->4 - <0> ex-const v ->4 4 <$> const[IV 2] s ->5 - <1> ex-rv2sv sKRM*/1 ->7 6 <#> gvsv[*x] s ->7 -e syntax OK >perl -MO=Concise -e"@x = (1,2)" a <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v ->3 9 <2> aassign[t3] vKS ->a - <1> ex-list lKP ->6 3 <0> pushmark s ->4 4 <$> const[IV 1] s ->5 5 <$> const[IV 2] s ->6 - <1> ex-list lK ->9 6 <0> pushmark s ->7 8 <1> rv2av[t2] lKRM*/1 ->9 7 <#> gv[*x] s ->8 -e syntax OK

      I would expect some consistency.