|
|
||
日記内の"morihyphen.hp.infoseek.co.jp"へのリンクは切れてます。必要な場合はお手数ですが int.main.jp へ書き換えをお願いします。
TODO: ファイル名確認を忘れないこと > 自分
大阪人…というように、今留守であることを書いておくのは、セキュリティの観点からよろしくないのではという気が。
http://www.pqrs.org/~tekezo/nikki/2006/08/15.html#y2006m08d15c1p2
なんだか面白そうなので調査。
まず、予想としては、中間形式での最適化時に__builtin_expectがただの関数扱いされて、最適化を控えているのではないかと思われます。
と、そういう感じではないかと。この場合だと、if ( bi == NULL )のほうは、ループ用の最適化をしてて、__builtin_expectのほうはそれをやってない感じですかね。
ループが変形してるのは、ループ脱出条件の最適化としては、結構簡単にできる有名な奴ではないかと思われます。
while ( cond ) {
....
loop_body;
....
}
ていうのは、普通にコンパイルすれば
... loop_begin: cmp cond jcc exit loop_body: ... ( ループ内処理 ) jmp loop_begin exit: ...
こんな感じ。ですが、これを
jmp loop_cond loop_body: ... ( ループ内処理 ) loop_cond cmp cond jcc loop_body # 条件ジャンプを後ろにする exit: ...
こんな風にしてやれば、ループ中の分岐が「条件分岐 + 無条件」から、「条件分岐一個」に減らせます。
と、思ったけど、よく見てみたら、continueがあるのでなんか違うような気がしてきましたが、「通常時」のほうの、eaeの前の命令が、「b ec6」もしくは、「NULLチェックしてループ処理飛ばす」みたいな感じだと、なんかそれに近いことをやってるんだと思います。(適当)
ただ、この最適化をやるには、「どこらへんがループで、どれが脱出条件か」というのを見つけないというのがあって、__builtin_expectを使ったほうは、多分、そこらへんができてないのではないかと。
対処法としては、手元にあった、GCC4.1の場合、
for ( ; __builtin_expect(nanika!=NULL,1); ) {
// ループ処理
}
こんなふうにしてやれば、Cフロントエンドが「forループ→中間形式」変換時に上のループ最適化をやってくれるようなのでなんとかなるようです。
(うーん…ていうことは、多少汚くなっても無理矢理forとかwhile使ったほうがいいってことなのか…?僕はbreak使うほうが好きなんだけど…)
あと、__builtin_expectは、PowerPCみたいな条件分岐に命令に直接分岐ヒント付けられるCPUじゃないとあんまり効果が無いような気がしたんですが、そこらへんは、誰か偉い人が。