LR生成の際に、式の相関により最適化を行うようにした。かなり効果があるハズだが、ときどき重いフェイズに突入してしまい、「ドツボ」ることがあるのでこれが今後の課題。
・木の最適化に、AND 1, OR 0 などの無意味項を丸める処理を追加。
・最適化の結果参照されなくなったLRノードを削除するようにした。ついでに削除ノードを最適化効果指標として報告するようにした。
・synth_extract_minterm() に記述されていた処理の大部分は、前段の synth_expand_terms() にて終わっているので、処理を大幅に削った。
・synth_simplify_qm() は、生成限界に達したときに全主項を返すようにした(未デバッグ)。
ついでに、N_INFLIGHT=2 にしてみた。いいのか?
@@ -23,6 +23,9 @@ | ||
23 | 23 | |
24 | 24 | static int g_tn = 32; |
25 | 25 | |
26 | +static int n_lrq[11]; | |
27 | +static struct ITREE **lrq[11]; | |
28 | + | |
26 | 29 | /* アンチョコから引用したビット数え */ |
27 | 30 | static unsigned popcnt32(uint32_t x) |
28 | 31 | { |
@@ -297,7 +300,7 @@ | ||
297 | 300 | /*************************************************************** |
298 | 301 | * |
299 | 302 | * ノードを切り離す |
300 | - * ref == 0 になったらメモリからも削除して 1 を返す | |
303 | + * ref == 0 になったらメモリからも削除して削除数を返す | |
301 | 304 | * |
302 | 305 | */ |
303 | 306 |
@@ -305,22 +308,38 @@ | ||
305 | 308 | synth_unlink(struct ITREE *node) |
306 | 309 | { |
307 | 310 | int i; |
311 | + int n = 0; | |
308 | 312 | |
309 | 313 | assert(node->ref > 0); |
310 | 314 | if (--node->ref > 0) |
311 | 315 | return 0; |
312 | 316 | |
313 | - assert(node->opcode != NI_LR); | |
314 | 317 | assert(node->opcode != NI_DICT); |
315 | 318 | |
316 | 319 | /* 枝を切り落とす */ |
317 | 320 | for (i = 0; i < node->n_ops; i++) |
318 | - synth_unlink(node->ops[i]); | |
321 | + n += synth_unlink(node->ops[i]); | |
319 | 322 | |
323 | + /* LR の場合、リストから切り離す */ | |
324 | + if (node->opcode == NI_LR) | |
325 | + { | |
326 | + for (i = 0; i < n_lrq[node->lrn]; i++) | |
327 | + if (lrq[node->lrn][i] == node) | |
328 | + { | |
329 | + memmove(&lrq[node->lrn][i], | |
330 | + &lrq[node->lrn][i + 1], | |
331 | + (--n_lrq[node->lrn] - i) * sizeof(*lrq[0][0])); | |
332 | + goto deleted; | |
333 | + } | |
334 | + assert(!"XXX orphan node"); | |
335 | + deleted: | |
336 | + ; | |
337 | + } | |
338 | + | |
320 | 339 | /* 自分自身を削除 */ |
321 | 340 | synth_free(node); |
322 | 341 | |
323 | - return 1; | |
342 | + return n + 1; | |
324 | 343 | } |
325 | 344 | |
326 | 345 | /*************************************************************** |
@@ -329,9 +348,6 @@ | ||
329 | 348 | * |
330 | 349 | */ |
331 | 350 | |
332 | -static int n_lrq[11]; | |
333 | -static struct ITREE **lrq[11]; | |
334 | - | |
335 | 351 | struct ITREE * |
336 | 352 | synth_make_lr(uint64_t bmp, int lrn) |
337 | 353 | { |
@@ -715,15 +731,14 @@ | ||
715 | 731 | static |
716 | 732 | int |
717 | 733 | synth_expand_terms(uint64_t *px, /* 展開先 */ |
718 | - int pxi, /* 展開先インデクス */ | |
719 | - uint64_t x, /* 積 */ | |
734 | + int maxpx, /* 限界個数 */ | |
720 | 735 | uint64_t const *cov, /* 被覆 */ |
721 | 736 | int covn) /* 被覆個数 */ |
722 | 737 | { |
723 | 738 | int i, j, k; |
739 | + int pxi = 0; | |
724 | 740 | |
725 | 741 | assert(covn > 0); |
726 | - assert(pxi == 0); | |
727 | 742 | |
728 | 743 | for (i = 0; i < covn; i++) |
729 | 744 | { |
@@ -756,6 +771,9 @@ | ||
756 | 771 | continue; |
757 | 772 | } |
758 | 773 | } |
774 | + assert(pxi <= maxpx); | |
775 | + if (pxi == maxpx) | |
776 | + return INT_MAX; /* 諦めてすべての項を選ばせる */ | |
759 | 777 | px[pxi++] = u; |
760 | 778 | exp_dup: |
761 | 779 | ; |
@@ -789,7 +807,7 @@ | ||
789 | 807 | int covn, |
790 | 808 | int etn) |
791 | 809 | { |
792 | - int i, j; | |
810 | + int i; | |
793 | 811 | int n; |
794 | 812 | uint64_t m; |
795 | 813 | int minc; |
@@ -802,13 +820,14 @@ | ||
802 | 820 | assert(term != NULL); |
803 | 821 | |
804 | 822 | n = synth_expand_terms(term, /* 展開先 */ |
805 | - 0, | |
806 | - 0ULL, /* 初期項 */ | |
823 | + etn, | |
807 | 824 | cov, |
808 | 825 | covn); |
809 | 826 | #if DEBUG>=1 |
810 | 827 | printf("generated etn=%d(pon=%d)\n", n, covn); |
811 | 828 | #endif |
829 | + if (n == INT_MAX) | |
830 | + return (uint64_t)-1; | |
812 | 831 | assert(n <= etn); |
813 | 832 | assert(n > 0); |
814 | 833 | #if DEBUG>=2 |
@@ -816,39 +835,18 @@ | ||
816 | 835 | printf("%3d: %08X%08X(%2d)\n", i, (unsigned)(term[i] >> 32), (unsigned)term[i], popcnt64(term[i])); |
817 | 836 | #endif |
818 | 837 | |
819 | - do | |
838 | + m = 0; | |
839 | + minc = INT_MAX; | |
840 | + for (i = 0; i < n; i++) | |
820 | 841 | { |
821 | - m = 0; | |
822 | - minc = INT_MAX; | |
823 | - for (i = 0; i < n; i++) | |
842 | + unsigned c = popcnt64(term[i]); | |
843 | + if (minc > c) | |
824 | 844 | { |
825 | - for (j = i + 1; j < n; j++) | |
826 | - { | |
827 | - /* 包含関係を丸める | |
828 | - すなわち (a & b) | a => a */ | |
829 | - if (term[i] == term[j]) | |
830 | - continue; | |
831 | - else if ((term[i] & term[j]) == term[j]) | |
832 | - term[i] = term[j]; | |
833 | - else if ((term[i] & term[j]) == term[i]) | |
834 | - term[j] = term[i]; | |
835 | - else | |
836 | - continue; | |
837 | - minc = 0; | |
838 | - } | |
839 | - if (0 < minc) | |
840 | - { | |
841 | - /* カウントを取る */ | |
842 | - unsigned c = popcnt64(term[i]); | |
843 | - if (minc > c) | |
844 | - { | |
845 | - minc = c; | |
846 | - m = term[i]; | |
847 | - } | |
848 | - } | |
845 | + minc = c; | |
846 | + m = term[i]; | |
849 | 847 | } |
850 | 848 | } |
851 | - while (!(0 < minc && minc <= 64)); | |
849 | + assert(minc > 0); | |
852 | 850 | |
853 | 851 | #if DEBUG>=2 |
854 | 852 | for (i = 0; i < n; i++) |
@@ -869,7 +867,8 @@ | ||
869 | 867 | * Quine-McCluskey 法により bmp を簡単化する |
870 | 868 | * 後段の被覆展開は Petrick 法による |
871 | 869 | * |
872 | - * 概算項数を返す(あきらめたときは INT_MAX) | |
870 | + * 概算項数を返す | |
871 | + * あきらめたときは INT_MAX を返し、全主項を生成する | |
873 | 872 | * |
874 | 873 | * aox に積和形による結果を返す(m==0 terminated) |
875 | 874 | * |
@@ -889,6 +888,7 @@ | ||
889 | 888 | static |
890 | 889 | int |
891 | 890 | synth_simplify_qm(struct QMX *aox, |
891 | + int maxn, /* 積和展開上限(最適化レベル) */ | |
892 | 892 | uint64_t bmp, /* 真理値表 */ |
893 | 893 | uint64_t dc) /* 1 のビットは D/C */ |
894 | 894 | { |
@@ -895,7 +895,7 @@ | ||
895 | 895 | int i, j; |
896 | 896 | uint64_t m; |
897 | 897 | int tn; |
898 | - int pon, dcn, prn, pgn, etn; | |
898 | + int pon, dcn, prn, pgn, etn, mtn; | |
899 | 899 | uint64_t cov[QMX_LEN]; /* 被覆 */ |
900 | 900 | struct QMX pox[QMX_LEN]; /* 最小項 */ |
901 | 901 | struct QMX atmx[256 * QMX_LEN]; /* 64k を超えないくらいが目安? */ |
@@ -1066,15 +1066,6 @@ | ||
1066 | 1066 | printf("%2d: %08X%08x\n", i, (unsigned)(cov[i] >> 32), (unsigned)cov[i]); |
1067 | 1067 | #endif |
1068 | 1068 | |
1069 | -#if 0 | |
1070 | - /* 項見積もりが超デカイ場合はあきらめてみる */ | |
1071 | - if (etn >= INT_MAX / sizeof(*cov) | |
1072 | - || etn == 0) | |
1073 | - return INT_MAX; | |
1074 | -#else | |
1075 | - etn = 0x20000; /* XXX */ | |
1076 | -#endif | |
1077 | - | |
1078 | 1069 | /* 最小被覆の抽出 |
1079 | 1070 | (最小なのか?) */ |
1080 | 1071 | #if DEBUG>=2 |
@@ -1081,15 +1072,17 @@ | ||
1081 | 1072 | for (i = 0; i < pon; i++) |
1082 | 1073 | printf("%2d: %08X%08x\n", i, (unsigned)(cov[i] >> 32), (unsigned)cov[i]); |
1083 | 1074 | #endif |
1084 | - m = synth_extract_minterm(cov, pon, etn); | |
1075 | + m = synth_extract_minterm(cov, pon, maxn); /* 耐えきれなかったら全ビット1 */ | |
1085 | 1076 | |
1086 | 1077 | /* 結果を展開 */ |
1087 | - tn = popcnt64(m) - 1; | |
1078 | + mtn = popcnt64(m); | |
1079 | + m &= ((1ULL << prn) - 1); | |
1080 | + tn = mtn; | |
1088 | 1081 | j = 0; |
1089 | 1082 | for (i = 0; i < prn; i++) |
1090 | 1083 | if (m & (1ULL << i)) |
1091 | 1084 | { |
1092 | - tn += popcnt32(tmx[i].m) - 1; | |
1085 | + tn += popcnt32(tmx[i].m); | |
1093 | 1086 | if (aox) |
1094 | 1087 | aox[j++] = tmx[i]; |
1095 | 1088 | #if DEBUG>=1 |
@@ -1110,7 +1103,8 @@ | ||
1110 | 1103 | if (tmx != atmx) |
1111 | 1104 | free(tmx); |
1112 | 1105 | |
1113 | - return tn; | |
1106 | + /* 全部展開してしまった場合 */ | |
1107 | + return (mtn > prn ? INT_MAX : tn); | |
1114 | 1108 | } |
1115 | 1109 | |
1116 | 1110 | /*************************************************************** |
@@ -1120,7 +1114,7 @@ | ||
1120 | 1114 | */ |
1121 | 1115 | |
1122 | 1116 | #define REG_RELOAD 0 /* 付け焼き刃の最適はむしろ有害 */ |
1123 | -#define N_INFLIGHT 1 /* 同時演算を試みる個数 */ | |
1117 | +#define N_INFLIGHT 2 /* 同時演算を試みる個数 */ | |
1124 | 1118 | |
1125 | 1119 | #define NREGS 8 |
1126 | 1120 | static struct ITREE *a_regs[NREGS]; |
@@ -1190,12 +1184,77 @@ | ||
1190 | 1184 | * |
1191 | 1185 | */ |
1192 | 1186 | |
1187 | +struct LRX | |
1188 | +{ | |
1189 | + struct ITREE *node; | |
1190 | + int mtn; | |
1191 | + int otn; | |
1192 | + /* 種類 | |
1193 | + 0:単独 | |
1194 | + 1:AND | |
1195 | + 2:OR | |
1196 | + 3:NAND */ | |
1197 | + int src; | |
1198 | + struct QMX *xp; | |
1199 | + unsigned mtm; | |
1200 | +}; | |
1201 | + | |
1193 | 1202 | static |
1194 | 1203 | int |
1204 | +cmp_lrx(void const *pa, void const *pb) | |
1205 | +{ | |
1206 | + struct LRX const *a = pa; | |
1207 | + struct LRX const *b = pb; | |
1208 | + int r; | |
1209 | + assert(a->node != NULL); | |
1210 | + assert(b->node != NULL); | |
1211 | + if ((r = a->mtn - b->mtn) | |
1212 | + || (r = a->mtn - b->mtn) | |
1213 | + || (r = a->mtm - b->mtm) | |
1214 | + || (r = (int)popcnt64(a->node->bmp) - (int)popcnt64(b->node->bmp)) | |
1215 | + || (r = (int)(a->node->bmp >> 32) - (int)(b->node->bmp >> 32))) | |
1216 | + return r; | |
1217 | + return (int)a->node->bmp - (int)b->node->bmp; | |
1218 | +} | |
1219 | + | |
1220 | +static | |
1221 | +void | |
1222 | +synth_load_lr(FILE *sfp, int pos, int i) | |
1223 | +{ | |
1224 | + int o = tr_fp[6 * pos + (5 - i)]; | |
1225 | + if (o < 32) | |
1226 | + reg_mem(sfp, | |
1227 | + OP_MOV, | |
1228 | + i, | |
1229 | + PTR_LR, | |
1230 | + sizeof(WS_T) * (o - 16)); | |
1231 | + else if (o < 64) | |
1232 | + reg_mem(sfp, | |
1233 | + OP_MOV, | |
1234 | + i, | |
1235 | + PTR_RL, | |
1236 | + sizeof(WS_T) * (o - 32 - 16)); | |
1237 | + assert(o < 64); | |
1238 | +} | |
1239 | + | |
1240 | +static | |
1241 | +int | |
1195 | 1242 | synth_assemble_lr(FILE *sfp, int pos, struct ITREE **nodea, int noden) |
1196 | 1243 | { |
1197 | 1244 | int i; |
1198 | 1245 | uint64_t m; |
1246 | + unsigned regs_loaded = 0; | |
1247 | + int maxtn = 0x400; | |
1248 | + int recon; | |
1249 | + struct LRX *lrx; | |
1250 | + struct QMX (*qmx)[QMX_LEN + 1]; | |
1251 | + int nts_total = 0; | |
1252 | + int nts_reduced = 0; | |
1253 | + assert(noden <= 10000); | |
1254 | +#if DEBUG>=1 | |
1255 | + fprintf(stderr, "WELCOME! (noden=%d)\n", noden); | |
1256 | +#endif | |
1257 | + recon = 0; | |
1199 | 1258 | |
1200 | 1259 | if (noden == 0) |
1201 | 1260 | return 0; |
@@ -1206,75 +1265,178 @@ | ||
1206 | 1265 | ? 0x0000000000000000ULL |
1207 | 1266 | : 0xEEEEEEEEEEEEEEEEULL); |
1208 | 1267 | |
1209 | - /* オペランドのセットアップ */ | |
1210 | - for (i = 0; i < 6; i++) | |
1211 | - { | |
1212 | - int o = tr_fp[6 * pos + (5 - i)]; | |
1213 | - if (o < 32) | |
1214 | - reg_mem(sfp, | |
1215 | - OP_MOV, | |
1216 | - i, | |
1217 | - PTR_LR, | |
1218 | - sizeof(WS_T) * (o - 16)); | |
1219 | - else if (o < 64) | |
1220 | - reg_mem(sfp, | |
1221 | - OP_MOV, | |
1222 | - i, | |
1223 | - PTR_RL, | |
1224 | - sizeof(WS_T) * (o - 32 - 16)); | |
1225 | - } | |
1268 | + /* ワークエリア */ | |
1269 | + lrx = calloc(noden, sizeof(*lrx)); | |
1270 | + assert(lrx != NULL); | |
1271 | + qmx = calloc(noden, sizeof(*qmx)); | |
1272 | + assert(qmx != NULL); | |
1226 | 1273 | |
1227 | 1274 | for (i = 0; i < noden; i++) |
1228 | 1275 | { |
1229 | - int tn; | |
1276 | + int j, k; | |
1230 | 1277 | unsigned opo, opa; |
1231 | - struct ITREE *node = nodea[i]; | |
1232 | - struct QMX xp[QMX_LEN + 1]; | |
1278 | + struct ITREE *node; | |
1279 | + struct QMX *xp; | |
1233 | 1280 | struct QMX const *px; |
1234 | 1281 | |
1235 | - assert(node != NULL); | |
1236 | - assert(node->opcode == NI_LR); | |
1237 | - xp[QMX_LEN].m = 0; | |
1282 | + for (j = i; j < noden; j++) | |
1283 | + { | |
1284 | + /* 最初のループで通るはず */ | |
1285 | + if (lrx[j].node == NULL) | |
1286 | + { | |
1287 | + lrx[j].node = nodea[j]; | |
1288 | + lrx[j].xp = qmx[j]; | |
1289 | + lrx[j].mtn = synth_simplify_qm(lrx[j].xp, maxtn, | |
1290 | + lrx[j].node->bmp, | |
1291 | + m); | |
1292 | + lrx[j].otn = lrx[j].mtn; | |
1293 | + lrx[j].mtm = OP_MOV; | |
1294 | + lrx[j].src = -256; /* 決してマッチしない */ | |
1295 | + } | |
1296 | + if (recon && lrx[j].mtn == INT_MAX) | |
1297 | + { | |
1298 | + lrx[j].mtn = synth_simplify_qm(lrx[j].xp, maxtn, | |
1299 | + lrx[j].node->bmp, | |
1300 | + m); | |
1301 | + lrx[j].otn = lrx[j].mtn; | |
1302 | + assert(lrx[j].mtm == OP_MOV); | |
1303 | + } | |
1304 | + /* 被覆を求める */ | |
1305 | + for (k = 0; k < i; k++) | |
1306 | + { | |
1307 | + int ttn; | |
1308 | + struct QMX txp[QMX_LEN + 1]; | |
1238 | 1309 | |
1310 | + if (!recon && k < i - 2) /* 計算する必要ナシ */ | |
1311 | + continue; | |
1312 | + | |
1313 | + if ((lrx[k].node->bmp & lrx[j].node->bmp) == lrx[j].node->bmp | |
1314 | + && (ttn = synth_simplify_qm(txp, maxtn, | |
1315 | + lrx[j].node->bmp, | |
1316 | + m | ~lrx[k].node->bmp)) < INT_MAX) | |
1317 | + { | |
1318 | + ttn++; /* ロードの分浪費 */ | |
1319 | + if (lrx[j].mtn > ttn) | |
1320 | + { | |
1321 | + lrx[j].mtn = ttn; | |
1322 | + lrx[j].mtm = OP_AND; | |
1323 | + lrx[j].src = k; | |
1324 | + memcpy(lrx[j].xp, txp, sizeof(txp)); | |
1325 | + } | |
1326 | + } | |
1327 | + | |
1328 | + if ((lrx[k].node->bmp & lrx[j].node->bmp) == lrx[k].node->bmp | |
1329 | + && (ttn = synth_simplify_qm(txp, maxtn, | |
1330 | + lrx[j].node->bmp, | |
1331 | + m | lrx[k].node->bmp)) < INT_MAX) | |
1332 | + { | |
1333 | + /* OR */ | |
1334 | + if (k != i - 1) /* 直前のものでなければ1段コスト増 */ | |
1335 | + ttn++; | |
1336 | + if (lrx[j].mtn > ttn) | |
1337 | + { | |
1338 | + lrx[j].mtn = ttn; | |
1339 | + lrx[j].mtm = OP_OR; | |
1340 | + lrx[j].src = k; | |
1341 | + memcpy(lrx[j].xp, txp, sizeof(txp)); | |
1342 | + } | |
1343 | + } | |
1344 | + | |
1345 | +#if defined (OP_ANDN) | |
1346 | + if ((~lrx[k].node->bmp & lrx[j].node->bmp) == lrx[j].node->bmp | |
1347 | + && (ttn = synth_simplify_qm(txp, maxtn, | |
1348 | + lrx[j].node->bmp, | |
1349 | + m | lrx[k].node->bmp)) < INT_MAX) | |
1350 | + { | |
1351 | + /* ANDN */ | |
1352 | + ttn++; /* ロードの分浪費 */ | |
1353 | + if (lrx[j].mtn > ttn) | |
1354 | + { | |
1355 | + lrx[j].mtn = ttn; | |
1356 | + lrx[j].mtm = OP_ANDN; | |
1357 | + lrx[j].src = k; | |
1358 | + memcpy(lrx[j].xp, txp, sizeof(txp)); | |
1359 | + } | |
1360 | + } | |
1361 | +#endif | |
1362 | + } | |
1363 | + } | |
1364 | + | |
1365 | + /* ソート */ | |
1366 | + recon = 0; | |
1367 | + qsort(&lrx[i], noden - i, sizeof(*lrx), cmp_lrx); | |
1368 | + | |
1369 | + if (lrx[i].mtn == INT_MAX) | |
1370 | + { | |
1371 | + if (maxtn < 0x4000) | |
1372 | + { | |
1373 | + maxtn <<= 2; | |
1374 | + assert(maxtn > 0); | |
1375 | + fprintf(stderr, | |
1376 | + "%d文字目にてドツボにハマり中…\t(%d)\n", | |
1377 | + pos, | |
1378 | + maxtn); | |
1379 | +#if DEBUG>=1 | |
1380 | + fprintf(stderr, "%4d: grow up to 0x%X\n", i, maxtn); | |
1381 | +#endif | |
1382 | + recon = 1; | |
1383 | + i--; continue; /* redo */ | |
1384 | + } | |
1385 | + else | |
1386 | + { | |
1387 | + /* gave up! 全項でつくってしまう */ | |
1388 | + fprintf(stderr, "%d文字目には参った!\n", pos); | |
1389 | + } | |
1390 | + } | |
1391 | + | |
1392 | +#if DEBUG>=1 | |
1393 | + fprintf(stderr, | |
1394 | + "%4d/%4d:n=%3d/%3d(mt=%02X:src=%4d) %08X%08X\n", | |
1395 | + i, (noden - i), | |
1396 | + lrx[i].mtn, | |
1397 | + lrx[i].otn, | |
1398 | + lrx[i].mtm, | |
1399 | + lrx[i].src, | |
1400 | + (unsigned)(lrx[i].node->bmp >> 32), | |
1401 | + (unsigned)lrx[i].node->bmp); | |
1402 | +#endif | |
1403 | + assert(lrx[i].mtn >= 0); | |
1404 | + nts_total += lrx[i].mtn; | |
1405 | + if (lrx[i].mtm && lrx[i].otn < INT_MAX) | |
1406 | + nts_reduced += lrx[i].otn - lrx[i].mtn; | |
1407 | + node = lrx[i].node; | |
1408 | + xp = lrx[i].xp; | |
1409 | + | |
1239 | 1410 | /* ワークエリア割り当て */ |
1240 | 1411 | node->tn = g_tn++; |
1241 | 1412 | assert(g_tn <= sizeof(((struct PARAM *)NULL)->hit) / sizeof(SLICE)); |
1242 | 1413 | |
1243 | - /* ノードが完全定数である場合 */ | |
1244 | - if (!(node->bmp & ~m)) | |
1414 | + switch (lrx[i].mtm) | |
1245 | 1415 | { |
1246 | - /* nil */ | |
1247 | - reg_op(sfp, OP_XOR, 7, 7); | |
1248 | - reg_mem(sfp, | |
1249 | - OP_STOR, | |
1250 | - 7, | |
1251 | - PTR_T, | |
1252 | - sizeof(WS_T) * (OFS_T + node->tn)); | |
1253 | - continue; | |
1416 | + case OP_OR: opo = OP_OR; break; | |
1417 | + default: opo = OP_MOV; break; | |
1254 | 1418 | } |
1255 | - else if (!~(node->bmp | m)) | |
1419 | + | |
1420 | + /* 既出の項を利用して演算するばあい */ | |
1421 | + if (lrx[i].mtm != OP_MOV && lrx[i].src != i - 1) | |
1422 | + reg_mem(sfp, | |
1423 | + OP_MOV, | |
1424 | + 7, | |
1425 | + PTR_T, | |
1426 | + sizeof(WS_T) * (OFS_T + lrx[lrx[i].src].node->tn)); | |
1427 | + | |
1428 | + if (!(node->bmp & ~m) | |
1429 | + || !~(node->bmp | m)) | |
1256 | 1430 | { |
1257 | - /* t てぬき */ | |
1258 | - reg_mem(sfp, | |
1259 | - OP_MOV, | |
1260 | - 7, | |
1261 | - PTR_T, | |
1262 | - sizeof(WS_T) * (OFS_T - 32 + 16)); | |
1263 | - reg_mem(sfp, | |
1264 | - OP_STOR, | |
1265 | - 7, | |
1266 | - PTR_T, | |
1267 | - sizeof(WS_T) * (OFS_T + node->tn)); | |
1268 | - continue; | |
1431 | + fprintf(stderr, | |
1432 | + "やっちゃったー %08X%08X\n", | |
1433 | + (unsigned)(node->bmp >> 32), | |
1434 | + (unsigned)node->bmp); | |
1435 | + assert(!!(node->bmp & ~m)); | |
1436 | + assert(!!~(node->bmp | m)); | |
1269 | 1437 | } |
1270 | 1438 | |
1271 | 1439 | /* 圧縮された式を展開 */ |
1272 | - tn = synth_simplify_qm(xp, | |
1273 | - node->bmp, | |
1274 | - m); | |
1275 | - assert(0 <= tn && tn < INT_MAX); | |
1276 | - assert(xp[0].m); | |
1277 | - opo = OP_MOV; | |
1278 | 1440 | for (px = xp; px->m; px++) |
1279 | 1441 | { |
1280 | 1442 | int j; |
@@ -1287,6 +1449,11 @@ | ||
1287 | 1449 | for (j = 0; j < 6; j++) |
1288 | 1450 | if (mi & (1 << j)) |
1289 | 1451 | { |
1452 | + if (!(regs_loaded & (1 << j))) | |
1453 | + { | |
1454 | + synth_load_lr(sfp, pos, j); | |
1455 | + regs_loaded |= (1 << j); | |
1456 | + } | |
1290 | 1457 | reg_op(sfp, opa, 6, j); |
1291 | 1458 | opa = OP_OR; |
1292 | 1459 | } |
@@ -1306,6 +1473,11 @@ | ||
1306 | 1473 | for (j = 0; j < 6; j++) |
1307 | 1474 | if (pi & (1 << j)) |
1308 | 1475 | { |
1476 | + if (!(regs_loaded & (1 << j))) | |
1477 | + { | |
1478 | + synth_load_lr(sfp, pos, j); | |
1479 | + regs_loaded |= (1 << j); | |
1480 | + } | |
1309 | 1481 | reg_op(sfp, opa, 6, j); |
1310 | 1482 | opa = OP_AND; |
1311 | 1483 | } |
@@ -1325,7 +1497,45 @@ | ||
1325 | 1497 | opo = OP_OR; |
1326 | 1498 | } |
1327 | 1499 | |
1328 | - assert(opo != OP_MOV); | |
1500 | + if (opo == OP_MOV) | |
1501 | + { | |
1502 | + /* 積和項が生成されなかった場合 */ | |
1503 | + assert(lrx[i].mtm != OP_MOV); | |
1504 | + assert(lrx[i].src >= 0); | |
1505 | + if (lrx[i].src != i - 1) | |
1506 | + reg_mem(sfp, | |
1507 | + OP_MOV, | |
1508 | + 7, | |
1509 | + PTR_T, | |
1510 | + sizeof(WS_T) * (OFS_T + lrx[lrx[i].src].node->tn)); | |
1511 | + switch (lrx[i].mtm) | |
1512 | + { | |
1513 | +#ifdef OP_ANDN | |
1514 | + case OP_ANDN: | |
1515 | + reg_mem(sfp, | |
1516 | + OP_XOR, | |
1517 | + 7, | |
1518 | + PTR_T, | |
1519 | + sizeof(WS_T) * (OFS_T - 32 + 16)); | |
1520 | + break; | |
1521 | +#endif | |
1522 | + } | |
1523 | + } | |
1524 | + else switch (lrx[i].mtm) /* 既出項との演算 */ | |
1525 | + { | |
1526 | + case OP_AND: | |
1527 | +#ifdef OP_ANDN | |
1528 | + case OP_ANDN: | |
1529 | +#endif | |
1530 | + reg_mem(sfp, | |
1531 | + lrx[i].mtm, | |
1532 | + 7, | |
1533 | + PTR_T, | |
1534 | + sizeof(WS_T) * (OFS_T + lrx[lrx[i].src].node->tn)); | |
1535 | + break; | |
1536 | + } | |
1537 | + | |
1538 | + /* 結果の格納 */ | |
1329 | 1539 | reg_mem(sfp, |
1330 | 1540 | OP_STOR, |
1331 | 1541 | 7, |
@@ -1334,7 +1544,13 @@ | ||
1334 | 1544 | |
1335 | 1545 | a_regs[7] = node; /* XXX 気休め */ |
1336 | 1546 | } |
1547 | +#if DEBUG>=1 | |
1548 | + fprintf(stderr, "term=%d (reduced %d)\n", nts_total, nts_reduced); | |
1549 | +#endif | |
1337 | 1550 | |
1551 | + free(lrx); | |
1552 | + free(qmx); | |
1553 | + | |
1338 | 1554 | return 0; |
1339 | 1555 | } |
1340 | 1556 |
@@ -1527,6 +1743,18 @@ | ||
1527 | 1743 | /* 先に、枝の最適化に挑戦 */ |
1528 | 1744 | neff += synth_optimize(child); |
1529 | 1745 | |
1746 | + /* 意味のないノードを落とす */ | |
1747 | + if (child->opcode == NI_LR | |
1748 | + && ((node->opcode == NI_AND && !~child->bmp) | |
1749 | + || (node->opcode == NI_OR && ~child->bmp))) | |
1750 | + { | |
1751 | + neff += 1 + synth_unlink(child); | |
1752 | + memmove(&node->ops[i], | |
1753 | + &node->ops[i + 1], | |
1754 | + (--node->n_ops - i) * sizeof(*node->ops)); | |
1755 | + i--; goto redo_i; | |
1756 | + } | |
1757 | + | |
1530 | 1758 | /* 同じポインタは無条件に融合できる */ |
1531 | 1759 | for (j = 0; j < i; j++) |
1532 | 1760 | if (node->ops[j] == child) |
@@ -1576,8 +1804,7 @@ | ||
1576 | 1804 | assert(child->tn < 0); |
1577 | 1805 | node->ops[i] = child->ops[0]; |
1578 | 1806 | child->n_ops--; |
1579 | - synth_unlink(child); | |
1580 | - neff++; | |
1807 | + neff += 1 + synth_unlink(child); | |
1581 | 1808 | i--; goto redo_i; |
1582 | 1809 | } |
1583 | 1810 |