History

arm64: Optimise some integer operations with a constant operand.

Edmund Grimley Evans committed 11 years ago

Commit d854ded1 parent ac70e6b3 files · +243 −2Browse files

Unified · Split

3 files
  1. arm64-gen.c +124 −2
  2. tests/tests2/73_arm64.c +83 −0
  3. tests/tests2/73_arm64.expect +36 −0
arm64-gen.c+124−2
@@ -1331,9 +1331,131 @@ ST_FUNC int gtst(int inv, int t) · 1330 unmodified lines
1331 return gjmp(t);1331 return gjmp(t);
1332}1332}
1333 1333
1334static void arm64_gen_opil(int op, int l)1334static int arm64_iconst(uint64_t *val, SValue *sv)
1335{1335{
1336 int x, a, b;1336 if ((sv->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
1337 return 0;
1338 if (val) {
1339 int t = sv->type.t & (VT_BTYPE | VT_UNSIGNED);
1340 // It's crazy how TCC has all these alternatives for storing a value:
1341 if (t == (VT_LLONG | VT_UNSIGNED))
1342 *val = sv->c.ull;
1343 else if (t == VT_LLONG)
1344 *val = sv->c.ll;
1345 else if (t & VT_UNSIGNED)
1346 *val = sv->c.ui;
1347 else
1348 *val = sv->c.i;
1349 }
1350 return 1;
1351}
1352
1353static int arm64_gen_opic(int op, uint32_t l, int rev, uint64_t val,
1354 uint32_t x, uint32_t a)
1355{
1356 if (op == '-' && !rev) {
1357 val = -val;
1358 op = '+';
1359 }
1360 val = l ? val : (uint32_t)val;
1361
1362 switch (op) {
1363
1364 case '+': {
1365 int s = l ? val >> 63 : val >> 31;
1366 val = s ? -val : val;
1367 val = l ? val : (uint32_t)val;
1368 if (!(val & ~(uint64_t)0xfff))
1369 o(0x11000000 | l << 31 | s << 30 | x | a << 5 | val << 10);
1370 else if (!(val & ~(uint64_t)0xfff000))
1371 o(0x11400000 | l << 31 | s << 30 | x | a << 5 | val >> 12 << 10);
1372 else {
1373 arm64_movimm(30, val); // use x30
1374 o(0x0b1e0000 | l << 31 | s << 30 | x | a << 5);
1375 }
1376 return 1;
1377 }
1378
1379 case '-':
1380 if (!val)
1381 o(0x4b0003e0 | l << 31 | x | a << 16); // neg
1382 else if (val == (l ? (uint64_t)-1 : (uint32_t)-1))
1383 o(0x2a2003e0 | l << 31 | x | a << 16); // mvn
1384 else {
1385 arm64_movimm(30, val); // use x30
1386 o(0x4b0003c0 | l << 31 | x | a << 16); // sub
1387 }
1388 return 1;
1389
1390 case '^':
1391 if (val == -1 || (val == 0xffffffff && !l)) {
1392 o(0x2a2003e0 | l << 31 | x | a << 16); // mvn
1393 return 1;
1394 }
1395 // fall through
1396 case '&':
1397 case '|': {
1398 int e = arm64_encode_bimm64(l ? val : val | val << 32);
1399 if (e < 0)
1400 return 0;
1401 o((op == '&' ? 0x12000000 :
1402 op == '|' ? 0x32000000 : 0x52000000) |
1403 l << 31 | x | a << 5 | (uint32_t)e << 10);
1404 return 1;
1405 }
1406
1407 case TOK_SAR:
1408 case TOK_SHL:
1409 case TOK_SHR: {
1410 uint32_t n = 32 << l;
1411 val = val & (n - 1);
1412 if (rev)
1413 return 0;
1414 if (!val)
1415 assert(0);
1416 else if (op == TOK_SHL)
1417 o(0x53000000 | l << 31 | l << 22 | x | a << 5 |
1418 (n - val) << 16 | (n - 1 - val) << 10); // lsl
1419 else
1420 o(0x13000000 | (op == TOK_SHR) << 30 | l << 31 | l << 22 |
1421 x | a << 5 | val << 16 | (n - 1) << 10); // lsr/asr
1422 return 1;
1423 }
1424
1425 }
1426 return 0;
1427}
1428
1429static void arm64_gen_opil(int op, uint32_t l)
1430{
1431 uint32_t x, a, b;
1432
1433 // Special treatment for operations with a constant operand:
1434 {
1435 uint64_t val;
1436 int rev = 1;
1437
1438 if (arm64_iconst(0, &vtop[0])) {
1439 vswap();
1440 rev = 0;
1441 }
1442 if (arm64_iconst(&val, &vtop[-1])) {
1443 gv(RC_INT);
1444 a = intr(vtop[0].r);
1445 --vtop;
1446 x = get_reg(RC_INT);
1447 ++vtop;
1448 if (arm64_gen_opic(op, l, rev, val, intr(x), a)) {
1449 vtop[0].r = x;
1450 vswap();
1451 --vtop;
1452 return;
1453 }
1454 }
1455 if (!rev)
1456 vswap();
1457 }
1458
1337 gv2(RC_INT, RC_INT);1459 gv2(RC_INT, RC_INT);
1338 assert(vtop[-1].r < VT_CONST && vtop[0].r < VT_CONST);1460 assert(vtop[-1].r < VT_CONST && vtop[0].r < VT_CONST);
1339 a = intr(vtop[-1].r);1461 a = intr(vtop[-1].r);
tests/tests2/73_arm64.c+83−0
@@ -2,6 +2,7 @@ · 1 unmodified line
2// calling convention, but should give the same results on any architecture.2// calling convention, but should give the same results on any architecture.
3 3
4#include <stdarg.h>4#include <stdarg.h>
5#include <stdint.h>
5#include <stdio.h>6#include <stdio.h>
6 7
7struct s1 { char x[1]; } s1 = { "0" };8struct s1 { char x[1]; } s1 = { "0" };
@@ -429,12 +430,94 @@ void movi(void) · 421 unmodified lines
429 pll(0xabcdef0123456789);430 pll(0xabcdef0123456789);
430}431}
431 432
433static uint32_t addip0(uint32_t x) { return x + 0; }
434static uint64_t sublp0(uint64_t x) { return x - 0; }
435static uint32_t addip123(uint32_t x) { return x + 123; }
436static uint64_t addlm123(uint64_t x) { return x + -123; }
437static uint64_t sublp4095(uint64_t x) { return x - 4095; }
438static uint32_t subim503808(uint32_t x) { return x - -503808; }
439static uint64_t addp12345(uint64_t x) { return x + 12345; }
440static uint32_t subp12345(uint32_t x) { return x - 12345; }
441
442static uint32_t mvni(uint32_t x) { return 0xffffffff - x; }
443static uint64_t negl(uint64_t x) { return 0 - x; }
444static uint32_t rsbi123(uint32_t x) { return 123 - x; }
445static uint64_t rsbl123(uint64_t x) { return 123 - x; }
446
447static uint32_t andi0(uint32_t x) { return x & 0; }
448static uint64_t andlm1(uint64_t x) { return x & -1; }
449static uint64_t orrl0(uint64_t x) { return x | 0; }
450static uint32_t orrim1(uint32_t x) { return x | -1; }
451static uint32_t eori0(uint32_t x) { return x ^ 0; }
452static uint64_t eorlm1(uint64_t x) { return x ^ -1; }
453static uint32_t and0xf0(uint32_t x) { return x & 0xf0; }
454static uint64_t orr0xf0(uint64_t x) { return x | 0xf0; }
455static uint64_t eor0xf0(uint64_t x) { return x ^ 0xf0; }
456
457static uint32_t lsli0(uint32_t x) { return x << 0; }
458static uint32_t lsri0(uint32_t x) { return x >> 0; }
459static int64_t asrl0(int64_t x) { return x >> 0; }
460static uint32_t lsli1(uint32_t x) { return x << 1; }
461static uint32_t lsli31(uint32_t x) { return x << 31; }
462static uint64_t lsll1(uint64_t x) { return x << 1; }
463static uint64_t lsll63(uint64_t x) { return x << 63; }
464static uint32_t lsri1(uint32_t x) { return x >> 1; }
465static uint32_t lsri31(uint32_t x) { return x >> 31; }
466static uint64_t lsrl1(uint64_t x) { return x >> 1; }
467static uint64_t lsrl63(uint64_t x) { return x >> 63; }
468static int32_t asri1(int32_t x) { return x >> 1; }
469static int32_t asri31(int32_t x) { return x >> 31; }
470static int64_t asrl1(int64_t x) { return x >> 1; }
471static int64_t asrl63(int64_t x) { return x >> 63; }
472
473void opi(void)
474{
475 int x = 1000;
476 pll(addip0(x));
477 pll(sublp0(x));
478 pll(addip123(x));
479 pll(addlm123(x));
480 pll(sublp4095(x));
481 pll(subim503808(x));
482 pll(addp12345(x));
483 pll(subp12345(x));
484 pll(mvni(x));
485 pll(negl(x));
486 pll(rsbi123(x));
487 pll(rsbl123(x));
488 pll(andi0(x));
489 pll(andlm1(x));
490 pll(orrl0(x));
491 pll(orrim1(x));
492 pll(eori0(x));
493 pll(eorlm1(x));
494 pll(and0xf0(x));
495 pll(orr0xf0(x));
496 pll(eor0xf0(x));
497 pll(lsli0(x));
498 pll(lsri0(x));
499 pll(asrl0(x));
500 pll(lsli1(x));
501 pll(lsli31(x));
502 pll(lsll1(x));
503 pll(lsll63(x));
504 pll(lsri1(x));
505 pll(lsri31(x));
506 pll(lsrl1(x));
507 pll(lsrl63(x));
508 pll(asri1(x));
509 pll(asri31(x));
510 pll(asrl1(x));
511 pll(asrl63(x));
512}
513
432void pcs(void)514void pcs(void)
433{515{
434 arg();516 arg();
435 ret();517 ret();
436 stdarg();518 stdarg();
437 movi();519 movi();
520 opi();
438}521}
439 522
440int main()523int main()
tests/tests2/73_arm64.expect+36−0
@@ -136,3 +136,39 @@ abcd1234ffffffff · 135 unmodified lines
136ffffef0123456789136ffffef0123456789
137abcdef012345ffff137abcdef012345ffff
138abcdef0123456789138abcdef0123456789
1393e8
1403e8
141463
14236d
143fffffffffffff3e9
1447b3e8
1453421
146ffffd3af
147fffffc17
148fffffffffffffc18
149fffffc93
150fffffffffffffc93
1510
1523e8
1533e8
154ffffffff
1553e8
156fffffffffffffc17
157e0
1583f8
159318
1603e8
1613e8
1623e8
1637d0
1640
1657d0
1660
1671f4
1680
1691f4
1700
1711f4
1720
1731f4
1740

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