ToDo:
http://alohakun.blog7.fc2.com/blog-entry-878.html
を見てたしかにどういう感じなのかなーと。
たぶん stmt.c の expand_case @gcc-4.2.2 。
最初に unique ならラベルの数とか適当に調べて、 default 以外ターゲットなかったらそこに jump とか。
んで bit なんちゃらがどうこうってのが入ってんだけど、 よくわからんかったからぐぐったら これ面白いな。
http://gcc.gnu.org/ml/gcc-patches/2003-01/msg01733.html
int main(int i) {
switch (i) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
return 1;
}
return 0;
}
こんなんを
subl $48, %ecx # とりあえず '0' をひく
cmpl $22, %ecx # 22 よりでかけりゃ ('F'-'0' == 22)
ja .L2 # 範囲外なので 0 返すところにゴー
movl $1, %eax
movl $1, %edx
sall %cl, %eax # 1 << (i - '0') を計算
testl $8258559, %eax # 0b11111100000001111111111 で bitmask
je .L2 # ビット立ってなきゃ 0 を返す
popl %ecx # 1 返す
movl %edx, %eax
popl %ebp
leal -4(%ecx), %esp
ret
.p2align 4,,7
.L2:
popl %ecx
xorl %edx, %edx
popl %ebp
movl %edx, %eax
leal -4(%ecx), %esp
ret
ほえーすごい。
あとは下記のような条件でテーブルジャンプにならないみたいだ。 case_values_threshold はアーキテクチャ依存で 4 か 5 で、 値の数字の範囲が最適化時は case の数の 10 倍よりデカけりゃ table 化する、って感じか。 あとは細かい話だろう。
else if (count < case_values_threshold ()
|| compare_tree_int (range,
(optimize_size ? 3 : 10) * count) > 0
/* RANGE may be signed, and really large ranges will show up
as negative numbers. */
|| compare_tree_int (range, 0) < 0
#ifndef ASM_OUTPUT_ADDR_DIFF_ELT
|| flag_pic
#endif
|| !flag_jump_tables
|| TREE_CONSTANT (index_expr)
/* If neither casesi or tablejump is available, we can
only go this way. */
|| (!HAVE_casesi && !HAVE_tablejump))
つまり
int main(int i) {
switch (i) {
case 0:
return 1;
case 1:
return 9;
case 2:
return 6546;
case 3:
return 4534;
case 50:
return 4324;
}
return 0;
}
が限界みたいな感じか。 これだと約 200 Byte くらいのテーブル作るから -Os の時は作られない。 で -Os なら 3 倍が限度なので 15 まで、って感じだな。
なんか読んだ通りの動きしてくれると嬉しいね。
(13:11)
| 前 | 2007年 11月 |
次 | ||||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | |
全てリンクフリーです。 コード片は自由に使用していただいて構いません。 その他のものはGPL扱いであればあらゆる使用に関して文句は言いません。 なにかあれば下記メールアドレスへ。
swtich 文のジャンプテーブル展開は (1)case ラベルの最小と最大からジャンプテーブルを仮作成 (2)テーブルの充填率を計算して一定以下ならテーブル分割 (3)テーブル群への分岐ツリーを配置、がセオリーだと思っていたのですけど、gcc3/4 はジャンプテーブルの分割ができないんですね。
普通にやっていると信じていたのでショックです。2.97 の頃はできてたような記憶があるんですけど…
GCC-2.97 って RedHat が勝手に名前つけた 2.95 とかでしたっけ…
GCC-2.95.3 のコードざっと見た感じだと table jump の方はあんまり賢いことやってなさそうな気がしますが、コンパイルせずに目視しただけなので正直 GCC のコード読めてる自信はありません…
一応テーブルジャンプにならん時は二分探索になってるように見えますので、やってないのは、分割統治が有効なくらい case が疎でかつテーブルジャンプが有効なほど部分的な case が密、っていう状況があんまり無いと判断した、とかなんですかねぇ。
2.97 は 2.95 の間違いでした。スイマセン。
さらに i386 の gcc 2.95.3 で確かめてみると、確かにテーブル分割してくれません。
10年くらい前に C コンパイラを書いた時に、この switch 展開コードを(テーブル分割あり)で作ったのですが、その時は``gccを参考''にしながら作った記憶があるのですが…
この間も俊太郎の詩をお http://www.stlouisbusinesslist.com/business/5021837.htm?info=viagra buy viagra 8-[