aboutsummaryrefslogtreecommitdiff
path: root/lcode.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-09-24 14:34:52 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-09-24 14:34:52 -0300
commit6ef366644f7c3c21cfb17434835edf4ebf970d6d (patch)
treed41df5b79bea32675f740a52d39c0b5ec37eb92b /lcode.c
parent03cde80b58ea7f112f1b7a35c037893093b59f2e (diff)
downloadlua-6ef366644f7c3c21cfb17434835edf4ebf970d6d.tar.gz
lua-6ef366644f7c3c21cfb17434835edf4ebf970d6d.tar.bz2
lua-6ef366644f7c3c21cfb17434835edf4ebf970d6d.zip
Subtraction of small constant integers optimized with OP_ADDI
Diffstat (limited to 'lcode.c')
-rw-r--r--lcode.c68
1 files changed, 41 insertions, 27 deletions
diff --git a/lcode.c b/lcode.c
index 053b66b2..bc86793a 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1213,6 +1213,15 @@ static int isSCint (expdesc *e) {
1213 1213
1214 1214
1215/* 1215/*
1216** Check whether expression 'e' and its negation are literal integers
1217** in proper range to fit in register sC
1218*/
1219static int isSCintN (expdesc *e) {
1220 return luaK_isKint(e) && fitsC(e->u.ival) && fitsC(-e->u.ival);
1221}
1222
1223
1224/*
1216** Check whether expression 'e' is a literal integer or float in 1225** Check whether expression 'e' is a literal integer or float in
1217** proper range to fit in a register (sB or sC). 1226** proper range to fit in a register (sB or sC).
1218*/ 1227*/
@@ -1373,6 +1382,18 @@ static void codebini (FuncState *fs, OpCode op,
1373} 1382}
1374 1383
1375 1384
1385/* Code binary operators negating the immediate operand for the
1386** opcode. For the metamethod, 'v2' must keep its original value.
1387*/
1388static void finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2,
1389 OpCode op, int line, TMS event) {
1390 int v2 = cast_int(e2->u.ival);
1391 finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event);
1392 /* correct metamethod argument */
1393 SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2));
1394}
1395
1396
1376static void swapexps (expdesc *e1, expdesc *e2) { 1397static void swapexps (expdesc *e1, expdesc *e2) {
1377 expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ 1398 expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */
1378} 1399}
@@ -1445,27 +1466,6 @@ static void codebitwise (FuncState *fs, BinOpr opr,
1445 1466
1446 1467
1447/* 1468/*
1448** Code shift operators. If second operand is constant, use immediate
1449** operand (negating it if shift is in the other direction).
1450*/
1451static void codeshift (FuncState *fs, OpCode op,
1452 expdesc *e1, expdesc *e2, int line) {
1453 if (isSCint(e2)) {
1454 if (op == OP_SHR)
1455 codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR);
1456 else {
1457 int offset = cast_int(e2->u.ival);
1458 finishbinexpval(fs, e1, e2, OP_SHRI, int2sC(offset),
1459 0, line, OP_MMBINI, TM_SHL);
1460 SETARG_C(fs->f->code[fs->pc - 2], int2sC(-offset));
1461 }
1462 }
1463 else
1464 codebinexpval(fs, op, e1, e2, line);
1465}
1466
1467
1468/*
1469** Emit code for order comparisons. When using an immediate operand, 1469** Emit code for order comparisons. When using an immediate operand,
1470** 'isfloat' tells whether the original value was a float. 1470** 'isfloat' tells whether the original value was a float.
1471*/ 1471*/
@@ -1646,8 +1646,15 @@ void luaK_posfix (FuncState *fs, BinOpr opr,
1646 codecommutative(fs, opr, e1, e2, line); 1646 codecommutative(fs, opr, e1, e2, line);
1647 break; 1647 break;
1648 } 1648 }
1649 case OPR_SUB: case OPR_DIV: 1649 case OPR_SUB: {
1650 case OPR_IDIV: case OPR_MOD: case OPR_POW: { 1650 if (isSCintN(e2)) { /* subtracting a small integer constant? */
1651 /* code it as (r1 + -I) */
1652 finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB);
1653 break;
1654 }
1655 /* ELSE *//* FALLTHROUGH */
1656 }
1657 case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: {
1651 codearith(fs, opr, e1, e2, 0, line); 1658 codearith(fs, opr, e1, e2, 0, line);
1652 break; 1659 break;
1653 } 1660 }
@@ -1658,14 +1665,21 @@ void luaK_posfix (FuncState *fs, BinOpr opr,
1658 case OPR_SHL: { 1665 case OPR_SHL: {
1659 if (isSCint(e1)) { 1666 if (isSCint(e1)) {
1660 swapexps(e1, e2); 1667 swapexps(e1, e2);
1661 codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); 1668 codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); /* I << r2 */
1669 }
1670 else if (isSCintN(e2)) { /* shifting by a small integer constant? */
1671 /* code it as (r1 >> -I) */
1672 finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL);
1662 } 1673 }
1663 else 1674 else /* regular case (two registers) */
1664 codeshift(fs, OP_SHL, e1, e2, line); 1675 codebinexpval(fs, OP_SHL, e1, e2, line);
1665 break; 1676 break;
1666 } 1677 }
1667 case OPR_SHR: { 1678 case OPR_SHR: {
1668 codeshift(fs, OP_SHR, e1, e2, line); 1679 if (isSCintN(e2))
1680 codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */
1681 else /* regular case (two registers) */
1682 codebinexpval(fs, OP_SHR, e1, e2, line);
1669 break; 1683 break;
1670 } 1684 }
1671 case OPR_EQ: case OPR_NE: { 1685 case OPR_EQ: case OPR_NE: {