a21_txt02_4
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
* 「10日くらいでできる!プログラミング言語自作入門」の続...
-(by [[K]], 2021.04.21)
** (1) HL-14
-さて、とにかくJITコンパイラにはなったものの、生成してい...
|ページ名|名前|行数|.exeの大きさ|説明|速度のめやす1|速度...
|[ [[a21_txt01]] ]|HL-1~HL-9a|RIGHT:49行~772行|RIGHT:6....
|[[a21_txt02]]|HL-11|RIGHT:692行|RIGHT:14.5KB|JITコンパイ...
|[[a21_txt02_1a]]|HL-11a|RIGHT:707行|RIGHT:15.0KB|簡単な...
|[[a21_txt02_2]]|HL-12|RIGHT:745行|RIGHT:16.0KB|ループ速...
|[[a21_txt02_2a]]|HL-12a|RIGHT:766行|RIGHT:16.5KB|codedum...
|[[a21_txt02_3]]|HL-13|RIGHT:827行|RIGHT:21.0KB|配列以外...
|[[a21_txt02_3a]]|HL-13a|RIGHT:819行|RIGHT:21.0KB|配列もJ...
-さすがに追いついたり追い越したりはできないと思いますが、...
----
-最適化をどこからやるかですが、おそらく効果が一番あるのは...
-x86の場合、演算に使えそうなレジスタは、EAXのほかにECX、E...
-一方で、プログラムで使われる変数は4個よりも多いことが普...
-ではHL-14ではどうしましょうか。人間が見れば、この変数を...
-ということで regVar()コマンドを作ります。
regVar(0, x); regVar(1, y); regVar(2, z);
-とすると、xを優先度0でレジスタ変数化してほしくて(=最優...
-上記のように三回もregVarと入力するのは面倒なので、
regVar(0, x, y, z);
-という省略形も使えるようにします。
-関数の形にしているのは、プログラム内で使った時にC言語と...
#define regVar(...)
-などと書いて、regVar()命令を無視させるようにします。
----
-[1]putIcX86_sub()関数の前に以下を追加
IntP regVarTbl[4]; // レジスタ変数の割り当て状況を記憶.
int regVarNo[4] = { 3, 5, 6, 7 }; // レジスタ変数番号か...
int regVar(IntP v) // もし変数vがレジスタに割り当てられ...
{
int i;
for (i = 0; i < 4; i++) {
if (regVarTbl[i] == v)
return i;
}
return -1;
}
-[2]putIcX86_sub()関数の一部を改造
if (s[i + 2] == 'm') { // mod r/m.
k = s[i + 3] - '0';
+ if (regVar(a[j]) < 0) {
*icq = 0x05 + k * 8;
put32(icq + 1, (int) a[j]);
icq += 5;
+ } else {
+ *icq = 0xc0 + regVarNo[regVar(a[j])]...
+ icq++;
+ }
i += 4;
continue;
}
-[3]putIcX86()関数の宣言の後に以下を追加
enum { RvSave = 0x89, RvLoad = 0x8b };
void regVarSaveLoad(int op) // レジスタ変数を準備するor...
{
int i;
for (i = 0; i < 4; i++) {
if (regVarTbl[i] != 0) {
putIcX86("%0c_%1c_%2i;", (IntP) op, (IntP) (...
}
}
}
-[4]compile()関数に1行追加(1)
icq = ic;
jp = 0;
putIcX86("60; 83_ec_7c;", 0, 0, 0, 0); // PUSHAD(); ...
+ regVarSaveLoad(RvLoad);
dump0 = icq;
-[5]compile()関数に14行追加
+ } else if (phrCmp(37, "regVar(!!*0", pc)) {
+ i = tc[wpc[0]] - Tc0;
+ for (pc = ppc1; tc[pc] != TcBrCls; pc++) {
+ if (tc[pc] == TcComma) continue;
+ if (0 <= i && i <= 3) {
+ regVarSaveLoad(RvSave);
+ regVarTbl[i] = &var[tc[pc]];
+ if (tc[pc] == Tc0)
+ regVarTbl[i] = 0;
+ regVarSaveLoad(RvLoad);
+ }
+ i++;
+ }
+ ppc1 = pc + 2;
-[6]compile()関数に1行追加(2)
defLabel(toExit);
dump1 = icq;
+ regVarSaveLoad(RvSave);
putIcX86("83_c4_7c; 61; c3;", 0, 0, 0, 0); // ADD(ES...
icq1 = icq;
----
-以上すべての改造を終えると、プログラムは865行になります。
** (2) プログラムの説明
-今回の改造で最も重要なのは、putIcX86_sub()関数の改造のと...
if (s[i + 2] == 'm') { // mod r/m.
k = s[i + 3] - '0';
+ if (regVar(a[j]) < 0) {
*icq = 0x05 + k * 8;
put32(icq + 1, (int) a[j]);
icq += 5;
+ } else {
+ *icq = 0xc0 + regVarNo[regVar(a[j])]...
+ icq++;
+ }
i += 4;
continue;
}
-これはつまり、%mで変数を指定されたときにレジスタ変数でな...
-あとはcompile()の最初のところで、レジスタ変数の場合はメ...
-またregVar()命令でレジスタ変数の設定状況を変更するときは...
-なおregVar()命令で、変数名の代わりに0を指定すると、その...
** (3) さて、これでどのくらい高速化されるか?
-10億回ループを実行する前に、 regVar(0, i); を実行してお...
-また、 run mandel.c する前には、 regVar(0, zx, zy, xx, y...
|ページ名|名前|行数|.exeの大きさ|説明|速度のめやす1|速度...
|[ [[a21_txt01]] ]|HL-1~HL-9a|RIGHT:49行~772行|RIGHT:6....
|[[a21_txt02]]|HL-11|RIGHT:692行|RIGHT:14.5KB|JITコンパイ...
|[[a21_txt02_1a]]|HL-11a|RIGHT:707行|RIGHT:15.0KB|簡単な...
|[[a21_txt02_2]]|HL-12|RIGHT:745行|RIGHT:16.0KB|ループ速...
|[[a21_txt02_2a]]|HL-12a|RIGHT:766行|RIGHT:16.5KB|codedum...
|[[a21_txt02_3]]|HL-13|RIGHT:827行|RIGHT:21.0KB|配列以外...
|[[a21_txt02_3a]]|HL-13a|RIGHT:819行|RIGHT:21.0KB|配列もJ...
|[[a21_txt02_4]]|HL-14|RIGHT:865行|RIGHT:21.5KB|レジスタ...
-はっきりと効果が出ています!!
** 次回に続く
-次回: [[a21_txt02_4a]]
*こめんと欄
#comment
終了行:
* 「10日くらいでできる!プログラミング言語自作入門」の続...
-(by [[K]], 2021.04.21)
** (1) HL-14
-さて、とにかくJITコンパイラにはなったものの、生成してい...
|ページ名|名前|行数|.exeの大きさ|説明|速度のめやす1|速度...
|[ [[a21_txt01]] ]|HL-1~HL-9a|RIGHT:49行~772行|RIGHT:6....
|[[a21_txt02]]|HL-11|RIGHT:692行|RIGHT:14.5KB|JITコンパイ...
|[[a21_txt02_1a]]|HL-11a|RIGHT:707行|RIGHT:15.0KB|簡単な...
|[[a21_txt02_2]]|HL-12|RIGHT:745行|RIGHT:16.0KB|ループ速...
|[[a21_txt02_2a]]|HL-12a|RIGHT:766行|RIGHT:16.5KB|codedum...
|[[a21_txt02_3]]|HL-13|RIGHT:827行|RIGHT:21.0KB|配列以外...
|[[a21_txt02_3a]]|HL-13a|RIGHT:819行|RIGHT:21.0KB|配列もJ...
-さすがに追いついたり追い越したりはできないと思いますが、...
----
-最適化をどこからやるかですが、おそらく効果が一番あるのは...
-x86の場合、演算に使えそうなレジスタは、EAXのほかにECX、E...
-一方で、プログラムで使われる変数は4個よりも多いことが普...
-ではHL-14ではどうしましょうか。人間が見れば、この変数を...
-ということで regVar()コマンドを作ります。
regVar(0, x); regVar(1, y); regVar(2, z);
-とすると、xを優先度0でレジスタ変数化してほしくて(=最優...
-上記のように三回もregVarと入力するのは面倒なので、
regVar(0, x, y, z);
-という省略形も使えるようにします。
-関数の形にしているのは、プログラム内で使った時にC言語と...
#define regVar(...)
-などと書いて、regVar()命令を無視させるようにします。
----
-[1]putIcX86_sub()関数の前に以下を追加
IntP regVarTbl[4]; // レジスタ変数の割り当て状況を記憶.
int regVarNo[4] = { 3, 5, 6, 7 }; // レジスタ変数番号か...
int regVar(IntP v) // もし変数vがレジスタに割り当てられ...
{
int i;
for (i = 0; i < 4; i++) {
if (regVarTbl[i] == v)
return i;
}
return -1;
}
-[2]putIcX86_sub()関数の一部を改造
if (s[i + 2] == 'm') { // mod r/m.
k = s[i + 3] - '0';
+ if (regVar(a[j]) < 0) {
*icq = 0x05 + k * 8;
put32(icq + 1, (int) a[j]);
icq += 5;
+ } else {
+ *icq = 0xc0 + regVarNo[regVar(a[j])]...
+ icq++;
+ }
i += 4;
continue;
}
-[3]putIcX86()関数の宣言の後に以下を追加
enum { RvSave = 0x89, RvLoad = 0x8b };
void regVarSaveLoad(int op) // レジスタ変数を準備するor...
{
int i;
for (i = 0; i < 4; i++) {
if (regVarTbl[i] != 0) {
putIcX86("%0c_%1c_%2i;", (IntP) op, (IntP) (...
}
}
}
-[4]compile()関数に1行追加(1)
icq = ic;
jp = 0;
putIcX86("60; 83_ec_7c;", 0, 0, 0, 0); // PUSHAD(); ...
+ regVarSaveLoad(RvLoad);
dump0 = icq;
-[5]compile()関数に14行追加
+ } else if (phrCmp(37, "regVar(!!*0", pc)) {
+ i = tc[wpc[0]] - Tc0;
+ for (pc = ppc1; tc[pc] != TcBrCls; pc++) {
+ if (tc[pc] == TcComma) continue;
+ if (0 <= i && i <= 3) {
+ regVarSaveLoad(RvSave);
+ regVarTbl[i] = &var[tc[pc]];
+ if (tc[pc] == Tc0)
+ regVarTbl[i] = 0;
+ regVarSaveLoad(RvLoad);
+ }
+ i++;
+ }
+ ppc1 = pc + 2;
-[6]compile()関数に1行追加(2)
defLabel(toExit);
dump1 = icq;
+ regVarSaveLoad(RvSave);
putIcX86("83_c4_7c; 61; c3;", 0, 0, 0, 0); // ADD(ES...
icq1 = icq;
----
-以上すべての改造を終えると、プログラムは865行になります。
** (2) プログラムの説明
-今回の改造で最も重要なのは、putIcX86_sub()関数の改造のと...
if (s[i + 2] == 'm') { // mod r/m.
k = s[i + 3] - '0';
+ if (regVar(a[j]) < 0) {
*icq = 0x05 + k * 8;
put32(icq + 1, (int) a[j]);
icq += 5;
+ } else {
+ *icq = 0xc0 + regVarNo[regVar(a[j])]...
+ icq++;
+ }
i += 4;
continue;
}
-これはつまり、%mで変数を指定されたときにレジスタ変数でな...
-あとはcompile()の最初のところで、レジスタ変数の場合はメ...
-またregVar()命令でレジスタ変数の設定状況を変更するときは...
-なおregVar()命令で、変数名の代わりに0を指定すると、その...
** (3) さて、これでどのくらい高速化されるか?
-10億回ループを実行する前に、 regVar(0, i); を実行してお...
-また、 run mandel.c する前には、 regVar(0, zx, zy, xx, y...
|ページ名|名前|行数|.exeの大きさ|説明|速度のめやす1|速度...
|[ [[a21_txt01]] ]|HL-1~HL-9a|RIGHT:49行~772行|RIGHT:6....
|[[a21_txt02]]|HL-11|RIGHT:692行|RIGHT:14.5KB|JITコンパイ...
|[[a21_txt02_1a]]|HL-11a|RIGHT:707行|RIGHT:15.0KB|簡単な...
|[[a21_txt02_2]]|HL-12|RIGHT:745行|RIGHT:16.0KB|ループ速...
|[[a21_txt02_2a]]|HL-12a|RIGHT:766行|RIGHT:16.5KB|codedum...
|[[a21_txt02_3]]|HL-13|RIGHT:827行|RIGHT:21.0KB|配列以外...
|[[a21_txt02_3a]]|HL-13a|RIGHT:819行|RIGHT:21.0KB|配列もJ...
|[[a21_txt02_4]]|HL-14|RIGHT:865行|RIGHT:21.5KB|レジスタ...
-はっきりと効果が出ています!!
** 次回に続く
-次回: [[a21_txt02_4a]]
*こめんと欄
#comment
ページ名: