diff options
-rw-r--r-- | src/lj_asm.c | 36 | ||||
-rw-r--r-- | src/lj_asm_x86.h | 13 |
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. */ |
922 | static void asm_phi(ASMState *as, IRIns *ir) | 922 | static 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. */ |
2193 | static void asm_stack_check(ASMState *as, BCReg topslot, | 2193 | static 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. */ |
2347 | static RegSet asm_head_side_base(ASMState *as, Reg pbase, RegSet allow) | 2348 | static 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 | } |