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

Hello Monks

I recently inherited a code base that has some... interesting constructs.

For instance this one:

if ($var || 2) { # do stuff here } else { # won't do stuff }

Now, I know that the else will never execute because the conditional is always true. But what does the compiler do? I would think it would Optimize away the else, would it even optimize away the if? How can I see what is happening? O=Deparse only deparses and doesn't actually compile the code, right?

Thanks for the assistance

Replies are listed 'Best First'.
Re: Compiler Optimization
by BrowserUk (Patriarch) on Feb 24, 2015 at 19:41 UTC
    I would think it would Optimize away the else, would it even optimize away the if? How can I see what is happening?

    No, it isn't optimised away:

    C:\test>perl -MO=Deparse if ($var || 2) { # do stuff here } else { # won't do stuff } ^Z if ($var or 2) { (); } else { (); } - syntax OK

    Why not? Because (for example) $var might be a tied variable; which means that just referencing it could have (required) side-effects. Else why would the programmer have coded it that way.

    O=Deparse only deparses and doesn't actually compile the code, right?

    How could it deparse it before it had been compiled?

    This shows that if the compiler can optimise the code, the Deparse output will reflect that:

    C:\test>perl -MO=Deparse if( 2 ) { } else { } ^Z do { () }; - syntax OK

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
    In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked
    network sites:
      Why not? Because (for example) $var might be a tied variable

      The optimizing behaviour further suggests that it's possible that ($var || 2) can evaluate as false - otherwise I would expect that (at least) the else{} would be optimized away.
      This is something I've not previously considered and I'm stumped as to how ($var || 2) could be false. Can it ?

      Cheers,
      Rob
        The optimizing behaviour further suggests that it's possible that ($var || 2) can evaluate as false - otherwise I would expect that (at least) the else{} would be optimized away.

        You're giving the optimiser too much credit.

        (I think; on the basis of the behaviour I've observed rather than analysis of the code) the optimiser has a relatively simple rule: if a conditional expression is a simple compile-time constant, it will optimise away any code that will never be reached as a result. Full stop.

        It doesn't make any attempt to reduce a non-simple expression to a simple one:

        $x = 1; if( $x ) { } else { } ^Z $x = 1; if ($x) { (); } else { (); } - syntax OK

        Even:

        C:\Users\HomeAdmin>perl -MO=Deparse my $x = 1; if($x, 1){ } else{ } ^Z my $x = 1; if ($x, 1) { (); } else { (); } - syntax OK

        Given that both branches of the if are empty; both of those ought to be reduced to just:$x;, just to cover the tied var side-effect case.

        I think that the reality is not "the optimiser", but rather "a few, simple, optimisations".

        There are hundreds of possibilities for compile time optimisations, but whilst the structure and formatting of the code remains so messy; it takes brave men to venture there looking for them.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
        In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked
        > to how ($var || 2) could be false. Can it

        Nope, but a method of a tied variable could raise an exception or goto label.

        A tied variable could also have side effects, like logging each access.

        IOW the FETCH can't be short circuited, even if the result is of no interest.

        Anyway optimizer rules are very simplistic, and if wanted such exotic edge cases could be forbidden in documentation.

        Tied variables are hell for any optimizer, I remember a talk of Reini Urban in Kiev where he presented details of his optimizer with factor 2 speed gain. I was so puzzled how one technique works and asked how this can handle tied variables.

        His answer was simple: tied variables are not allowed! :)

        Anyway JS shows that JIT compiling is the way to go.

        (NB no tied vars in ECMA JS)

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)

        PS: Je suis Charlie!

        update

        There are several cases where optimization already causes strange effects.

        For instance try to goto into a code chunk which is optimized away with 'if(0)'

Re: Compiler Optimization
by Anonymous Monk on Feb 24, 2015 at 19:49 UTC
    O=Deparse only deparses and doesn't actually compile the code, right?

    The first sentence B::Deparse's description (emphasis mine):

    B::Deparse is a backend module for the Perl compiler that generates perl source code, based on the internal compiled structure that perl itself creates after parsing a program.
    But what does the compiler do?

    Try it out:

    $ perl -MO=Deparse -e 'if($var||2) {print "foo"} else {print "bar"}' if ($var or 2) { print 'foo'; } else { print 'bar'; } -e syntax OK $ perl -MO=Deparse -e 'if(2) {print "foo"} else {print "bar"}' do { print 'foo' }; -e syntax OK

    In the second example you see the code being compiled away.