| ページ名 | 名前 | 行数 | .exeの大きさ | 速度のめやす1 | 速度のめやす2 |
| a21_txt02_6a | HL-16a | 1081行 | 24.5KB | 1.0倍 | 0.9倍 |
| a21_txt02_12a | HL-22a | 1223行 | 1.0倍 | 0.7倍 |
MOV RAX,[b] ADD RAX,[c] MOV [tmp],RAXを出力します。どのレジスタを使ったらいいかとか、そんなのは考えていません。RAXに固定です。・・・もしかしたら、これはa=b+c;の中のb+cかもしれないです。それだったら、[tmp]なんていらないはずです。直接[a]に代入すればいいですよね。でもそんな気の利いたことはしません。気の利いたことをするためには前後を確認しなければいけません。それをやったら複雑になるので、とりあえずは単純に、
MOV RAX,[b] ADD RAX,[c] MOV [tmp],RAX MOV RAX,[tmp] MOV [a],RAXを出力するのです。こんな程度なら簡単です。
MOV RAX,R13 ADD RAX,R14 MOV [tmp],RAX MOV RAX,[tmp] MOV R12,RAX
ADD reg,?
zx = cx; zy = cy;
for (n = 1; n < 447; n++) {
xx = mul64shr(zx, zx, 24);
yy = mul64shr(zy, zy, 24);
t = xx + yy;
if (t > 0x4000000) break;
zy = mul64shr(zy, zx, 23);
zx = xx + cx;
zy = zy + cy;
zx = zx - yy;
}
sn = sn + n;if (xx + yy > 0x4000000) break;とは書かなかったことや、
zy = mul64shr(zy, zx, 23) + cy; zx = xx - yy + cx;とは書かなかったところが、ズルを有効活用しているポイントです。
zx, zy, xx, yy, t, cx, cyがレジスタ変数になるように指示を与えています。そのため、
xx = mul64shr(zx, zx, 24); // MOV(xx, zx); IMUL(xx, zx); SAR(xx, 24); yy = mul64shr(zy, zy, 24); // MOV(yy, zy); IMUL(yy, zy); SAR(yy, 24); t = xx + yy; // MOV(t, xx); ADD(t, yy); // ここはLEA命令を使えば1命令にできる(gccはちゃんとそうしている)。 if (t > 0x4000000) break; // CMP(t, 0x4000000); JG(label_break); zy = mul64shr(zy, zx, 23); // IMUL(zy, zx); SAR(zy, 23); zx = xx + cx; // MOV(zx, xx); ADD(zx, cx); // ここはLEA命令を使えば1命令にできる(gccはちゃんとそうしている)。 zy = zy + cy; // ADD(zy, cy); zx = zx - yy; // SUB(zx, yy);という機械語を生成しています。これは二か所のLEA命令の利用をサボっているところ以外はgcc-O3と同じ最速コードです。
| インタプリタを[3]のレベルのJITコンパイラへ | x86(32bit): +047行 (HL-9a→HL-13a) | x64(64bit): +127行 (HL-9a→HL-19a) |
| [3]レベルのJITコンパイラを[4]レベルへ改良 | x86(32bit): +046行 (HL-13a→HL-14) | x64(64bit): +065行 (HL-19a→HL-20) |
| [4]レベルのJITコンパイラを[5]レベルへ改良 | x86(32bit): +041行 (HL-14→HL-14a) | x64(64bit): +050行 (HL-20→HL-20a) |
| 無駄なメモリアクセスを削減(*1) | x86(32bit): +106行 (HL-14a→HL-15a) | x64(64bit): +137行 (HL-20a→HL-21a) |
| コンパイル時の定数計算 | x86(32bit): +053行 (HL-15a→HL-16) | x64(64bit): +053行 (HL-21a→HL-22) |
| コメント | お名前 | NameLink | |