Browse Source

new opcodes with immediate integer operand for all arithmetic operations

Roberto Ierusalimschy 7 years ago
parent
commit
8fbe9e3470
5 changed files with 170 additions and 28 deletions
  1. 52 19
      lcode.c
  2. 8 5
      ldebug.c
  3. 13 1
      lopcodes.c
  4. 8 1
      lopcodes.h
  5. 89 2
      lvm.c

+ 52 - 19
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.127 2017/10/01 19:13:43 roberto Exp roberto $
+** $Id: lcode.c,v 2.128 2017/10/02 22:50:57 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -1171,22 +1171,8 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) {
 */
 static void codebinexpval (FuncState *fs, OpCode op,
                            expdesc *e1, expdesc *e2, int line) {
-  int v1, v2;
-  if (op == OP_ADD && (isKint(e1) || isKint(e2))) {
-    if (isKint(e2)) {
-      v2 = cast_int(e2->u.ival);
-      v1 = luaK_exp2anyreg(fs, e1);
-    }
-    else {  /* exchange operands to make 2nd one a constant */
-      v2 = cast_int(e1->u.ival) | BITRK;  /* K bit signal the exchange */
-      v1 = luaK_exp2anyreg(fs, e2);
-    }
-    op = OP_ADDI;
-  }
-  else {
-    v2 = luaK_exp2anyreg(fs, e2);  /* both operands are in registers */
-    v1 = luaK_exp2anyreg(fs, e1);
-  }
+  int v2 = luaK_exp2anyreg(fs, e2);  /* both operands are in registers */
+  int v1 = luaK_exp2anyreg(fs, e1);
   freeexps(fs, e1, e2);
   e1->u.info = luaK_codeABC(fs, op, 0, v1, v2);  /* generate opcode */
   e1->k = VRELOCABLE;  /* all those operations are relocatable */
@@ -1194,6 +1180,44 @@ static void codebinexpval (FuncState *fs, OpCode op,
 }
 
 
+/*
+** Code arithmetic operators ('+', '-', ...). If second operand is a
+** constant in the proper range, use variant opcodes with immediate
+** operands.
+*/
+static void codearith (FuncState *fs, OpCode op,
+                       expdesc *e1, expdesc *e2, int flip, int line) {
+  if (!isKint(e2))
+    codebinexpval(fs, op, e1, e2, line);  /* use standard operators */
+  else {  /* use immediate operators */
+    int v2 = cast_int(e2->u.ival);  /* immediate operand */
+    int v1 = luaK_exp2anyreg(fs, e1);
+    if (flip)
+      v2 |= BITRK;  /* signal that operands were flipped */
+    op = cast(OpCode, op - OP_ADD + OP_ADDI);
+    freeexp(fs, e1);
+    e1->u.info = luaK_codeABC(fs, op, 0, v1, v2);  /* generate opcode */
+    e1->k = VRELOCABLE;  /* all those operations are relocatable */
+    luaK_fixline(fs, line);
+  }
+}
+
+
+/*
+** Code commutative operators ('+', '*'). If first operand is a
+** constant, change order of operands to use immediate operator.
+*/
+static void codecommutative (FuncState *fs, OpCode op,
+                             expdesc *e1, expdesc *e2, int line) {
+  int flip = 0;
+  if (isKint(e1)) {
+    expdesc temp = *e1; *e1 = *e2; *e2 = temp;  /* swap 'e1' and 'e2' */
+    flip = 1;
+  }
+  codearith(fs, op, e1, e2, flip, line);
+}
+
+
 /*
 ** Emit code for comparisons.
 ** 'e1' was already put in register by 'luaK_infix'.
@@ -1318,8 +1342,17 @@ void luaK_posfix (FuncState *fs, BinOpr op,
       }
       break;
     }
-    case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
-    case OPR_IDIV: case OPR_MOD: case OPR_POW:
+    case OPR_ADD: case OPR_MUL: {
+      if (!constfolding(fs, op + LUA_OPADD, e1, e2))
+        codecommutative(fs, cast(OpCode, op + OP_ADD), e1, e2, line);
+      break;
+    }
+    case OPR_SUB: case OPR_DIV:
+    case OPR_IDIV: case OPR_MOD: case OPR_POW: {
+      if (!constfolding(fs, op + LUA_OPADD, e1, e2))
+        codearith(fs, cast(OpCode, op + OP_ADD), e1, e2, 0, line);
+      break;
+    }
     case OPR_BAND: case OPR_BOR: case OPR_BXOR:
     case OPR_SHL: case OPR_SHR: {
       if (!constfolding(fs, op + LUA_OPADD, e1, e2))

+ 8 - 5
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.129 2017/07/07 16:34:32 roberto Exp roberto $
+** $Id: ldebug.c,v 2.130 2017/07/10 17:35:12 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -592,14 +592,17 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
     case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD:
       tm = TM_NEWINDEX;
       break;
-    case OP_ADDI:
-      tm =  TM_ADD;
+    case OP_ADDI: case OP_SUBI: case OP_MULI: case OP_MODI:
+    case OP_POWI: case OP_DIVI: case OP_IDIVI: {
+      int offset = GET_OPCODE(i) - OP_ADDI;  /* ORDER OP */
+      tm = cast(TMS, offset + TM_ADD);  /* ORDER TM */
       break;
+    }
     case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD:
     case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND:
     case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: {
-      int offset = cast_int(GET_OPCODE(i)) - cast_int(OP_ADD);  /* ORDER OP */
-      tm = cast(TMS, offset + cast_int(TM_ADD));  /* ORDER TM */
+      int offset = GET_OPCODE(i) - OP_ADD;  /* ORDER OP */
+      tm = cast(TMS, offset + TM_ADD);  /* ORDER TM */
       break;
     }
     case OP_UNM: tm = TM_UNM; break;

+ 13 - 1
lopcodes.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.c,v 1.64 2017/09/26 18:14:45 roberto Exp roberto $
+** $Id: lopcodes.c,v 1.65 2017/09/28 16:53:29 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -38,6 +38,12 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
   "NEWTABLE",
   "SELF",
   "ADDI",
+  "SUBI",
+  "MULI",
+  "MODI",
+  "POWI",
+  "DIVI",
+  "IDIVI",
   "ADD",
   "SUB",
   "MUL",
@@ -99,6 +105,12 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
  ,opmode(0, 1, iABC)		/* OP_NEWTABLE */
  ,opmode(0, 1, iABC)		/* OP_SELF */
  ,opmode(0, 1, iABC)		/* OP_ADDI */
+ ,opmode(0, 1, iABC)		/* OP_SUBI */
+ ,opmode(0, 1, iABC)		/* OP_MULI */
+ ,opmode(0, 1, iABC)		/* OP_MODI */
+ ,opmode(0, 1, iABC)		/* OP_POWI */
+ ,opmode(0, 1, iABC)		/* OP_DIVI */
+ ,opmode(0, 1, iABC)		/* OP_IDIVI */
  ,opmode(0, 1, iABC)		/* OP_ADD */
  ,opmode(0, 1, iABC)		/* OP_SUB */
  ,opmode(0, 1, iABC)		/* OP_MUL */

+ 8 - 1
lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.163 2017/10/01 19:13:43 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.164 2017/10/02 22:51:32 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -201,6 +201,13 @@ OP_NEWTABLE,/*	A B C	R(A) := {} (size = B,C)				*/
 OP_SELF,/*	A B C	R(A+1) := R(B); R(A) := R(B)[RK(C):string]	*/
 
 OP_ADDI,/*	A B C	R(A) := R(B) + C				*/
+OP_SUBI,/*	A B C	R(A) := R(B) - C				*/
+OP_MULI,/*	A B C	R(A) := R(B) * C				*/
+OP_MODI,/*	A B C	R(A) := R(B) % C				*/
+OP_POWI,/*	A B C	R(A) := R(B) ^ C				*/
+OP_DIVI,/*	A B C	R(A) := R(B) / C				*/
+OP_IDIVI,/*	A B C	R(A) := R(B) // C				*/
+
 OP_ADD,/*	A B C	R(A) := R(B) + R(C)				*/
 OP_SUB,/*	A B C	R(A) := R(B) - R(C)				*/
 OP_MUL,/*	A B C	R(A) := R(B) * R(C)				*/

+ 89 - 2
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.296 2017/09/28 16:53:29 roberto Exp roberto $
+** $Id: lvm.c,v 2.297 2017/10/01 19:13:43 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -663,7 +663,10 @@ void luaV_finishOp (lua_State *L) {
   Instruction inst = *(ci->u.l.savedpc - 1);  /* interrupted instruction */
   OpCode op = GET_OPCODE(inst);
   switch (op) {  /* finish its execution */
-    case OP_ADDI: case OP_ADD: case OP_SUB:
+    case OP_ADDI: case OP_SUBI:
+    case OP_MULI: case OP_DIVI: case OP_IDIVI:
+    case OP_MODI: case OP_POWI:
+    case OP_ADD: case OP_SUB:
     case OP_MUL: case OP_DIV: case OP_IDIV:
     case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR:
     case OP_MOD: case OP_POW:
@@ -1001,6 +1004,90 @@ void luaV_execute (lua_State *L) {
           Protect(luaT_trybiniTM(L, rb, ic, GETARG_Ck(i), ra, TM_ADD));
         vmbreak;
       }
+      vmcase(OP_SUBI) {
+        TValue *rb = vRB(i);
+        int ic = GETARG_Cr(i);
+        lua_Number nb;
+        if (ttisinteger(rb)) {
+          setivalue(s2v(ra), intop(-, ivalue(rb), ic));
+        }
+        else if (tonumberns(rb, nb)) {
+          setfltvalue(s2v(ra), luai_numsub(L, nb, cast_num(ic)));
+        }
+        else
+          Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_SUB));
+        vmbreak;
+      }
+      vmcase(OP_MULI) {
+        TValue *rb = vRB(i);
+        int ic = GETARG_Cr(i);
+        lua_Number nb;
+        if (ttisinteger(rb)) {
+          setivalue(s2v(ra), intop(*, ivalue(rb), ic));
+        }
+        else if (tonumberns(rb, nb)) {
+          setfltvalue(s2v(ra), luai_nummul(L, nb, cast_num(ic)));
+        }
+        else
+          Protect(luaT_trybiniTM(L, rb, ic, GETARG_Ck(i), ra, TM_MUL));
+        vmbreak;
+      }
+      vmcase(OP_MODI) {
+        TValue *rb = vRB(i);
+        int ic = GETARG_Cr(i);
+        lua_Number nb;
+        if (ttisinteger(rb)) {
+          setivalue(s2v(ra), luaV_mod(L, ivalue(rb), ic));
+        }
+        else if (tonumberns(rb, nb)) {
+          lua_Number m;
+          lua_Number nc = cast_num(ic);
+          luai_nummod(L, nb, nc, m);
+          setfltvalue(s2v(ra), m);
+        }
+        else
+          Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_MOD));
+        vmbreak;
+      }
+      vmcase(OP_POWI) {
+        TValue *rb = vRB(i);
+        int ic = GETARG_Cr(i);
+        lua_Number nb;
+        if (tonumberns(rb, nb)) {
+          lua_Number nc = cast_num(ic);
+          setfltvalue(s2v(ra), luai_numpow(L, nb, nc));
+        }
+        else
+          Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_POW));
+        vmbreak;
+      }
+      vmcase(OP_DIVI) {
+        TValue *rb = vRB(i);
+        int ic = GETARG_Cr(i);
+        lua_Number nb;
+        if (tonumberns(rb, nb)) {
+          lua_Number nc = cast_num(ic);
+          setfltvalue(s2v(ra), luai_numdiv(L, nb, nc));
+        }
+        else
+          Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_DIV));
+        vmbreak;
+      }
+      vmcase(OP_IDIVI) {
+        TValue *rb = vRB(i);
+        int ic = GETARG_Cr(i);
+        lua_Number nb;
+        if (ttisinteger(rb)) {
+          setivalue(s2v(ra), luaV_div(L, ivalue(rb), ic));
+        }
+        else if (tonumberns(rb, nb)) {
+          lua_Number nc = cast_num(ic);
+          setfltvalue(s2v(ra), luai_numdiv(L, nb, nc));
+        }
+        else
+          Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_IDIV));
+        vmbreak;
+      }
       vmcase(OP_ADD) {
         TValue *rb = vRB(i);
         TValue *rc = vRC(i);