diff options
author | Mike Pall <mike> | 2011-05-22 17:41:59 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2011-05-22 17:44:58 +0200 |
commit | 138f54352ad604ef50f77cbcc15abec6dbd883c0 (patch) | |
tree | f8ac2d3599cec2af1007da1c894847d3d0e2ff95 /src/lj_asm.c | |
parent | d0115c65f5ad80af2a113332906a0c5a010f9812 (diff) | |
download | luajit-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.c | 112 |
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. */ |
606 | static 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. */ | ||
600 | static void asm_snap_alloc(ASMState *as) | 627 | static 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. */ | ||
1016 | static 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 | } |