浏览代码

DUALNUM: Add integer variant of MIN/MAX.

Mike Pall 14 年之前
父节点
当前提交
7fb1075903
共有 6 个文件被更改,包括 64 次插入7 次删除
  1. 23 2
      src/lj_asm.c
  2. 11 3
      src/lj_ffrecord.c
  3. 12 0
      src/lj_ir.c
  4. 1 0
      src/lj_iropt.h
  5. 16 2
      src/lj_opt_fold.c
  6. 1 0
      src/lj_target_x86.h

+ 23 - 2
src/lj_asm.c

@@ -3005,6 +3005,17 @@ static void asm_neg_not(ASMState *as, IRIns *ir, x86Group3 xg)
   ra_left(as, dest, ir->op1);
 }
 
+static void asm_min_max(ASMState *as, IRIns *ir, int cc)
+{
+  Reg right, dest = ra_dest(as, ir, RSET_GPR);
+  IRRef lref = ir->op1, rref = ir->op2;
+  if (irref_isk(rref)) { lref = rref; rref = ir->op1; }
+  right = ra_alloc1(as, rref, rset_exclude(RSET_GPR, dest));
+  emit_rr(as, XO_CMOV + (cc<<24), REX_64IR(ir, dest), right);
+  emit_rr(as, XO_CMP, REX_64IR(ir, dest), right);
+  ra_left(as, dest, lref);
+}
+
 static void asm_bitswap(ASMState *as, IRIns *ir)
 {
   Reg dest = ra_dest(as, ir, RSET_GPR);
@@ -4067,8 +4078,18 @@ static void asm_ir(ASMState *as, IRIns *ir)
     break;
   case IR_ABS: asm_fparith(as, ir, XO_ANDPS); break;
 
-  case IR_MIN: asm_fparith(as, ir, XO_MINSD); break;
-  case IR_MAX: asm_fparith(as, ir, XO_MAXSD); break;
+  case IR_MIN:
+    if (irt_isnum(ir->t))
+      asm_fparith(as, ir, XO_MINSD);
+    else
+      asm_min_max(as, ir, CC_G);
+    break;
+  case IR_MAX:
+    if (irt_isnum(ir->t))
+      asm_fparith(as, ir, XO_MAXSD);
+    else
+      asm_min_max(as, ir, CC_L);
+    break;
 
   case IR_FPMATH: case IR_ATAN2: case IR_LDEXP:
     asm_fpmath(as, ir);

+ 11 - 3
src/lj_ffrecord.c

@@ -488,11 +488,19 @@ static void LJ_FASTCALL recff_math_pow(jit_State *J, RecordFFData *rd)
 
 static void LJ_FASTCALL recff_math_minmax(jit_State *J, RecordFFData *rd)
 {
-  TRef tr = lj_ir_tonum(J, J->base[0]);
+  TRef tr = lj_ir_tonumber(J, J->base[0]);
   uint32_t op = rd->data;
   BCReg i;
-  for (i = 1; J->base[i] != 0; i++)
-    tr = emitir(IRTN(op), tr, lj_ir_tonum(J, J->base[i]));
+  for (i = 1; J->base[i] != 0; i++) {
+    TRef tr2 = lj_ir_tonumber(J, J->base[i]);
+    IRType t = IRT_INT;
+    if (!(tref_isinteger(tr) && tref_isinteger(tr2))) {
+      if (tref_isinteger(tr)) tr = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT);
+      if (tref_isinteger(tr2)) tr2 = emitir(IRTN(IR_CONV), tr2, IRCONV_NUM_INT);
+      t = IRT_NUM;
+    }
+    tr = emitir(IRT(op, t), tr, tr2);
+  }
   J->base[0] = tr;
 }
 

+ 12 - 0
src/lj_ir.c

@@ -401,6 +401,18 @@ void lj_ir_kvalue(lua_State *L, TValue *tv, const IRIns *ir)
 
 /* -- Convert IR operand types -------------------------------------------- */
 
+/* Convert from string to number. */
+TRef LJ_FASTCALL lj_ir_tonumber(jit_State *J, TRef tr)
+{
+  if (!tref_isnumber(tr)) {
+    if (tref_isstr(tr))
+      tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0);
+    else
+      lj_trace_err(J, LJ_TRERR_BADTYPE);
+  }
+  return tr;
+}
+
 /* Convert from integer or string to number. */
 TRef LJ_FASTCALL lj_ir_tonum(jit_State *J, TRef tr)
 {

+ 1 - 0
src/lj_iropt.h

@@ -82,6 +82,7 @@ static LJ_AINLINE TRef lj_ir_knum(jit_State *J, lua_Number n)
 LJ_FUNC void lj_ir_kvalue(lua_State *L, TValue *tv, const IRIns *ir);
 
 /* Convert IR operand types. */
+LJ_FUNC TRef LJ_FASTCALL lj_ir_tonumber(jit_State *J, TRef tr);
 LJ_FUNC TRef LJ_FASTCALL lj_ir_tonum(jit_State *J, TRef tr);
 LJ_FUNC TRef LJ_FASTCALL lj_ir_tostr(jit_State *J, TRef tr);
 

+ 16 - 2
src/lj_opt_fold.c

@@ -226,6 +226,8 @@ static int32_t kfold_intop(int32_t k1, int32_t k2, IROp op)
   case IR_BSAR: k1 >>= (k2 & 31); break;
   case IR_BROL: k1 = (int32_t)lj_rol((uint32_t)k1, (k2 & 31)); break;
   case IR_BROR: k1 = (int32_t)lj_ror((uint32_t)k1, (k2 & 31)); break;
+  case IR_MIN: k1 = k1 < k2 ? k1 : k2; break;
+  case IR_MAX: k1 = k1 > k2 ? k1 : k2; break;
   default: lua_assert(0); break;
   }
   return k1;
@@ -242,6 +244,8 @@ LJFOLD(BSHR KINT KINT)
 LJFOLD(BSAR KINT KINT)
 LJFOLD(BROL KINT KINT)
 LJFOLD(BROR KINT KINT)
+LJFOLD(MIN KINT KINT)
+LJFOLD(MAX KINT KINT)
 LJFOLDF(kfold_intarith)
 {
   return INTFOLD(kfold_intop(fleft->i, fright->i, (IROp)fins->o));
@@ -1434,19 +1438,29 @@ LJFOLDF(reassoc_shift)
 
 LJFOLD(MIN MIN KNUM)
 LJFOLD(MAX MAX KNUM)
+LJFOLD(MIN MIN KINT)
+LJFOLD(MAX MAX KINT)
 LJFOLDF(reassoc_minmax_k)
 {
   IRIns *irk = IR(fleft->op2);
   if (irk->o == IR_KNUM) {
     lua_Number a = ir_knum(irk)->n;
-    lua_Number b = knumright;
-    lua_Number y = lj_vm_foldarith(a, b, fins->o - IR_ADD);
+    lua_Number y = lj_vm_foldarith(a, knumright, fins->o - IR_ADD);
     if (a == y)  /* (x o k1) o k2 ==> x o k1, if (k1 o k2) == k1. */
       return LEFTFOLD;
     PHIBARRIER(fleft);
     fins->op1 = fleft->op1;
     fins->op2 = (IRRef1)lj_ir_knum(J, y);
     return RETRYFOLD;  /* (x o k1) o k2 ==> x o (k1 o k2) */
+  } else if (irk->o == IR_KINT) {
+    int32_t a = irk->i;
+    int32_t y = kfold_intop(a, fright->i, fins->o);
+    if (a == y)  /* (x o k1) o k2 ==> x o k1, if (k1 o k2) == k1. */
+      return LEFTFOLD;
+    PHIBARRIER(fleft);
+    fins->op1 = fleft->op1;
+    fins->op2 = (IRRef1)lj_ir_kint(J, y);
+    return RETRYFOLD;  /* (x o k1) o k2 ==> x o (k1 o k2) */
   }
   return NEXTFOLD;
 }

+ 1 - 0
src/lj_target_x86.h

@@ -234,6 +234,7 @@ typedef enum {
   XO_MOVSXw =	XO_0f(bf),
   XO_MOVSXd =	XO_(63),
   XO_BSWAP =	XO_0f(c8),
+  XO_CMOV =	XO_0f(40),
 
   XO_MOVSD =	XO_f20f(10),
   XO_MOVSDto =	XO_f20f(11),