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
.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)
$ cat ack-unless.pir
.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)
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.
Not sure if this appears at the Parrot level... (Score:2)
PBP (Score:1)
Also... (Score:1)
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