diff options
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r-- | src/lj_asm.c | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 1a78e32a..4da1a0a3 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -1079,6 +1079,64 @@ static void asm_phi_shuffle(ASMState *as) | |||
1079 | } | 1079 | } |
1080 | } | 1080 | } |
1081 | 1081 | ||
1082 | /* Copy unsynced left/right PHI spill slots. Rarely needed. */ | ||
1083 | static void asm_phi_copyspill(ASMState *as) | ||
1084 | { | ||
1085 | int need = 0; | ||
1086 | IRIns *ir; | ||
1087 | for (ir = IR(as->orignins-1); ir->o == IR_PHI; ir--) | ||
1088 | if (ra_hasspill(ir->s) && ra_hasspill(IR(ir->op1)->s)) | ||
1089 | need |= irt_isfp(ir->t) ? 2 : 1; /* Unsynced spill slot? */ | ||
1090 | if ((need & 1)) { /* Copy integer spill slots. */ | ||
1091 | #if !LJ_TARGET_X86ORX64 | ||
1092 | Reg r = RID_TMP; | ||
1093 | #else | ||
1094 | Reg r = RID_RET; | ||
1095 | if ((as->freeset & RSET_GPR)) | ||
1096 | r = rset_pickbot((as->freeset & RSET_GPR)); | ||
1097 | else | ||
1098 | emit_spload(as, IR(regcost_ref(as->cost[r])), r, SPOFS_TMP); | ||
1099 | #endif | ||
1100 | for (ir = IR(as->orignins-1); ir->o == IR_PHI; ir--) { | ||
1101 | if (ra_hasspill(ir->s)) { | ||
1102 | IRIns *irl = IR(ir->op1); | ||
1103 | if (ra_hasspill(irl->s) && !irt_isfp(ir->t)) { | ||
1104 | emit_spstore(as, irl, r, sps_scale(irl->s)); | ||
1105 | emit_spload(as, ir, r, sps_scale(ir->s)); | ||
1106 | } | ||
1107 | } | ||
1108 | } | ||
1109 | #if LJ_TARGET_X86ORX64 | ||
1110 | if (!rset_test(as->freeset, r)) | ||
1111 | emit_spstore(as, IR(regcost_ref(as->cost[r])), r, SPOFS_TMP); | ||
1112 | #endif | ||
1113 | } | ||
1114 | #if !LJ_SOFTFP | ||
1115 | if ((need & 2)) { /* Copy FP spill slots. */ | ||
1116 | #if LJ_TARGET_X86 | ||
1117 | Reg r = RID_XMM0; | ||
1118 | #else | ||
1119 | Reg r = RID_FPRET; | ||
1120 | #endif | ||
1121 | if ((as->freeset & RSET_FPR)) | ||
1122 | r = rset_pickbot((as->freeset & RSET_FPR)); | ||
1123 | if (!rset_test(as->freeset, r)) | ||
1124 | emit_spload(as, IR(regcost_ref(as->cost[r])), r, SPOFS_TMP); | ||
1125 | for (ir = IR(as->orignins-1); ir->o == IR_PHI; ir--) { | ||
1126 | if (ra_hasspill(ir->s)) { | ||
1127 | IRIns *irl = IR(ir->op1); | ||
1128 | if (ra_hasspill(irl->s) && irt_isfp(ir->t)) { | ||
1129 | emit_spstore(as, irl, r, sps_scale(irl->s)); | ||
1130 | emit_spload(as, ir, r, sps_scale(ir->s)); | ||
1131 | } | ||
1132 | } | ||
1133 | } | ||
1134 | if (!rset_test(as->freeset, r)) | ||
1135 | emit_spstore(as, IR(regcost_ref(as->cost[r])), r, SPOFS_TMP); | ||
1136 | } | ||
1137 | #endif | ||
1138 | } | ||
1139 | |||
1082 | /* Emit renames for left PHIs which are only spilled outside the loop. */ | 1140 | /* Emit renames for left PHIs which are only spilled outside the loop. */ |
1083 | static void asm_phi_fixup(ASMState *as) | 1141 | static void asm_phi_fixup(ASMState *as) |
1084 | { | 1142 | { |
@@ -1132,7 +1190,7 @@ static void asm_phi(ASMState *as, IRIns *ir) | |||
1132 | if (ra_hasreg(irl->r) || ra_hasreg(irr->r)) | 1190 | if (ra_hasreg(irl->r) || ra_hasreg(irr->r)) |
1133 | lj_trace_err(as->J, LJ_TRERR_NYIPHI); | 1191 | lj_trace_err(as->J, LJ_TRERR_NYIPHI); |
1134 | ra_spill(as, ir); | 1192 | ra_spill(as, ir); |
1135 | irl->s = irr->s = ir->s; /* Sync left/right PHI spill slots. */ | 1193 | irr->s = ir->s; /* Set right PHI spill slot. Sync left slot later. */ |
1136 | } | 1194 | } |
1137 | } | 1195 | } |
1138 | 1196 | ||
@@ -1142,6 +1200,7 @@ static void asm_loop_fixup(ASMState *as); | |||
1142 | /* Middle part of a loop. */ | 1200 | /* Middle part of a loop. */ |
1143 | static void asm_loop(ASMState *as) | 1201 | static void asm_loop(ASMState *as) |
1144 | { | 1202 | { |
1203 | MCode *mcspill; | ||
1145 | /* LOOP is a guard, so the snapno is up to date. */ | 1204 | /* LOOP is a guard, so the snapno is up to date. */ |
1146 | as->loopsnapno = as->snapno; | 1205 | as->loopsnapno = as->snapno; |
1147 | if (as->gcsteps) | 1206 | if (as->gcsteps) |
@@ -1151,10 +1210,14 @@ static void asm_loop(ASMState *as) | |||
1151 | as->sectref = 0; | 1210 | as->sectref = 0; |
1152 | if (!neverfuse(as)) as->fuseref = 0; | 1211 | if (!neverfuse(as)) as->fuseref = 0; |
1153 | asm_phi_shuffle(as); | 1212 | asm_phi_shuffle(as); |
1213 | mcspill = as->mcp; | ||
1214 | asm_phi_copyspill(as); | ||
1154 | asm_loop_fixup(as); | 1215 | asm_loop_fixup(as); |
1155 | as->mcloop = as->mcp; | 1216 | as->mcloop = as->mcp; |
1156 | RA_DBGX((as, "===== LOOP =====")); | 1217 | RA_DBGX((as, "===== LOOP =====")); |
1157 | if (!as->realign) RA_DBG_FLUSH(); | 1218 | if (!as->realign) RA_DBG_FLUSH(); |
1219 | if (as->mcp != mcspill) | ||
1220 | emit_jmp(as, mcspill); | ||
1158 | } | 1221 | } |
1159 | 1222 | ||
1160 | /* -- Target-specific assembler ------------------------------------------- */ | 1223 | /* -- Target-specific assembler ------------------------------------------- */ |