Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

leo (5366)

leo
  (email not shown publicly)

Journal of leo (5366)

Saturday February 18, 2006
04:12 PM

Parrot: if vs. unless

[ #28727 ]

Parrot provides two opcodes to branch on the truthness of a register: if and unless. It looks like that it's just a matter of taste, which one to use. Is it really?

Not with modern CPUs with branch prediction rules and with JIT code inside tight inner loops. Below are two versions of the ackermann function, one written with if and one using unless. (If you are missing the loop in the code, well, that's coming from tailcall optimization, turned on with -Oc.)

$ cat ack-if.pir
.sub ack
  .param int x
  .param int y
  if x goto a1
    inc y
    .return (y)
a1:
  if y goto a2
    dec x
    .return ack(x, 1)
a2:
  dec y
  y = ack(x, y)
  dec x
  .return ack(x, y)
.end

$ cat ack-unless.pir
.sub ack
  .param int x
  .param int y
  unless x goto a1
  unless y goto a2
  dec y
  y = ack(x, y)
  dec x
  .return ack(x, y)
a1:
  inc y
  .return (y)
a2:
  dec x
  .return ack(x, 1)
.end

And here are the timings of both with ./parrot -Oc -Cj ack-xx.pir 12 on an AMD X2@2000:

ack-if      2.9 s
ack-unless  2.4 s

Branches with positive branch offsets (downwards) are considered to be likely not taken, that is the fall-through case is the default one. As there are a lot more positive numbers than the one zero, the unless is the better choice here (for some CPUs, YMMV). Well, that's at least my conclusion for now. But there is another issue: branch alignment. I've not yet experimented with different label alignments, but I know that alignment can cause timing differences like above too.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • But "if" cannot be replaced by "unless" and vice versa in every case. Witness:
    sub using_if {
      $value = 3;
      "bogus" if not $value;
    }
    sub using_unless {
      $value = 3;
      "bogus" unless $value;
    }
    my $result_if = using_if(); # will be "false" (result of "not $value")
    my $result_unless = using_unless(); # will be 3 (result of $value)
    A similar dichotomy results from "while" vs "until". So, both are needed.
    --
    • Randal L. Schwartz
    • Stonehenge
  • Since I am trying to get my code inline with "Perl Best Practices", "unless" is discouraged.
  • "Branches with positive branch offsets (downwards) are considered to be likely not taken, that is the fall-through case is the default one."

    Yup, this comes down to branch prediction in the CPU which is one of many performance tricks they do. You've probably guessed this, but they also expect that branches with negative branch offsets are likely to be taken, since they are probably loops. That means you're better off putting your termination test at the end of the loop, and to account for loops where you tes