a21_txt02_10
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
* 「10日くらいでできる!プログラミング言語自作入門」の続...
-(by [[K]], 2021.05.12)
** (1) HL-20
-さて、とにかくJITコンパイラにはなったものの、生成してい...
|ページ名|名前|行数|.exeの大きさ|説明|速度のめやす1|速度...
|[ [[a21_txt01]] ]|HL-1~HL-9a|RIGHT:49行~772行|RIGHT:6....
|[[a21_txt02_7]]|HL-17|RIGHT:741行|RIGHT:25.0KB|x64に対応...
|[[a21_txt02_7a]]|HL-17a|RIGHT:756行|RIGHT:26.0KB|簡単な...
|[[a21_txt02_8]]|HL-18|RIGHT:795行|RIGHT:27.0KB|ループ速...
|[[a21_txt02_8a]]|HL-18a|RIGHT:816行|RIGHT:27.5KB|codedum...
|[[a21_txt02_9]]|HL-19|RIGHT:893行|RIGHT:35.5KB|配列以外...
|[[a21_txt02_9a]]|HL-19a|RIGHT:899行|RIGHT:36.0KB|配列もJ...
-さすがに追いついたり追い越したりはできないと思いますが、...
----
-最適化をどこからやるかですが、おそらく効果が一番あるのは...
-x64の場合、演算に使えそうなレジスタは、RAXのほかにRCX、R...
-その上、関数呼び出しで破壊されるレジスタがたくさんありま...
--[ABI_MSW64のとき] RBX、RSI、RDI、R12~R15 (合計7つ)
--[ABI_SYSV64のとき] RBX、R12~R15 (合計5つ)
-一方で、プログラムで使われる変数は5個よりも多いことが普...
-ではHL-20ではどうしましょうか。人間が見れば、この変数を...
-ということで regVar()コマンドを作ります。
regVar(0, x); regVar(1, y); regVar(2, z);
-とすると、xを優先度0でレジスタ変数化してほしくて(=最優...
-上記のように三回もregVarと入力するのは面倒なので、
regVar(0, x, y, z);
-という省略形も使えるようにします。
-関数の形にしているのは、プログラム内で使った時にC言語と...
#define regVar(...)
-などと書いて、regVar()命令を無視させるようにします。
----
-[1]putIcX64_sub()関数の前に以下を追加
#if (ABI_MSW64 != 0)
#define RegVarLen 7
int regVarNo[7] = { 3, 6, 7, 12, 13, 14, 15 }; // レ...
#elif (ABI_SYSV64 != 0)
#define RegVarLen 5
int regVarNo[5] = { 3, 12, 13, 14, 15 }; // レジスタ...
#endif
IntP regVarTbl[RegVarLen]; // レジスタ変数の割り当て状況...
int regVar(IntP v) // もし変数vがレジスタに割り当てられ...
{
int i;
for (i = 0; i < RegVarLen; i++) {
if (regVarTbl[i] == v)
return i;
}
return -1;
}
-[2]putIcX64_sub()関数の一部を改造
if (s[i + 2] == 'm') { // mod r/m.
k = s[i + 3] - '0';
if (s[i + 3] >= 'a') { // もしかしたらこ...
k = s[i + 3] - 'a' + 10;
}
+ if (k >= 8) {
+ *putIcX64_rex += 4;
+ k -= 8;
+ }
+ int rv = regVar(a[j]);
+ if (rv < 0) {
*icq = 0x85 + k * 8;
put32(icq + 1, (a[j] - var) * 8);
icq += 5;
+ } else {
+ rv = regVarNo[rv];
+ if (rv >= 8) {
+ *putIcX64_rex += 1;
+ rv -= 8;
+ }
+ *icq = 0xc0 + rv + k * 8;
+ icq++;
+ }
i += 4;
continue;
}
-[3]putIcX64()関数の宣言の後に以下を追加
enum { RvSave = 0x89, RvLoad = 0x8b };
void regVarSaveLoad(int op) // レジスタ変数を準備するor...
{
int i, rv, rex;
for (i = 0; i < RegVarLen; i++) {
if (regVarTbl[i] != 0) {
rv = regVarNo[i];
rex = 0x48;
if (rv >= 8) {
rex = 0x48 + 4;
rv -= 8;
}
putIcX64("%0c_%1c_%2c_%3i;", (IntP) (AInt) r...
}
}
}
-[4]compile()関数に1行追加(1)
icq = ic;
jp = 0;
putIcX64("41_57; 41_56; 41_55; 41_54; 41_53; 41_52;"...
putIcX64("41_51; 41_50; 57; 56; 55; 54; 53; 52; 51; ...
putIcX64("%R_81_ec_f8_01_00_00; %R_bd_%0q;", var, 0,...
+ regVarSaveLoad(RvLoad);
dump0 = icq;
-[5]compile()関数に14行追加
+ } else if (phrCmp(37, "regVar(!!*0", pc)) {
+ i = tc[wpc[0]] - Tc0;
+ regVarSaveLoad(RvSave);
+ for (pc = ppc1; tc[pc] != TcBrCls; pc++) {
+ if (tc[pc] == TcComma) continue;
+ if (0 <= i && i < RegVarLen) {
+ regVarTbl[i] = &var[tc[pc]];
+ if (tc[pc] == Tc0)
+ regVarTbl[i] = 0;
+ }
+ i++;
+ }
+ regVarSaveLoad(RvLoad);
+ ppc1 = pc + 2;
-[6]compile()関数に1行追加(2)
defLabel(toExit);
dump1 = icq;
+ regVarSaveLoad(RvSave);
putIcX64("%R_81_c4_f8_01_00_00;", 0, 0, 0, 0);
putIcX64("58; 59; 5a; 5b; 5c; 5d; 5e; 5f; 41_58; 41_...
putIcX64("41_5a; 41_5b; 41_5c; 41_5d; 41_5e; 41_5f; ...
icq1 = icq;
----
-以上すべての改造を終えると、プログラムは964行になります。
** (2) プログラムの説明
-今回の改造で最も重要なのは、putIcX86_sub()関数の改造のと...
if (s[i + 2] == 'm') { // mod r/m.
k = s[i + 3] - '0';
if (s[i + 3] >= 'a') { // もしかしたらこ...
k = s[i + 3] - 'a' + 10;
}
+ if (k >= 8) {
+ *putIcX64_rex += 4;
+ k -= 8;
+ }
+ int rv = regVar(a[j]);
+ if (rv < 0) {
*icq = 0x85 + k * 8;
put32(icq + 1, (a[j] - var) * 8);
icq += 5;
+ } else {
+ rv = regVarNo[rv];
+ if (rv >= 8) {
+ *putIcX64_rex += 1;
+ rv -= 8;
+ }
+ *icq = 0xc0 + rv + k * 8;
+ icq++;
+ }
i += 4;
continue;
}
-これはつまり、%mで変数を指定されたときにレジスタ変数でな...
-またレジスタ番号が8以上になってあふれた時は、REX命令のと...
-あとは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_7]]|HL-17|RIGHT:741行|RIGHT:25.0KB|x64に対応...
|[[a21_txt02_7a]]|HL-17a|RIGHT:756行|RIGHT:26.0KB|簡単な...
|[[a21_txt02_8]]|HL-18|RIGHT:795行|RIGHT:27.0KB|ループ速...
|[[a21_txt02_8a]]|HL-18a|RIGHT:816行|RIGHT:27.5KB|codedum...
|[[a21_txt02_9]]|HL-19|RIGHT:893行|RIGHT:35.5KB|配列以外...
|[[a21_txt02_9a]]|HL-19a|RIGHT:899行|RIGHT:36.0KB|配列もJ...
|[[a21_txt02_10]]|HL-20|RIGHT:964行|RIGHT:36.0KB|レジスタ...
-はっきりと効果が出ています!!
** 次回に続く
-次回: [[a21_txt02_10a]]
*こめんと欄
#comment
終了行:
* 「10日くらいでできる!プログラミング言語自作入門」の続...
-(by [[K]], 2021.05.12)
** (1) HL-20
-さて、とにかくJITコンパイラにはなったものの、生成してい...
|ページ名|名前|行数|.exeの大きさ|説明|速度のめやす1|速度...
|[ [[a21_txt01]] ]|HL-1~HL-9a|RIGHT:49行~772行|RIGHT:6....
|[[a21_txt02_7]]|HL-17|RIGHT:741行|RIGHT:25.0KB|x64に対応...
|[[a21_txt02_7a]]|HL-17a|RIGHT:756行|RIGHT:26.0KB|簡単な...
|[[a21_txt02_8]]|HL-18|RIGHT:795行|RIGHT:27.0KB|ループ速...
|[[a21_txt02_8a]]|HL-18a|RIGHT:816行|RIGHT:27.5KB|codedum...
|[[a21_txt02_9]]|HL-19|RIGHT:893行|RIGHT:35.5KB|配列以外...
|[[a21_txt02_9a]]|HL-19a|RIGHT:899行|RIGHT:36.0KB|配列もJ...
-さすがに追いついたり追い越したりはできないと思いますが、...
----
-最適化をどこからやるかですが、おそらく効果が一番あるのは...
-x64の場合、演算に使えそうなレジスタは、RAXのほかにRCX、R...
-その上、関数呼び出しで破壊されるレジスタがたくさんありま...
--[ABI_MSW64のとき] RBX、RSI、RDI、R12~R15 (合計7つ)
--[ABI_SYSV64のとき] RBX、R12~R15 (合計5つ)
-一方で、プログラムで使われる変数は5個よりも多いことが普...
-ではHL-20ではどうしましょうか。人間が見れば、この変数を...
-ということで regVar()コマンドを作ります。
regVar(0, x); regVar(1, y); regVar(2, z);
-とすると、xを優先度0でレジスタ変数化してほしくて(=最優...
-上記のように三回もregVarと入力するのは面倒なので、
regVar(0, x, y, z);
-という省略形も使えるようにします。
-関数の形にしているのは、プログラム内で使った時にC言語と...
#define regVar(...)
-などと書いて、regVar()命令を無視させるようにします。
----
-[1]putIcX64_sub()関数の前に以下を追加
#if (ABI_MSW64 != 0)
#define RegVarLen 7
int regVarNo[7] = { 3, 6, 7, 12, 13, 14, 15 }; // レ...
#elif (ABI_SYSV64 != 0)
#define RegVarLen 5
int regVarNo[5] = { 3, 12, 13, 14, 15 }; // レジスタ...
#endif
IntP regVarTbl[RegVarLen]; // レジスタ変数の割り当て状況...
int regVar(IntP v) // もし変数vがレジスタに割り当てられ...
{
int i;
for (i = 0; i < RegVarLen; i++) {
if (regVarTbl[i] == v)
return i;
}
return -1;
}
-[2]putIcX64_sub()関数の一部を改造
if (s[i + 2] == 'm') { // mod r/m.
k = s[i + 3] - '0';
if (s[i + 3] >= 'a') { // もしかしたらこ...
k = s[i + 3] - 'a' + 10;
}
+ if (k >= 8) {
+ *putIcX64_rex += 4;
+ k -= 8;
+ }
+ int rv = regVar(a[j]);
+ if (rv < 0) {
*icq = 0x85 + k * 8;
put32(icq + 1, (a[j] - var) * 8);
icq += 5;
+ } else {
+ rv = regVarNo[rv];
+ if (rv >= 8) {
+ *putIcX64_rex += 1;
+ rv -= 8;
+ }
+ *icq = 0xc0 + rv + k * 8;
+ icq++;
+ }
i += 4;
continue;
}
-[3]putIcX64()関数の宣言の後に以下を追加
enum { RvSave = 0x89, RvLoad = 0x8b };
void regVarSaveLoad(int op) // レジスタ変数を準備するor...
{
int i, rv, rex;
for (i = 0; i < RegVarLen; i++) {
if (regVarTbl[i] != 0) {
rv = regVarNo[i];
rex = 0x48;
if (rv >= 8) {
rex = 0x48 + 4;
rv -= 8;
}
putIcX64("%0c_%1c_%2c_%3i;", (IntP) (AInt) r...
}
}
}
-[4]compile()関数に1行追加(1)
icq = ic;
jp = 0;
putIcX64("41_57; 41_56; 41_55; 41_54; 41_53; 41_52;"...
putIcX64("41_51; 41_50; 57; 56; 55; 54; 53; 52; 51; ...
putIcX64("%R_81_ec_f8_01_00_00; %R_bd_%0q;", var, 0,...
+ regVarSaveLoad(RvLoad);
dump0 = icq;
-[5]compile()関数に14行追加
+ } else if (phrCmp(37, "regVar(!!*0", pc)) {
+ i = tc[wpc[0]] - Tc0;
+ regVarSaveLoad(RvSave);
+ for (pc = ppc1; tc[pc] != TcBrCls; pc++) {
+ if (tc[pc] == TcComma) continue;
+ if (0 <= i && i < RegVarLen) {
+ regVarTbl[i] = &var[tc[pc]];
+ if (tc[pc] == Tc0)
+ regVarTbl[i] = 0;
+ }
+ i++;
+ }
+ regVarSaveLoad(RvLoad);
+ ppc1 = pc + 2;
-[6]compile()関数に1行追加(2)
defLabel(toExit);
dump1 = icq;
+ regVarSaveLoad(RvSave);
putIcX64("%R_81_c4_f8_01_00_00;", 0, 0, 0, 0);
putIcX64("58; 59; 5a; 5b; 5c; 5d; 5e; 5f; 41_58; 41_...
putIcX64("41_5a; 41_5b; 41_5c; 41_5d; 41_5e; 41_5f; ...
icq1 = icq;
----
-以上すべての改造を終えると、プログラムは964行になります。
** (2) プログラムの説明
-今回の改造で最も重要なのは、putIcX86_sub()関数の改造のと...
if (s[i + 2] == 'm') { // mod r/m.
k = s[i + 3] - '0';
if (s[i + 3] >= 'a') { // もしかしたらこ...
k = s[i + 3] - 'a' + 10;
}
+ if (k >= 8) {
+ *putIcX64_rex += 4;
+ k -= 8;
+ }
+ int rv = regVar(a[j]);
+ if (rv < 0) {
*icq = 0x85 + k * 8;
put32(icq + 1, (a[j] - var) * 8);
icq += 5;
+ } else {
+ rv = regVarNo[rv];
+ if (rv >= 8) {
+ *putIcX64_rex += 1;
+ rv -= 8;
+ }
+ *icq = 0xc0 + rv + k * 8;
+ icq++;
+ }
i += 4;
continue;
}
-これはつまり、%mで変数を指定されたときにレジスタ変数でな...
-またレジスタ番号が8以上になってあふれた時は、REX命令のと...
-あとは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_7]]|HL-17|RIGHT:741行|RIGHT:25.0KB|x64に対応...
|[[a21_txt02_7a]]|HL-17a|RIGHT:756行|RIGHT:26.0KB|簡単な...
|[[a21_txt02_8]]|HL-18|RIGHT:795行|RIGHT:27.0KB|ループ速...
|[[a21_txt02_8a]]|HL-18a|RIGHT:816行|RIGHT:27.5KB|codedum...
|[[a21_txt02_9]]|HL-19|RIGHT:893行|RIGHT:35.5KB|配列以外...
|[[a21_txt02_9a]]|HL-19a|RIGHT:899行|RIGHT:36.0KB|配列もJ...
|[[a21_txt02_10]]|HL-20|RIGHT:964行|RIGHT:36.0KB|レジスタ...
-はっきりと効果が出ています!!
** 次回に続く
-次回: [[a21_txt02_10a]]
*こめんと欄
#comment
ページ名: