diff options
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r-- | src/lj_asm.c | 67 |
1 files changed, 52 insertions, 15 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 9bce9292..8ff3eaf7 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -782,19 +782,44 @@ static int asm_snap_canremat(ASMState *as) | |||
782 | static void asm_snap_alloc1(ASMState *as, IRRef ref) | 782 | static void asm_snap_alloc1(ASMState *as, IRRef ref) |
783 | { | 783 | { |
784 | IRIns *ir = IR(ref); | 784 | IRIns *ir = IR(ref); |
785 | if (!ra_used(ir)) { | 785 | if (!(ra_used(ir) || ir->r == RID_SUNK)) { |
786 | RegSet allow = (!LJ_SOFTFP && irt_isnum(ir->t)) ? RSET_FPR : RSET_GPR; | 786 | if (ir->r == RID_SINK) { |
787 | /* Get a weak register if we have a free one or can rematerialize. */ | 787 | ir->r = RID_SUNK; |
788 | if ((as->freeset & allow) || | 788 | #if LJ_HASFFI |
789 | (allow == RSET_FPR && asm_snap_canremat(as))) { | 789 | if (ir->o == IR_CNEWI) { /* Allocate CNEWI value. */ |
790 | Reg r = ra_allocref(as, ref, allow); /* Allocate a register. */ | 790 | asm_snap_alloc1(as, ir->op2); |
791 | if (!irt_isphi(ir->t)) | 791 | if (LJ_32 && (ir+1)->o == IR_HIOP) |
792 | ra_weak(as, r); /* But mark it as weakly referenced. */ | 792 | asm_snap_alloc1(as, (ir+1)->op2); |
793 | checkmclim(as); | 793 | } |
794 | RA_DBGX((as, "snapreg $f $r", ref, ir->r)); | 794 | #endif |
795 | else { /* Allocate stored values for TNEW, TDUP and CNEW. */ | ||
796 | IRIns *irs; | ||
797 | lua_assert(ir->o == IR_TNEW || ir->o == IR_TDUP || ir->o == IR_CNEW); | ||
798 | for (irs = IR(as->curins); irs > ir; irs--) | ||
799 | if (irs->r == RID_SINK && ir + irs->s == irs) { | ||
800 | lua_assert(irs->o == IR_ASTORE || irs->o == IR_HSTORE || | ||
801 | irs->o == IR_FSTORE || irs->o == IR_XSTORE); | ||
802 | asm_snap_alloc1(as, irs->op2); | ||
803 | if (LJ_32 && (irs+1)->o == IR_HIOP) | ||
804 | asm_snap_alloc1(as, (irs+1)->op2); | ||
805 | } | ||
806 | } | ||
807 | } else if (ir->o == IR_CONV && ir->op2 == IRCONV_NUM_INT) { | ||
808 | asm_snap_alloc1(as, ir->op1); | ||
795 | } else { | 809 | } else { |
796 | ra_spill(as, ir); /* Otherwise force a spill slot. */ | 810 | RegSet allow = (!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR; |
797 | RA_DBGX((as, "snapspill $f $s", ref, ir->s)); | 811 | if ((as->freeset & allow) || |
812 | (allow == RSET_FPR && asm_snap_canremat(as))) { | ||
813 | /* Get a weak register if we have a free one or can rematerialize. */ | ||
814 | Reg r = ra_allocref(as, ref, allow); /* Allocate a register. */ | ||
815 | if (!irt_isphi(ir->t)) | ||
816 | ra_weak(as, r); /* But mark it as weakly referenced. */ | ||
817 | checkmclim(as); | ||
818 | RA_DBGX((as, "snapreg $f $r", ref, ir->r)); | ||
819 | } else { | ||
820 | ra_spill(as, ir); /* Otherwise force a spill slot. */ | ||
821 | RA_DBGX((as, "snapspill $f $s", ref, ir->s)); | ||
822 | } | ||
798 | } | 823 | } |
799 | } | 824 | } |
800 | } | 825 | } |
@@ -848,7 +873,7 @@ static void asm_snap_prep(ASMState *as) | |||
848 | { | 873 | { |
849 | if (as->curins < as->snapref) { | 874 | if (as->curins < as->snapref) { |
850 | do { | 875 | do { |
851 | lua_assert(as->snapno != 0); | 876 | if (as->snapno == 0) return; /* Called by sunk stores before snap #0. */ |
852 | as->snapno--; | 877 | as->snapno--; |
853 | as->snapref = as->T->snap[as->snapno].ref; | 878 | as->snapref = as->T->snap[as->snapno].ref; |
854 | } while (as->curins < as->snapref); | 879 | } while (as->curins < as->snapref); |
@@ -1180,6 +1205,8 @@ static void asm_phi(ASMState *as, IRIns *ir) | |||
1180 | RegSet afree = (as->freeset & allow); | 1205 | RegSet afree = (as->freeset & allow); |
1181 | IRIns *irl = IR(ir->op1); | 1206 | IRIns *irl = IR(ir->op1); |
1182 | IRIns *irr = IR(ir->op2); | 1207 | IRIns *irr = IR(ir->op2); |
1208 | if (ir->r == RID_SINK) /* Sink PHI. */ | ||
1209 | return; | ||
1183 | /* Spill slot shuffling is not implemented yet (but rarely needed). */ | 1210 | /* Spill slot shuffling is not implemented yet (but rarely needed). */ |
1184 | if (ra_hasspill(irl->s) || ra_hasspill(irr->s)) | 1211 | if (ra_hasspill(irl->s) || ra_hasspill(irr->s)) |
1185 | lj_trace_err(as->J, LJ_TRERR_NYIPHI); | 1212 | lj_trace_err(as->J, LJ_TRERR_NYIPHI); |
@@ -1494,7 +1521,7 @@ static void asm_tail_link(ASMState *as) | |||
1494 | /* -- Trace setup --------------------------------------------------------- */ | 1521 | /* -- Trace setup --------------------------------------------------------- */ |
1495 | 1522 | ||
1496 | /* Clear reg/sp for all instructions and add register hints. */ | 1523 | /* Clear reg/sp for all instructions and add register hints. */ |
1497 | static void asm_setup_regsp(ASMState *as) | 1524 | static void asm_setup_regsp(ASMState *as, int sink) |
1498 | { | 1525 | { |
1499 | GCtrace *T = as->T; | 1526 | GCtrace *T = as->T; |
1500 | IRRef nins = T->nins; | 1527 | IRRef nins = T->nins; |
@@ -1545,6 +1572,14 @@ static void asm_setup_regsp(ASMState *as) | |||
1545 | inloop = 0; | 1572 | inloop = 0; |
1546 | as->evenspill = SPS_FIRST; | 1573 | as->evenspill = SPS_FIRST; |
1547 | for (lastir = IR(nins); ir < lastir; ir++) { | 1574 | for (lastir = IR(nins); ir < lastir; ir++) { |
1575 | if (sink) { | ||
1576 | if (ir->r == RID_SINK) | ||
1577 | continue; | ||
1578 | if (ir->r == RID_SUNK) { /* Revert after ASM restart. */ | ||
1579 | ir->r = RID_SINK; | ||
1580 | continue; | ||
1581 | } | ||
1582 | } | ||
1548 | switch (ir->o) { | 1583 | switch (ir->o) { |
1549 | case IR_LOOP: | 1584 | case IR_LOOP: |
1550 | inloop = 1; | 1585 | inloop = 1; |
@@ -1716,6 +1751,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T) | |||
1716 | ASMState as_; | 1751 | ASMState as_; |
1717 | ASMState *as = &as_; | 1752 | ASMState *as = &as_; |
1718 | MCode *origtop; | 1753 | MCode *origtop; |
1754 | int sink; | ||
1719 | 1755 | ||
1720 | /* Ensure an initialized instruction beyond the last one for HIOP checks. */ | 1756 | /* Ensure an initialized instruction beyond the last one for HIOP checks. */ |
1721 | J->cur.nins = lj_ir_nextins(J); | 1757 | J->cur.nins = lj_ir_nextins(J); |
@@ -1736,6 +1772,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T) | |||
1736 | as->mcp = as->mctop; | 1772 | as->mcp = as->mctop; |
1737 | as->mclim = as->mcbot + MCLIM_REDZONE; | 1773 | as->mclim = as->mcbot + MCLIM_REDZONE; |
1738 | asm_setup_target(as); | 1774 | asm_setup_target(as); |
1775 | sink = (IR(REF_BASE)->prev == 1); | ||
1739 | 1776 | ||
1740 | do { | 1777 | do { |
1741 | as->mcp = as->mctop; | 1778 | as->mcp = as->mctop; |
@@ -1751,7 +1788,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T) | |||
1751 | as->gcsteps = 0; | 1788 | as->gcsteps = 0; |
1752 | as->sectref = as->loopref; | 1789 | as->sectref = as->loopref; |
1753 | as->fuseref = (as->flags & JIT_F_OPT_FUSE) ? as->loopref : FUSE_DISABLED; | 1790 | as->fuseref = (as->flags & JIT_F_OPT_FUSE) ? as->loopref : FUSE_DISABLED; |
1754 | asm_setup_regsp(as); | 1791 | asm_setup_regsp(as, sink); |
1755 | if (!as->loopref) | 1792 | if (!as->loopref) |
1756 | asm_tail_link(as); | 1793 | asm_tail_link(as); |
1757 | 1794 | ||