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
13311331 return gjmp(t);
13321332 }
13331333
1334−static void arm64_gen_opil(int op, int l)
1334+static int arm64_iconst(uint64_t *val, SValue *sv)
13351335 {
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+
1353+static 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+
1429+static 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+
13371459 gv2(RC_INT, RC_INT);
13381460 assert(vtop[-1].r < VT_CONST && vtop[0].r < VT_CONST);
13391461 a = intr(vtop[-1].r);
tests/tests2/73_arm64.c+83−0
@@ -2,6 +2,7 @@ · 1 unmodified line
22 // calling convention, but should give the same results on any architecture.
33
44 #include <stdarg.h>
5+#include <stdint.h>
56 #include <stdio.h>
67
78 struct s1 { char x[1]; } s1 = { "0" };
@@ -429,12 +430,94 @@ void movi(void) · 421 unmodified lines
429430 pll(0xabcdef0123456789);
430431 }
431432
433+static uint32_t addip0(uint32_t x) { return x + 0; }
434+static uint64_t sublp0(uint64_t x) { return x - 0; }
435+static uint32_t addip123(uint32_t x) { return x + 123; }
436+static uint64_t addlm123(uint64_t x) { return x + -123; }
437+static uint64_t sublp4095(uint64_t x) { return x - 4095; }
438+static uint32_t subim503808(uint32_t x) { return x - -503808; }
439+static uint64_t addp12345(uint64_t x) { return x + 12345; }
440+static uint32_t subp12345(uint32_t x) { return x - 12345; }
441+
442+static uint32_t mvni(uint32_t x) { return 0xffffffff - x; }
443+static uint64_t negl(uint64_t x) { return 0 - x; }
444+static uint32_t rsbi123(uint32_t x) { return 123 - x; }
445+static uint64_t rsbl123(uint64_t x) { return 123 - x; }
446+
447+static uint32_t andi0(uint32_t x) { return x & 0; }
448+static uint64_t andlm1(uint64_t x) { return x & -1; }
449+static uint64_t orrl0(uint64_t x) { return x | 0; }
450+static uint32_t orrim1(uint32_t x) { return x | -1; }
451+static uint32_t eori0(uint32_t x) { return x ^ 0; }
452+static uint64_t eorlm1(uint64_t x) { return x ^ -1; }
453+static uint32_t and0xf0(uint32_t x) { return x & 0xf0; }
454+static uint64_t orr0xf0(uint64_t x) { return x | 0xf0; }
455+static uint64_t eor0xf0(uint64_t x) { return x ^ 0xf0; }
456+
457+static uint32_t lsli0(uint32_t x) { return x << 0; }
458+static uint32_t lsri0(uint32_t x) { return x >> 0; }
459+static int64_t asrl0(int64_t x) { return x >> 0; }
460+static uint32_t lsli1(uint32_t x) { return x << 1; }
461+static uint32_t lsli31(uint32_t x) { return x << 31; }
462+static uint64_t lsll1(uint64_t x) { return x << 1; }
463+static uint64_t lsll63(uint64_t x) { return x << 63; }
464+static uint32_t lsri1(uint32_t x) { return x >> 1; }
465+static uint32_t lsri31(uint32_t x) { return x >> 31; }
466+static uint64_t lsrl1(uint64_t x) { return x >> 1; }
467+static uint64_t lsrl63(uint64_t x) { return x >> 63; }
468+static int32_t asri1(int32_t x) { return x >> 1; }
469+static int32_t asri31(int32_t x) { return x >> 31; }
470+static int64_t asrl1(int64_t x) { return x >> 1; }
471+static int64_t asrl63(int64_t x) { return x >> 63; }
472+
473+void 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+
432514 void pcs(void)
433515 {
434516 arg();
435517 ret();
436518 stdarg();
437519 movi();
520+ opi();
438521 }
439522
440523 int main()
tests/tests2/73_arm64.expect+36−0
@@ -136,3 +136,39 @@ abcd1234ffffffff · 135 unmodified lines
136136 ffffef0123456789
137137 abcdef012345ffff
138138 abcdef0123456789
139+3e8
140+3e8
141+463
142+36d
143+fffffffffffff3e9
144+7b3e8
145+3421
146+ffffd3af
147+fffffc17
148+fffffffffffffc18
149+fffffc93
150+fffffffffffffc93
151+0
152+3e8
153+3e8
154+ffffffff
155+3e8
156+fffffffffffffc17
157+e0
158+3f8
159+318
160+3e8
161+3e8
162+3e8
163+7d0
164+0
165+7d0
166+0
167+1f4
168+0
169+1f4
170+0
171+1f4
172+0
173+1f4
174+0

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