]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
Fix PHI stack slot syncing.
authorMike Pall <mike>
Mon, 7 May 2012 21:16:19 +0000 (23:16 +0200)
committerMike Pall <mike>
Mon, 7 May 2012 21:16:19 +0000 (23:16 +0200)
src/lj_asm.c
src/lj_emit_arm.h
src/lj_emit_mips.h
src/lj_emit_ppc.h
src/lj_emit_x86.h
src/lj_target_arm.h
src/lj_target_mips.h
src/lj_target_x86.h

index 1a78e32a46d50ef7524d9e647e7f3d7649354a8b..4da1a0a37a74717426f12cb76731af33097c9e19 100644 (file)
@@ -1079,6 +1079,64 @@ static void asm_phi_shuffle(ASMState *as)
   }
 }
 
+/* Copy unsynced left/right PHI spill slots. Rarely needed. */
+static void asm_phi_copyspill(ASMState *as)
+{
+  int need = 0;
+  IRIns *ir;
+  for (ir = IR(as->orignins-1); ir->o == IR_PHI; ir--)
+    if (ra_hasspill(ir->s) && ra_hasspill(IR(ir->op1)->s))
+      need |= irt_isfp(ir->t) ? 2 : 1;  /* Unsynced spill slot? */
+  if ((need & 1)) {  /* Copy integer spill slots. */
+#if !LJ_TARGET_X86ORX64
+    Reg r = RID_TMP;
+#else
+    Reg r = RID_RET;
+    if ((as->freeset & RSET_GPR))
+      r = rset_pickbot((as->freeset & RSET_GPR));
+    else
+      emit_spload(as, IR(regcost_ref(as->cost[r])), r, SPOFS_TMP);
+#endif
+    for (ir = IR(as->orignins-1); ir->o == IR_PHI; ir--) {
+      if (ra_hasspill(ir->s)) {
+       IRIns *irl = IR(ir->op1);
+       if (ra_hasspill(irl->s) && !irt_isfp(ir->t)) {
+         emit_spstore(as, irl, r, sps_scale(irl->s));
+         emit_spload(as, ir, r, sps_scale(ir->s));
+       }
+      }
+    }
+#if LJ_TARGET_X86ORX64
+    if (!rset_test(as->freeset, r))
+      emit_spstore(as, IR(regcost_ref(as->cost[r])), r, SPOFS_TMP);
+#endif
+  }
+#if !LJ_SOFTFP
+  if ((need & 2)) {  /* Copy FP spill slots. */
+#if LJ_TARGET_X86
+    Reg r = RID_XMM0;
+#else
+    Reg r = RID_FPRET;
+#endif
+    if ((as->freeset & RSET_FPR))
+      r = rset_pickbot((as->freeset & RSET_FPR));
+    if (!rset_test(as->freeset, r))
+      emit_spload(as, IR(regcost_ref(as->cost[r])), r, SPOFS_TMP);
+    for (ir = IR(as->orignins-1); ir->o == IR_PHI; ir--) {
+      if (ra_hasspill(ir->s)) {
+       IRIns *irl = IR(ir->op1);
+       if (ra_hasspill(irl->s) && irt_isfp(ir->t)) {
+         emit_spstore(as, irl, r, sps_scale(irl->s));
+         emit_spload(as, ir, r, sps_scale(ir->s));
+       }
+      }
+    }
+    if (!rset_test(as->freeset, r))
+      emit_spstore(as, IR(regcost_ref(as->cost[r])), r, SPOFS_TMP);
+  }
+#endif
+}
+
 /* Emit renames for left PHIs which are only spilled outside the loop. */
 static void asm_phi_fixup(ASMState *as)
 {
@@ -1132,7 +1190,7 @@ static void asm_phi(ASMState *as, IRIns *ir)
     if (ra_hasreg(irl->r) || ra_hasreg(irr->r))
       lj_trace_err(as->J, LJ_TRERR_NYIPHI);
     ra_spill(as, ir);
-    irl->s = irr->s = ir->s;  /* Sync left/right PHI spill slots. */
+    irr->s = ir->s;  /* Set right PHI spill slot. Sync left slot later. */
   }
 }
 
@@ -1142,6 +1200,7 @@ static void asm_loop_fixup(ASMState *as);
 /* Middle part of a loop. */
 static void asm_loop(ASMState *as)
 {
+  MCode *mcspill;
   /* LOOP is a guard, so the snapno is up to date. */
   as->loopsnapno = as->snapno;
   if (as->gcsteps)
@@ -1151,10 +1210,14 @@ static void asm_loop(ASMState *as)
   as->sectref = 0;
   if (!neverfuse(as)) as->fuseref = 0;
   asm_phi_shuffle(as);
+  mcspill = as->mcp;
+  asm_phi_copyspill(as);
   asm_loop_fixup(as);
   as->mcloop = as->mcp;
   RA_DBGX((as, "===== LOOP ====="));
   if (!as->realign) RA_DBG_FLUSH();
+  if (as->mcp != mcspill)
+    emit_jmp(as, mcspill);
 }
 
 /* -- Target-specific assembler ------------------------------------------- */
index 7654c19b151975e4ced76ceec4b77082bfdf543c..21ece88e7586614b711ef66649f8e0e9d620cd73 100644 (file)
@@ -231,6 +231,8 @@ static void emit_branch(ASMState *as, ARMIns ai, MCode *target)
   as->mcp = p;
 }
 
+#define emit_jmp(as, target) emit_branch(as, ARMI_B, (target))
+
 static void emit_call(ASMState *as, void *target)
 {
   MCode *p = --as->mcp;
index 59f0640bb236ef6b8430c869d535de5e70347cec..3edf8851e1fffe231f758f4152a44b8d2ebde3dc 100644 (file)
@@ -146,6 +146,12 @@ static void emit_branch(ASMState *as, MIPSIns mi, Reg rs, Reg rt, MCode *target)
   as->mcp = p;
 }
 
+static void emit_jmp(ASMState *as, MCode *target)
+{
+  *--as->mcp = MIPSI_NOP;
+  emit_branch(as, MIPSI_B, RID_ZERO, RID_ZERO, (target));
+}
+
 static void emit_call(ASMState *as, void *target)
 {
   MCode *p = as->mcp;
index bc361c5bc08e51f551ea25c5056671f881d3fbc6..f2bf0a9444efc3d328d9450730bdc7145a3c1d03 100644 (file)
@@ -142,12 +142,18 @@ typedef MCode *MCLabel;
 
 static void emit_condbranch(ASMState *as, PPCIns pi, PPCCC cc, MCode *target)
 {
-  MCode *p = as->mcp;
-  ptrdiff_t delta = ((char *)target - (char *)p) + 4;
+  MCode *p = --as->mcp;
+  ptrdiff_t delta = (char *)target - (char *)p;
   lua_assert(((delta + 0x8000) >> 16) == 0);
   pi ^= (delta & 0x8000) * (PPCF_Y/0x8000);
-  *--p = pi | PPCF_CC(cc) | ((uint32_t)delta & 0xffffu);
-  as->mcp = p;
+  *p = pi | PPCF_CC(cc) | ((uint32_t)delta & 0xffffu);
+}
+
+static void emit_jmp(ASMState *as, MCode *target)
+{
+  MCode *p = --as->mcp;
+  ptrdiff_t delta = (char *)target - (char *)p;
+  *p = PPCI_B | (delta & 0x03fffffcu);
 }
 
 static void emit_call(ASMState *as, void *target)
index 4f3a08a1644afeb900a97ff77a45883fa02e2cae..dfb70574e477b550a8156cf385a671d428fc7c41 100644 (file)
@@ -383,6 +383,15 @@ static void emit_jcc(ASMState *as, int cc, MCode *target)
   as->mcp = p - 6;
 }
 
+/* jmp target */
+static void emit_jmp(ASMState *as, MCode *target)
+{
+  MCode *p = as->mcp;
+  *(int32_t *)(p-4) = jmprel(p, target);
+  p[-5] = XI_JMP;
+  as->mcp = p - 5;
+}
+
 /* call target */
 static void emit_call_(ASMState *as, MCode *target)
 {
index 96fc85e3bca1784fa4ebf11f929ea3af29df5d45..a24fc81925db0598de22eea003d7ffb630c60120 100644 (file)
@@ -101,6 +101,8 @@ enum {
 #define SPS_FIXED      2
 #define SPS_FIRST      2
 
+#define SPOFS_TMP      0
+
 #define sps_scale(slot)                (4 * (int32_t)(slot))
 #define sps_align(slot)                (((slot) - SPS_FIXED + 1) & ~1)
 
index e81d55bdd56fa69927b898a1d74dbaeaa960c2fa..1b7727d01097e513785ca2b4e1c5f797f3ffc953 100644 (file)
@@ -102,6 +102,8 @@ enum {
 #define SPS_FIXED      5
 #define SPS_FIRST      4
 
+#define SPOFS_TMP      0
+
 #define sps_scale(slot)                (4 * (int32_t)(slot))
 #define sps_align(slot)                (((slot) - SPS_FIXED + 1) & ~1)
 
index 3de408cc366d9bb070de0a21b857c21a61f2e8be..cc15490b6169ed3a9b7acb94b08198789975a9ce 100644 (file)
@@ -139,6 +139,8 @@ enum {
 #define SPS_FIRST      2
 #endif
 
+#define SPOFS_TMP      0
+
 #define sps_scale(slot)                (4 * (int32_t)(slot))
 #define sps_align(slot)                (((slot) - SPS_FIXED + 3) & ~3)