diff options
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r-- | src/lj_asm.c | 47 |
1 files changed, 29 insertions, 18 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 7773abe1..d26d0b4b 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -1110,23 +1110,34 @@ static int noconflict(ASMState *as, IRRef ref, IROp conflict) | |||
1110 | return 1; /* Ok, no conflict. */ | 1110 | return 1; /* Ok, no conflict. */ |
1111 | } | 1111 | } |
1112 | 1112 | ||
1113 | /* Fuse array base into memory operand. */ | ||
1114 | static IRRef asm_fuseabase(ASMState *as, IRRef ref) | ||
1115 | { | ||
1116 | IRIns *irb = IR(ref); | ||
1117 | as->mrm.ofs = 0; | ||
1118 | if (irb->o == IR_FLOAD) { | ||
1119 | IRIns *ira = IR(irb->op1); | ||
1120 | lua_assert(irb->op2 == IRFL_TAB_ARRAY); | ||
1121 | /* We can avoid the FLOAD of t->array for colocated arrays. */ | ||
1122 | if (ira->o == IR_TNEW && ira->op1 <= LJ_MAX_COLOSIZE && | ||
1123 | noconflict(as, irb->op1, IR_NEWREF)) { | ||
1124 | as->mrm.ofs = (int32_t)sizeof(GCtab); /* Ofs to colocated array. */ | ||
1125 | return irb->op1; /* Table obj. */ | ||
1126 | } | ||
1127 | } else if (irb->o == IR_ADD && irref_isk(irb->op2)) { | ||
1128 | /* Fuse base offset (vararg load). */ | ||
1129 | as->mrm.ofs = IR(irb->op2)->i; | ||
1130 | return irb->op1; | ||
1131 | } | ||
1132 | return ref; /* Otherwise use the given array base. */ | ||
1133 | } | ||
1134 | |||
1113 | /* Fuse array reference into memory operand. */ | 1135 | /* Fuse array reference into memory operand. */ |
1114 | static void asm_fusearef(ASMState *as, IRIns *ir, RegSet allow) | 1136 | static void asm_fusearef(ASMState *as, IRIns *ir, RegSet allow) |
1115 | { | 1137 | { |
1116 | IRIns *irb = IR(ir->op1); | 1138 | IRIns *irx; |
1117 | IRIns *ira, *irx; | ||
1118 | lua_assert(ir->o == IR_AREF); | 1139 | lua_assert(ir->o == IR_AREF); |
1119 | lua_assert(irb->o == IR_FLOAD && irb->op2 == IRFL_TAB_ARRAY); | 1140 | as->mrm.base = (uint8_t)ra_alloc1(as, asm_fuseabase(as, ir->op1), allow); |
1120 | ira = IR(irb->op1); | ||
1121 | if (ira->o == IR_TNEW && ira->op1 <= LJ_MAX_COLOSIZE && | ||
1122 | noconflict(as, irb->op1, IR_NEWREF)) { | ||
1123 | /* We can avoid the FLOAD of t->array for colocated arrays. */ | ||
1124 | as->mrm.base = (uint8_t)ra_alloc1(as, irb->op1, allow); /* Table obj. */ | ||
1125 | as->mrm.ofs = (int32_t)sizeof(GCtab); /* Ofs to colocated array. */ | ||
1126 | } else { | ||
1127 | as->mrm.base = (uint8_t)ra_alloc1(as, ir->op1, allow); /* Array base. */ | ||
1128 | as->mrm.ofs = 0; | ||
1129 | } | ||
1130 | irx = IR(ir->op2); | 1141 | irx = IR(ir->op2); |
1131 | if (irref_isk(ir->op2)) { | 1142 | if (irref_isk(ir->op2)) { |
1132 | as->mrm.ofs += 8*irx->i; | 1143 | as->mrm.ofs += 8*irx->i; |
@@ -1277,10 +1288,10 @@ static Reg asm_fuseload(ASMState *as, IRRef ref, RegSet allow) | |||
1277 | } else if (mayfuse(as, ref)) { | 1288 | } else if (mayfuse(as, ref)) { |
1278 | RegSet xallow = (allow & RSET_GPR) ? allow : RSET_GPR; | 1289 | RegSet xallow = (allow & RSET_GPR) ? allow : RSET_GPR; |
1279 | if (ir->o == IR_SLOAD) { | 1290 | if (ir->o == IR_SLOAD) { |
1280 | if (!irt_isint(ir->t) && !(ir->op2 & IRSLOAD_PARENT) && | 1291 | if ((!irt_isint(ir->t) || (ir->op2 & IRSLOAD_FRAME)) && |
1281 | noconflict(as, ref, IR_RETF)) { | 1292 | !(ir->op2 & IRSLOAD_PARENT) && noconflict(as, ref, IR_RETF)) { |
1282 | as->mrm.base = (uint8_t)ra_alloc1(as, REF_BASE, xallow); | 1293 | as->mrm.base = (uint8_t)ra_alloc1(as, REF_BASE, xallow); |
1283 | as->mrm.ofs = 8*((int32_t)ir->op1-1); | 1294 | as->mrm.ofs = 8*((int32_t)ir->op1-1) + ((ir->op2&IRSLOAD_FRAME)?4:0); |
1284 | as->mrm.idx = RID_NONE; | 1295 | as->mrm.idx = RID_NONE; |
1285 | return RID_MRM; | 1296 | return RID_MRM; |
1286 | } | 1297 | } |
@@ -2031,7 +2042,7 @@ static void asm_ahustore(ASMState *as, IRIns *ir) | |||
2031 | 2042 | ||
2032 | static void asm_sload(ASMState *as, IRIns *ir) | 2043 | static void asm_sload(ASMState *as, IRIns *ir) |
2033 | { | 2044 | { |
2034 | int32_t ofs = 8*((int32_t)ir->op1-1); | 2045 | int32_t ofs = 8*((int32_t)ir->op1-1) + ((ir->op2 & IRSLOAD_FRAME) ? 4 : 0); |
2035 | IRType1 t = ir->t; | 2046 | IRType1 t = ir->t; |
2036 | Reg base; | 2047 | Reg base; |
2037 | lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */ | 2048 | lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */ |
@@ -2056,7 +2067,7 @@ static void asm_sload(ASMState *as, IRIns *ir) | |||
2056 | Reg dest = ra_dest(as, ir, allow); | 2067 | Reg dest = ra_dest(as, ir, allow); |
2057 | base = ra_alloc1(as, REF_BASE, RSET_GPR); | 2068 | base = ra_alloc1(as, REF_BASE, RSET_GPR); |
2058 | lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t)); | 2069 | lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t)); |
2059 | if (irt_isint(t)) | 2070 | if (irt_isint(t) && !(ir->op2 & IRSLOAD_FRAME)) |
2060 | emit_rmro(as, XO_CVTSD2SI, dest, base, ofs); | 2071 | emit_rmro(as, XO_CVTSD2SI, dest, base, ofs); |
2061 | else if (irt_isnum(t)) | 2072 | else if (irt_isnum(t)) |
2062 | emit_rmro(as, XMM_MOVRM(as), dest, base, ofs); | 2073 | emit_rmro(as, XMM_MOVRM(as), dest, base, ofs); |