Many soft-float-related fixes to SPLIT pass and assembler backend.

This commit is contained in:
Mike Pall 2011-06-02 01:24:36 +02:00
parent 9e153003b4
commit a770bf3741
2 changed files with 109 additions and 41 deletions

View File

@ -741,8 +741,9 @@ static int asm_snap_checkrename(ASMState *as, IRRef ren)
SnapEntry *map = &as->T->snapmap[snap->mapofs]; SnapEntry *map = &as->T->snapmap[snap->mapofs];
MSize n, nent = snap->nent; MSize n, nent = snap->nent;
for (n = 0; n < nent; n++) { for (n = 0; n < nent; n++) {
IRRef ref = snap_ref(map[n]); SnapEntry sn = map[n];
if (ref == ren) { IRRef ref = snap_ref(sn);
if (ref == ren || (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM) && ++ref == ren)) {
IRIns *ir = IR(ref); IRIns *ir = IR(ref);
ra_spill(as, ir); /* Register renamed, so force a spill slot. */ ra_spill(as, ir); /* Register renamed, so force a spill slot. */
RA_DBGX((as, "snaprensp $f $s", ref, ir->s)); RA_DBGX((as, "snaprensp $f $s", ref, ir->s));
@ -785,9 +786,9 @@ static void asm_collectargs(ASMState *as, IRIns *ir,
while (n-- > 1) { while (n-- > 1) {
ir = IR(ir->op1); ir = IR(ir->op1);
lua_assert(ir->o == IR_CARG); lua_assert(ir->o == IR_CARG);
args[n] = ir->op2; args[n] = ir->op2 == REF_NIL ? 0 : ir->op2;
} }
args[0] = ir->op1; args[0] = ir->op1 == REF_NIL ? 0 : ir->op1;
lua_assert(IR(ir->op1)->o != IR_CARG); lua_assert(IR(ir->op1)->o != IR_CARG);
} }
@ -1181,12 +1182,6 @@ static void asm_head_side(ASMState *as)
} }
as->T->spadjust = (uint16_t)spadj; as->T->spadjust = (uint16_t)spadj;
#if !LJ_TARGET_X86ORX64
/* Restore BASE register from parent spill slot. */
if (ra_hasspill(irp->s))
emit_spload(as, IR(REF_BASE), IR(REF_BASE)->r, spdelta + sps_scale(irp->s));
#endif
/* Reload spilled target registers. */ /* Reload spilled target registers. */
if (pass2) { if (pass2) {
for (i = as->stopins; i > REF_BASE; i--) { for (i = as->stopins; i > REF_BASE; i--) {
@ -1222,6 +1217,12 @@ static void asm_head_side(ASMState *as)
emit_setvmstate(as, (int32_t)as->T->traceno); emit_setvmstate(as, (int32_t)as->T->traceno);
emit_spsub(as, spdelta); emit_spsub(as, spdelta);
#if !LJ_TARGET_X86ORX64
/* Restore BASE register from parent spill slot. */
if (ra_hasspill(irp->s))
emit_spload(as, IR(REF_BASE), IR(REF_BASE)->r, sps_scale(irp->s));
#endif
/* Restore target registers from parent spill slots. */ /* Restore target registers from parent spill slots. */
if (pass3) { if (pass3) {
RegSet work = ~as->freeset & RSET_ALL; RegSet work = ~as->freeset & RSET_ALL;

View File

@ -107,6 +107,25 @@ static IRRef split_emit(jit_State *J, uint16_t ot, IRRef1 op1, IRRef1 op2)
} }
#if LJ_SOFTFP #if LJ_SOFTFP
/* Emit a (checked) number to integer conversion. */
static IRRef split_num2int(jit_State *J, IRRef lo, IRRef hi, int check)
{
IRRef tmp, res;
#if LJ_LE
tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), lo, hi);
#else
tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), hi, lo);
#endif
res = split_emit(J, IRTI(IR_CALLN), tmp, IRCALL_softfp_d2i);
if (check) {
tmp = split_emit(J, IRTI(IR_CALLN), res, IRCALL_softfp_i2d);
split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp);
split_emit(J, IRTGI(IR_EQ), tmp, lo);
split_emit(J, IRTG(IR_HIOP, IRT_SOFTFP), tmp+1, hi);
}
return res;
}
/* Emit a CALLN with one split 64 bit argument. */ /* Emit a CALLN with one split 64 bit argument. */
static IRRef split_call_l(jit_State *J, IRRef1 *hisubst, IRIns *oir, static IRRef split_call_l(jit_State *J, IRRef1 *hisubst, IRIns *oir,
IRIns *ir, IRCallID id) IRIns *ir, IRCallID id)
@ -161,16 +180,18 @@ static IRRef split_call_ll(jit_State *J, IRRef1 *hisubst, IRIns *oir,
} }
/* Get a pointer to the other 32 bit word (LE: hiword, BE: loword). */ /* Get a pointer to the other 32 bit word (LE: hiword, BE: loword). */
static IRRef split_ptr(jit_State *J, IRRef ref) static IRRef split_ptr(jit_State *J, IRIns *oir, IRRef ref)
{ {
IRIns *ir = IR(ref); IRRef nref = oir[ref].prev;
IRIns *ir = IR(nref);
int32_t ofs = 4; int32_t ofs = 4;
if (ir->o == IR_ADD && irref_isk(ir->op2)) { /* Reassociate address. */ if (ir->o == IR_ADD && irref_isk(ir->op2) && !irt_isphi(oir[ref].t)) {
/* Reassociate address. */
ofs += IR(ir->op2)->i; ofs += IR(ir->op2)->i;
ref = ir->op1; nref = ir->op1;
if (ofs == 0) return ref; if (ofs == 0) return nref;
} }
return split_emit(J, IRTI(IR_ADD), ref, lj_ir_kint(J, ofs)); return split_emit(J, IRTI(IR_ADD), nref, lj_ir_kint(J, ofs));
} }
/* Transform the old IR to the new IR. */ /* Transform the old IR to the new IR. */
@ -279,13 +300,22 @@ static void split_ir(jit_State *J)
hi = split_emit(J, IRT(ir->o == IR_NEG ? IR_BXOR : IR_BAND, IRT_SOFTFP), hi = split_emit(J, IRT(ir->o == IR_NEG ? IR_BXOR : IR_BAND, IRT_SOFTFP),
hisubst[ir->op1], hisubst[ir->op2]); hisubst[ir->op1], hisubst[ir->op2]);
break; break;
case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: case IR_SLOAD:
case IR_MIN: case IR_MAX: case IR_STRTO: if ((nir->op2 & IRSLOAD_CONVERT)) { /* Convert from int to number. */
nir->op2 &= ~IRSLOAD_CONVERT;
ir->prev = nref = split_emit(J, IRTI(IR_CALLN), nref,
IRCALL_softfp_i2d);
hi = split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), nref, nref);
break;
}
/* fallthrough */
case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
case IR_STRTO:
hi = split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), nref, nref); hi = split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), nref, nref);
break; break;
case IR_XLOAD: case IR_XLOAD:
hi = split_emit(J, IRT(IR_XLOAD, IRT_SOFTFP), hi = split_emit(J, IRT(IR_XLOAD, IRT_SOFTFP),
split_ptr(J, nir->op1), ir->op2); split_ptr(J, oir, ir->op1), ir->op2);
#if LJ_BE #if LJ_BE
ir->prev = hi; hi = nref; ir->prev = hi; hi = nref;
#endif #endif
@ -300,7 +330,7 @@ static void split_ir(jit_State *J)
IRRef hiref = nir->op2; nir->op2 = hisubst[ir->op2]; IRRef hiref = nir->op2; nir->op2 = hisubst[ir->op2];
#endif #endif
split_emit(J, IRT(IR_XSTORE, IRT_SOFTFP), split_emit(J, IRT(IR_XSTORE, IRT_SOFTFP),
split_ptr(J, nir->op1), hiref); split_ptr(J, oir, ir->op1), hiref);
break; break;
} }
case IR_CONV: { /* Conversion to number. Others handled below. */ case IR_CONV: { /* Conversion to number. Others handled below. */
@ -336,8 +366,8 @@ static void split_ir(jit_State *J)
hisubst[ir->op1], hisubst[ir->op2]); hisubst[ir->op1], hisubst[ir->op2]);
break; break;
default: default:
lua_assert(ir->o <= IR_NE); lua_assert(ir->o <= IR_NE || ir->o == IR_MIN || ir->o == IR_MAX);
split_emit(J, IRTG(IR_HIOP, IRT_SOFTFP), hi = split_emit(J, IRTG(IR_HIOP, IRT_SOFTFP),
hisubst[ir->op1], hisubst[ir->op2]); hisubst[ir->op1], hisubst[ir->op2]);
break; break;
} }
@ -387,7 +417,7 @@ static void split_ir(jit_State *J)
#endif #endif
break; break;
case IR_XLOAD: case IR_XLOAD:
hi = split_emit(J, IRTI(IR_XLOAD), split_ptr(J, nir->op1), ir->op2); hi = split_emit(J, IRTI(IR_XLOAD), split_ptr(J, oir, ir->op1), ir->op2);
#if LJ_BE #if LJ_BE
ir->prev = hi; hi = nref; ir->prev = hi; hi = nref;
#endif #endif
@ -398,13 +428,13 @@ static void split_ir(jit_State *J)
#else #else
hiref = nir->op2; nir->op2 = hisubst[ir->op2]; hiref = nir->op2; nir->op2 = hisubst[ir->op2];
#endif #endif
split_emit(J, IRTI(IR_XSTORE), split_ptr(J, nir->op1), hiref); split_emit(J, IRTI(IR_XSTORE), split_ptr(J, oir, ir->op1), hiref);
break; break;
case IR_CONV: { /* Conversion to 64 bit integer. Others handled below. */ case IR_CONV: { /* Conversion to 64 bit integer. Others handled below. */
IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK);
#if LJ_SOFTFP #if LJ_SOFTFP
if (st == IRT_NUM) { /* NUM to 64 bit int conv. */ if (st == IRT_NUM) { /* NUM to 64 bit int conv. */
split_call_l(J, hisubst, oir, ir, hi = split_call_l(J, hisubst, oir, ir,
irt_isi64(ir->t) ? IRCALL_softfp_d2l : IRCALL_softfp_d2ul); irt_isi64(ir->t) ? IRCALL_softfp_d2l : IRCALL_softfp_d2ul);
} else if (st == IRT_FLOAT) { /* FLOAT to 64 bit int conv. */ } else if (st == IRT_FLOAT) { /* FLOAT to 64 bit int conv. */
nir->o = IR_CALLN; nir->o = IR_CALLN;
@ -452,7 +482,15 @@ static void split_ir(jit_State *J)
} else } else
#endif #endif
#if LJ_SOFTFP #if LJ_SOFTFP
if (ir->o == IR_TOBIT) { if (ir->o == IR_SLOAD) {
if ((nir->op2 & IRSLOAD_CONVERT)) { /* Convert from number to int. */
nir->op2 &= ~IRSLOAD_CONVERT;
if (!(nir->op2 & IRSLOAD_TYPECHECK))
nir->t.irt = IRT_INT; /* Drop guard. */
split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), nref, nref);
ir->prev = split_num2int(J, nref, nref+1, irt_isguard(ir->t));
}
} else if (ir->o == IR_TOBIT) {
IRRef tmp, op1 = ir->op1; IRRef tmp, op1 = ir->op1;
J->cur.nins--; J->cur.nins--;
#if LJ_LE #if LJ_LE
@ -461,6 +499,16 @@ static void split_ir(jit_State *J)
tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), hisubst[op1], oir[op1].prev); tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), hisubst[op1], oir[op1].prev);
#endif #endif
ir->prev = split_emit(J, IRTI(IR_CALLN), tmp, IRCALL_lj_vm_tobit); ir->prev = split_emit(J, IRTI(IR_CALLN), tmp, IRCALL_lj_vm_tobit);
} else if (ir->o == IR_TOSTR) {
if (hisubst[ir->op1]) {
if (irref_isk(ir->op1))
nir->op1 = ir->op1;
else
split_emit(J, IRT(IR_HIOP, IRT_NIL), hisubst[ir->op1], nref);
}
} else if (ir->o == IR_HREF || ir->o == IR_NEWREF) {
if (irref_isk(ir->op2) && hisubst[ir->op2])
nir->op2 = ir->op2;
} else } else
#endif #endif
if (ir->o == IR_CONV) { /* See above, too. */ if (ir->o == IR_CONV) { /* See above, too. */
@ -505,17 +553,22 @@ static void split_ir(jit_State *J)
#if LJ_SOFTFP #if LJ_SOFTFP
if (st == IRT_NUM || (LJ_32 && LJ_HASFFI && st == IRT_FLOAT)) { if (st == IRT_NUM || (LJ_32 && LJ_HASFFI && st == IRT_FLOAT)) {
if (irt_isguard(ir->t)) { if (irt_isguard(ir->t)) {
lua_assert(0); /* NYI: missing check. */ lua_assert(st == IRT_NUM && irt_isint(ir->t));
} J->cur.nins--;
ir->prev = split_num2int(J, nir->op1, hisubst[ir->op1], 1);
} else {
split_call_l(J, hisubst, oir, ir, split_call_l(J, hisubst, oir, ir,
#if LJ_32 && LJ_HASFFI #if LJ_32 && LJ_HASFFI
st == IRT_NUM ? IRCALL_softfp_d2i : IRCALL_softfp_f2i st == IRT_NUM ?
(irt_isint(ir->t) ? IRCALL_softfp_d2i : IRCALL_softfp_d2ui) :
(irt_isint(ir->t) ? IRCALL_softfp_f2i : IRCALL_softfp_f2ui)
#else #else
IRCALL_softfp_d2i IRCALL_softfp_d2i
#endif #endif
); );
J->cur.nins--; /* Drop unused HIOP. */ J->cur.nins--; /* Drop unused HIOP. */
} }
}
#endif #endif
} else if (ir->o == IR_CALLXS) { } else if (ir->o == IR_CALLXS) {
IRRef hiref; IRRef hiref;
@ -550,8 +603,20 @@ static void split_ir(jit_State *J)
} }
hiref = hisubst[ir->op2]; hiref = hisubst[ir->op2];
if (hiref) { if (hiref) {
#if !LJ_TARGET_X86
int carg = 0;
IRIns *cir;
for (cir = IR(nir->op1); cir->o == IR_CARG; cir = IR(cir->op1))
carg++;
if ((carg & 1) == 0) { /* Align 64 bit arguments. */
IRRef op2 = nir->op2;
nir->op2 = REF_NIL;
nref = split_emit(J, IRT(IR_CARG, IRT_NIL), nref, op2);
nir = IR(nref);
}
#endif
#if LJ_BE #if LJ_BE
IRRef tmp = nir->op2; nir->op2 = hiref; hiref = tmp; { IRRef tmp = nir->op2; nir->op2 = hiref; hiref = tmp; }
#endif #endif
ir->prev = split_emit(J, IRT(IR_CARG, IRT_NIL), nref, hiref); ir->prev = split_emit(J, IRT(IR_CARG, IRT_NIL), nref, hiref);
} }
@ -580,14 +645,11 @@ static void split_ir(jit_State *J)
SnapShot *snap = &J->cur.snap[i]; SnapShot *snap = &J->cur.snap[i];
SnapEntry *map = &J->cur.snapmap[snap->mapofs]; SnapEntry *map = &J->cur.snapmap[snap->mapofs];
MSize n, nent = snap->nent; MSize n, nent = snap->nent;
snap->ref = oir[snap->ref].prev; snap->ref = snap->ref == REF_FIRST ? REF_FIRST : oir[snap->ref].prev;
for (n = 0; n < nent; n++) { for (n = 0; n < nent; n++) {
SnapEntry sn = map[n]; SnapEntry sn = map[n];
IRIns *ir = &oir[snap_ref(sn)]; IRIns *ir = &oir[snap_ref(sn)];
if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM) && irref_isk(snap_ref(sn))) if (!(LJ_SOFTFP && (sn & SNAP_SOFTFPNUM) && irref_isk(snap_ref(sn))))
map[n] = ((sn & 0xffff0000) |
(IRRef1)lj_ir_k64(J, IR_KNUM, ir_knum(ir)));
else
map[n] = ((sn & 0xffff0000) | ir->prev); map[n] = ((sn & 0xffff0000) | ir->prev);
} }
} }
@ -612,6 +674,11 @@ static int split_needsplit(jit_State *J)
for (ir = IR(REF_FIRST), irend = IR(J->cur.nins); ir < irend; ir++) for (ir = IR(REF_FIRST), irend = IR(J->cur.nins); ir < irend; ir++)
if (LJ_SOFTFP ? irt_is64(ir->t) : irt_isint64(ir->t)) if (LJ_SOFTFP ? irt_is64(ir->t) : irt_isint64(ir->t))
return 1; return 1;
if (LJ_SOFTFP) {
for (ref = J->chain[IR_SLOAD]; ref; ref = IR(ref)->prev)
if ((IR(ref)->op2 & IRSLOAD_CONVERT))
return 1;
}
for (ref = J->chain[IR_CONV]; ref; ref = IR(ref)->prev) for (ref = J->chain[IR_CONV]; ref; ref = IR(ref)->prev)
if ((LJ_SOFTFP && (IR(ref)->op2 & IRCONV_SRCMASK) == IRT_NUM) || if ((LJ_SOFTFP && (IR(ref)->op2 & IRCONV_SRCMASK) == IRT_NUM) ||
(IR(ref)->op2 & IRCONV_SRCMASK) == IRT_I64 || (IR(ref)->op2 & IRCONV_SRCMASK) == IRT_I64 ||