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 | |
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.
-rw-r--r-- | lib/dump.lua | 10 | ||||
-rw-r--r-- | src/Makefile.dep | 2 | ||||
-rw-r--r-- | src/lj_asm.c | 112 | ||||
-rw-r--r-- | src/lj_ffrecord.c | 7 | ||||
-rw-r--r-- | src/lj_ir.c | 1 | ||||
-rw-r--r-- | src/lj_ir.h | 2 | ||||
-rw-r--r-- | src/lj_ircall.h | 123 | ||||
-rw-r--r-- | src/lj_iropt.h | 2 | ||||
-rw-r--r-- | src/lj_jit.h | 4 | ||||
-rw-r--r-- | src/lj_opt_split.c | 271 | ||||
-rw-r--r-- | src/lj_record.c | 10 | ||||
-rw-r--r-- | src/lj_snap.c | 4 | ||||
-rw-r--r-- | src/lj_snap.h | 3 |
13 files changed, 479 insertions, 72 deletions
diff --git a/lib/dump.lua b/lib/dump.lua index 0f9f7b2b..a6b61f53 100644 --- a/lib/dump.lua +++ b/lib/dump.lua | |||
@@ -147,6 +147,7 @@ local irtype_text = { | |||
147 | "u32", | 147 | "u32", |
148 | "i64", | 148 | "i64", |
149 | "u64", | 149 | "u64", |
150 | "sfp", | ||
150 | } | 151 | } |
151 | 152 | ||
152 | local colortype_ansi = { | 153 | local colortype_ansi = { |
@@ -173,6 +174,7 @@ local colortype_ansi = { | |||
173 | "\027[35m%s\027[m", | 174 | "\027[35m%s\027[m", |
174 | "\027[35m%s\027[m", | 175 | "\027[35m%s\027[m", |
175 | "\027[35m%s\027[m", | 176 | "\027[35m%s\027[m", |
177 | "\027[35m%s\027[m", | ||
176 | } | 178 | } |
177 | 179 | ||
178 | local function colorize_text(s, t) | 180 | local function colorize_text(s, t) |
@@ -318,11 +320,11 @@ local function printsnap(tr, snap) | |||
318 | if ref < 0 then | 320 | if ref < 0 then |
319 | out:write(formatk(tr, ref)) | 321 | out:write(formatk(tr, ref)) |
320 | else | 322 | else |
321 | local m, ot, op1, op2 = traceir(tr, ref) | ||
322 | out:write(colorize(format("%04d", ref), band(ot, 31))) | ||
323 | if band(sn, 0x80000) ~= 0 then -- SNAP_SOFTFPNUM | 323 | if band(sn, 0x80000) ~= 0 then -- SNAP_SOFTFPNUM |
324 | local m, ot, op1, op2 = traceir(tr, ref+1) | 324 | out:write(colorize(format("%04d/%04d", ref, ref+1), 14)) |
325 | out:write(colorize(format("/%04d", ref+1), band(ot, 31))) | 325 | else |
326 | local m, ot, op1, op2 = traceir(tr, ref) | ||
327 | out:write(colorize(format("%04d", ref), band(ot, 31))) | ||
326 | end | 328 | end |
327 | end | 329 | end |
328 | out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME | 330 | out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME |
diff --git a/src/Makefile.dep b/src/Makefile.dep index 89ac79e8..8e0d7a1c 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep | |||
@@ -108,7 +108,7 @@ lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
108 | lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 108 | lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
109 | lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \ | 109 | lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \ |
110 | lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h lj_carith.h \ | 110 | lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h lj_carith.h \ |
111 | lj_lib.h | 111 | lj_vm.h lj_lib.h |
112 | lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 112 | lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
113 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h lualib.h \ | 113 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h lualib.h \ |
114 | lj_state.h lj_lex.h lj_parse.h lj_char.h | 114 | lj_state.h lj_lex.h lj_parse.h lj_char.h |
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 | } |
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index 91d31b29..0de54f04 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c | |||
@@ -438,7 +438,12 @@ static void LJ_FASTCALL recff_math_unary(jit_State *J, RecordFFData *rd) | |||
438 | static void LJ_FASTCALL recff_math_binary(jit_State *J, RecordFFData *rd) | 438 | static void LJ_FASTCALL recff_math_binary(jit_State *J, RecordFFData *rd) |
439 | { | 439 | { |
440 | TRef tr = lj_ir_tonum(J, J->base[0]); | 440 | TRef tr = lj_ir_tonum(J, J->base[0]); |
441 | J->base[0] = emitir(IRTN(rd->data), tr, lj_ir_tonum(J, J->base[1])); | 441 | #if LJ_TARGET_X86ORX64 |
442 | TRef tr2 = lj_ir_tonum(J, J->base[1]); | ||
443 | #else | ||
444 | TRef tr2 = lj_opt_narrow_toint(J, J->base[1]); | ||
445 | #endif | ||
446 | J->base[0] = emitir(IRTN(rd->data), tr, tr2); | ||
442 | } | 447 | } |
443 | 448 | ||
444 | /* Record math.asin, math.acos, math.atan. */ | 449 | /* Record math.asin, math.acos, math.atan. */ |
diff --git a/src/lj_ir.c b/src/lj_ir.c index b7d1e7a7..59ffcfde 100644 --- a/src/lj_ir.c +++ b/src/lj_ir.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "lj_cdata.h" | 27 | #include "lj_cdata.h" |
28 | #include "lj_carith.h" | 28 | #include "lj_carith.h" |
29 | #endif | 29 | #endif |
30 | #include "lj_vm.h" | ||
30 | #include "lj_lib.h" | 31 | #include "lj_lib.h" |
31 | 32 | ||
32 | /* Some local macros to save typing. Undef'd at the end. */ | 33 | /* Some local macros to save typing. Undef'd at the end. */ |
diff --git a/src/lj_ir.h b/src/lj_ir.h index 1bc6c332..aac34350 100644 --- a/src/lj_ir.h +++ b/src/lj_ir.h | |||
@@ -283,7 +283,7 @@ LJ_DATA const uint8_t lj_ir_mode[IR__MAX+1]; | |||
283 | _(NIL) _(FALSE) _(TRUE) _(LIGHTUD) _(STR) _(P32) _(THREAD) \ | 283 | _(NIL) _(FALSE) _(TRUE) _(LIGHTUD) _(STR) _(P32) _(THREAD) \ |
284 | _(PROTO) _(FUNC) _(P64) _(CDATA) _(TAB) _(UDATA) \ | 284 | _(PROTO) _(FUNC) _(P64) _(CDATA) _(TAB) _(UDATA) \ |
285 | _(FLOAT) _(NUM) _(I8) _(U8) _(I16) _(U16) _(INT) _(U32) _(I64) _(U64) \ | 285 | _(FLOAT) _(NUM) _(I8) _(U8) _(I16) _(U16) _(INT) _(U32) _(I64) _(U64) \ |
286 | /* There is room for 10 more types. */ | 286 | _(SOFTFP) /* There is room for 9 more types. */ |
287 | 287 | ||
288 | /* IR result type and flags (8 bit). */ | 288 | /* IR result type and flags (8 bit). */ |
289 | typedef enum { | 289 | typedef enum { |
diff --git a/src/lj_ircall.h b/src/lj_ircall.h index 3131b15d..b83a0a81 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h | |||
@@ -38,6 +38,72 @@ typedef struct CCallInfo { | |||
38 | #define CCI_FASTCALL 0x0800 /* Fastcall convention. */ | 38 | #define CCI_FASTCALL 0x0800 /* Fastcall convention. */ |
39 | 39 | ||
40 | /* Function definitions for CALL* instructions. */ | 40 | /* Function definitions for CALL* instructions. */ |
41 | #if LJ_SOFTFP | ||
42 | #if LJ_HASFFI | ||
43 | #define IRCALLDEF_SOFTFP_FFI(_) \ | ||
44 | _(softfp_ui2d, 1, N, NUM, 0) \ | ||
45 | _(softfp_l2d, 2, N, NUM, 0) \ | ||
46 | _(softfp_ul2d, 2, N, NUM, 0) \ | ||
47 | _(softfp_f2d, 1, N, NUM, 0) \ | ||
48 | _(softfp_d2ui, 2, N, INT, 0) \ | ||
49 | _(softfp_d2l, 2, N, I64, 0) \ | ||
50 | _(softfp_d2ul, 2, N, U64, 0) \ | ||
51 | _(softfp_d2f, 2, N, FLOAT, 0) \ | ||
52 | _(softfp_i2f, 1, N, FLOAT, 0) \ | ||
53 | _(softfp_ui2f, 1, N, FLOAT, 0) \ | ||
54 | _(softfp_l2f, 2, N, FLOAT, 0) \ | ||
55 | _(softfp_ul2f, 2, N, FLOAT, 0) \ | ||
56 | _(softfp_f2i, 1, N, INT, 0) \ | ||
57 | _(softfp_f2ui, 1, N, INT, 0) \ | ||
58 | _(softfp_f2l, 1, N, I64, 0) \ | ||
59 | _(softfp_f2ul, 1, N, U64, 0) | ||
60 | #else | ||
61 | #define IRCALLDEF_SOFTFP_FFI(_) | ||
62 | #endif | ||
63 | #define IRCALLDEF_SOFTFP(_) \ | ||
64 | _(lj_vm_tobit, 2, N, INT, 0) \ | ||
65 | _(softfp_add, 4, N, NUM, 0) \ | ||
66 | _(softfp_sub, 4, N, NUM, 0) \ | ||
67 | _(softfp_mul, 4, N, NUM, 0) \ | ||
68 | _(softfp_div, 4, N, NUM, 0) \ | ||
69 | _(softfp_cmp, 4, N, NIL, 0) \ | ||
70 | _(softfp_i2d, 1, N, NUM, 0) \ | ||
71 | _(softfp_d2i, 2, N, INT, 0) \ | ||
72 | IRCALLDEF_SOFTFP_FFI(_) | ||
73 | #else | ||
74 | #define IRCALLDEF_SOFTFP(_) | ||
75 | #endif | ||
76 | |||
77 | #if LJ_TARGET_X86ORX64 | ||
78 | /* Use lj_vm_* helpers and x87 ops. */ | ||
79 | #define IRCALLDEF_FPMATH(_) | ||
80 | #else | ||
81 | /* Use standard math library calls. */ | ||
82 | #if LJ_SOFTFP | ||
83 | #define ARG1_FP 2 /* Treat as 2 32 bit arguments. */ | ||
84 | #else | ||
85 | #define ARG1_FP 1 | ||
86 | #endif | ||
87 | /* ORDER FPM */ | ||
88 | #define IRCALLDEF_FPMATH(_) \ | ||
89 | _(lj_vm_floor, ARG1_FP, N, NUM, 0) \ | ||
90 | _(lj_vm_ceil, ARG1_FP, N, NUM, 0) \ | ||
91 | _(lj_vm_trunc, ARG1_FP, N, NUM, 0) \ | ||
92 | _(sqrt, ARG1_FP, N, NUM, 0) \ | ||
93 | _(exp, ARG1_FP, N, NUM, 0) \ | ||
94 | _(exp2, ARG1_FP, N, NUM, 0) \ | ||
95 | _(log, ARG1_FP, N, NUM, 0) \ | ||
96 | _(log2, ARG1_FP, N, NUM, 0) \ | ||
97 | _(log10, ARG1_FP, N, NUM, 0) \ | ||
98 | _(sin, ARG1_FP, N, NUM, 0) \ | ||
99 | _(cos, ARG1_FP, N, NUM, 0) \ | ||
100 | _(tan, ARG1_FP, N, NUM, 0) \ | ||
101 | _(lj_vm_powi, ARG1_FP+1, N, NUM, 0) \ | ||
102 | _(pow, ARG1_FP*2, N, NUM, 0) \ | ||
103 | _(atan2, ARG1_FP*2, N, NUM, 0) \ | ||
104 | _(ldexp, ARG1_FP+1, N, NUM, 0) | ||
105 | #endif | ||
106 | |||
41 | #if LJ_HASFFI | 107 | #if LJ_HASFFI |
42 | #if LJ_32 | 108 | #if LJ_32 |
43 | #define ARG2_64 4 /* Treat as 4 32 bit arguments. */ | 109 | #define ARG2_64 4 /* Treat as 4 32 bit arguments. */ |
@@ -62,6 +128,7 @@ typedef struct CCallInfo { | |||
62 | #else | 128 | #else |
63 | #define IRCALLDEF_FFI(_) | 129 | #define IRCALLDEF_FFI(_) |
64 | #endif | 130 | #endif |
131 | |||
65 | #define IRCALLDEF(_) \ | 132 | #define IRCALLDEF(_) \ |
66 | _(lj_str_cmp, 2, FN, INT, CCI_NOFPRCLOBBER) \ | 133 | _(lj_str_cmp, 2, FN, INT, CCI_NOFPRCLOBBER) \ |
67 | _(lj_str_new, 3, S, STR, CCI_L) \ | 134 | _(lj_str_new, 3, S, STR, CCI_L) \ |
@@ -76,6 +143,8 @@ typedef struct CCallInfo { | |||
76 | _(lj_gc_barrieruv, 2, FS, NIL, 0) \ | 143 | _(lj_gc_barrieruv, 2, FS, NIL, 0) \ |
77 | _(lj_mem_newgco, 2, FS, P32, CCI_L) \ | 144 | _(lj_mem_newgco, 2, FS, P32, CCI_L) \ |
78 | _(lj_math_random_step, 1, FS, NUM, CCI_CASTU64|CCI_NOFPRCLOBBER) \ | 145 | _(lj_math_random_step, 1, FS, NUM, CCI_CASTU64|CCI_NOFPRCLOBBER) \ |
146 | IRCALLDEF_SOFTFP(_) \ | ||
147 | IRCALLDEF_FPMATH(_) \ | ||
79 | IRCALLDEF_FFI(_) \ | 148 | IRCALLDEF_FFI(_) \ |
80 | _(sinh, 1, N, NUM, 0) \ | 149 | _(sinh, 1, N, NUM, 0) \ |
81 | _(cosh, 1, N, NUM, 0) \ | 150 | _(cosh, 1, N, NUM, 0) \ |
@@ -97,4 +166,58 @@ LJ_FUNC TRef lj_ir_call(jit_State *J, IRCallID id, ...); | |||
97 | 166 | ||
98 | LJ_DATA const CCallInfo lj_ir_callinfo[IRCALL__MAX+1]; | 167 | LJ_DATA const CCallInfo lj_ir_callinfo[IRCALL__MAX+1]; |
99 | 168 | ||
169 | /* Soft-float declarations. */ | ||
170 | #if LJ_SOFTFP | ||
171 | #if LJ_TARGET_ARM | ||
172 | #define softfp_add __aeabi_dadd | ||
173 | #define softfp_sub __aeabi_dsub | ||
174 | #define softfp_mul __aeabi_dmul | ||
175 | #define softfp_div __aeabi_ddiv | ||
176 | #define softfp_cmp __aeabi_cdcmple | ||
177 | #define softfp_i2d __aeabi_i2d | ||
178 | #define softfp_ui2d __aeabi_ui2d | ||
179 | #define softfp_l2d __aeabi_l2d | ||
180 | #define softfp_ul2d __aeabi_ul2d | ||
181 | #define softfp_f2d __aeabi_f2d | ||
182 | #define softfp_d2i __aeabi_d2iz | ||
183 | #define softfp_d2ui __aeabi_d2uiz | ||
184 | #define softfp_d2l __aeabi_d2lz | ||
185 | #define softfp_d2ul __aeabi_d2ulz | ||
186 | #define softfp_d2f __aeabi_d2f | ||
187 | #define softfp_i2f __aeabi_i2f | ||
188 | #define softfp_ui2f __aeabi_ui2f | ||
189 | #define softfp_l2f __aeabi_l2f | ||
190 | #define softfp_ul2f __aeabi_ul2f | ||
191 | #define softfp_f2i __aeabi_f2iz | ||
192 | #define softfp_f2ui __aeabi_f2uiz | ||
193 | #define softfp_f2l __aeabi_f2lz | ||
194 | #define softfp_f2ul __aeabi_f2ulz | ||
195 | #else | ||
196 | #error "Missing soft-float definitions for target architecture" | ||
197 | #endif | ||
198 | extern double softfp_add(double a, double b); | ||
199 | extern double softfp_sub(double a, double b); | ||
200 | extern double softfp_mul(double a, double b); | ||
201 | extern double softfp_div(double a, double b); | ||
202 | extern void softfp_cmp(double a, double b); | ||
203 | extern double softfp_i2d(int32_t a); | ||
204 | extern double softfp_ui2d(uint32_t a); | ||
205 | extern double softfp_l2d(int64_t a); | ||
206 | extern double softfp_ul2d(uint64_t a); | ||
207 | extern double softfp_f2d(float a); | ||
208 | extern int32_t softfp_d2i(double a); | ||
209 | extern uint32_t softfp_d2ui(double a); | ||
210 | extern int64_t softfp_d2l(double a); | ||
211 | extern uint64_t softfp_d2ul(double a); | ||
212 | extern float softfp_d2f(double a); | ||
213 | extern float softfp_i2f(int32_t a); | ||
214 | extern float softfp_ui2f(uint32_t a); | ||
215 | extern float softfp_l2f(int64_t a); | ||
216 | extern float softfp_ul2f(uint64_t a); | ||
217 | extern int32_t softfp_f2i(float a); | ||
218 | extern uint32_t softfp_f2ui(float a); | ||
219 | extern int64_t softfp_f2l(float a); | ||
220 | extern uint64_t softfp_f2ul(float a); | ||
221 | #endif | ||
222 | |||
100 | #endif | 223 | #endif |
diff --git a/src/lj_iropt.h b/src/lj_iropt.h index daba5296..7ab42b7a 100644 --- a/src/lj_iropt.h +++ b/src/lj_iropt.h | |||
@@ -148,7 +148,7 @@ LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase); | |||
148 | /* Optimization passes. */ | 148 | /* Optimization passes. */ |
149 | LJ_FUNC void lj_opt_dce(jit_State *J); | 149 | LJ_FUNC void lj_opt_dce(jit_State *J); |
150 | LJ_FUNC int lj_opt_loop(jit_State *J); | 150 | LJ_FUNC int lj_opt_loop(jit_State *J); |
151 | #if LJ_HASFFI && LJ_32 | 151 | #if LJ_SOFTFP || (LJ_32 && LJ_HASFFI) |
152 | LJ_FUNC void lj_opt_split(jit_State *J); | 152 | LJ_FUNC void lj_opt_split(jit_State *J); |
153 | #else | 153 | #else |
154 | #define lj_opt_split(J) UNUSED(J) | 154 | #define lj_opt_split(J) UNUSED(J) |
diff --git a/src/lj_jit.h b/src/lj_jit.h index dd74dedb..63584355 100644 --- a/src/lj_jit.h +++ b/src/lj_jit.h | |||
@@ -250,7 +250,7 @@ enum { | |||
250 | ((TValue *)(((intptr_t)&J->ksimd[2*(n)] + 15) & ~(intptr_t)15)) | 250 | ((TValue *)(((intptr_t)&J->ksimd[2*(n)] + 15) & ~(intptr_t)15)) |
251 | 251 | ||
252 | /* Set/reset flag to activate the SPLIT pass for the current trace. */ | 252 | /* Set/reset flag to activate the SPLIT pass for the current trace. */ |
253 | #if LJ_32 && LJ_HASFFI | 253 | #if LJ_SOFTFP || (LJ_32 && LJ_HASFFI) |
254 | #define lj_needsplit(J) (J->needsplit = 1) | 254 | #define lj_needsplit(J) (J->needsplit = 1) |
255 | #define lj_resetsplit(J) (J->needsplit = 0) | 255 | #define lj_resetsplit(J) (J->needsplit = 0) |
256 | #else | 256 | #else |
@@ -311,7 +311,7 @@ typedef struct jit_State { | |||
311 | MSize sizesnapmap; /* Size of temp. snapshot map buffer. */ | 311 | MSize sizesnapmap; /* Size of temp. snapshot map buffer. */ |
312 | 312 | ||
313 | PostProc postproc; /* Required post-processing after execution. */ | 313 | PostProc postproc; /* Required post-processing after execution. */ |
314 | #if LJ_32 && LJ_HASFFI | 314 | #if LJ_SOFTFP || (LJ_32 && LJ_HASFFI) |
315 | int needsplit; /* Need SPLIT pass. */ | 315 | int needsplit; /* Need SPLIT pass. */ |
316 | #endif | 316 | #endif |
317 | 317 | ||
diff --git a/src/lj_opt_split.c b/src/lj_opt_split.c index 2f8b1e9c..67436a65 100644 --- a/src/lj_opt_split.c +++ b/src/lj_opt_split.c | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | #include "lj_obj.h" | 9 | #include "lj_obj.h" |
10 | 10 | ||
11 | #if LJ_HASJIT && LJ_HASFFI && LJ_32 | 11 | #if LJ_HASJIT && (LJ_SOFTFP || (LJ_32 && LJ_HASFFI)) |
12 | 12 | ||
13 | #include "lj_err.h" | 13 | #include "lj_err.h" |
14 | #include "lj_str.h" | 14 | #include "lj_str.h" |
@@ -21,9 +21,9 @@ | |||
21 | /* SPLIT pass: | 21 | /* SPLIT pass: |
22 | ** | 22 | ** |
23 | ** This pass splits up 64 bit IR instructions into multiple 32 bit IR | 23 | ** This pass splits up 64 bit IR instructions into multiple 32 bit IR |
24 | ** instructions. It's only active for 32 bit CPUs which lack native 64 bit | 24 | ** instructions. It's only active for soft-float targets or for 32 bit CPUs |
25 | ** operations. The FFI is currently the only emitter for 64 bit | 25 | ** which lack native 64 bit integer operations (the FFI is currently the |
26 | ** instructions, so this pass is disabled if the FFI is disabled. | 26 | ** only emitter for 64 bit integer instructions). |
27 | ** | 27 | ** |
28 | ** Splitting the IR in a separate pass keeps each 32 bit IR assembler | 28 | ** Splitting the IR in a separate pass keeps each 32 bit IR assembler |
29 | ** backend simple. Only a small amount of extra functionality needs to be | 29 | ** backend simple. Only a small amount of extra functionality needs to be |
@@ -41,14 +41,19 @@ | |||
41 | ** The operands of HIOP hold the hiword input references. The output of HIOP | 41 | ** The operands of HIOP hold the hiword input references. The output of HIOP |
42 | ** is the hiword output reference, which is also used to hold the hiword | 42 | ** is the hiword output reference, which is also used to hold the hiword |
43 | ** register or spill slot information. The register allocator treats this | 43 | ** register or spill slot information. The register allocator treats this |
44 | ** instruction independent of any other instruction, which improves code | 44 | ** instruction independently of any other instruction, which improves code |
45 | ** quality compared to using fixed register pairs. | 45 | ** quality compared to using fixed register pairs. |
46 | ** | 46 | ** |
47 | ** It's easier to split up some instructions into two regular 32 bit | 47 | ** It's easier to split up some instructions into two regular 32 bit |
48 | ** instructions. E.g. XLOAD is split up into two XLOADs with two different | 48 | ** instructions. E.g. XLOAD is split up into two XLOADs with two different |
49 | ** addresses. Obviously 64 bit constants need to be split up into two 32 bit | 49 | ** addresses. Obviously 64 bit constants need to be split up into two 32 bit |
50 | ** constants, too. Some hiword instructions can be entirely omitted, e.g. | 50 | ** constants, too. Some hiword instructions can be entirely omitted, e.g. |
51 | ** when zero-extending a 32 bit value to 64 bits. | 51 | ** when zero-extending a 32 bit value to 64 bits. 64 bit arguments for calls |
52 | ** are split up into two 32 bit arguments each. | ||
53 | ** | ||
54 | ** On soft-float targets, floating-point instructions are directly converted | ||
55 | ** to soft-float calls by the SPLIT pass (except for comparisons and MIN/MAX). | ||
56 | ** HIOP for number results has the type IRT_SOFTFP ("sfp" in -jdump). | ||
52 | ** | 57 | ** |
53 | ** Here's the IR and x64 machine code for 'x.b = x.a + 1' for a struct with | 58 | ** Here's the IR and x64 machine code for 'x.b = x.a + 1' for a struct with |
54 | ** two int64_t fields: | 59 | ** two int64_t fields: |
@@ -101,10 +106,43 @@ static IRRef split_emit(jit_State *J, uint16_t ot, IRRef1 op1, IRRef1 op2) | |||
101 | return nref; | 106 | return nref; |
102 | } | 107 | } |
103 | 108 | ||
104 | /* Emit a CALLN with two split 64 bit arguments. */ | 109 | #if LJ_SOFTFP |
105 | static IRRef split_call64(jit_State *J, IRRef1 *hisubst, IRIns *oir, | 110 | /* Emit a CALLN with one split 64 bit argument. */ |
111 | static IRRef split_call_l(jit_State *J, IRRef1 *hisubst, IRIns *oir, | ||
106 | IRIns *ir, IRCallID id) | 112 | IRIns *ir, IRCallID id) |
107 | { | 113 | { |
114 | IRRef tmp, op1 = ir->op1; | ||
115 | J->cur.nins--; | ||
116 | #if LJ_LE | ||
117 | tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), oir[op1].prev, hisubst[op1]); | ||
118 | #else | ||
119 | tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), hisubst[op1], oir[op1].prev); | ||
120 | #endif | ||
121 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); | ||
122 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); | ||
123 | } | ||
124 | |||
125 | /* Emit a CALLN with one split 64 bit argument and a 32 bit argument. */ | ||
126 | static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir, | ||
127 | IRIns *ir, IRCallID id) | ||
128 | { | ||
129 | IRRef tmp, op1 = ir->op1, op2 = ir->op2; | ||
130 | J->cur.nins--; | ||
131 | #if LJ_LE | ||
132 | tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), oir[op1].prev, hisubst[op1]); | ||
133 | #else | ||
134 | tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), hisubst[op1], oir[op1].prev); | ||
135 | #endif | ||
136 | tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), tmp, oir[op2].prev); | ||
137 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); | ||
138 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); | ||
139 | } | ||
140 | #endif | ||
141 | |||
142 | /* Emit a CALLN with two split 64 bit arguments. */ | ||
143 | static IRRef split_call_ll(jit_State *J, IRRef1 *hisubst, IRIns *oir, | ||
144 | IRIns *ir, IRCallID id) | ||
145 | { | ||
108 | IRRef tmp, op1 = ir->op1, op2 = ir->op2; | 146 | IRRef tmp, op1 = ir->op1, op2 = ir->op2; |
109 | J->cur.nins--; | 147 | J->cur.nins--; |
110 | #if LJ_LE | 148 | #if LJ_LE |
@@ -117,7 +155,9 @@ static IRRef split_call64(jit_State *J, IRRef1 *hisubst, IRIns *oir, | |||
117 | tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), tmp, oir[op2].prev); | 155 | tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), tmp, oir[op2].prev); |
118 | #endif | 156 | #endif |
119 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); | 157 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); |
120 | return split_emit(J, IRTI(IR_HIOP), tmp, tmp); | 158 | return split_emit(J, |
159 | IRT(IR_HIOP, (LJ_SOFTFP && irt_isnum(ir->t)) ? IRT_SOFTFP : IRT_INT), | ||
160 | tmp, tmp); | ||
121 | } | 161 | } |
122 | 162 | ||
123 | /* Get a pointer to the other 32 bit word (LE: hiword, BE: loword). */ | 163 | /* Get a pointer to the other 32 bit word (LE: hiword, BE: loword). */ |
@@ -155,7 +195,8 @@ static void split_ir(jit_State *J) | |||
155 | /* Process constants and fixed references. */ | 195 | /* Process constants and fixed references. */ |
156 | for (ref = nk; ref <= REF_BASE; ref++) { | 196 | for (ref = nk; ref <= REF_BASE; ref++) { |
157 | IRIns *ir = &oir[ref]; | 197 | IRIns *ir = &oir[ref]; |
158 | if (ir->o == IR_KINT64) { /* Split up 64 bit constant. */ | 198 | if ((LJ_SOFTFP && ir->o == IR_KNUM) || ir->o == IR_KINT64) { |
199 | /* Split up 64 bit constant. */ | ||
159 | TValue tv = *ir_k64(ir); | 200 | TValue tv = *ir_k64(ir); |
160 | ir->prev = lj_ir_kint(J, (int32_t)tv.u32.lo); | 201 | ir->prev = lj_ir_kint(J, (int32_t)tv.u32.lo); |
161 | hisubst[ref] = lj_ir_kint(J, (int32_t)tv.u32.hi); | 202 | hisubst[ref] = lj_ir_kint(J, (int32_t)tv.u32.hi); |
@@ -181,6 +222,106 @@ static void split_ir(jit_State *J) | |||
181 | hisubst[ref] = 0; | 222 | hisubst[ref] = 0; |
182 | 223 | ||
183 | /* Split 64 bit instructions. */ | 224 | /* Split 64 bit instructions. */ |
225 | #if LJ_SOFTFP | ||
226 | if (irt_isnum(ir->t)) { | ||
227 | nir->t.irt = IRT_INT | (nir->t.irt & IRT_GUARD); /* Turn into INT op. */ | ||
228 | /* Note: hi ref = lo ref + 1! Required for SNAP_SOFTFPNUM logic. */ | ||
229 | switch (ir->o) { | ||
230 | case IR_ADD: | ||
231 | hi = split_call_ll(J, hisubst, oir, ir, IRCALL_softfp_add); | ||
232 | break; | ||
233 | case IR_SUB: | ||
234 | hi = split_call_ll(J, hisubst, oir, ir, IRCALL_softfp_sub); | ||
235 | break; | ||
236 | case IR_MUL: | ||
237 | hi = split_call_ll(J, hisubst, oir, ir, IRCALL_softfp_mul); | ||
238 | break; | ||
239 | case IR_DIV: | ||
240 | hi = split_call_ll(J, hisubst, oir, ir, IRCALL_softfp_div); | ||
241 | break; | ||
242 | case IR_POW: | ||
243 | hi = split_call_li(J, hisubst, oir, ir, IRCALL_lj_vm_powi); | ||
244 | break; | ||
245 | case IR_FPMATH: | ||
246 | hi = split_call_l(J, hisubst, oir, ir, IRCALL_lj_vm_floor + ir->op2); | ||
247 | break; | ||
248 | case IR_ATAN2: | ||
249 | hi = split_call_ll(J, hisubst, oir, ir, IRCALL_atan2); | ||
250 | break; | ||
251 | case IR_LDEXP: | ||
252 | hi = split_call_li(J, hisubst, oir, ir, IRCALL_ldexp); | ||
253 | break; | ||
254 | case IR_NEG: case IR_ABS: | ||
255 | nir->o = IR_CONV; /* Pass through loword. */ | ||
256 | nir->op2 = (IRT_INT << 5) | IRT_INT; | ||
257 | hi = split_emit(J, IRT(ir->o == IR_NEG ? IR_BXOR : IR_BAND, IRT_SOFTFP), | ||
258 | hisubst[ir->op1], hisubst[ir->op2]); | ||
259 | break; | ||
260 | case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: | ||
261 | case IR_MIN: case IR_MAX: | ||
262 | hi = split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), nref, nref); | ||
263 | break; | ||
264 | case IR_XLOAD: | ||
265 | hi = split_emit(J, IRT(IR_XLOAD, IRT_SOFTFP), | ||
266 | split_ptr(J, nir->op1), ir->op2); | ||
267 | #if LJ_BE | ||
268 | ir->prev = hi; hi = nref; | ||
269 | #endif | ||
270 | break; | ||
271 | case IR_ASTORE: case IR_HSTORE: case IR_USTORE: | ||
272 | split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), nir->op1, hisubst[ir->op2]); | ||
273 | break; | ||
274 | case IR_XSTORE: { | ||
275 | #if LJ_LE | ||
276 | IRRef hiref = hisubst[ir->op2]; | ||
277 | #else | ||
278 | IRRef hiref = nir->op2; nir->op2 = hisubst[ir->op2]; | ||
279 | #endif | ||
280 | split_emit(J, IRT(IR_XSTORE, IRT_SOFTFP), | ||
281 | split_ptr(J, nir->op1), hiref); | ||
282 | break; | ||
283 | } | ||
284 | case IR_CONV: { /* Conversion to number. Others handled below. */ | ||
285 | IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); | ||
286 | #if LJ_32 && LJ_HASFFI | ||
287 | if (st == IRT_I64 || st == IRT_U64) { | ||
288 | hi = split_call_l(J, hisubst, oir, ir, | ||
289 | st == IRT_I64 ? IRCALL_softfp_l2d : IRCALL_softfp_ul2d); | ||
290 | break; | ||
291 | } | ||
292 | #endif | ||
293 | lua_assert(st == IRT_INT || | ||
294 | (LJ_32 && LJ_HASFFI && (st == IRT_U32 || st == IRT_FLOAT))); | ||
295 | nir->o = IR_CALLN; | ||
296 | #if LJ_32 && LJ_HASFFI | ||
297 | nir->op2 = st == IRT_INT ? IRCALL_softfp_i2d : | ||
298 | st == IRT_FLOAT ? IRCALL_softfp_f2d : | ||
299 | IRCALL_softfp_ui2d; | ||
300 | #else | ||
301 | nir->op2 = IRCALL_softfp_i2d; | ||
302 | #endif | ||
303 | hi = split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), nref, nref); | ||
304 | break; | ||
305 | } | ||
306 | case IR_CALLS: | ||
307 | case IR_CALLXS: | ||
308 | goto split_call; | ||
309 | case IR_PHI: | ||
310 | if (nir->op1 == nir->op2) | ||
311 | J->cur.nins--; /* Drop useless PHIs. */ | ||
312 | if (hisubst[ir->op1] != hisubst[ir->op2]) | ||
313 | split_emit(J, IRT(IR_PHI, IRT_SOFTFP), | ||
314 | hisubst[ir->op1], hisubst[ir->op2]); | ||
315 | break; | ||
316 | default: | ||
317 | lua_assert(ir->o <= IR_NE); | ||
318 | split_emit(J, IRTG(IR_HIOP, IRT_SOFTFP), | ||
319 | hisubst[ir->op1], hisubst[ir->op2]); | ||
320 | break; | ||
321 | } | ||
322 | } else | ||
323 | #endif | ||
324 | #if LJ_32 && LJ_HASFFI | ||
184 | if (irt_isint64(ir->t)) { | 325 | if (irt_isint64(ir->t)) { |
185 | IRRef hiref = hisubst[ir->op1]; | 326 | IRRef hiref = hisubst[ir->op1]; |
186 | nir->t.irt = IRT_INT | (nir->t.irt & IRT_GUARD); /* Turn into INT op. */ | 327 | nir->t.irt = IRT_INT | (nir->t.irt & IRT_GUARD); /* Turn into INT op. */ |
@@ -199,22 +340,22 @@ static void split_ir(jit_State *J) | |||
199 | hi = split_emit(J, IRTI(IR_HIOP), hiref, hisubst[ir->op2]); | 340 | hi = split_emit(J, IRTI(IR_HIOP), hiref, hisubst[ir->op2]); |
200 | break; | 341 | break; |
201 | case IR_MUL: | 342 | case IR_MUL: |
202 | hi = split_call64(J, hisubst, oir, ir, IRCALL_lj_carith_mul64); | 343 | hi = split_call_ll(J, hisubst, oir, ir, IRCALL_lj_carith_mul64); |
203 | break; | 344 | break; |
204 | case IR_DIV: | 345 | case IR_DIV: |
205 | hi = split_call64(J, hisubst, oir, ir, | 346 | hi = split_call_ll(J, hisubst, oir, ir, |
206 | irt_isi64(ir->t) ? IRCALL_lj_carith_divi64 : | 347 | irt_isi64(ir->t) ? IRCALL_lj_carith_divi64 : |
207 | IRCALL_lj_carith_divu64); | 348 | IRCALL_lj_carith_divu64); |
208 | break; | 349 | break; |
209 | case IR_MOD: | 350 | case IR_MOD: |
210 | hi = split_call64(J, hisubst, oir, ir, | 351 | hi = split_call_ll(J, hisubst, oir, ir, |
211 | irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 : | 352 | irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 : |
212 | IRCALL_lj_carith_modu64); | 353 | IRCALL_lj_carith_modu64); |
213 | break; | 354 | break; |
214 | case IR_POW: | 355 | case IR_POW: |
215 | hi = split_call64(J, hisubst, oir, ir, | 356 | hi = split_call_ll(J, hisubst, oir, ir, |
216 | irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : | 357 | irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : |
217 | IRCALL_lj_carith_powu64); | 358 | IRCALL_lj_carith_powu64); |
218 | break; | 359 | break; |
219 | case IR_FLOAD: | 360 | case IR_FLOAD: |
220 | lua_assert(ir->op2 == IRFL_CDATA_INT64); | 361 | lua_assert(ir->op2 == IRFL_CDATA_INT64); |
@@ -239,9 +380,21 @@ static void split_ir(jit_State *J) | |||
239 | break; | 380 | break; |
240 | case IR_CONV: { /* Conversion to 64 bit integer. Others handled below. */ | 381 | case IR_CONV: { /* Conversion to 64 bit integer. Others handled below. */ |
241 | IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); | 382 | IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); |
383 | #if LJ_SOFTFP | ||
384 | if (st == IRT_NUM) { /* NUM to 64 bit int conv. */ | ||
385 | split_call_l(J, hisubst, oir, ir, | ||
386 | irt_isi64(ir->t) ? IRCALL_softfp_d2l : IRCALL_softfp_d2ul); | ||
387 | } else if (st == IRT_FLOAT) { /* FLOAT to 64 bit int conv. */ | ||
388 | nir->o = IR_CALLN; | ||
389 | nir->op2 = irt_isi64(ir->t) ? IRCALL_softfp_f2l : IRCALL_softfp_f2ul; | ||
390 | hi = split_emit(J, IRTI(IR_HIOP), nref, nref); | ||
391 | } | ||
392 | #else | ||
242 | if (st == IRT_NUM || st == IRT_FLOAT) { /* FP to 64 bit int conv. */ | 393 | if (st == IRT_NUM || st == IRT_FLOAT) { /* FP to 64 bit int conv. */ |
243 | hi = split_emit(J, IRTI(IR_HIOP), nir->op1, nref); | 394 | hi = split_emit(J, IRTI(IR_HIOP), nir->op1, nref); |
244 | } else if (st == IRT_I64 || st == IRT_U64) { /* 64/64 bit cast. */ | 395 | } |
396 | #endif | ||
397 | else if (st == IRT_I64 || st == IRT_U64) { /* 64/64 bit cast. */ | ||
245 | /* Drop cast, since assembler doesn't care. */ | 398 | /* Drop cast, since assembler doesn't care. */ |
246 | goto fwdlo; | 399 | goto fwdlo; |
247 | } else if ((ir->op2 & IRCONV_SEXT)) { /* Sign-extend to 64 bit. */ | 400 | } else if ((ir->op2 & IRCONV_SEXT)) { /* Sign-extend to 64 bit. */ |
@@ -274,13 +427,37 @@ static void split_ir(jit_State *J) | |||
274 | split_emit(J, IRTGI(IR_HIOP), hiref, hisubst[ir->op2]); | 427 | split_emit(J, IRTGI(IR_HIOP), hiref, hisubst[ir->op2]); |
275 | break; | 428 | break; |
276 | } | 429 | } |
277 | } else if (ir->o == IR_CONV) { /* See above, too. */ | 430 | } else |
431 | #endif | ||
432 | #if LJ_SOFTFP | ||
433 | if (ir->o == IR_TOBIT) { | ||
434 | IRRef tmp, op1 = ir->op1; | ||
435 | J->cur.nins--; | ||
436 | #if LJ_LE | ||
437 | tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), oir[op1].prev, hisubst[op1]); | ||
438 | #else | ||
439 | tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), hisubst[op1], oir[op1].prev); | ||
440 | #endif | ||
441 | ir->prev = split_emit(J, IRTI(IR_CALLN), tmp, IRCALL_lj_vm_tobit); | ||
442 | } else | ||
443 | #endif | ||
444 | if (ir->o == IR_CONV) { /* See above, too. */ | ||
278 | IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); | 445 | IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); |
446 | #if LJ_32 && LJ_HASFFI | ||
279 | if (st == IRT_I64 || st == IRT_U64) { /* Conversion from 64 bit int. */ | 447 | if (st == IRT_I64 || st == IRT_U64) { /* Conversion from 64 bit int. */ |
448 | #if LJ_SOFTFP | ||
449 | if (irt_isfloat(ir->t)) { | ||
450 | split_call_l(J, hisubst, oir, ir, | ||
451 | st == IRT_I64 ? IRCALL_softfp_l2f : IRCALL_softfp_ul2f); | ||
452 | J->cur.nins--; /* Drop unused HIOP. */ | ||
453 | } | ||
454 | #else | ||
280 | if (irt_isfp(ir->t)) { /* 64 bit integer to FP conversion. */ | 455 | if (irt_isfp(ir->t)) { /* 64 bit integer to FP conversion. */ |
281 | ir->prev = split_emit(J, IRT(IR_HIOP, irt_type(ir->t)), | 456 | ir->prev = split_emit(J, IRT(IR_HIOP, irt_type(ir->t)), |
282 | hisubst[ir->op1], nref); | 457 | hisubst[ir->op1], nref); |
283 | } else { /* Truncate to lower 32 bits. */ | 458 | } |
459 | #endif | ||
460 | else { /* Truncate to lower 32 bits. */ | ||
284 | fwdlo: | 461 | fwdlo: |
285 | ir->prev = nir->op1; /* Forward loword. */ | 462 | ir->prev = nir->op1; /* Forward loword. */ |
286 | /* Replace with NOP to avoid messing up the snapshot logic. */ | 463 | /* Replace with NOP to avoid messing up the snapshot logic. */ |
@@ -288,6 +465,36 @@ static void split_ir(jit_State *J) | |||
288 | nir->op1 = nir->op2 = 0; | 465 | nir->op1 = nir->op2 = 0; |
289 | } | 466 | } |
290 | } | 467 | } |
468 | #endif | ||
469 | #if LJ_SOFTFP && LJ_32 && LJ_HASFFI | ||
470 | else if (irt_isfloat(ir->t)) { | ||
471 | if (st == IRT_NUM) { | ||
472 | split_call_l(J, hisubst, oir, ir, IRCALL_softfp_d2f); | ||
473 | J->cur.nins--; /* Drop unused HIOP. */ | ||
474 | } else { | ||
475 | nir->o = IR_CALLN; | ||
476 | nir->op2 = st == IRT_INT ? IRCALL_softfp_i2f : IRCALL_softfp_ui2f; | ||
477 | } | ||
478 | } else if (st == IRT_FLOAT) { | ||
479 | nir->o = IR_CALLN; | ||
480 | nir->op2 = irt_isint(ir->t) ? IRCALL_softfp_f2i : IRCALL_softfp_f2ui; | ||
481 | } else | ||
482 | #endif | ||
483 | #if LJ_SOFTFP | ||
484 | if (st == IRT_NUM || (LJ_32 && LJ_HASFFI && st == IRT_FLOAT)) { | ||
485 | if (irt_isguard(ir->t)) { | ||
486 | lua_assert(0); /* NYI: missing check. */ | ||
487 | } | ||
488 | split_call_l(J, hisubst, oir, ir, | ||
489 | #if LJ_32 && LJ_HASFFI | ||
490 | st == IRT_NUM ? IRCALL_softfp_d2i : IRCALL_softfp_f2i | ||
491 | #else | ||
492 | IRCALL_softfp_d2i | ||
493 | #endif | ||
494 | ); | ||
495 | J->cur.nins--; /* Drop unused HIOP. */ | ||
496 | } | ||
497 | #endif | ||
291 | } else if (ir->o == IR_CALLXS) { | 498 | } else if (ir->o == IR_CALLXS) { |
292 | IRRef hiref; | 499 | IRRef hiref; |
293 | split_call: | 500 | split_call: |
@@ -303,8 +510,10 @@ static void split_ir(jit_State *J) | |||
303 | #endif | 510 | #endif |
304 | ir->prev = nref = split_emit(J, ot, nref, op2); | 511 | ir->prev = nref = split_emit(J, ot, nref, op2); |
305 | } | 512 | } |
306 | if (irt_isint64(ir->t)) | 513 | if (LJ_SOFTFP ? irt_is64(ir->t) : irt_isint64(ir->t)) |
307 | hi = split_emit(J, IRTI(IR_HIOP), nref, nref); | 514 | hi = split_emit(J, |
515 | IRT(IR_HIOP, (LJ_SOFTFP && irt_isnum(ir->t)) ? IRT_SOFTFP : IRT_INT), | ||
516 | nref, nref); | ||
308 | } else if (ir->o == IR_CARG) { | 517 | } else if (ir->o == IR_CARG) { |
309 | IRRef hiref = hisubst[ir->op1]; | 518 | IRRef hiref = hisubst[ir->op1]; |
310 | if (hiref) { | 519 | if (hiref) { |
@@ -367,17 +576,18 @@ static TValue *cpsplit(lua_State *L, lua_CFunction dummy, void *ud) | |||
367 | return NULL; | 576 | return NULL; |
368 | } | 577 | } |
369 | 578 | ||
370 | #ifdef LUA_USE_ASSERT | 579 | #if defined(LUA_USE_ASSERT) || LJ_SOFTFP |
371 | /* Slow, but sure way to check whether a SPLIT pass is needed. */ | 580 | /* Slow, but sure way to check whether a SPLIT pass is needed. */ |
372 | static int split_needsplit(jit_State *J) | 581 | static int split_needsplit(jit_State *J) |
373 | { | 582 | { |
374 | IRIns *ir, *irend; | 583 | IRIns *ir, *irend; |
375 | IRRef ref; | 584 | IRRef ref; |
376 | for (ir = IR(REF_FIRST), irend = IR(J->cur.nins); ir < irend; ir++) | 585 | for (ir = IR(REF_FIRST), irend = IR(J->cur.nins); ir < irend; ir++) |
377 | if (irt_isint64(ir->t)) | 586 | if (LJ_SOFTFP ? irt_is64(ir->t) : irt_isint64(ir->t)) |
378 | return 1; | 587 | return 1; |
379 | for (ref = J->chain[IR_CONV]; ref; ref = IR(ref)->prev) | 588 | for (ref = J->chain[IR_CONV]; ref; ref = IR(ref)->prev) |
380 | if ((IR(ref)->op2 & IRCONV_SRCMASK) == IRT_I64 || | 589 | if ((LJ_SOFTFP && (IR(ref)->op2 & IRCONV_SRCMASK) == IRT_NUM) || |
590 | (IR(ref)->op2 & IRCONV_SRCMASK) == IRT_I64 || | ||
381 | (IR(ref)->op2 & IRCONV_SRCMASK) == IRT_U64) | 591 | (IR(ref)->op2 & IRCONV_SRCMASK) == IRT_U64) |
382 | return 1; | 592 | return 1; |
383 | return 0; /* Nope. */ | 593 | return 0; /* Nope. */ |
@@ -387,7 +597,12 @@ static int split_needsplit(jit_State *J) | |||
387 | /* SPLIT pass. */ | 597 | /* SPLIT pass. */ |
388 | void lj_opt_split(jit_State *J) | 598 | void lj_opt_split(jit_State *J) |
389 | { | 599 | { |
600 | #if LJ_SOFTFP | ||
601 | if (!J->needsplit) | ||
602 | J->needsplit = split_needsplit(J); | ||
603 | #else | ||
390 | lua_assert(J->needsplit >= split_needsplit(J)); /* Verify flag. */ | 604 | lua_assert(J->needsplit >= split_needsplit(J)); /* Verify flag. */ |
605 | #endif | ||
391 | if (J->needsplit) { | 606 | if (J->needsplit) { |
392 | int errcode = lj_vm_cpcall(J->L, NULL, J, cpsplit); | 607 | int errcode = lj_vm_cpcall(J->L, NULL, J, cpsplit); |
393 | if (errcode) { | 608 | if (errcode) { |
diff --git a/src/lj_record.c b/src/lj_record.c index 64eba291..b712ec56 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -1992,6 +1992,7 @@ static void rec_setup_side(jit_State *J, GCtrace *T) | |||
1992 | IRRef ref = snap_ref(sn); | 1992 | IRRef ref = snap_ref(sn); |
1993 | BCReg s = snap_slot(sn); | 1993 | BCReg s = snap_slot(sn); |
1994 | IRIns *ir = &T->ir[ref]; | 1994 | IRIns *ir = &T->ir[ref]; |
1995 | IRType t = irt_type(ir->t); | ||
1995 | TRef tr; | 1996 | TRef tr; |
1996 | /* The bloom filter avoids O(nent^2) overhead for de-duping slots. */ | 1997 | /* The bloom filter avoids O(nent^2) overhead for de-duping slots. */ |
1997 | if (bloomtest(seen, ref)) { | 1998 | if (bloomtest(seen, ref)) { |
@@ -2005,7 +2006,7 @@ static void rec_setup_side(jit_State *J, GCtrace *T) | |||
2005 | bloomset(seen, ref); | 2006 | bloomset(seen, ref); |
2006 | switch ((IROp)ir->o) { | 2007 | switch ((IROp)ir->o) { |
2007 | /* Only have to deal with constants that can occur in stack slots. */ | 2008 | /* Only have to deal with constants that can occur in stack slots. */ |
2008 | case IR_KPRI: tr = TREF_PRI(irt_type(ir->t)); break; | 2009 | case IR_KPRI: tr = TREF_PRI(t); break; |
2009 | case IR_KINT: tr = lj_ir_kint(J, ir->i); break; | 2010 | case IR_KINT: tr = lj_ir_kint(J, ir->i); break; |
2010 | case IR_KGC: tr = lj_ir_kgc(J, ir_kgc(ir), irt_t(ir->t)); break; | 2011 | case IR_KGC: tr = lj_ir_kgc(J, ir_kgc(ir), irt_t(ir->t)); break; |
2011 | case IR_KNUM: tr = lj_ir_k64(J, IR_KNUM, ir_knum(ir)); break; | 2012 | case IR_KNUM: tr = lj_ir_k64(J, IR_KNUM, ir_knum(ir)); break; |
@@ -2013,13 +2014,14 @@ static void rec_setup_side(jit_State *J, GCtrace *T) | |||
2013 | case IR_KPTR: tr = lj_ir_kptr(J, ir_kptr(ir)); break; /* Continuation. */ | 2014 | case IR_KPTR: tr = lj_ir_kptr(J, ir_kptr(ir)); break; /* Continuation. */ |
2014 | /* Inherited SLOADs don't need a guard or type check. */ | 2015 | /* Inherited SLOADs don't need a guard or type check. */ |
2015 | case IR_SLOAD: | 2016 | case IR_SLOAD: |
2016 | tr = emitir_raw(ir->ot & ~IRT_GUARD, s, | 2017 | if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) t = IRT_NUM; |
2018 | tr = emitir_raw(IRT(IR_SLOAD, t), s, | ||
2017 | (ir->op2&IRSLOAD_READONLY) | IRSLOAD_INHERIT|IRSLOAD_PARENT); | 2019 | (ir->op2&IRSLOAD_READONLY) | IRSLOAD_INHERIT|IRSLOAD_PARENT); |
2018 | break; | 2020 | break; |
2019 | /* Parent refs are already typed and don't need a guard. */ | 2021 | /* Parent refs are already typed and don't need a guard. */ |
2020 | default: | 2022 | default: |
2021 | tr = emitir_raw(IRT(IR_SLOAD, irt_type(ir->t)), s, | 2023 | if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) t = IRT_NUM; |
2022 | IRSLOAD_INHERIT|IRSLOAD_PARENT); | 2024 | tr = emitir_raw(IRT(IR_SLOAD, t), s, IRSLOAD_INHERIT|IRSLOAD_PARENT); |
2023 | break; | 2025 | break; |
2024 | } | 2026 | } |
2025 | setslot: | 2027 | setslot: |
diff --git a/src/lj_snap.c b/src/lj_snap.c index dd70ece1..1af7ef85 100644 --- a/src/lj_snap.c +++ b/src/lj_snap.c | |||
@@ -307,7 +307,7 @@ static RegSP snap_renameref(GCtrace *T, SnapNo lim, IRRef ref, RegSP rs) | |||
307 | /* Convert a snapshot into a linear slot -> RegSP map. | 307 | /* Convert a snapshot into a linear slot -> RegSP map. |
308 | ** Note: unused slots are not initialized! | 308 | ** Note: unused slots are not initialized! |
309 | */ | 309 | */ |
310 | void lj_snap_regspmap(uint16_t *rsmap, GCtrace *T, SnapNo snapno) | 310 | void lj_snap_regspmap(uint16_t *rsmap, GCtrace *T, SnapNo snapno, int hi) |
311 | { | 311 | { |
312 | SnapShot *snap = &T->snap[snapno]; | 312 | SnapShot *snap = &T->snap[snapno]; |
313 | MSize n, nent = snap->nent; | 313 | MSize n, nent = snap->nent; |
@@ -316,7 +316,7 @@ void lj_snap_regspmap(uint16_t *rsmap, GCtrace *T, SnapNo snapno) | |||
316 | for (n = 0; n < nent; n++) { | 316 | for (n = 0; n < nent; n++) { |
317 | SnapEntry sn = map[n]; | 317 | SnapEntry sn = map[n]; |
318 | IRRef ref = snap_ref(sn); | 318 | IRRef ref = snap_ref(sn); |
319 | if (!irref_isk(ref)) { | 319 | if ((LJ_SOFTFP && hi) ? (ref++, (sn & SNAP_SOFTFPNUM)) : !irref_isk(ref)) { |
320 | IRIns *ir = &T->ir[ref]; | 320 | IRIns *ir = &T->ir[ref]; |
321 | uint32_t rs = ir->prev; | 321 | uint32_t rs = ir->prev; |
322 | if (bloomtest(rfilt, ref)) | 322 | if (bloomtest(rfilt, ref)) |
diff --git a/src/lj_snap.h b/src/lj_snap.h index 031b0ac3..da9813b9 100644 --- a/src/lj_snap.h +++ b/src/lj_snap.h | |||
@@ -13,7 +13,8 @@ | |||
13 | LJ_FUNC void lj_snap_add(jit_State *J); | 13 | LJ_FUNC void lj_snap_add(jit_State *J); |
14 | LJ_FUNC void lj_snap_purge(jit_State *J); | 14 | LJ_FUNC void lj_snap_purge(jit_State *J); |
15 | LJ_FUNC void lj_snap_shrink(jit_State *J); | 15 | LJ_FUNC void lj_snap_shrink(jit_State *J); |
16 | LJ_FUNC void lj_snap_regspmap(uint16_t *rsmap, GCtrace *T, SnapNo snapno); | 16 | LJ_FUNC void lj_snap_regspmap(uint16_t *rsmap, GCtrace *T, SnapNo snapno, |
17 | int hi); | ||
17 | LJ_FUNC const BCIns *lj_snap_restore(jit_State *J, void *exptr); | 18 | LJ_FUNC const BCIns *lj_snap_restore(jit_State *J, void *exptr); |
18 | LJ_FUNC void lj_snap_grow_buf_(jit_State *J, MSize need); | 19 | LJ_FUNC void lj_snap_grow_buf_(jit_State *J, MSize need); |
19 | LJ_FUNC void lj_snap_grow_map_(jit_State *J, MSize need); | 20 | LJ_FUNC void lj_snap_grow_map_(jit_State *J, MSize need); |