aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lj_asm.c36
-rw-r--r--src/lj_asm_x86.h13
2 files changed, 30 insertions, 19 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c
index 78f2484a..f33dc790 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -260,10 +260,8 @@ static void ra_setup(ASMState *as)
260 as->weakset = RSET_EMPTY; 260 as->weakset = RSET_EMPTY;
261 as->phiset = RSET_EMPTY; 261 as->phiset = RSET_EMPTY;
262 memset(as->phireg, 0, sizeof(as->phireg)); 262 memset(as->phireg, 0, sizeof(as->phireg));
263 memset(as->cost, 0, sizeof(as->cost));
264 for (r = RID_MIN_GPR; r < RID_MAX; r++) 263 for (r = RID_MIN_GPR; r < RID_MAX; r++)
265 if (!rset_test(RSET_INIT, r)) 264 as->cost[r] = REGCOST(~0u, 0u);
266 as->cost[r] = REGCOST(~0u, 0u);
267} 265}
268 266
269/* Rematerialize constants. */ 267/* Rematerialize constants. */
@@ -369,7 +367,7 @@ static Reg ra_evict(ASMState *as, RegSet allow)
369 IRRef ref; 367 IRRef ref;
370 RegCost cost = ~(RegCost)0; 368 RegCost cost = ~(RegCost)0;
371 lua_assert(allow != RSET_EMPTY); 369 lua_assert(allow != RSET_EMPTY);
372 if (allow < RID2RSET(RID_MAX_GPR)) { 370 if (RID_NUM_FPR == 0 || allow < RID2RSET(RID_MAX_GPR)) {
373 GPRDEF(MINCOST) 371 GPRDEF(MINCOST)
374 } else { 372 } else {
375 FPRDEF(MINCOST) 373 FPRDEF(MINCOST)
@@ -539,6 +537,7 @@ static void ra_destreg(ASMState *as, IRIns *ir, Reg r)
539 } 537 }
540} 538}
541 539
540#if LJ_TARGET_X86ORX64
542/* Propagate dest register to left reference. Emit moves as needed. 541/* Propagate dest register to left reference. Emit moves as needed.
543** This is a required fixup step for all 2-operand machine instructions. 542** This is a required fixup step for all 2-operand machine instructions.
544*/ 543*/
@@ -583,6 +582,7 @@ static void ra_left(ASMState *as, Reg dest, IRRef lref)
583 } 582 }
584 } 583 }
585} 584}
585#endif
586 586
587/* -- Snapshot handling --------- ----------------------------------------- */ 587/* -- Snapshot handling --------- ----------------------------------------- */
588 588
@@ -866,7 +866,7 @@ static void asm_phi_shuffle(ASMState *as)
866 if (!blocked) break; /* Finished. */ 866 if (!blocked) break; /* Finished. */
867 if (!(as->freeset & blocked)) { /* Break cycles if none are free. */ 867 if (!(as->freeset & blocked)) { /* Break cycles if none are free. */
868 asm_phi_break(as, blocked, blockedby, RSET_GPR); 868 asm_phi_break(as, blocked, blockedby, RSET_GPR);
869 asm_phi_break(as, blocked, blockedby, RSET_FPR); 869 if (!LJ_SOFTFP) asm_phi_break(as, blocked, blockedby, RSET_FPR);
870 checkmclim(as); 870 checkmclim(as);
871 } /* Else retry some more renames. */ 871 } /* Else retry some more renames. */
872 } 872 }
@@ -921,7 +921,8 @@ static void asm_phi_fixup(ASMState *as)
921/* Setup right PHI reference. */ 921/* Setup right PHI reference. */
922static void asm_phi(ASMState *as, IRIns *ir) 922static void asm_phi(ASMState *as, IRIns *ir)
923{ 923{
924 RegSet allow = (irt_isfp(ir->t) ? RSET_FPR : RSET_GPR) & ~as->phiset; 924 RegSet allow = ((!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR) &
925 ~as->phiset;
925 RegSet afree = (as->freeset & allow); 926 RegSet afree = (as->freeset & allow);
926 IRIns *irl = IR(ir->op1); 927 IRIns *irl = IR(ir->op1);
927 IRIns *irr = IR(ir->op2); 928 IRIns *irr = IR(ir->op2);
@@ -1009,13 +1010,13 @@ static void asm_head_side(ASMState *as)
1009 IRRef1 sloadins[RID_MAX]; 1010 IRRef1 sloadins[RID_MAX];
1010 RegSet allow = RSET_ALL; /* Inverse of all coalesced registers. */ 1011 RegSet allow = RSET_ALL; /* Inverse of all coalesced registers. */
1011 RegSet live = RSET_EMPTY; /* Live parent registers. */ 1012 RegSet live = RSET_EMPTY; /* Live parent registers. */
1012 Reg pbase = as->parent->ir[REF_BASE].r; /* Parent base register (if any). */ 1013 IRIns *irp = &as->parent->ir[REF_BASE]; /* Parent base. */
1013 int32_t spadj, spdelta; 1014 int32_t spadj, spdelta;
1014 int pass2 = 0; 1015 int pass2 = 0;
1015 int pass3 = 0; 1016 int pass3 = 0;
1016 IRRef i; 1017 IRRef i;
1017 1018
1018 allow = asm_head_side_base(as, pbase, allow); 1019 allow = asm_head_side_base(as, irp, allow);
1019 1020
1020 /* Scan all parent SLOADs and collect register dependencies. */ 1021 /* Scan all parent SLOADs and collect register dependencies. */
1021 for (i = as->stopins; i > REF_BASE; i--) { 1022 for (i = as->stopins; i > REF_BASE; i--) {
@@ -1129,7 +1130,7 @@ static void asm_head_side(ASMState *as)
1129 lj_trace_err(as->J, LJ_TRERR_NYICOAL); 1130 lj_trace_err(as->J, LJ_TRERR_NYICOAL);
1130 ra_rename(as, rset_pickbot(live & RSET_GPR), rset_pickbot(tmpset)); 1131 ra_rename(as, rset_pickbot(live & RSET_GPR), rset_pickbot(tmpset));
1131 } 1132 }
1132 if (live & RSET_FPR) { 1133 if (!LJ_SOFTFP && (live & RSET_FPR)) {
1133 RegSet tmpset = as->freeset & ~live & allow & RSET_FPR; 1134 RegSet tmpset = as->freeset & ~live & allow & RSET_FPR;
1134 if (tmpset == RSET_EMPTY) 1135 if (tmpset == RSET_EMPTY)
1135 lj_trace_err(as->J, LJ_TRERR_NYICOAL); 1136 lj_trace_err(as->J, LJ_TRERR_NYICOAL);
@@ -1144,7 +1145,7 @@ static void asm_head_side(ASMState *as)
1144 if (as->topslot > as->T->topslot) { /* Need to check for higher slot? */ 1145 if (as->topslot > as->T->topslot) { /* Need to check for higher slot? */
1145 as->T->topslot = (uint8_t)as->topslot; /* Remember for child traces. */ 1146 as->T->topslot = (uint8_t)as->topslot; /* Remember for child traces. */
1146 /* Reuse the parent exit in the context of the parent trace. */ 1147 /* Reuse the parent exit in the context of the parent trace. */
1147 asm_stack_check(as, as->topslot, pbase, allow & RSET_GPR, as->J->exitno); 1148 asm_stack_check(as, as->topslot, irp, allow & RSET_GPR, as->J->exitno);
1148 } 1149 }
1149} 1150}
1150 1151
@@ -1191,7 +1192,7 @@ static void asm_tail_link(ASMState *as)
1191 1192
1192 /* Root traces that grow the stack need to check the stack at the end. */ 1193 /* Root traces that grow the stack need to check the stack at the end. */
1193 if (!as->parent && as->topslot) 1194 if (!as->parent && as->topslot)
1194 asm_stack_check(as, as->topslot, RID_BASE, as->freeset & RSET_GPR, snapno); 1195 asm_stack_check(as, as->topslot, NULL, as->freeset & RSET_GPR, snapno);
1195} 1196}
1196 1197
1197/* -- Trace setup --------------------------------------------------------- */ 1198/* -- Trace setup --------------------------------------------------------- */
@@ -1283,7 +1284,7 @@ static void asm_setup_regsp(ASMState *as)
1283 as->modset = RSET_SCRATCH; 1284 as->modset = RSET_SCRATCH;
1284 break; 1285 break;
1285 case IR_POW: 1286 case IR_POW:
1286 if (irt_isnum(ir->t)) { 1287 if (!LJ_SOFTFP && irt_isnum(ir->t)) {
1287#if LJ_TARGET_X86ORX64 1288#if LJ_TARGET_X86ORX64
1288 ir->prev = REGSP_HINT(RID_XMM0); 1289 ir->prev = REGSP_HINT(RID_XMM0);
1289 if (inloop) 1290 if (inloop)
@@ -1341,8 +1342,13 @@ static void asm_setup_regsp(ASMState *as)
1341 break; 1342 break;
1342#endif 1343#endif
1343 /* Do not propagate hints across type conversions. */ 1344 /* Do not propagate hints across type conversions. */
1344 case IR_CONV: case IR_TOBIT: 1345 case IR_TOBIT:
1345 break; 1346 break;
1347 case IR_CONV:
1348 if (irt_isfp(ir->t) || (ir->op2 & IRCONV_SRCMASK) == IRT_NUM ||
1349 (ir->op2 & IRCONV_SRCMASK) == IRT_FLOAT)
1350 break;
1351 /* fallthrough */
1346 default: 1352 default:
1347 /* Propagate hints across likely 'op reg, imm' or 'op reg'. */ 1353 /* Propagate hints across likely 'op reg, imm' or 'op reg'. */
1348 if (irref_isk(ir->op2) && !irref_isk(ir->op1)) { 1354 if (irref_isk(ir->op2) && !irref_isk(ir->op1)) {
@@ -1367,6 +1373,10 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
1367 ASMState as_; 1373 ASMState as_;
1368 ASMState *as = &as_; 1374 ASMState *as = &as_;
1369 1375
1376 /* Ensure an initialized instruction beyond the last one for HIOP checks. */
1377 J->cur.nins = lj_ir_nextins(J);
1378 J->cur.ir[J->cur.nins].o = IR_NOP;
1379
1370 /* Setup initial state. Copy some fields to reduce indirections. */ 1380 /* Setup initial state. Copy some fields to reduce indirections. */
1371 as->J = J; 1381 as->J = J;
1372 as->T = T; 1382 as->T = T;
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h
index fb46b3ad..dfc853dd 100644
--- a/src/lj_asm_x86.h
+++ b/src/lj_asm_x86.h
@@ -2191,9 +2191,10 @@ static void asm_hiop(ASMState *as, IRIns *ir)
2191 2191
2192/* Check Lua stack size for overflow. Use exit handler as fallback. */ 2192/* Check Lua stack size for overflow. Use exit handler as fallback. */
2193static void asm_stack_check(ASMState *as, BCReg topslot, 2193static void asm_stack_check(ASMState *as, BCReg topslot,
2194 Reg pbase, RegSet allow, ExitNo exitno) 2194 IRIns *irp, RegSet allow, ExitNo exitno)
2195{ 2195{
2196 /* Try to get an unused temp. register, otherwise spill/restore eax. */ 2196 /* Try to get an unused temp. register, otherwise spill/restore eax. */
2197 Reg pbase = irp ? irp->r : RID_BASE;
2197 Reg r = allow ? rset_pickbot(allow) : RID_EAX; 2198 Reg r = allow ? rset_pickbot(allow) : RID_EAX;
2198 emit_jcc(as, CC_B, exitstub_addr(as->J, exitno)); 2199 emit_jcc(as, CC_B, exitstub_addr(as->J, exitno));
2199 if (allow == RSET_EMPTY) /* Restore temp. register. */ 2200 if (allow == RSET_EMPTY) /* Restore temp. register. */
@@ -2344,7 +2345,7 @@ static void asm_head_root_base(ASMState *as)
2344} 2345}
2345 2346
2346/* Coalesce or reload BASE register for a side trace. */ 2347/* Coalesce or reload BASE register for a side trace. */
2347static RegSet asm_head_side_base(ASMState *as, Reg pbase, RegSet allow) 2348static RegSet asm_head_side_base(ASMState *as, IRIns *irp, RegSet allow)
2348{ 2349{
2349 IRIns *ir = IR(REF_BASE); 2350 IRIns *ir = IR(REF_BASE);
2350 Reg r = ir->r; 2351 Reg r = ir->r;
@@ -2352,11 +2353,11 @@ static RegSet asm_head_side_base(ASMState *as, Reg pbase, RegSet allow)
2352 ra_free(as, r); 2353 ra_free(as, r);
2353 if (rset_test(as->modset, r)) 2354 if (rset_test(as->modset, r))
2354 ir->r = RID_INIT; /* No inheritance for modified BASE register. */ 2355 ir->r = RID_INIT; /* No inheritance for modified BASE register. */
2355 if (pbase == r) { 2356 if (irp->r == r) {
2356 rset_clear(allow, r); /* Mark same BASE register as coalesced. */ 2357 rset_clear(allow, r); /* Mark same BASE register as coalesced. */
2357 } else if (ra_hasreg(pbase) && rset_test(as->freeset, pbase)) { 2358 } else if (ra_hasreg(irp->r) && rset_test(as->freeset, irp->r)) {
2358 rset_clear(allow, pbase); 2359 rset_clear(allow, irp->r);
2359 emit_rr(as, XO_MOV, r, pbase); /* Move from coalesced parent register. */ 2360 emit_rr(as, XO_MOV, r, irp->r); /* Move from coalesced parent reg. */
2360 } else { 2361 } else {
2361 emit_getgl(as, r, jit_base); /* Otherwise reload BASE. */ 2362 emit_getgl(as, r, jit_base); /* Otherwise reload BASE. */
2362 } 2363 }