Browse Source

Add weak guards. Emit TNEW/TDUP with a guard bit.

Mike Pall 15 years ago
parent
commit
5ff994fa37
5 changed files with 63 additions and 63 deletions
  1. 2 2
      lib/dump.lua
  2. 18 21
      src/lj_asm.c
  3. 40 37
      src/lj_ir.h
  4. 1 1
      src/lj_opt_dce.c
  5. 2 2
      src/lj_record.c

+ 2 - 2
lib/dump.lua

@@ -391,8 +391,8 @@ local function dump_ir(tr, dumpsnap, dumpreg)
 	out:write(format("%04d ", ins))
 	out:write(format("%04d ", ins))
       end
       end
       out:write(format("%s%s %s %s ",
       out:write(format("%s%s %s %s ",
-		       band(ot, 64) == 0 and " " or ">",
-		       band(ot, 128) == 0 and " " or "+",
+		       band(ot, 128) == 0 and " " or ">",
+		       band(ot, 64) == 0 and " " or "+",
 		       irtype[t], op))
 		       irtype[t], op))
       local m1 = band(m, 3)
       local m1 = band(m, 3)
       if sub(op, 1, 4) == "CALL" then
       if sub(op, 1, 4) == "CALL" then

+ 18 - 21
src/lj_asm.c

@@ -1842,26 +1842,24 @@ static void asm_newref(ASMState *as, IRIns *ir)
 static void asm_uref(ASMState *as, IRIns *ir)
 static void asm_uref(ASMState *as, IRIns *ir)
 {
 {
   /* NYI: Check that UREFO is still open and not aliasing a slot. */
   /* NYI: Check that UREFO is still open and not aliasing a slot. */
-  if (ra_used(ir)) {
-    Reg dest = ra_dest(as, ir, RSET_GPR);
-    if (irref_isk(ir->op1)) {
-      GCfunc *fn = ir_kfunc(IR(ir->op1));
-      MRef *v = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.v;
-      emit_rma(as, XO_MOV, dest, v);
+  Reg dest = ra_dest(as, ir, RSET_GPR);
+  if (irref_isk(ir->op1)) {
+    GCfunc *fn = ir_kfunc(IR(ir->op1));
+    MRef *v = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.v;
+    emit_rma(as, XO_MOV, dest, v);
+  } else {
+    Reg uv = ra_scratch(as, RSET_GPR);
+    Reg func = ra_alloc1(as, ir->op1, RSET_GPR);
+    if (ir->o == IR_UREFC) {
+      emit_rmro(as, XO_LEA, dest, uv, offsetof(GCupval, tv));
+      asm_guardcc(as, CC_NE);
+      emit_i8(as, 1);
+      emit_rmro(as, XO_ARITHib, XOg_CMP, uv, offsetof(GCupval, closed));
     } else {
     } else {
-      Reg uv = ra_scratch(as, RSET_GPR);
-      Reg func = ra_alloc1(as, ir->op1, RSET_GPR);
-      if (ir->o == IR_UREFC) {
-	emit_rmro(as, XO_LEA, dest, uv, offsetof(GCupval, tv));
-	asm_guardcc(as, CC_NE);
-	emit_i8(as, 1);
-	emit_rmro(as, XO_ARITHib, XOg_CMP, uv, offsetof(GCupval, closed));
-      } else {
-	emit_rmro(as, XO_MOV, dest, uv, offsetof(GCupval, v));
-      }
-      emit_rmro(as, XO_MOV, uv, func,
-		(int32_t)offsetof(GCfuncL, uvptr) + 4*(int32_t)(ir->op2 >> 8));
+      emit_rmro(as, XO_MOV, dest, uv, offsetof(GCupval, v));
     }
     }
+    emit_rmro(as, XO_MOV, uv, func,
+	      (int32_t)offsetof(GCfuncL, uvptr) + 4*(int32_t)(ir->op2 >> 8));
   }
   }
 }
 }
 
 
@@ -3423,11 +3421,10 @@ static void asm_trace(ASMState *as)
 {
 {
   for (as->curins--; as->curins > as->stopins; as->curins--) {
   for (as->curins--; as->curins > as->stopins; as->curins--) {
     IRIns *ir = IR(as->curins);
     IRIns *ir = IR(as->curins);
+    if (!ra_used(ir) && !ir_sideeff(ir) && (as->flags & JIT_F_OPT_DCE))
+      continue;  /* Dead-code elimination can be soooo easy. */
     if (irt_isguard(ir->t))
     if (irt_isguard(ir->t))
       asm_snap_prep(as);
       asm_snap_prep(as);
-    else if (!ra_used(ir) && !irm_sideeff(lj_ir_mode[ir->o]) &&
-	     (as->flags & JIT_F_OPT_DCE))
-      continue;  /* Dead-code elimination can be soooo easy. */
     RA_DBG_REF();
     RA_DBG_REF();
     checkmclim(as);
     checkmclim(as);
     asm_ir(as, ir);
     asm_ir(as, ir);

+ 40 - 37
src/lj_ir.h

@@ -15,7 +15,7 @@
   /* Miscellaneous ops. */ \
   /* Miscellaneous ops. */ \
   _(NOP,	N , ___, ___) \
   _(NOP,	N , ___, ___) \
   _(BASE,	N , lit, lit) \
   _(BASE,	N , lit, lit) \
-  _(LOOP,	G , ___, ___) \
+  _(LOOP,	S , ___, ___) \
   _(PHI,	S , ref, ref) \
   _(PHI,	S , ref, ref) \
   _(RENAME,	S , ref, lit) \
   _(RENAME,	S , ref, lit) \
   \
   \
@@ -30,21 +30,21 @@
   \
   \
   /* Guarded assertions. */ \
   /* Guarded assertions. */ \
   /* Must be properly aligned to flip opposites (^1) and (un)ordered (^4). */ \
   /* Must be properly aligned to flip opposites (^1) and (un)ordered (^4). */ \
-  _(EQ,		GC, ref, ref) \
-  _(NE,		GC, ref, ref) \
+  _(EQ,		C , ref, ref) \
+  _(NE,		C , ref, ref) \
   \
   \
-  _(ABC,	G , ref, ref) \
-  _(RETF,	SG, ref, ref) \
+  _(ABC,	N , ref, ref) \
+  _(RETF,	S , ref, ref) \
   \
   \
-  _(LT,		G , ref, ref) \
-  _(GE,		G , ref, ref) \
-  _(LE,		G , ref, ref) \
-  _(GT,		G , ref, ref) \
+  _(LT,		N , ref, ref) \
+  _(GE,		N , ref, ref) \
+  _(LE,		N , ref, ref) \
+  _(GT,		N , ref, ref) \
   \
   \
-  _(ULT,	G , ref, ref) \
-  _(UGE,	G , ref, ref) \
-  _(ULE,	G , ref, ref) \
-  _(UGT,	G , ref, ref) \
+  _(ULT,	N , ref, ref) \
+  _(UGE,	N , ref, ref) \
+  _(ULE,	N , ref, ref) \
+  _(UGT,	N , ref, ref) \
   \
   \
   /* Bit ops. */ \
   /* Bit ops. */ \
   _(BNOT,	N , ref, ___) \
   _(BNOT,	N , ref, ___) \
@@ -75,27 +75,27 @@
   _(MAX,	C , ref, ref) \
   _(MAX,	C , ref, ref) \
   \
   \
   /* Overflow-checking arithmetic ops. */ \
   /* Overflow-checking arithmetic ops. */ \
-  _(ADDOV,	GC, ref, ref) \
-  _(SUBOV,	G , ref, ref) \
+  _(ADDOV,	C , ref, ref) \
+  _(SUBOV,	N , ref, ref) \
   \
   \
   /* Memory ops. A = array, H = hash, U = upvalue, F = field, S = stack. */ \
   /* Memory ops. A = array, H = hash, U = upvalue, F = field, S = stack. */ \
   \
   \
   /* Memory references. */ \
   /* Memory references. */ \
   _(AREF,	R , ref, ref) \
   _(AREF,	R , ref, ref) \
-  _(HREFK,	RG, ref, ref) \
+  _(HREFK,	R , ref, ref) \
   _(HREF,	L , ref, ref) \
   _(HREF,	L , ref, ref) \
   _(NEWREF,	S , ref, ref) \
   _(NEWREF,	S , ref, ref) \
-  _(UREFO,	LG, ref, lit) \
-  _(UREFC,	LG, ref, lit) \
+  _(UREFO,	LW, ref, lit) \
+  _(UREFC,	LW, ref, lit) \
   _(FREF,	R , ref, lit) \
   _(FREF,	R , ref, lit) \
   _(STRREF,	N , ref, ref) \
   _(STRREF,	N , ref, ref) \
   \
   \
   /* Loads and Stores. These must be in the same order. */ \
   /* Loads and Stores. These must be in the same order. */ \
-  _(ALOAD,	LG, ref, ___) \
-  _(HLOAD,	LG, ref, ___) \
-  _(ULOAD,	LG, ref, ___) \
+  _(ALOAD,	L , ref, ___) \
+  _(HLOAD,	L , ref, ___) \
+  _(ULOAD,	L , ref, ___) \
   _(FLOAD,	L , ref, lit) \
   _(FLOAD,	L , ref, lit) \
-  _(SLOAD,	LG, lit, lit) \
+  _(SLOAD,	L , lit, lit) \
   _(XLOAD,	L , ref, lit) \
   _(XLOAD,	L , ref, lit) \
   \
   \
   _(ASTORE,	S , ref, ref) \
   _(ASTORE,	S , ref, ref) \
@@ -105,8 +105,8 @@
   \
   \
   /* Allocations. */ \
   /* Allocations. */ \
   _(SNEW,	N , ref, ref) /* CSE is ok, so not marked as A. */ \
   _(SNEW,	N , ref, ref) /* CSE is ok, so not marked as A. */ \
-  _(TNEW,	A , lit, lit) \
-  _(TDUP,	A , ref, ___) \
+  _(TNEW,	AW, lit, lit) \
+  _(TDUP,	AW, ref, ___) \
   \
   \
   /* Write barriers. */ \
   /* Write barriers. */ \
   _(TBAR,	S , ref, ___) \
   _(TBAR,	S , ref, ___) \
@@ -117,7 +117,7 @@
   _(TOINT,	N , ref, lit) \
   _(TOINT,	N , ref, lit) \
   _(TOBIT,	N , ref, ref) \
   _(TOBIT,	N , ref, ref) \
   _(TOSTR,	N , ref, ___) \
   _(TOSTR,	N , ref, ___) \
-  _(STRTO,	G , ref, ___) \
+  _(STRTO,	N , ref, ___) \
   \
   \
   /* Calls. */ \
   /* Calls. */ \
   _(CALLN,	N , ref, lit) \
   _(CALLN,	N , ref, lit) \
@@ -274,7 +274,7 @@ typedef enum {
 } IRMode;
 } IRMode;
 #define IRM___		IRMnone
 #define IRM___		IRMnone
 
 
-/* Mode bits: Commutative, {Normal/Ref, Alloc, Load, Store}, Guard. */
+/* Mode bits: Commutative, {Normal/Ref, Alloc, Load, Store}, Non-weak guard. */
 #define IRM_C			0x10
 #define IRM_C			0x10
 
 
 #define IRM_N			0x00
 #define IRM_N			0x00
@@ -283,22 +283,17 @@ typedef enum {
 #define IRM_L			0x40
 #define IRM_L			0x40
 #define IRM_S			0x60
 #define IRM_S			0x60
 
 
-#define IRM_G			0x80
+#define IRM_W			0x80
 
 
-#define IRM_GC			(IRM_G|IRM_C)
-#define IRM_RG			(IRM_R|IRM_G)
-#define IRM_LG			(IRM_L|IRM_G)
-#define IRM_SG			(IRM_S|IRM_G)
+#define IRM_AW			(IRM_A|IRM_W)
+#define IRM_LW			(IRM_L|IRM_W)
 
 
 #define irm_op1(m)		(cast(IRMode, (m)&3))
 #define irm_op1(m)		(cast(IRMode, (m)&3))
 #define irm_op2(m)		(cast(IRMode, ((m)>>2)&3))
 #define irm_op2(m)		(cast(IRMode, ((m)>>2)&3))
 #define irm_iscomm(m)		((m) & IRM_C)
 #define irm_iscomm(m)		((m) & IRM_C)
 #define irm_kind(m)		((m) & IRM_S)
 #define irm_kind(m)		((m) & IRM_S)
-#define irm_isguard(m)		((m) & IRM_G)
-/* Stores or any other op with a guard has a side-effect. */
-#define irm_sideeff(m)		((m) >= IRM_S)
 
 
-#define IRMODE(name, m, m1, m2)	((IRM##m1)|((IRM##m2)<<2)|(IRM_##m)),
+#define IRMODE(name, m, m1, m2)	(((IRM##m1)|((IRM##m2)<<2)|(IRM_##m))^IRM_W),
 
 
 LJ_DATA const uint8_t lj_ir_mode[IR__MAX+1];
 LJ_DATA const uint8_t lj_ir_mode[IR__MAX+1];
 
 
@@ -335,8 +330,8 @@ typedef enum {
 
 
   /* Additional flags. */
   /* Additional flags. */
   IRT_MARK = 0x20,	/* Marker for misc. purposes. */
   IRT_MARK = 0x20,	/* Marker for misc. purposes. */
-  IRT_GUARD = 0x40,	/* Instruction is a guard. */
-  IRT_ISPHI = 0x80,	/* Instruction is left or right PHI operand. */
+  IRT_ISPHI = 0x40,	/* Instruction is left or right PHI operand. */
+  IRT_GUARD = 0x80,	/* Instruction is a guard. */
 
 
   /* Masks. */
   /* Masks. */
   IRT_TYPE = 0x1f,
   IRT_TYPE = 0x1f,
@@ -531,4 +526,12 @@ typedef union IRIns {
 #define ir_knum(ir)	check_exp((ir)->o == IR_KNUM, mref((ir)->ptr, cTValue))
 #define ir_knum(ir)	check_exp((ir)->o == IR_KNUM, mref((ir)->ptr, cTValue))
 #define ir_kptr(ir)	check_exp((ir)->o == IR_KPTR, mref((ir)->ptr, void))
 #define ir_kptr(ir)	check_exp((ir)->o == IR_KPTR, mref((ir)->ptr, void))
 
 
+LJ_STATIC_ASSERT((int)IRT_GUARD == (int)IRM_W);
+
+/* A store or any other op with a non-weak guard has a side-effect. */
+static LJ_AINLINE int ir_sideeff(IRIns *ir)
+{
+  return (((ir->t.irt | ~IRT_GUARD) & lj_ir_mode[ir->o]) >= IRM_S);
+}
+
 #endif
 #endif

+ 1 - 1
src/lj_opt_dce.c

@@ -45,7 +45,7 @@ static void dce_propagate(jit_State *J)
     if (irt_ismarked(ir->t)) {
     if (irt_ismarked(ir->t)) {
       irt_clearmark(ir->t);
       irt_clearmark(ir->t);
       pchain[ir->o] = &ir->prev;
       pchain[ir->o] = &ir->prev;
-    } else if (!(irt_isguard(ir->t) || irm_sideeff(lj_ir_mode[ir->o]))) {
+    } else if (!ir_sideeff(ir)) {
       *pchain[ir->o] = ir->prev;  /* Reroute original instruction chain. */
       *pchain[ir->o] = ir->prev;  /* Reroute original instruction chain. */
       *pchain[IR_NOP] = (IRRef1)ins;
       *pchain[IR_NOP] = (IRRef1)ins;
       ir->t.irt = IRT_NIL;
       ir->t.irt = IRT_NIL;

+ 2 - 2
src/lj_record.c

@@ -1883,7 +1883,7 @@ static TRef rec_tnew(jit_State *J, uint32_t ah)
   uint32_t asize = ah & 0x7ff;
   uint32_t asize = ah & 0x7ff;
   uint32_t hbits = ah >> 11;
   uint32_t hbits = ah >> 11;
   if (asize == 0x7ff) asize = 0x801;
   if (asize == 0x7ff) asize = 0x801;
-  return emitir(IRT(IR_TNEW, IRT_TAB), asize, hbits);
+  return emitir(IRTG(IR_TNEW, IRT_TAB), asize, hbits);
 }
 }
 
 
 /* -- Record bytecode ops ------------------------------------------------- */
 /* -- Record bytecode ops ------------------------------------------------- */
@@ -2167,7 +2167,7 @@ void lj_record_ins(jit_State *J)
     rc = rec_tnew(J, rc);
     rc = rec_tnew(J, rc);
     break;
     break;
   case BC_TDUP:
   case BC_TDUP:
-    rc = emitir(IRT(IR_TDUP, IRT_TAB),
+    rc = emitir(IRTG(IR_TDUP, IRT_TAB),
 		lj_ir_ktab(J, gco2tab(proto_kgc(J->pt, ~(ptrdiff_t)rc))), 0);
 		lj_ir_ktab(J, gco2tab(proto_kgc(J->pt, ~(ptrdiff_t)rc))), 0);
     break;
     break;