aboutsummaryrefslogtreecommitdiff
path: root/src/lj_asm.c
diff options
context:
space:
mode:
authorMike Pall <mike>2011-05-22 17:41:59 +0200
committerMike Pall <mike>2011-05-22 17:44:58 +0200
commit138f54352ad604ef50f77cbcc15abec6dbd883c0 (patch)
treef8ac2d3599cec2af1007da1c894847d3d0e2ff95 /src/lj_asm.c
parentd0115c65f5ad80af2a113332906a0c5a010f9812 (diff)
downloadluajit-138f54352ad604ef50f77cbcc15abec6dbd883c0.tar.gz
luajit-138f54352ad604ef50f77cbcc15abec6dbd883c0.tar.bz2
luajit-138f54352ad604ef50f77cbcc15abec6dbd883c0.zip
Split up FP IR instructions with SPLIT pass for soft-float targets.
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r--src/lj_asm.c112
1 files changed, 85 insertions, 27 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c
index f33dc790..18383bcc 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -85,6 +85,9 @@ typedef struct ASMState {
85 85
86 IRRef1 phireg[RID_MAX]; /* PHI register references. */ 86 IRRef1 phireg[RID_MAX]; /* PHI register references. */
87 uint16_t parentmap[LJ_MAX_JSLOTS]; /* Parent slot to RegSP map. */ 87 uint16_t parentmap[LJ_MAX_JSLOTS]; /* Parent slot to RegSP map. */
88#if LJ_SOFTFP
89 uint16_t parentmaphi[LJ_MAX_JSLOTS]; /* Parent slot to hi RegSP map. */
90#endif
88} ASMState; 91} ASMState;
89 92
90#define IR(ref) (&as->ir[(ref)]) 93#define IR(ref) (&as->ir[(ref)])
@@ -273,9 +276,12 @@ static Reg ra_rematk(ASMState *as, IRIns *ir)
273 ra_modified(as, r); 276 ra_modified(as, r);
274 ir->r = RID_INIT; /* Do not keep any hint. */ 277 ir->r = RID_INIT; /* Do not keep any hint. */
275 RA_DBGX((as, "remat $i $r", ir, r)); 278 RA_DBGX((as, "remat $i $r", ir, r));
279#if !LJ_SOFTFP
276 if (ir->o == IR_KNUM) { 280 if (ir->o == IR_KNUM) {
277 emit_loadn(as, r, ir_knum(ir)); 281 emit_loadn(as, r, ir_knum(ir));
278 } else if (emit_canremat(REF_BASE) && ir->o == IR_BASE) { 282 } else
283#endif
284 if (emit_canremat(REF_BASE) && ir->o == IR_BASE) {
279 ra_sethint(ir->r, RID_BASE); /* Restore BASE register hint. */ 285 ra_sethint(ir->r, RID_BASE); /* Restore BASE register hint. */
280 emit_getgl(as, r, jit_base); 286 emit_getgl(as, r, jit_base);
281 } else if (emit_canremat(ASMREF_L) && ir->o == IR_KPRI) { 287 } else if (emit_canremat(ASMREF_L) && ir->o == IR_KPRI) {
@@ -596,31 +602,40 @@ static int asm_snap_canremat(ASMState *as)
596 return 0; 602 return 0;
597} 603}
598 604
599/* Allocate registers or spill slots for refs escaping to a snapshot. */ 605/* Allocate register or spill slot for a ref that escapes to a snapshot. */
606static void asm_snap_alloc1(ASMState *as, IRRef ref)
607{
608 IRIns *ir = IR(ref);
609 if (!ra_used(ir)) {
610 RegSet allow = (!LJ_SOFTFP && irt_isnum(ir->t)) ? RSET_FPR : RSET_GPR;
611 /* Get a weak register if we have a free one or can rematerialize. */
612 if ((as->freeset & allow) ||
613 (allow == RSET_FPR && asm_snap_canremat(as))) {
614 Reg r = ra_allocref(as, ref, allow); /* Allocate a register. */
615 if (!irt_isphi(ir->t))
616 ra_weak(as, r); /* But mark it as weakly referenced. */
617 checkmclim(as);
618 RA_DBGX((as, "snapreg $f $r", ref, ir->r));
619 } else {
620 ra_spill(as, ir); /* Otherwise force a spill slot. */
621 RA_DBGX((as, "snapspill $f $s", ref, ir->s));
622 }
623 }
624}
625
626/* Allocate refs escaping to a snapshot. */
600static void asm_snap_alloc(ASMState *as) 627static void asm_snap_alloc(ASMState *as)
601{ 628{
602 SnapShot *snap = &as->T->snap[as->snapno]; 629 SnapShot *snap = &as->T->snap[as->snapno];
603 SnapEntry *map = &as->T->snapmap[snap->mapofs]; 630 SnapEntry *map = &as->T->snapmap[snap->mapofs];
604 MSize n, nent = snap->nent; 631 MSize n, nent = snap->nent;
605 for (n = 0; n < nent; n++) { 632 for (n = 0; n < nent; n++) {
606 IRRef ref = snap_ref(map[n]); 633 SnapEntry sn = map[n];
634 IRRef ref = snap_ref(sn);
607 if (!irref_isk(ref)) { 635 if (!irref_isk(ref)) {
608 IRIns *ir = IR(ref); 636 asm_snap_alloc1(as, ref);
609 if (!ra_used(ir)) { 637 if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM))
610 RegSet allow = irt_isnum(ir->t) ? RSET_FPR : RSET_GPR; 638 asm_snap_alloc1(as, ref+1);
611 /* Get a weak register if we have a free one or can rematerialize. */
612 if ((as->freeset & allow) ||
613 (allow == RSET_FPR && asm_snap_canremat(as))) {
614 Reg r = ra_allocref(as, ref, allow); /* Allocate a register. */
615 if (!irt_isphi(ir->t))
616 ra_weak(as, r); /* But mark it as weakly referenced. */
617 checkmclim(as);
618 RA_DBGX((as, "snapreg $f $r", ref, ir->r));
619 } else {
620 ra_spill(as, ir); /* Otherwise force a spill slot. */
621 RA_DBGX((as, "snapspill $f $s", ref, ir->s));
622 }
623 }
624 } 639 }
625 } 640 }
626} 641}
@@ -997,6 +1012,15 @@ static void asm_head_root(ASMState *as)
997 as->T->topslot = gcref(as->T->startpt)->pt.framesize; 1012 as->T->topslot = gcref(as->T->startpt)->pt.framesize;
998} 1013}
999 1014
1015/* Get RegSP for parent slot. */
1016static LJ_AINLINE RegSP asm_head_parentrs(ASMState *as, IRIns *ir)
1017{
1018#if LJ_SOFTFP
1019 if (ir->o == IR_HIOP) return as->parentmaphi[(ir-1)->op1];
1020#endif
1021 return as->parentmap[ir->op1];
1022}
1023
1000/* Head of a side trace. 1024/* Head of a side trace.
1001** 1025**
1002** The current simplistic algorithm requires that all slots inherited 1026** The current simplistic algorithm requires that all slots inherited
@@ -1022,8 +1046,9 @@ static void asm_head_side(ASMState *as)
1022 for (i = as->stopins; i > REF_BASE; i--) { 1046 for (i = as->stopins; i > REF_BASE; i--) {
1023 IRIns *ir = IR(i); 1047 IRIns *ir = IR(i);
1024 RegSP rs; 1048 RegSP rs;
1025 lua_assert(ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_PARENT)); 1049 lua_assert((ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_PARENT)) ||
1026 rs = as->parentmap[ir->op1]; 1050 (LJ_SOFTFP && ir->o == IR_HIOP));
1051 rs = asm_head_parentrs(as, ir);
1027 if (ra_hasreg(ir->r)) { 1052 if (ra_hasreg(ir->r)) {
1028 rset_clear(allow, ir->r); 1053 rset_clear(allow, ir->r);
1029 if (ra_hasspill(ir->s)) 1054 if (ra_hasspill(ir->s))
@@ -1052,6 +1077,12 @@ static void asm_head_side(ASMState *as)
1052 } 1077 }
1053 as->T->spadjust = (uint16_t)spadj; 1078 as->T->spadjust = (uint16_t)spadj;
1054 1079
1080#if !LJ_TARGET_X86ORX64
1081 /* Restore BASE register from parent spill slot. */
1082 if (ra_hasspill(irp->s))
1083 emit_spload(as, IR(REF_BASE), IR(REF_BASE)->r, spdelta + sps_scale(irp->s));
1084#endif
1085
1055 /* Reload spilled target registers. */ 1086 /* Reload spilled target registers. */
1056 if (pass2) { 1087 if (pass2) {
1057 for (i = as->stopins; i > REF_BASE; i--) { 1088 for (i = as->stopins; i > REF_BASE; i--) {
@@ -1061,12 +1092,12 @@ static void asm_head_side(ASMState *as)
1061 Reg r; 1092 Reg r;
1062 RegSP rs; 1093 RegSP rs;
1063 irt_clearmark(ir->t); 1094 irt_clearmark(ir->t);
1064 rs = as->parentmap[ir->op1]; 1095 rs = asm_head_parentrs(as, ir);
1065 if (!ra_hasspill(regsp_spill(rs))) 1096 if (!ra_hasspill(regsp_spill(rs)))
1066 ra_sethint(ir->r, rs); /* Hint may be gone, set it again. */ 1097 ra_sethint(ir->r, rs); /* Hint may be gone, set it again. */
1067 else if (sps_scale(regsp_spill(rs))+spdelta == sps_scale(ir->s)) 1098 else if (sps_scale(regsp_spill(rs))+spdelta == sps_scale(ir->s))
1068 continue; /* Same spill slot, do nothing. */ 1099 continue; /* Same spill slot, do nothing. */
1069 mask = (irt_isnum(ir->t) ? RSET_FPR : RSET_GPR) & allow; 1100 mask = ((!LJ_SOFTFP && irt_isnum(ir->t)) ? RSET_FPR : RSET_GPR) & allow;
1070 if (mask == RSET_EMPTY) 1101 if (mask == RSET_EMPTY)
1071 lj_trace_err(as->J, LJ_TRERR_NYICOAL); 1102 lj_trace_err(as->J, LJ_TRERR_NYICOAL);
1072 r = ra_allocref(as, i, mask); 1103 r = ra_allocref(as, i, mask);
@@ -1093,7 +1124,7 @@ static void asm_head_side(ASMState *as)
1093 while (work) { 1124 while (work) {
1094 Reg r = rset_pickbot(work); 1125 Reg r = rset_pickbot(work);
1095 IRIns *ir = IR(regcost_ref(as->cost[r])); 1126 IRIns *ir = IR(regcost_ref(as->cost[r]));
1096 RegSP rs = as->parentmap[ir->op1]; 1127 RegSP rs = asm_head_parentrs(as, ir);
1097 rset_clear(work, r); 1128 rset_clear(work, r);
1098 if (ra_hasspill(regsp_spill(rs))) { 1129 if (ra_hasspill(regsp_spill(rs))) {
1099 int32_t ofs = sps_scale(regsp_spill(rs)); 1130 int32_t ofs = sps_scale(regsp_spill(rs));
@@ -1262,14 +1293,38 @@ static void asm_setup_regsp(ASMState *as)
1262 (RSET_SCRATCH & ~RSET_FPR) : RSET_SCRATCH; 1293 (RSET_SCRATCH & ~RSET_FPR) : RSET_SCRATCH;
1263 continue; 1294 continue;
1264 } 1295 }
1265#if LJ_32 && LJ_HASFFI 1296#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
1266 case IR_HIOP: 1297 case IR_HIOP:
1267 if ((ir-1)->o == IR_CALLN) { 1298 switch ((ir-1)->o) {
1299#if LJ_SOFTFP
1300 case IR_SLOAD:
1301 if (((ir-1)->op2 & IRSLOAD_PARENT)) {
1302 RegSP rs = as->parentmaphi[(ir-1)->op1];
1303 lua_assert(regsp_used(rs));
1304 as->stopins = i;
1305 if (!ra_hasspill(regsp_spill(rs)) && ra_hasreg(regsp_reg(rs))) {
1306 ir->prev = (uint16_t)REGSP_HINT(regsp_reg(rs));
1307 continue;
1308 }
1309 }
1310 break;
1311#endif
1312 case IR_CALLN: case IR_CALLXS:
1313#if LJ_SOFTFP
1314 case IR_MIN: case IR_MAX:
1315#endif
1268 ir->prev = REGSP_HINT(RID_RETHI); 1316 ir->prev = REGSP_HINT(RID_RETHI);
1269 continue; 1317 continue;
1318 default:
1319 break;
1270 } 1320 }
1271 break; 1321 break;
1272#endif 1322#endif
1323#if LJ_SOFTFP
1324 case IR_MIN: case IR_MAX:
1325 if ((ir+1)->o != IR_HIOP) break;
1326 /* fallthrough */
1327#endif
1273 /* C calls evict all scratch regs and return results in RID_RET. */ 1328 /* C calls evict all scratch regs and return results in RID_RET. */
1274 case IR_SNEW: case IR_XSNEW: case IR_NEWREF: 1329 case IR_SNEW: case IR_XSNEW: case IR_NEWREF:
1275 if (REGARG_NUMGPR < 3 && as->evenspill < 3) 1330 if (REGARG_NUMGPR < 3 && as->evenspill < 3)
@@ -1387,7 +1442,10 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
1387 as->loopinv = 0; 1442 as->loopinv = 0;
1388 if (J->parent) { 1443 if (J->parent) {
1389 as->parent = traceref(J, J->parent); 1444 as->parent = traceref(J, J->parent);
1390 lj_snap_regspmap(as->parentmap, as->parent, J->exitno); 1445 lj_snap_regspmap(as->parentmap, as->parent, J->exitno, 0);
1446#if LJ_SOFTFP
1447 lj_snap_regspmap(as->parentmaphi, as->parent, J->exitno, 1);
1448#endif
1391 } else { 1449 } else {
1392 as->parent = NULL; 1450 as->parent = NULL;
1393 } 1451 }