mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-12 17:24:09 +00:00
More portability cleanups for assembler backend.
This commit is contained in:
parent
919ba5fd74
commit
d0115c65f5
36
src/lj_asm.c
36
src/lj_asm.c
@ -260,10 +260,8 @@ static void ra_setup(ASMState *as)
|
|||||||
as->weakset = RSET_EMPTY;
|
as->weakset = RSET_EMPTY;
|
||||||
as->phiset = RSET_EMPTY;
|
as->phiset = RSET_EMPTY;
|
||||||
memset(as->phireg, 0, sizeof(as->phireg));
|
memset(as->phireg, 0, sizeof(as->phireg));
|
||||||
memset(as->cost, 0, sizeof(as->cost));
|
|
||||||
for (r = RID_MIN_GPR; r < RID_MAX; r++)
|
for (r = RID_MIN_GPR; r < RID_MAX; r++)
|
||||||
if (!rset_test(RSET_INIT, r))
|
as->cost[r] = REGCOST(~0u, 0u);
|
||||||
as->cost[r] = REGCOST(~0u, 0u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rematerialize constants. */
|
/* Rematerialize constants. */
|
||||||
@ -369,7 +367,7 @@ static Reg ra_evict(ASMState *as, RegSet allow)
|
|||||||
IRRef ref;
|
IRRef ref;
|
||||||
RegCost cost = ~(RegCost)0;
|
RegCost cost = ~(RegCost)0;
|
||||||
lua_assert(allow != RSET_EMPTY);
|
lua_assert(allow != RSET_EMPTY);
|
||||||
if (allow < RID2RSET(RID_MAX_GPR)) {
|
if (RID_NUM_FPR == 0 || allow < RID2RSET(RID_MAX_GPR)) {
|
||||||
GPRDEF(MINCOST)
|
GPRDEF(MINCOST)
|
||||||
} else {
|
} else {
|
||||||
FPRDEF(MINCOST)
|
FPRDEF(MINCOST)
|
||||||
@ -539,6 +537,7 @@ static void ra_destreg(ASMState *as, IRIns *ir, Reg r)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LJ_TARGET_X86ORX64
|
||||||
/* Propagate dest register to left reference. Emit moves as needed.
|
/* Propagate dest register to left reference. Emit moves as needed.
|
||||||
** This is a required fixup step for all 2-operand machine instructions.
|
** This is a required fixup step for all 2-operand machine instructions.
|
||||||
*/
|
*/
|
||||||
@ -583,6 +582,7 @@ static void ra_left(ASMState *as, Reg dest, IRRef lref)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* -- Snapshot handling --------- ----------------------------------------- */
|
/* -- Snapshot handling --------- ----------------------------------------- */
|
||||||
|
|
||||||
@ -866,7 +866,7 @@ static void asm_phi_shuffle(ASMState *as)
|
|||||||
if (!blocked) break; /* Finished. */
|
if (!blocked) break; /* Finished. */
|
||||||
if (!(as->freeset & blocked)) { /* Break cycles if none are free. */
|
if (!(as->freeset & blocked)) { /* Break cycles if none are free. */
|
||||||
asm_phi_break(as, blocked, blockedby, RSET_GPR);
|
asm_phi_break(as, blocked, blockedby, RSET_GPR);
|
||||||
asm_phi_break(as, blocked, blockedby, RSET_FPR);
|
if (!LJ_SOFTFP) asm_phi_break(as, blocked, blockedby, RSET_FPR);
|
||||||
checkmclim(as);
|
checkmclim(as);
|
||||||
} /* Else retry some more renames. */
|
} /* Else retry some more renames. */
|
||||||
}
|
}
|
||||||
@ -921,7 +921,8 @@ static void asm_phi_fixup(ASMState *as)
|
|||||||
/* Setup right PHI reference. */
|
/* Setup right PHI reference. */
|
||||||
static void asm_phi(ASMState *as, IRIns *ir)
|
static void asm_phi(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
RegSet allow = (irt_isfp(ir->t) ? RSET_FPR : RSET_GPR) & ~as->phiset;
|
RegSet allow = ((!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR) &
|
||||||
|
~as->phiset;
|
||||||
RegSet afree = (as->freeset & allow);
|
RegSet afree = (as->freeset & allow);
|
||||||
IRIns *irl = IR(ir->op1);
|
IRIns *irl = IR(ir->op1);
|
||||||
IRIns *irr = IR(ir->op2);
|
IRIns *irr = IR(ir->op2);
|
||||||
@ -1009,13 +1010,13 @@ static void asm_head_side(ASMState *as)
|
|||||||
IRRef1 sloadins[RID_MAX];
|
IRRef1 sloadins[RID_MAX];
|
||||||
RegSet allow = RSET_ALL; /* Inverse of all coalesced registers. */
|
RegSet allow = RSET_ALL; /* Inverse of all coalesced registers. */
|
||||||
RegSet live = RSET_EMPTY; /* Live parent registers. */
|
RegSet live = RSET_EMPTY; /* Live parent registers. */
|
||||||
Reg pbase = as->parent->ir[REF_BASE].r; /* Parent base register (if any). */
|
IRIns *irp = &as->parent->ir[REF_BASE]; /* Parent base. */
|
||||||
int32_t spadj, spdelta;
|
int32_t spadj, spdelta;
|
||||||
int pass2 = 0;
|
int pass2 = 0;
|
||||||
int pass3 = 0;
|
int pass3 = 0;
|
||||||
IRRef i;
|
IRRef i;
|
||||||
|
|
||||||
allow = asm_head_side_base(as, pbase, allow);
|
allow = asm_head_side_base(as, irp, allow);
|
||||||
|
|
||||||
/* Scan all parent SLOADs and collect register dependencies. */
|
/* Scan all parent SLOADs and collect register dependencies. */
|
||||||
for (i = as->stopins; i > REF_BASE; i--) {
|
for (i = as->stopins; i > REF_BASE; i--) {
|
||||||
@ -1129,7 +1130,7 @@ static void asm_head_side(ASMState *as)
|
|||||||
lj_trace_err(as->J, LJ_TRERR_NYICOAL);
|
lj_trace_err(as->J, LJ_TRERR_NYICOAL);
|
||||||
ra_rename(as, rset_pickbot(live & RSET_GPR), rset_pickbot(tmpset));
|
ra_rename(as, rset_pickbot(live & RSET_GPR), rset_pickbot(tmpset));
|
||||||
}
|
}
|
||||||
if (live & RSET_FPR) {
|
if (!LJ_SOFTFP && (live & RSET_FPR)) {
|
||||||
RegSet tmpset = as->freeset & ~live & allow & RSET_FPR;
|
RegSet tmpset = as->freeset & ~live & allow & RSET_FPR;
|
||||||
if (tmpset == RSET_EMPTY)
|
if (tmpset == RSET_EMPTY)
|
||||||
lj_trace_err(as->J, LJ_TRERR_NYICOAL);
|
lj_trace_err(as->J, LJ_TRERR_NYICOAL);
|
||||||
@ -1144,7 +1145,7 @@ static void asm_head_side(ASMState *as)
|
|||||||
if (as->topslot > as->T->topslot) { /* Need to check for higher slot? */
|
if (as->topslot > as->T->topslot) { /* Need to check for higher slot? */
|
||||||
as->T->topslot = (uint8_t)as->topslot; /* Remember for child traces. */
|
as->T->topslot = (uint8_t)as->topslot; /* Remember for child traces. */
|
||||||
/* Reuse the parent exit in the context of the parent trace. */
|
/* Reuse the parent exit in the context of the parent trace. */
|
||||||
asm_stack_check(as, as->topslot, pbase, allow & RSET_GPR, as->J->exitno);
|
asm_stack_check(as, as->topslot, irp, allow & RSET_GPR, as->J->exitno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1191,7 +1192,7 @@ static void asm_tail_link(ASMState *as)
|
|||||||
|
|
||||||
/* Root traces that grow the stack need to check the stack at the end. */
|
/* Root traces that grow the stack need to check the stack at the end. */
|
||||||
if (!as->parent && as->topslot)
|
if (!as->parent && as->topslot)
|
||||||
asm_stack_check(as, as->topslot, RID_BASE, as->freeset & RSET_GPR, snapno);
|
asm_stack_check(as, as->topslot, NULL, as->freeset & RSET_GPR, snapno);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Trace setup --------------------------------------------------------- */
|
/* -- Trace setup --------------------------------------------------------- */
|
||||||
@ -1283,7 +1284,7 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
as->modset = RSET_SCRATCH;
|
as->modset = RSET_SCRATCH;
|
||||||
break;
|
break;
|
||||||
case IR_POW:
|
case IR_POW:
|
||||||
if (irt_isnum(ir->t)) {
|
if (!LJ_SOFTFP && irt_isnum(ir->t)) {
|
||||||
#if LJ_TARGET_X86ORX64
|
#if LJ_TARGET_X86ORX64
|
||||||
ir->prev = REGSP_HINT(RID_XMM0);
|
ir->prev = REGSP_HINT(RID_XMM0);
|
||||||
if (inloop)
|
if (inloop)
|
||||||
@ -1341,8 +1342,13 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
/* Do not propagate hints across type conversions. */
|
/* Do not propagate hints across type conversions. */
|
||||||
case IR_CONV: case IR_TOBIT:
|
case IR_TOBIT:
|
||||||
break;
|
break;
|
||||||
|
case IR_CONV:
|
||||||
|
if (irt_isfp(ir->t) || (ir->op2 & IRCONV_SRCMASK) == IRT_NUM ||
|
||||||
|
(ir->op2 & IRCONV_SRCMASK) == IRT_FLOAT)
|
||||||
|
break;
|
||||||
|
/* fallthrough */
|
||||||
default:
|
default:
|
||||||
/* Propagate hints across likely 'op reg, imm' or 'op reg'. */
|
/* Propagate hints across likely 'op reg, imm' or 'op reg'. */
|
||||||
if (irref_isk(ir->op2) && !irref_isk(ir->op1)) {
|
if (irref_isk(ir->op2) && !irref_isk(ir->op1)) {
|
||||||
@ -1367,6 +1373,10 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||||||
ASMState as_;
|
ASMState as_;
|
||||||
ASMState *as = &as_;
|
ASMState *as = &as_;
|
||||||
|
|
||||||
|
/* Ensure an initialized instruction beyond the last one for HIOP checks. */
|
||||||
|
J->cur.nins = lj_ir_nextins(J);
|
||||||
|
J->cur.ir[J->cur.nins].o = IR_NOP;
|
||||||
|
|
||||||
/* Setup initial state. Copy some fields to reduce indirections. */
|
/* Setup initial state. Copy some fields to reduce indirections. */
|
||||||
as->J = J;
|
as->J = J;
|
||||||
as->T = T;
|
as->T = T;
|
||||||
|
@ -2191,9 +2191,10 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
|
|
||||||
/* Check Lua stack size for overflow. Use exit handler as fallback. */
|
/* Check Lua stack size for overflow. Use exit handler as fallback. */
|
||||||
static void asm_stack_check(ASMState *as, BCReg topslot,
|
static void asm_stack_check(ASMState *as, BCReg topslot,
|
||||||
Reg pbase, RegSet allow, ExitNo exitno)
|
IRIns *irp, RegSet allow, ExitNo exitno)
|
||||||
{
|
{
|
||||||
/* Try to get an unused temp. register, otherwise spill/restore eax. */
|
/* Try to get an unused temp. register, otherwise spill/restore eax. */
|
||||||
|
Reg pbase = irp ? irp->r : RID_BASE;
|
||||||
Reg r = allow ? rset_pickbot(allow) : RID_EAX;
|
Reg r = allow ? rset_pickbot(allow) : RID_EAX;
|
||||||
emit_jcc(as, CC_B, exitstub_addr(as->J, exitno));
|
emit_jcc(as, CC_B, exitstub_addr(as->J, exitno));
|
||||||
if (allow == RSET_EMPTY) /* Restore temp. register. */
|
if (allow == RSET_EMPTY) /* Restore temp. register. */
|
||||||
@ -2344,7 +2345,7 @@ static void asm_head_root_base(ASMState *as)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Coalesce or reload BASE register for a side trace. */
|
/* Coalesce or reload BASE register for a side trace. */
|
||||||
static RegSet asm_head_side_base(ASMState *as, Reg pbase, RegSet allow)
|
static RegSet asm_head_side_base(ASMState *as, IRIns *irp, RegSet allow)
|
||||||
{
|
{
|
||||||
IRIns *ir = IR(REF_BASE);
|
IRIns *ir = IR(REF_BASE);
|
||||||
Reg r = ir->r;
|
Reg r = ir->r;
|
||||||
@ -2352,11 +2353,11 @@ static RegSet asm_head_side_base(ASMState *as, Reg pbase, RegSet allow)
|
|||||||
ra_free(as, r);
|
ra_free(as, r);
|
||||||
if (rset_test(as->modset, r))
|
if (rset_test(as->modset, r))
|
||||||
ir->r = RID_INIT; /* No inheritance for modified BASE register. */
|
ir->r = RID_INIT; /* No inheritance for modified BASE register. */
|
||||||
if (pbase == r) {
|
if (irp->r == r) {
|
||||||
rset_clear(allow, r); /* Mark same BASE register as coalesced. */
|
rset_clear(allow, r); /* Mark same BASE register as coalesced. */
|
||||||
} else if (ra_hasreg(pbase) && rset_test(as->freeset, pbase)) {
|
} else if (ra_hasreg(irp->r) && rset_test(as->freeset, irp->r)) {
|
||||||
rset_clear(allow, pbase);
|
rset_clear(allow, irp->r);
|
||||||
emit_rr(as, XO_MOV, r, pbase); /* Move from coalesced parent register. */
|
emit_rr(as, XO_MOV, r, irp->r); /* Move from coalesced parent reg. */
|
||||||
} else {
|
} else {
|
||||||
emit_getgl(as, r, jit_base); /* Otherwise reload BASE. */
|
emit_getgl(as, r, jit_base); /* Otherwise reload BASE. */
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user