History

jump optimizations

This unifies VT_CMP with VT_JMP(i) by using mostly VT_CMP with both a positive and a negative jump target list. Such we can delay putting the non-inverted or inverted jump until we can see which one is nore suitable (in most cases). example: if (a && b || c && d) e = 0; before this patch: a: 8b 45 fc mov 0xfffffffc(%ebp),%eax d: 83 f8 00 cmp $0x0,%eax 10: 0f 84 11 00 00 00 je 27 <main+0x27> 16: 8b 45 f8 mov 0xfffffff8(%ebp),%eax 19: 83 f8 00 cmp $0x0,%eax 1c: 0f 84 05 00 00 00 je 27 <main+0x27> 22: e9 22 00 00 00 jmp 49 <main+0x49> 27: 8b 45 f4 mov 0xfffffff4(%ebp),%eax 2a: 83 f8 00 cmp $0x0,%eax 2d: 0f 84 11 00 00 00 je 44 <main+0x44> 33: 8b 45 f0 mov 0xfffffff0(%ebp),%eax 36: 83 f8 00 cmp $0x0,%eax 39: 0f 84 05 00 00 00 je 44 <main+0x44> 3f: e9 05 00 00 00 jmp 49 <main+0x49> 44: e9 08 00 00 00 jmp 51 <main+0x51> 49: b8 00 00 00 00 mov $0x0,%eax 4e: 89 45 ec mov %eax,0xffffffec(%ebp) 51: ... with this patch: a: 8b 45 fc mov 0xfffffffc(%ebp),%eax d: 83 f8 00 cmp $0x0,%eax 10: 0f 84 0c 00 00 00 je 22 <main+0x22> 16: 8b 45 f8 mov 0xfffffff8(%ebp),%eax 19: 83 f8 00 cmp $0x0,%eax 1c: 0f 85 18 00 00 00 jne 3a <main+0x3a> 22: 8b 45 f4 mov 0xfffffff4(%ebp),%eax 25: 83 f8 00 cmp $0x0,%eax 28: 0f 84 14 00 00 00 je 42 <main+0x42> 2e: 8b 45 f0 mov 0xfffffff0(%ebp),%eax 31: 83 f8 00 cmp $0x0,%eax 34: 0f 84 08 00 00 00 je 42 <main+0x42> 3a: b8 00 00 00 00 mov $0x0,%eax 3f: 89 45 ec mov %eax,0xffffffec(%ebp) 42: ...

grischka committed 7 years ago

Commit 8227db31 parent 1b575609 files · +346 −283Browse files

Unified · Split

9 files
  1. Makefile +1 −1
  2. arm-gen.c +30 −47
  3. arm64-gen.c +63 −2
  4. c67-gen.c +16 −24
  5. i386-gen.c +32 −60
  6. tcc.h +12 −9
  7. tccgen.c +158 −70
  8. tests/tcctest.c +3 −1
  9. x86_64-gen.c +31 −69
Makefile+1−1
@@ -125,7 +125,7 @@ DEF-i386-win32 = -DTCC_TARGET_PE -DTCC_TARGET_I386 · 124 unmodified lines
125DEF-x86_64-win32= -DTCC_TARGET_PE -DTCC_TARGET_X86_64125DEF-x86_64-win32= -DTCC_TARGET_PE -DTCC_TARGET_X86_64
126DEF-x86_64-osx = -DTCC_TARGET_MACHO -DTCC_TARGET_X86_64126DEF-x86_64-osx = -DTCC_TARGET_MACHO -DTCC_TARGET_X86_64
127DEF-arm-wince = -DTCC_TARGET_PE -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_VFP -DTCC_ARM_HARDFLOAT127DEF-arm-wince = -DTCC_TARGET_PE -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_VFP -DTCC_ARM_HARDFLOAT
128DEF-arm64 = -DTCC_TARGET_ARM64128DEF-arm64 = -DTCC_TARGET_ARM64 -Wno-format
129DEF-c67 = -DTCC_TARGET_C67 -w # disable warnigs129DEF-c67 = -DTCC_TARGET_C67 -w # disable warnigs
130DEF-arm-fpa = -DTCC_TARGET_ARM130DEF-arm-fpa = -DTCC_TARGET_ARM
131DEF-arm-fpa-ld = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12131DEF-arm-fpa-ld = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12
arm-gen.c+30−47
@@ -1419,7 +1419,7 @@ ST_FUNC void gen_fill_nops(int bytes) · 1418 unmodified lines
1419}1419}
1420 1420
1421/* generate a jump to a label */1421/* generate a jump to a label */
1422int gjmp(int t)1422ST_FUNC int gjmp(int t)
1423{1423{
1424 int r;1424 int r;
1425 if (nocode_wanted)1425 if (nocode_wanted)
@@ -1430,51 +1430,37 @@ int gjmp(int t) · 4 unmodified lines
1430}1430}
1431 1431
1432/* generate a jump to a fixed address */1432/* generate a jump to a fixed address */
1433void gjmp_addr(int a)1433ST_FUNC void gjmp_addr(int a)
1434{1434{
1435 gjmp(a);1435 gjmp(a);
1436}1436}
1437 1437
1438/* generate a test. set 'inv' to invert test. Stack entry is popped */1438ST_FUNC int gjmp_cond(int op, int t)
1439int gtst(int inv, int t)
1440{1439{
1441 int v, r;1440 int r;
1442 uint32_t op;1441 if (nocode_wanted)
1443 1442 return t;
1444 v = vtop->r & VT_VALMASK;
1445 r=ind;1443 r=ind;
1444 op=mapcc(op);
1445 op|=encbranch(r,t,1);
1446 o(op);
1447 return r;
1448}
1446 1449
1447 if (nocode_wanted) {1450ST_FUNC int gjmp_append(int n, int t)
1448 ;1451{
1449 } else if (v == VT_CMP) {1452 uint32_t *x;
1450 op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);1453 int p,lp;
1451 op|=encbranch(r,t,1);1454 if(n) {
1452 o(op);1455 p = n;
1453 t=r;1456 do {
1454 } else if (v == VT_JMP || v == VT_JMPI) {1457 p = decbranch(lp=p);
1455 if ((v & 1) == inv) {1458 } while(p);
1456 if(!vtop->c.i)1459 x = (uint32_t *)(cur_text_section->data + lp);
1457 vtop->c.i=t;1460 *x &= 0xff000000;
1458 else {1461 *x |= encbranch(lp,t,1);
1459 uint32_t *x;1462 t = n;
1460 int p,lp;
1461 if(t) {
1462 p = vtop->c.i;
1463 do {
1464 p = decbranch(lp=p);
1465 } while(p);
1466 x = (uint32_t *)(cur_text_section->data + lp);
1467 *x &= 0xff000000;
1468 *x |= encbranch(lp,t,1);
1469 }
1470 t = vtop->c.i;
1471 }
1472 } else {
1473 t = gjmp(t);
1474 gsym(vtop->c.i);
1475 }
1476 }1463 }
1477 vtop--;
1478 return t;1464 return t;
1479}1465}
1480 1466
@@ -1611,10 +1597,8 @@ void gen_opi(int op) · 130 unmodified lines
1611 o(opc|(r<<12)|fr);1597 o(opc|(r<<12)|fr);
1612done:1598done:
1613 vtop--;1599 vtop--;
1614 if (op >= TOK_ULT && op <= TOK_GT) {1600 if (op >= TOK_ULT && op <= TOK_GT)
1615 vtop->r = VT_CMP;1601 vset_VT_CMP(op);
1616 vtop->c.i = op;
1617 }
1618 break;1602 break;
1619 case 2:1603 case 2:
1620 opc=0xE1A00000|(opc<<5);1604 opc=0xE1A00000|(opc<<5);
@@ -1730,9 +1714,7 @@ void gen_opf(int op) · 109 unmodified lines
1730 case TOK_UGE: op=TOK_GE; break;1714 case TOK_UGE: op=TOK_GE; break;
1731 case TOK_UGT: op=TOK_GT; break;1715 case TOK_UGT: op=TOK_GT; break;
1732 }1716 }
1733 1717 vset_VT_CMP(op);
1734 vtop->r = VT_CMP;
1735 vtop->c.i = op;
1736 return;1718 return;
1737 }1719 }
1738 r=gv(RC_FLOAT);1720 r=gv(RC_FLOAT);
@@ -1934,8 +1916,9 @@ void gen_opf(int op) · 195 unmodified lines
1934 } else {1916 } else {
1935 r2=fpr(gv(RC_FLOAT));1917 r2=fpr(gv(RC_FLOAT));
1936 }1918 }
1937 vtop[-1].r = VT_CMP;1919 --vtop;
1938 vtop[-1].c.i = op;1920 vset_VT_CMP(op);
1921 ++vtop;
1939 } else {1922 } else {
1940 tcc_error("unknown fp op %x!",op);1923 tcc_error("unknown fp op %x!",op);
1941 return;1924 return;
arm64-gen.c+63−2
@@ -91,6 +91,9 @@ static uint32_t fltr(int r) · 90 unmodified lines
91 return r - TREG_F(0);91 return r - TREG_F(0);
92}92}
93 93
94#define dprintf(x) ((void)(tcc_state->verbose == 2 && printf x))
95//#define dprintf(x)
96
94// Add an instruction to text section:97// Add an instruction to text section:
95ST_FUNC void o(unsigned int c)98ST_FUNC void o(unsigned int c)
96{99{
@@ -100,6 +103,7 @@ ST_FUNC void o(unsigned int c) · 3 unmodified lines
100 if (ind1 > cur_text_section->data_allocated)103 if (ind1 > cur_text_section->data_allocated)
101 section_realloc(cur_text_section, ind1);104 section_realloc(cur_text_section, ind1);
102 write32le(cur_text_section->data + ind, c);105 write32le(cur_text_section->data + ind, c);
106 dprintf(("o %04x : %08x\n", ind, c)); //gr
103 ind = ind1;107 ind = ind1;
104}108}
105 109
@@ -232,6 +236,7 @@ ST_FUNC void gsym_addr(int t_, int a_) · 126 unmodified lines
232 tcc_error("branch out of range");236 tcc_error("branch out of range");
233 write32le(ptr, (a - t == 4 ? 0xd503201f : // nop237 write32le(ptr, (a - t == 4 ? 0xd503201f : // nop
234 0x14000000 | ((a - t) >> 2 & 0x3ffffff))); // b238 0x14000000 | ((a - t) >> 2 & 0x3ffffff))); // b
239 dprintf((". gsym TARG=%04x ADDR=%04x\n", t, a)); //gr
235 t = next;240 t = next;
236 }241 }
237}242}
@@ -440,6 +445,8 @@ static void arm64_sym(int r, Sym *sym, unsigned long addend) · 202 unmodified lines
440 }445 }
441}446}
442 447
448static void arm64_load_cmp(int r, SValue *sv);
449
443ST_FUNC void load(int r, SValue *sv)450ST_FUNC void load(int r, SValue *sv)
444{451{
445 int svtt = sv->type.t;452 int svtt = sv->type.t;
@@ -531,6 +538,11 @@ ST_FUNC void load(int r, SValue *sv) · 85 unmodified lines
531 return;538 return;
532 }539 }
533 540
541 if (svr == VT_CMP) {
542 arm64_load_cmp(r, sv);
543 return;
544 }
545
534 printf("load(%x, (%x, %x, %llx))\n", r, svtt, sv->r, (long long)svcul);546 printf("load(%x, (%x, %x, %llx))\n", r, svtt, sv->r, (long long)svcul);
535 assert(0);547 assert(0);
536}548}
@@ -1284,6 +1296,7 @@ ST_FUNC void gen_fill_nops(int bytes) · 747 unmodified lines
1284ST_FUNC int gjmp(int t)1296ST_FUNC int gjmp(int t)
1285{1297{
1286 int r = ind;1298 int r = ind;
1299 dprintf((". gjmp T=%04x\n", t)); //gr
1287 if (nocode_wanted)1300 if (nocode_wanted)
1288 return t;1301 return t;
1289 o(t);1302 o(t);
@@ -1295,11 +1308,57 @@ ST_FUNC void gjmp_addr(int a) · 5 unmodified lines
1295{1308{
1296 assert(a - ind + 0x8000000 < 0x10000000);1309 assert(a - ind + 0x8000000 < 0x10000000);
1297 o(0x14000000 | ((a - ind) >> 2 & 0x3ffffff));1310 o(0x14000000 | ((a - ind) >> 2 & 0x3ffffff));
1311 dprintf((". gjmp_addr T=%04x\n", a)); //gr
1298}1312}
1299 1313
1300ST_FUNC int gtst(int inv, int t)1314ST_FUNC int gjmp_append(int n, int t)
1315{
1316 void *p;
1317 /* insert vtop->c jump list in t */
1318 if (n) {
1319 uint32_t n1 = n, n2;
1320 while ((n2 = read32le(p = cur_text_section->data + n1)))
1321 n1 = n2;
1322 write32le(p, t);
1323 t = n;
1324 }
1325 return t;
1326}
1327
1328void arm64_vset_VT_CMP(int op)
1329{
1330 if (op >= TOK_ULT && op <= TOK_GT) {
1331 vtop->cmp_r = vtop->r;
1332 vset_VT_CMP(0x80);
1333 dprintf((". set VT_CMP OP(%s) R=%x\n", get_tok_str(op, 0), vtop->cmp_r));
1334 }
1335}
1336
1337static void arm64_gen_opil(int op, uint32_t l);
1338
1339static void arm64_load_cmp(int r, SValue *sv)
1340{
1341 sv->r = sv->cmp_r;
1342 dprintf((". load VT_CMP OP(%x), R=%x/%x\n", (int)sv->c.i, sv->r, r));
1343 if (sv->c.i & 1) {
1344 vpushi(1);
1345 arm64_gen_opil('^', 0);
1346 }
1347 if (r != sv->r) {
1348 load(r, sv);
1349 sv->r = r;
1350 }
1351 dprintf((". load VT_CMP done\n")); //gr
1352}
1353
1354ST_FUNC int gjmp_cond(int op, int t)
1301{1355{
1302 int bt = vtop->type.t & VT_BTYPE;1356 int bt = vtop->type.t & VT_BTYPE;
1357
1358 int inv = op & 1;
1359 vtop->r = vtop->cmp_r;
1360 dprintf((". gjmp_cond OP(%x) R=%x T=%04x\n", op, vtop->r, t)); //gr
1361
1303 if (bt == VT_LDOUBLE) {1362 if (bt == VT_LDOUBLE) {
1304 uint32_t a, b, f = fltr(gv(RC_FLOAT));1363 uint32_t a, b, f = fltr(gv(RC_FLOAT));
1305 a = get_reg(RC_INT);1364 a = get_reg(RC_INT);
@@ -1324,7 +1383,6 @@ ST_FUNC int gtst(int inv, int t) · 18 unmodified lines
1324 uint32_t a = intr(gv(RC_INT));1383 uint32_t a = intr(gv(RC_INT));
1325 o(0x34000040 | a | !!inv << 24 | ll << 31); // cbz/cbnz wA,.+81384 o(0x34000040 | a | !!inv << 24 | ll << 31); // cbz/cbnz wA,.+8
1326 }1385 }
1327 --vtop;
1328 return gjmp(t);1386 return gjmp(t);
1329}1387}
1330 1388
@@ -1553,11 +1611,13 @@ static void arm64_gen_opil(int op, uint32_t l) · 222 unmodified lines
1553ST_FUNC void gen_opi(int op)1611ST_FUNC void gen_opi(int op)
1554{1612{
1555 arm64_gen_opil(op, 0);1613 arm64_gen_opil(op, 0);
1614 arm64_vset_VT_CMP(op);
1556}1615}
1557 1616
1558ST_FUNC void gen_opl(int op)1617ST_FUNC void gen_opl(int op)
1559{1618{
1560 arm64_gen_opil(op, 1);1619 arm64_gen_opil(op, 1);
1620 arm64_vset_VT_CMP(op);
1561}1621}
1562 1622
1563ST_FUNC void gen_opf(int op)1623ST_FUNC void gen_opf(int op)
@@ -1657,6 +1717,7 @@ ST_FUNC void gen_opf(int op) · 93 unmodified lines
1657 default:1717 default:
1658 assert(0);1718 assert(0);
1659 }1719 }
1720 arm64_vset_VT_CMP(op);
1660}1721}
1661 1722
1662// Generate sign extension from 32 to 64 bits:1723// Generate sign extension from 32 to 64 bits:
c67-gen.c+16−24
@@ -2072,15 +2072,13 @@ void gjmp_addr(int a) · 2071 unmodified lines
2072}2072}
2073 2073
2074/* generate a test. set 'inv' to invert test. Stack entry is popped */2074/* generate a test. set 'inv' to invert test. Stack entry is popped */
2075int gtst(int inv, int t)2075ST_FUNC int gjmp_cond(int op, int t)
2076{2076{
2077 int ind1, n;2077 int ind1;
2078 int v, *p;2078 int inv = op & 1;
2079 if (nocode_wanted)
2080 return t;
2079 2081
2080 v = vtop->r & VT_VALMASK;
2081 if (nocode_wanted) {
2082 ;
2083 } else if (v == VT_CMP) {
2084 /* fast case : can jump directly since flags are set */2082 /* fast case : can jump directly since flags are set */
2085 // C67 uses B2 sort of as flags register2083 // C67 uses B2 sort of as flags register
2086 ind1 = ind;2084 ind1 = ind;
@@ -2098,16 +2096,18 @@ int gtst(int inv, int t) · 11 unmodified lines
2098 C67_NOP(5);2096 C67_NOP(5);
2099 t = ind1; //return where we need to patch2097 t = ind1; //return where we need to patch
2100 2098
2101 } else if (v == VT_JMP || v == VT_JMPI) {2099 return t;
2102 /* && or || optimization */2100}
2103 if ((v & 1) == inv) {2101
2102ST_FUNC int gjmp_append(int n0, int t)
2103{
2104 if (n0) {
2105 int n = n0, *p;
2104 /* insert vtop->c jump list in t */2106 /* insert vtop->c jump list in t */
2105 2107
2106 // I guess the idea is to traverse to the2108 // I guess the idea is to traverse to the
2107 // null at the end of the list and store t2109 // null at the end of the list and store t
2108 // there2110 // there
2109
2110 n = vtop->c.i;
2111 while (n != 0) {2111 while (n != 0) {
2112 p = (int *) (cur_text_section->data + n);2112 p = (int *) (cur_text_section->data + n);
2113 2113
@@ -2117,14 +2117,8 @@ int gtst(int inv, int t) · 3 unmodified lines
2117 }2117 }
2118 *p |= (t & 0xffff) << 7;2118 *p |= (t & 0xffff) << 7;
2119 *(p + 1) |= ((t >> 16) & 0xffff) << 7;2119 *(p + 1) |= ((t >> 16) & 0xffff) << 7;
2120 t = vtop->c.i;2120 t = n0;
2121
2122 } else {
2123 t = gjmp(t);
2124 gsym(vtop->c.i);
2125 }
2126 }2121 }
2127 vtop--;
2128 return t;2122 return t;
2129}2123}
2130 2124
@@ -2200,10 +2194,8 @@ void gen_opi(int op) · 69 unmodified lines
2200 ALWAYS_ASSERT(FALSE);2194 ALWAYS_ASSERT(FALSE);
2201 2195
2202 vtop--;2196 vtop--;
2203 if (op >= TOK_ULT && op <= TOK_GT) {2197 if (op >= TOK_ULT && op <= TOK_GT)
2204 vtop->r = VT_CMP;2198 vset_VT_CMP(0x80);
2205 vtop->c.i = op;
2206 }
2207 break;2199 break;
2208 case '-':2200 case '-':
2209 case TOK_SUBC1: /* sub with carry generation */2201 case TOK_SUBC1: /* sub with carry generation */
@@ -2359,7 +2351,7 @@ void gen_opf(int op) · 149 unmodified lines
2359 } else {2351 } else {
2360 ALWAYS_ASSERT(FALSE);2352 ALWAYS_ASSERT(FALSE);
2361 }2353 }
2362 vtop->r = VT_CMP; // tell TCC that result is in "flags" actually B22354 vset_VT_CMP(0x80);
2363 } else {2355 } else {
2364 if (op == '+') {2356 if (op == '+') {
2365 if ((ft & VT_BTYPE) == VT_DOUBLE) {2357 if ((ft & VT_BTYPE) == VT_DOUBLE) {
i386-gen.c+32−60
@@ -261,10 +261,10 @@ ST_FUNC void load(int r, SValue *sv) · 260 unmodified lines
261 o(0xe8 + r); /* mov %ebp, r */261 o(0xe8 + r); /* mov %ebp, r */
262 }262 }
263 } else if (v == VT_CMP) {263 } else if (v == VT_CMP) {
264 oad(0xb8 + r, 0); /* mov $0, r */
265 o(0x0f); /* setxx %br */264 o(0x0f); /* setxx %br */
266 o(fc);265 o(fc);
267 o(0xc0 + r);266 o(0xc0 + r);
267 o(0xc0b60f + r * 0x90000); /* movzbl %al, %eax */
268 } else if (v == VT_JMP || v == VT_JMPI) {268 } else if (v == VT_JMP || v == VT_JMPI) {
269 t = v & 1;269 t = v & 1;
270 oad(0xb8 + r, t); /* mov $1, r */270 oad(0xb8 + r, t); /* mov $1, r */
@@ -692,63 +692,39 @@ ST_FUNC void gjmp_addr(int a) · 421 unmodified lines
692 }692 }
693}693}
694 694
695ST_FUNC void gtst_addr(int inv, int a)695#if 0
696/* generate a jump to a fixed address */
697ST_FUNC void gjmp_cond_addr(int a, int op)
696{698{
697 int v = vtop->r & VT_VALMASK;699 int r = a - ind - 2;
698 if (v == VT_CMP) {700 if (r == (char)r)
699 inv ^= (vtop--)->c.i;701 g(op - 32), g(r);
700 a -= ind + 2;702 else
701 if (a == (char)a) {703 g(0x0f), gjmp2(op - 16, r - 4);
702 g(inv - 32);
703 g(a);
704 } else {
705 g(0x0f);
706 oad(inv - 16, a - 4);
707 }
708 } else if ((v & ~1) == VT_JMP) {
709 if ((v & 1) != inv) {
710 gjmp_addr(a);
711 gsym(vtop->c.i);
712 } else {
713 gsym(vtop->c.i);
714 o(0x05eb);
715 gjmp_addr(a);
716 }
717 vtop--;
718 }
719}704}
705#endif
720 706
721/* generate a test. set 'inv' to invert test. Stack entry is popped */707ST_FUNC int gjmp_append(int n, int t)
722ST_FUNC int gtst(int inv, int t)
723{708{
724 int v = vtop->r & VT_VALMASK;709 void *p;
725 if (nocode_wanted) {710 /* insert vtop->c jump list in t */
726 ;711 if (n) {
727 } else if (v == VT_CMP) {712 uint32_t n1 = n, n2;
728 /* fast case : can jump directly since flags are set */713 while ((n2 = read32le(p = cur_text_section->data + n1)))
729 g(0x0f);714 n1 = n2;
730 t = gjmp2((vtop->c.i - 16) ^ inv, t);715 write32le(p, t);
731 } else if (v == VT_JMP || v == VT_JMPI) {716 t = n;
732 /* && or || optimization */
733 if ((v & 1) == inv) {
734 /* insert vtop->c jump list in t */
735 uint32_t n1, n = vtop->c.i;
736 if (n) {
737 while ((n1 = read32le(cur_text_section->data + n)))
738 n = n1;
739 write32le(cur_text_section->data + n, t);
740 t = vtop->c.i;
741 }
742 } else {
743 t = gjmp(t);
744 gsym(vtop->c.i);
745 }
746 }717 }
747 vtop--;
748 return t;718 return t;
749}719}
750 720
751/* generate an integer binary operation */721ST_FUNC int gjmp_cond(int op, int t)
722{
723 g(0x0f);
724 t = gjmp2(op - 16, t);
725 return t;
726}
727
752ST_FUNC void gen_opi(int op)728ST_FUNC void gen_opi(int op)
753{729{
754 int r, fr, opc, c;730 int r, fr, opc, c;
@@ -766,10 +742,9 @@ ST_FUNC void gen_opi(int op) · 11 unmodified lines
766 c = vtop->c.i;742 c = vtop->c.i;
767 if (c == (char)c) {743 if (c == (char)c) {
768 /* generate inc and dec for smaller code */744 /* generate inc and dec for smaller code */
769 if (c==1 && opc==0 && op != TOK_ADDC1) {745 if ((c == 1 || c == -1) && (op == '+' || op == '-')) {
770 o (0x40 | r); // inc746 opc = (c == 1) ^ (op == '+');
771 } else if (c==1 && opc==5 && op != TOK_SUBC1) {747 o (0x40 | (opc << 3) | r); // inc,dec
772 o (0x48 | r); // dec
773 } else {748 } else {
774 o(0x83);749 o(0x83);
775 o(0xc0 | (opc << 3) | r);750 o(0xc0 | (opc << 3) | r);
@@ -787,10 +762,8 @@ ST_FUNC void gen_opi(int op) · 11 unmodified lines
787 o(0xc0 + r + fr * 8); 762 o(0xc0 + r + fr * 8);
788 }763 }
789 vtop--;764 vtop--;
790 if (op >= TOK_ULT && op <= TOK_GT) {765 if (op >= TOK_ULT && op <= TOK_GT)
791 vtop->r = VT_CMP;766 vset_VT_CMP(op);
792 vtop->c.i = op;
793 }
794 break;767 break;
795 case '-':768 case '-':
796 case TOK_SUBC1: /* sub with carry generation */769 case TOK_SUBC1: /* sub with carry generation */
@@ -948,8 +921,7 @@ ST_FUNC void gen_opf(int op) · 151 unmodified lines
948 op = TOK_EQ;921 op = TOK_EQ;
949 }922 }
950 vtop--;923 vtop--;
951 vtop->r = VT_CMP;924 vset_VT_CMP(op);
952 vtop->c.i = op;
953 } else {925 } else {
954 /* no memory reference possible for long double operations */926 /* no memory reference possible for long double operations */
955 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {927 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
tcc.h+12−9
@@ -430,9 +430,15 @@ typedef struct SValue { · 429 unmodified lines
430 unsigned short r; /* register + flags */430 unsigned short r; /* register + flags */
431 unsigned short r2; /* second register, used for 'long long'431 unsigned short r2; /* second register, used for 'long long'
432 type. If not used, set to VT_CONST */432 type. If not used, set to VT_CONST */
433 CValue c; /* constant, if VT_CONST */433 union {
434 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST), or if434 struct { int jtrue, jfalse; }; /* forward jmps */
435 result of unary() for an identifier. */435 CValue c; /* constant, if VT_CONST */
436 };
437 union {
438 struct { unsigned short cmp_op, cmp_r; }; /* VT_CMP operation */
439 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST), or if */
440 }; /* result of unary() for an identifier. */
441
436} SValue;442} SValue;
437 443
438/* symbol attributes */444/* symbol attributes */
@@ -1322,6 +1328,7 @@ ST_FUNC ElfSym *elfsym(Sym *); · 883 unmodified lines
1322ST_FUNC void update_storage(Sym *sym);1328ST_FUNC void update_storage(Sym *sym);
1323ST_FUNC Sym *external_global_sym(int v, CType *type);1329ST_FUNC Sym *external_global_sym(int v, CType *type);
1324ST_FUNC void vset(CType *type, int r, int v);1330ST_FUNC void vset(CType *type, int r, int v);
1331ST_FUNC void vset_VT_CMP(int op);
1325ST_FUNC void vswap(void);1332ST_FUNC void vswap(void);
1326ST_FUNC void vpush_global_sym(CType *type, int v);1333ST_FUNC void vpush_global_sym(CType *type, int v);
1327ST_FUNC void vrote(SValue *e, int n);1334ST_FUNC void vrote(SValue *e, int n);
@@ -1490,12 +1497,8 @@ ST_FUNC void gfunc_epilog(void); · 162 unmodified lines
1490ST_FUNC void gen_fill_nops(int);1497ST_FUNC void gen_fill_nops(int);
1491ST_FUNC int gjmp(int t);1498ST_FUNC int gjmp(int t);
1492ST_FUNC void gjmp_addr(int a);1499ST_FUNC void gjmp_addr(int a);
1493ST_FUNC int gtst(int inv, int t);1500ST_FUNC int gjmp_cond(int op, int t);
1494#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_641501ST_FUNC int gjmp_append(int n, int t);
1495ST_FUNC void gtst_addr(int inv, int a);
1496#else
1497#define gtst_addr(inv, a) gsym_addr(gtst(inv, 0), a)
1498#endif
1499ST_FUNC void gen_opi(int op);1502ST_FUNC void gen_opi(int op);
1500ST_FUNC void gen_opf(int op);1503ST_FUNC void gen_opf(int op);
1501ST_FUNC void gen_cvt_ftoi(int t);1504ST_FUNC void gen_cvt_ftoi(int t);
tccgen.c+158−70
@@ -681,13 +681,8 @@ ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep) · 680 unmodified lines
681}681}
682 682
683/* ------------------------------------------------------------------------- */683/* ------------------------------------------------------------------------- */
684 684static void vcheck_cmp(void)
685static void vsetc(CType *type, int r, CValue *vc)
686{685{
687 int v;
688
689 if (vtop >= vstack + (VSTACK_SIZE - 1))
690 tcc_error("memory full (vstack)");
691 /* cannot let cpu flags if other instruction are generated. Also686 /* cannot let cpu flags if other instruction are generated. Also
692 avoid leaving VT_JMP anywhere except on the top of the stack687 avoid leaving VT_JMP anywhere except on the top of the stack
693 because it would complicate the code generator.688 because it would complicate the code generator.
@@ -698,15 +693,17 @@ static void vsetc(CType *type, int r, CValue *vc) · 4 unmodified lines
698 as their value might still be used for real. All values693 as their value might still be used for real. All values
699 we push under nocode_wanted will eventually be popped694 we push under nocode_wanted will eventually be popped
700 again, so that the VT_CMP/VT_JMP value will be in vtop695 again, so that the VT_CMP/VT_JMP value will be in vtop
701 when code is unsuppressed again.696 when code is unsuppressed again. */
702 697
703 Same logic below in vswap(); */698 if (vtop->r == VT_CMP && !nocode_wanted)
704 if (vtop >= vstack && !nocode_wanted) {699 gv(RC_INT);
705 v = vtop->r & VT_VALMASK;700}
706 if (v == VT_CMP || (v & ~1) == VT_JMP)
707 gv(RC_INT);
708 }
709 701
702static void vsetc(CType *type, int r, CValue *vc)
703{
704 if (vtop >= vstack + (VSTACK_SIZE - 1))
705 tcc_error("memory full (vstack)");
706 vcheck_cmp();
710 vtop++;707 vtop++;
711 vtop->type = *type;708 vtop->type = *type;
712 vtop->r = r;709 vtop->r = r;
@@ -718,12 +715,8 @@ static void vsetc(CType *type, int r, CValue *vc) · 5 unmodified lines
718ST_FUNC void vswap(void)715ST_FUNC void vswap(void)
719{716{
720 SValue tmp;717 SValue tmp;
721 /* cannot vswap cpu flags. See comment at vsetc() above */718
722 if (vtop >= vstack && !nocode_wanted) {719 vcheck_cmp();
723 int v = vtop->r & VT_VALMASK;
724 if (v == VT_CMP || (v & ~1) == VT_JMP)
725 gv(RC_INT);
726 }
727 tmp = vtop[0];720 tmp = vtop[0];
728 vtop[0] = vtop[-1];721 vtop[0] = vtop[-1];
729 vtop[-1] = tmp;722 vtop[-1] = tmp;
@@ -740,9 +733,10 @@ ST_FUNC void vpop(void) · 10 unmodified lines
740 o(0xd8dd); /* fstp %st(0) */733 o(0xd8dd); /* fstp %st(0) */
741 } else734 } else
742#endif735#endif
743 if (v == VT_JMP || v == VT_JMPI) {736 if (v == VT_CMP) {
744 /* need to put correct jump if && or || without test */737 /* need to put correct jump if && or || without test */
745 gsym(vtop->c.i);738 gsym(vtop->jtrue);
739 gsym(vtop->jfalse);
746 }740 }
747 vtop--;741 vtop--;
748}742}
@@ -823,6 +817,7 @@ ST_FUNC void vrotb(int n) · 74 unmodified lines
823 int i;817 int i;
824 SValue tmp;818 SValue tmp;
825 819
820 vcheck_cmp();
826 tmp = vtop[-n + 1];821 tmp = vtop[-n + 1];
827 for(i=-n+1;i!=0;i++)822 for(i=-n+1;i!=0;i++)
828 vtop[i] = vtop[i+1];823 vtop[i] = vtop[i+1];
@@ -837,6 +832,7 @@ ST_FUNC void vrote(SValue *e, int n) · 8 unmodified lines
837 int i;832 int i;
838 SValue tmp;833 SValue tmp;
839 834
835 vcheck_cmp();
840 tmp = *e;836 tmp = *e;
841 for(i = 0;i < n - 1; i++)837 for(i = 0;i < n - 1; i++)
842 e[-i] = e[-i - 1];838 e[-i] = e[-i - 1];
@@ -851,6 +847,75 @@ ST_FUNC void vrott(int n) · 8 unmodified lines
851 vrote(vtop, n);847 vrote(vtop, n);
852}848}
853 849
850/* ------------------------------------------------------------------------- */
851/* vtop->r = VT_CMP means CPU-flags have been set from comparison or test. */
852
853/* called from generators to set the result from relational ops */
854ST_FUNC void vset_VT_CMP(int op)
855{
856 vtop->r = VT_CMP;
857 vtop->cmp_op = op;
858 vtop->jfalse = 0;
859 vtop->jtrue = 0;
860}
861
862/* called once before asking generators to load VT_CMP to a register */
863static void vset_VT_JMP(void)
864{
865 int op = vtop->cmp_op;
866 if (vtop->jtrue || vtop->jfalse) {
867 /* we need to jump to 'mov $0,%R' or 'mov $1,%R' */
868 int inv = op & (op < 2); /* small optimization */
869 vseti(VT_JMP+inv, gvtst(inv, 0));
870 } else {
871 /* otherwise convert flags (rsp. 0/1) to register */
872 vtop->c.i = op;
873 if (op < 2) /* doesn't seem to happen */
874 vtop->r = VT_CONST;
875 }
876}
877
878/* Set CPU Flags, doesn't yet jump */
879static void gvtst_set(int inv, int t)
880{
881 int *p;
882 if (vtop->r != VT_CMP) {
883 vpushi(0);
884 gen_op(TOK_NE);
885 if (vtop->r != VT_CMP) /* must be VT_CONST then */
886 vset_VT_CMP(vtop->c.i != 0);
887 }
888 p = inv ? &vtop->jfalse : &vtop->jtrue;
889 *p = gjmp_append(*p, t);
890}
891
892/* Generate value test
893 *
894 * Generate a test for any value (jump, comparison and integers) */
895static int gvtst(int inv, int t)
896{
897 int op, u, x;
898
899 gvtst_set(inv, t);
900
901 t = vtop->jtrue, u = vtop->jfalse;
902 if (inv)
903 x = u, u = t, t = x;
904 op = vtop->cmp_op;
905
906 /* jump to the wanted target */
907 if (op > 1)
908 t = gjmp_cond(op ^ inv, t);
909 else if (op != inv)
910 t = gjmp(t);
911 /* resolve complementary jumps to here */
912 gsym(u);
913
914 vtop--;
915 return t;
916}
917
918/* ------------------------------------------------------------------------- */
854/* push a symbol value of TYPE */919/* push a symbol value of TYPE */
855static inline void vpushsym(CType *type, Sym *sym)920static inline void vpushsym(CType *type, Sym *sym)
856{921{
@@ -1591,6 +1656,8 @@ ST_FUNC int gv(int rc) · 734 unmodified lines
1591 /* restore wanted type */1656 /* restore wanted type */
1592 vtop->type.t = t1;1657 vtop->type.t = t1;
1593 } else {1658 } else {
1659 if (vtop->r == VT_CMP)
1660 vset_VT_JMP();
1594 /* one register type load */1661 /* one register type load */
1595 load(r, vtop);1662 load(r, vtop);
1596 }1663 }
@@ -1608,13 +1675,10 @@ ST_FUNC int gv(int rc) · 11 unmodified lines
1608/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */1675/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
1609ST_FUNC void gv2(int rc1, int rc2)1676ST_FUNC void gv2(int rc1, int rc2)
1610{1677{
1611 int v;
1612
1613 /* generate more generic register first. But VT_JMP or VT_CMP1678 /* generate more generic register first. But VT_JMP or VT_CMP
1614 values must be generated first in all cases to avoid possible1679 values must be generated first in all cases to avoid possible
1615 reload errors */1680 reload errors */
1616 v = vtop[0].r & VT_VALMASK;1681 if (vtop->r != VT_CMP && rc1 <= rc2) {
1617 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
1618 vswap();1682 vswap();
1619 gv(rc1);1683 gv(rc1);
1620 vswap();1684 vswap();
@@ -1749,26 +1813,6 @@ static void gv_dup(void) · 128 unmodified lines
1749 }1813 }
1750}1814}
1751 1815
1752/* Generate value test
1753 *
1754 * Generate a test for any value (jump, comparison and integers) */
1755ST_FUNC int gvtst(int inv, int t)
1756{
1757 int v = vtop->r & VT_VALMASK;
1758 if (v != VT_CMP && v != VT_JMP && v != VT_JMPI) {
1759 vpushi(0);
1760 gen_op(TOK_NE);
1761 }
1762 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1763 /* constant jmp optimization */
1764 if ((vtop->c.i != 0) != inv)
1765 t = gjmp(t);
1766 vtop--;
1767 return t;
1768 }
1769 return gtst(inv, t);
1770}
1771
1772#if PTR_SIZE == 41816#if PTR_SIZE == 4
1773/* generate CPU independent (unsigned) long long operations */1817/* generate CPU independent (unsigned) long long operations */
1774static void gen_opl(int op)1818static void gen_opl(int op)
@@ -1974,8 +2018,8 @@ static void gen_opl(int op) · 199 unmodified lines
1974 a = gvtst(1, 0);2018 a = gvtst(1, 0);
1975 if (op != TOK_EQ) {2019 if (op != TOK_EQ) {
1976 /* generate non equal test */2020 /* generate non equal test */
1977 vpushi(TOK_NE);2021 vpushi(0);
1978 vtop->r = VT_CMP;2022 vset_VT_CMP(TOK_NE);
1979 b = gvtst(0, 0);2023 b = gvtst(0, 0);
1980 }2024 }
1981 }2025 }
@@ -1990,9 +2034,12 @@ static void gen_opl(int op) · 8 unmodified lines
1990 else if (op1 == TOK_GE)2034 else if (op1 == TOK_GE)
1991 op1 = TOK_UGE;2035 op1 = TOK_UGE;
1992 gen_op(op1);2036 gen_op(op1);
1993 a = gvtst(1, a);2037#if 0//def TCC_TARGET_I386
1994 gsym(b);2038 if (op == TOK_NE) { gsym(b); break; }
1995 vseti(VT_JMPI, a);2039 if (op == TOK_EQ) { gsym(a); break; }
2040#endif
2041 gvtst_set(1, a);
2042 gvtst_set(0, b);
1996 break;2043 break;
1997 }2044 }
1998}2045}
@@ -5001,11 +5048,12 @@ ST_FUNC void unary(void) · 3002 unmodified lines
5001 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {5048 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5002 gen_cast_s(VT_BOOL);5049 gen_cast_s(VT_BOOL);
5003 vtop->c.i = !vtop->c.i;5050 vtop->c.i = !vtop->c.i;
5004 } else if ((vtop->r & VT_VALMASK) == VT_CMP)5051 } else if (vtop->r == VT_CMP) {
5005 vtop->c.i ^= 1;5052 vtop->cmp_op ^= 1;
5006 else {5053 n = vtop->jfalse, vtop->jfalse = vtop->jtrue, vtop->jtrue = n;
5007 save_regs(1);5054 } else {
5008 vseti(VT_JMP, gvtst(1, 0));5055 vpushi(0);
5056 gen_op(TOK_EQ);
5009 }5057 }
5010 break;5058 break;
5011 case '~':5059 case '~':
@@ -5035,7 +5083,9 @@ ST_FUNC void unary(void) · 23 unmodified lines
5035 next();5083 next();
5036 in_sizeof++;5084 in_sizeof++;
5037 expr_type(&type, unary); /* Perform a in_sizeof = 0; */5085 expr_type(&type, unary); /* Perform a in_sizeof = 0; */
5038 s = vtop[1].sym; /* hack: accessing previous vtop */5086 s = NULL;
5087 if (vtop[1].r & VT_SYM)
5088 s = vtop[1].sym; /* hack: accessing previous vtop */
5039 size = type_size(&type, &align);5089 size = type_size(&type, &align);
5040 if (s && s->a.aligned)5090 if (s && s->a.aligned)
5041 align = 1 << (s->a.aligned - 1);5091 align = 1 << (s->a.aligned - 1);
@@ -5653,7 +5703,7 @@ static void expr_landor(void(*e_fn)(void), int e_op, int i) · 611 unmodified lines
5653 gsym(t);5703 gsym(t);
5654 nocode_wanted -= f;5704 nocode_wanted -= f;
5655 } else {5705 } else {
5656 vseti(VT_JMP + i, gvtst(i, t));5706 gvtst_set(i, t);
5657 }5707 }
5658 break;5708 break;
5659 }5709 }
@@ -5696,6 +5746,16 @@ static int condition_3way(void) · 36 unmodified lines
5696 return c;5746 return c;
5697}5747}
5698 5748
5749static int is_cond_bool(SValue *sv)
5750{
5751 if ((sv->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST
5752 && (sv->type.t & VT_BTYPE) == VT_INT)
5753 return (unsigned)sv->c.i < 2;
5754 if (sv->r == VT_CMP)
5755 return 1;
5756 return 0;
5757}
5758
5699static void expr_cond(void)5759static void expr_cond(void)
5700{5760{
5701 int tt, u, r1, r2, rc, t1, t2, bt1, bt2, islv, c, g;5761 int tt, u, r1, r2, rc, t1, t2, bt1, bt2, islv, c, g;
@@ -5741,6 +5801,12 @@ static void expr_cond(void) · 39 unmodified lines
5741 if (!g)5801 if (!g)
5742 gexpr();5802 gexpr();
5743 5803
5804 if (c < 0 && vtop->r == VT_CMP) {
5805 t1 = gvtst(0, 0);
5806 vpushi(0);
5807 gvtst_set(0, t1);
5808 }
5809
5744 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)5810 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
5745 mk_pointer(&vtop->type);5811 mk_pointer(&vtop->type);
5746 type1 = vtop->type;5812 type1 = vtop->type;
@@ -5761,6 +5827,22 @@ static void expr_cond(void) · 14 unmodified lines
5761 skip(':');5827 skip(':');
5762 expr_cond();5828 expr_cond();
5763 5829
5830 if (c < 0 && is_cond_bool(vtop) && is_cond_bool(&sv)) {
5831 if (sv.r == VT_CMP) {
5832 t1 = sv.jtrue;
5833 t2 = u;
5834 } else {
5835 t1 = gvtst(0, 0);
5836 t2 = gjmp(0);
5837 gsym(u);
5838 vpushv(&sv);
5839 }
5840 gvtst_set(0, t1);
5841 gvtst_set(1, t2);
5842 nocode_wanted = ncw_prev;
5843 // tcc_warning("two conditions expr_cond");
5844 return;
5845 }
5764 5846
5765 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)5847 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
5766 mk_pointer(&vtop->type);5848 mk_pointer(&vtop->type);
@@ -6059,12 +6141,16 @@ static int case_cmp(const void *pa, const void *pb) · 292 unmodified lines
6059 return a < b ? -1 : a > b;6141 return a < b ? -1 : a > b;
6060}6142}
6061 6143
6144static void gtst_addr(int t, int a)
6145{
6146 gsym_addr(gvtst(0, t), a);
6147}
6148
6062static void gcase(struct case_t **base, int len, int *bsym)6149static void gcase(struct case_t **base, int len, int *bsym)
6063{6150{
6064 struct case_t *p;6151 struct case_t *p;
6065 int e;6152 int e;
6066 int ll = (vtop->type.t & VT_BTYPE) == VT_LLONG;6153 int ll = (vtop->type.t & VT_BTYPE) == VT_LLONG;
6067 gv(RC_INT);
6068 while (len > 4) {6154 while (len > 4) {
6069 /* binary search */6155 /* binary search */
6070 p = base[len/2];6156 p = base[len/2];
@@ -6074,7 +6160,7 @@ static void gcase(struct case_t **base, int len, int *bsym) · 3 unmodified lines
6074 else6160 else
6075 vpushi(p->v2);6161 vpushi(p->v2);
6076 gen_op(TOK_LE);6162 gen_op(TOK_LE);
6077 e = gtst(1, 0);6163 e = gvtst(1, 0);
6078 vdup();6164 vdup();
6079 if (ll)6165 if (ll)
6080 vpushll(p->v1);6166 vpushll(p->v1);
@@ -6084,10 +6170,6 @@ static void gcase(struct case_t **base, int len, int *bsym) · 3 unmodified lines
6084 gtst_addr(0, p->sym); /* v1 <= x <= v2 */6170 gtst_addr(0, p->sym); /* v1 <= x <= v2 */
6085 /* x < v1 */6171 /* x < v1 */
6086 gcase(base, len/2, bsym);6172 gcase(base, len/2, bsym);
6087 if (cur_switch->def_sym)
6088 gjmp_addr(cur_switch->def_sym);
6089 else
6090 *bsym = gjmp(*bsym);
6091 /* x > v2 */6173 /* x > v2 */
6092 gsym(e);6174 gsym(e);
6093 e = len/2 + 1;6175 e = len/2 + 1;
@@ -6106,7 +6188,7 @@ static void gcase(struct case_t **base, int len, int *bsym) · 12 unmodified lines
6106 gtst_addr(0, p->sym);6188 gtst_addr(0, p->sym);
6107 } else {6189 } else {
6108 gen_op(TOK_LE);6190 gen_op(TOK_LE);
6109 e = gtst(1, 0);6191 e = gvtst(1, 0);
6110 vdup();6192 vdup();
6111 if (ll)6193 if (ll)
6112 vpushll(p->v1);6194 vpushll(p->v1);
@@ -6117,6 +6199,7 @@ static void gcase(struct case_t **base, int len, int *bsym) · 4 unmodified lines
6117 gsym(e);6199 gsym(e);
6118 }6200 }
6119 }6201 }
6202 *bsym = gjmp(*bsym);
6120}6203}
6121 6204
6122/* call 'func' for each __attribute__((cleanup(func))) */6205/* call 'func' for each __attribute__((cleanup(func))) */
@@ -6367,15 +6450,17 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 244 unmodified lines
6367 gexpr();6450 gexpr();
6368 skip(')');6451 skip(')');
6369 switchval = *vtop--;6452 switchval = *vtop--;
6370 a = 0;6453
6371 b = gjmp(0); /* jump to first case */
6372 sw.p = NULL; sw.n = 0; sw.def_sym = 0;6454 sw.p = NULL; sw.n = 0; sw.def_sym = 0;
6373 saved = cur_switch;6455 saved = cur_switch;
6374 cur_switch = &sw;6456 cur_switch = &sw;
6457 a = 0;
6458 b = gjmp(0); /* jump to first case */
6375 block(&a, current_cleanups, csym, ccl, 0);6459 block(&a, current_cleanups, csym, ccl, 0);
6376 a = gjmp(a); /* add implicit break */6460 a = gjmp(a); /* add implicit break */
6377 /* case lookup */6461 /* case lookup */
6378 gsym(b);6462 gsym(b);
6463
6379 qsort(sw.p, sw.n, sizeof(void*), case_cmp);6464 qsort(sw.p, sw.n, sizeof(void*), case_cmp);
6380 for (b = 1; b < sw.n; b++)6465 for (b = 1; b < sw.n; b++)
6381 if (sw.p[b - 1]->v2 >= sw.p[b]->v1)6466 if (sw.p[b - 1]->v2 >= sw.p[b]->v1)
@@ -6385,14 +6470,17 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 3 unmodified lines
6385 if ((switchval.type.t & VT_BTYPE) == VT_LLONG)6470 if ((switchval.type.t & VT_BTYPE) == VT_LLONG)
6386 switchval.type.t &= ~VT_UNSIGNED;6471 switchval.type.t &= ~VT_UNSIGNED;
6387 vpushv(&switchval);6472 vpushv(&switchval);
6388 gcase(sw.p, sw.n, &a);6473 gv(RC_INT);
6474 d = 0, gcase(sw.p, sw.n, &d);
6389 vpop();6475 vpop();
6390 if (sw.def_sym)6476 if (sw.def_sym)
6391 gjmp_addr(sw.def_sym);6477 gsym_addr(d, sw.def_sym);
6392 dynarray_reset(&sw.p, &sw.n);6478 else
6393 cur_switch = saved;6479 gsym(d);
6394 /* break label */6480 /* break label */
6395 gsym(a);6481 gsym(a);
6482 dynarray_reset(&sw.p, &sw.n);
6483 cur_switch = saved;
6396 6484
6397 } else if (t == TOK_CASE) {6485 } else if (t == TOK_CASE) {
6398 struct case_t *cr = tcc_malloc(sizeof(struct case_t));6486 struct case_t *cr = tcc_malloc(sizeof(struct case_t));
tests/tcctest.c+3−1
@@ -3777,6 +3777,7 @@ void math_cmp_test(void) · 3776 unmodified lines
3777 double one = 1.0;3777 double one = 1.0;
3778 double two = 2.0;3778 double two = 2.0;
3779 int comp = 0;3779 int comp = 0;
3780 int v;
3780#define bug(a,b,op,iop,part) printf("Test broken: %s %s %s %s %d\n", #a, #b, #op, #iop, part)3781#define bug(a,b,op,iop,part) printf("Test broken: %s %s %s %s %d\n", #a, #b, #op, #iop, part)
3781 3782
3782 /* This asserts that "a op b" is _not_ true, but "a iop b" is true.3783 /* This asserts that "a op b" is _not_ true, but "a iop b" is true.
@@ -3798,7 +3799,8 @@ void math_cmp_test(void) · 15 unmodified lines
3798 if ((a iop b) || comp) \3799 if ((a iop b) || comp) \
3799 ; \3800 ; \
3800 else \3801 else \
3801 bug (a,b,op,iop,5);3802 bug (a,b,op,iop,5); \
3803 if (v = !(a op b), !v) bug(a,b,op,iop,7);
3802 3804
3803 /* Equality tests. */3805 /* Equality tests. */
3804 FCMP(nan, nan, ==, !=, 0);3806 FCMP(nan, nan, ==, !=, 0);
x86_64-gen.c+31−69
@@ -471,22 +471,22 @@ void load(int r, SValue *sv) · 470 unmodified lines
471 orex(1,0,r,0x8d); /* lea xxx(%ebp), r */471 orex(1,0,r,0x8d); /* lea xxx(%ebp), r */
472 gen_modrm(r, VT_LOCAL, sv->sym, fc);472 gen_modrm(r, VT_LOCAL, sv->sym, fc);
473 } else if (v == VT_CMP) {473 } else if (v == VT_CMP) {
474 orex(0,r,0,0);
475 if ((fc & ~0x100) != TOK_NE)
476 oad(0xb8 + REG_VALUE(r), 0); /* mov $0, r */
477 else
478 oad(0xb8 + REG_VALUE(r), 1); /* mov $1, r */
479 if (fc & 0x100)474 if (fc & 0x100)
480 {475 {
476 v = vtop->cmp_r;
477 fc &= ~0x100;
481 /* This was a float compare. If the parity bit is478 /* This was a float compare. If the parity bit is
482 set the result was unordered, meaning false for everything479 set the result was unordered, meaning false for everything
483 except TOK_NE, and true for TOK_NE. */480 except TOK_NE, and true for TOK_NE. */
484 fc &= ~0x100;481 orex(0, r, 0, 0xb0 + REG_VALUE(r)); /* mov $0/1,%al */
485 o(0x037a + (REX_BASE(r) << 8));482 g(v ^ fc ^ (v == TOK_NE));
486 }483 o(0x037a + (REX_BASE(r) << 8));
484 }
487 orex(0,r,0, 0x0f); /* setxx %br */485 orex(0,r,0, 0x0f); /* setxx %br */
488 o(fc);486 o(fc);
489 o(0xc0 + REG_VALUE(r));487 o(0xc0 + REG_VALUE(r));
488 orex(0,r,0, 0x0f);
489 o(0xc0b6 + REG_VALUE(r) * 0x900); /* movzbl %al, %eax */
490 } else if (v == VT_JMP || v == VT_JMPI) {490 } else if (v == VT_JMP || v == VT_JMPI) {
491 t = v & 1;491 t = v & 1;
492 orex(0,r,0,0);492 orex(0,r,0,0);
@@ -1666,42 +1666,23 @@ void gjmp_addr(int a) · 1173 unmodified lines
1666 }1666 }
1667}1667}
1668 1668
1669ST_FUNC void gtst_addr(int inv, int a)1669ST_FUNC int gjmp_append(int n, int t)
1670{1670{
1671 int v = vtop->r & VT_VALMASK;1671 void *p;
1672 if (v == VT_CMP) {1672 /* insert vtop->c jump list in t */
1673 inv ^= (vtop--)->c.i;1673 if (n) {
1674 a -= ind + 2;1674 uint32_t n1 = n, n2;
1675 if (a == (char)a) {1675 while ((n2 = read32le(p = cur_text_section->data + n1)))
1676 g(inv - 32);1676 n1 = n2;
1677 g(a);1677 write32le(p, t);
1678 } else {1678 t = n;
1679 g(0x0f);
1680 oad(inv - 16, a - 4);
1681 }
1682 } else if ((v & ~1) == VT_JMP) {
1683 if ((v & 1) != inv) {
1684 gjmp_addr(a);
1685 gsym(vtop->c.i);
1686 } else {
1687 gsym(vtop->c.i);
1688 o(0x05eb);
1689 gjmp_addr(a);
1690 }
1691 vtop--;
1692 }1679 }
1680 return t;
1693}1681}
1694 1682
1695/* generate a test. set 'inv' to invert test. Stack entry is popped */1683ST_FUNC int gjmp_cond(int op, int t)
1696ST_FUNC int gtst(int inv, int t)
1697{1684{
1698 int v = vtop->r & VT_VALMASK;1685 if (op & 0x100)
1699
1700 if (nocode_wanted) {
1701 ;
1702 } else if (v == VT_CMP) {
1703 /* fast case : can jump directly since flags are set */
1704 if (vtop->c.i & 0x100)
1705 {1686 {
1706 /* This was a float compare. If the parity flag is set1687 /* This was a float compare. If the parity flag is set
1707 the result was unordered. For anything except != this1688 the result was unordered. For anything except != this
@@ -1710,9 +1691,10 @@ ST_FUNC int gtst(int inv, int t) · 2 unmodified lines
1710 Take care about inverting the test. We need to jump1691 Take care about inverting the test. We need to jump
1711 to our target if the result was unordered and test wasn't NE,1692 to our target if the result was unordered and test wasn't NE,
1712 otherwise if unordered we don't want to jump. */1693 otherwise if unordered we don't want to jump. */
1713 vtop->c.i &= ~0x100;1694 int v = vtop->cmp_r;
1714 if (inv == (vtop->c.i == TOK_NE))1695 op &= ~0x100;
1715 o(0x067a); /* jp +6 */1696 if (op ^ v ^ (v != TOK_NE))
1697 o(0x067a); /* jp +6 */
1716 else1698 else
1717 {1699 {
1718 g(0x0f);1700 g(0x0f);
@@ -1720,25 +1702,8 @@ ST_FUNC int gtst(int inv, int t) · 1 unmodified line
1720 }1702 }
1721 }1703 }
1722 g(0x0f);1704 g(0x0f);
1723 t = gjmp2((vtop->c.i - 16) ^ inv, t);1705 t = gjmp2(op - 16, t);
1724 } else if (v == VT_JMP || v == VT_JMPI) {1706 return t;
1725 /* && or || optimization */
1726 if ((v & 1) == inv) {
1727 /* insert vtop->c jump list in t */
1728 uint32_t n1, n = vtop->c.i;
1729 if (n) {
1730 while ((n1 = read32le(cur_text_section->data + n)))
1731 n = n1;
1732 write32le(cur_text_section->data + n, t);
1733 t = vtop->c.i;
1734 }
1735 } else {
1736 t = gjmp(t);
1737 gsym(vtop->c.i);
1738 }
1739 }
1740 vtop--;
1741 return t;
1742}1707}
1743 1708
1744/* generate an integer binary operation */1709/* generate an integer binary operation */
@@ -1779,10 +1744,8 @@ void gen_opi(int op) · 34 unmodified lines
1779 o(0xc0 + REG_VALUE(r) + REG_VALUE(fr) * 8);1744 o(0xc0 + REG_VALUE(r) + REG_VALUE(fr) * 8);
1780 }1745 }
1781 vtop--;1746 vtop--;
1782 if (op >= TOK_ULT && op <= TOK_GT) {1747 if (op >= TOK_ULT && op <= TOK_GT)
1783 vtop->r = VT_CMP;1748 vset_VT_CMP(op);
1784 vtop->c.i = op;
1785 }
1786 break;1749 break;
1787 case '-':1750 case '-':
1788 case TOK_SUBC1: /* sub with carry generation */1751 case TOK_SUBC1: /* sub with carry generation */
@@ -1937,8 +1900,7 @@ void gen_opf(int op) · 148 unmodified lines
1937 op = TOK_EQ;1900 op = TOK_EQ;
1938 }1901 }
1939 vtop--;1902 vtop--;
1940 vtop->r = VT_CMP;1903 vset_VT_CMP(op);
1941 vtop->c.i = op;
1942 } else {1904 } else {
1943 /* no memory reference possible for long double operations */1905 /* no memory reference possible for long double operations */
1944 load(TREG_ST0, vtop);1906 load(TREG_ST0, vtop);
@@ -2016,8 +1978,8 @@ void gen_opf(int op) · 71 unmodified lines
2016 }1978 }
2017 1979
2018 vtop--;1980 vtop--;
2019 vtop->r = VT_CMP;1981 vset_VT_CMP(op | 0x100);
2020 vtop->c.i = op | 0x100;1982 vtop->cmp_r = op;
2021 } else {1983 } else {
2022 assert((vtop->type.t & VT_BTYPE) != VT_LDOUBLE);1984 assert((vtop->type.t & VT_BTYPE) != VT_LDOUBLE);
2023 switch(op) {1985 switch(op) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t