diff options
| -rw-r--r-- | src/lj_asm.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 6231f134..9c72a864 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
| @@ -1307,12 +1307,44 @@ static void asm_fusexref(ASMState *as, IRRef ref, RegSet allow) | |||
| 1307 | as->mrm.base = RID_NONE; | 1307 | as->mrm.base = RID_NONE; |
| 1308 | } else if (ir->o == IR_STRREF) { | 1308 | } else if (ir->o == IR_STRREF) { |
| 1309 | asm_fusestrref(as, ir, allow); | 1309 | asm_fusestrref(as, ir, allow); |
| 1310 | } else if (mayfuse(as, ref) && ir->o == IR_ADD && | ||
| 1311 | asm_isk32(as, ir->op2, &as->mrm.ofs)) { | ||
| 1312 | /* NYI: gather index and shifts. */ | ||
| 1313 | as->mrm.base = (uint8_t)ra_alloc1(as, ir->op1, allow); | ||
| 1314 | } else { | 1310 | } else { |
| 1315 | as->mrm.ofs = 0; | 1311 | as->mrm.ofs = 0; |
| 1312 | if (mayfuse(as, ref) && ir->o == IR_ADD && ra_noreg(ir->r)) { | ||
| 1313 | /* Gather (base+idx*sz)+ofs as emitted by cdata ptr/array indexing. */ | ||
| 1314 | IRIns *irx; | ||
| 1315 | IRRef idx; | ||
| 1316 | Reg r; | ||
| 1317 | if (asm_isk32(as, ir->op2, &as->mrm.ofs)) { /* Recognize x+ofs. */ | ||
| 1318 | ref = ir->op1; | ||
| 1319 | ir = IR(ref); | ||
| 1320 | if (!(ir->o == IR_ADD && mayfuse(as, ref) && ra_noreg(ir->r))) | ||
| 1321 | goto noadd; | ||
| 1322 | } | ||
| 1323 | as->mrm.scale = XM_SCALE1; | ||
| 1324 | idx = ir->op1; | ||
| 1325 | ref = ir->op2; | ||
| 1326 | irx = IR(idx); | ||
| 1327 | if (!(irx->o == IR_BSHL || irx->o == IR_ADD)) { /* Try other operand. */ | ||
| 1328 | idx = ir->op2; | ||
| 1329 | ref = ir->op1; | ||
| 1330 | irx = IR(idx); | ||
| 1331 | } | ||
| 1332 | if (mayfuse(as, idx) && ra_noreg(irx->r)) { | ||
| 1333 | if (irx->o == IR_BSHL && irref_isk(irx->op2) && IR(irx->op2)->i <= 3) { | ||
| 1334 | /* Recognize idx<<b with b = 0-3, corresponding to sz = (1),2,4,8. */ | ||
| 1335 | idx = irx->op1; | ||
| 1336 | as->mrm.scale = (uint8_t)(IR(irx->op2)->i << 6); | ||
| 1337 | } else if (irx->o == IR_ADD && irx->op1 == irx->op2) { | ||
| 1338 | /* FOLD does idx*2 ==> idx<<1 ==> idx+idx. */ | ||
| 1339 | idx = irx->op1; | ||
| 1340 | as->mrm.scale = XM_SCALE2; | ||
| 1341 | } | ||
| 1342 | } | ||
| 1343 | r = ra_alloc1(as, idx, allow); | ||
| 1344 | rset_clear(allow, r); | ||
| 1345 | as->mrm.idx = (uint8_t)r; | ||
| 1346 | } | ||
| 1347 | noadd: | ||
| 1316 | as->mrm.base = (uint8_t)ra_alloc1(as, ref, allow); | 1348 | as->mrm.base = (uint8_t)ra_alloc1(as, ref, allow); |
| 1317 | } | 1349 | } |
| 1318 | } | 1350 | } |
