PowerPCの条件分岐について
PowerPCアセンブリと戯れていると,x86アセンブリでは見かけないようなものがちらほらと散見される.その中でも,個人的に気になり面白いと思った条件分岐の1トピックについて取り上げてみようと思う.
x86でいうjmp系の命令はPowerPCではbranch系の命令になる.このbranch命令の末尾に"+"が付くことがある.参考文献には以下の記述がある.
On most conditional branch instructions, appending a + to the instruction will signal to the branch processor that this branch will probably be taken.
つまり,基本的に分岐するであろう分岐命令には"+"をつけることでプロセッサに明示的に伝えられるということである."+"があるなら"-"もあるわけで,きちんと記述されている.
Appending a - to the instruction will signal that this branch will probably not be taken.
しかし,どうやら明示的に書かずともPOWER5 CPU以降は分良く分岐予測をしてくれるとのこと.
もちろん"+", "-"の違いで吐き出されるバイナリは異なる.最高.
個人的にこのプラスマイナス問題がとても気になったので,この2つで違いが生じるのかを確かめる簡単な実験をしてみた.
やったことはシンプルで概要は以下の通りである.
・多くループさせるような計算をさせる
・ループの分岐命令に"+", "-"の2通りを用いた関数をそれぞれ用意する
・それぞれを実行し,それらの実行時間を計測する
実験を行うために,配列の総和を計算する簡単なアセンブリプログラムを作成した.以下の通りである.違いは後半の分岐に"+"を使っているか"-"を使っているかだけである.これをCell Broadband Engineで実行させた.
add_array_asm_plus:
li 0, 32767
mtctr 0
mr 9, 3
xor 3, 3, 3
xor 10, 10, 10
lwzx 0, 9, 10
add 3, 3, 0
addi 10, 10, 4
bdnz+ -0xc
blr
add_array_asm_minus:
li 0, 32767
mtctr 0
mr 9, 3
xor 3, 3, 3
xor 10, 10, 10
lwzx 0, 9, 10
add 3, 3, 0
addi 10, 10, 4
bdnz- -0xc
blr
これらの関数を10000回呼び出して計算させた.実験結果は以下の通りになった.
./a.out
add_array_asm_minus = 536854528
time = 1.141511 [s]
add_array_asm_plus = 536854528
time = 1.147471 [s]
1から32767までの総和を求めたが,結果も正しく出ていることが確認できた.そして肝心の実行時間であるが,ほとんど差が見られない結果となった.複数回実行して見たが似たような結果であった.
実験したあとで気付いたが,世代による違いの他にもパソコン向けのPowerPCとは異なるCell Broadband Engineを用いたためではないかとか,一概に言えない部分もあるが,これはこれで一つ実験による知見が得られた.アセンブリ楽しい.