aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2013-04-22 20:47:39 +0200
committerMike Pall <mike>2013-04-22 20:47:39 +0200
commit2cd4ce614167804896c54e04d3d8a69ec16321c7 (patch)
tree24fdcebc4fac059abc3015114dffb01e75822028
parent988e1839658523e772de53f89df389b568883fde (diff)
downloadluajit-2cd4ce614167804896c54e04d3d8a69ec16321c7.tar.gz
luajit-2cd4ce614167804896c54e04d3d8a69ec16321c7.tar.bz2
luajit-2cd4ce614167804896c54e04d3d8a69ec16321c7.zip
Use same HREF+EQ/NE optimization in all assembler backends.
-rw-r--r--src/lj_asm_mips.h48
-rw-r--r--src/lj_asm_x86.h46
2 files changed, 47 insertions, 47 deletions
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h
index 44cb85e5..cbbd2966 100644
--- a/src/lj_asm_mips.h
+++ b/src/lj_asm_mips.h
@@ -570,7 +570,7 @@ static void asm_aref(ASMState *as, IRIns *ir)
570** } while ((n = nextnode(n))); 570** } while ((n = nextnode(n)));
571** return niltv(L); 571** return niltv(L);
572*/ 572*/
573static void asm_href(ASMState *as, IRIns *ir) 573static void asm_href(ASMState *as, IRIns *ir, IROp merge)
574{ 574{
575 RegSet allow = RSET_GPR; 575 RegSet allow = RSET_GPR;
576 int destused = ra_used(ir); 576 int destused = ra_used(ir);
@@ -596,37 +596,42 @@ static void asm_href(ASMState *as, IRIns *ir)
596 tmp2 = ra_scratch(as, allow); 596 tmp2 = ra_scratch(as, allow);
597 rset_clear(allow, tmp2); 597 rset_clear(allow, tmp2);
598 598
599 /* Key not found in chain: load niltv. */ 599 /* Key not found in chain: jump to exit (if merged) or load niltv. */
600 l_end = emit_label(as); 600 l_end = emit_label(as);
601 if (destused) 601 as->invmcp = NULL;
602 if (merge == IR_NE)
603 asm_guard(as, MIPSI_B, RID_ZERO, RID_ZERO);
604 else if (destused)
602 emit_loada(as, dest, niltvg(J2G(as->J))); 605 emit_loada(as, dest, niltvg(J2G(as->J)));
603 else
604 *--as->mcp = MIPSI_NOP;
605 /* Follow hash chain until the end. */ 606 /* Follow hash chain until the end. */
606 emit_move(as, dest, tmp1); 607 emit_move(as, dest, tmp2);
607 l_loop = --as->mcp; 608 l_loop = --as->mcp;
608 emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, next)); 609 emit_tsi(as, MIPSI_LW, tmp2, dest, (int32_t)offsetof(Node, next));
609 l_next = emit_label(as); 610 l_next = emit_label(as);
610 611
611 /* Type and value comparison. */ 612 /* Type and value comparison. */
613 if (merge == IR_EQ) { /* Must match asm_guard(). */
614 emit_ti(as, MIPSI_LI, RID_TMP, as->snapno);
615 l_end = asm_exitstub_addr(as);
616 }
612 if (irt_isnum(kt)) { 617 if (irt_isnum(kt)) {
613 emit_branch(as, MIPSI_BC1T, 0, 0, l_end); 618 emit_branch(as, MIPSI_BC1T, 0, 0, l_end);
614 emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key); 619 emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key);
615 emit_tg(as, MIPSI_MFC1, tmp1, key+1); 620 *--as->mcp = MIPSI_NOP; /* Avoid NaN comparison overhead. */
616 emit_branch(as, MIPSI_BEQ, tmp1, RID_ZERO, l_next); 621 emit_branch(as, MIPSI_BEQ, tmp2, RID_ZERO, l_next);
617 emit_tsi(as, MIPSI_SLTIU, tmp1, tmp1, (int32_t)LJ_TISNUM); 622 emit_tsi(as, MIPSI_SLTIU, tmp2, tmp2, (int32_t)LJ_TISNUM);
618 emit_hsi(as, MIPSI_LDC1, tmpnum, dest, (int32_t)offsetof(Node, key.n)); 623 emit_hsi(as, MIPSI_LDC1, tmpnum, dest, (int32_t)offsetof(Node, key.n));
619 } else { 624 } else {
620 if (irt_ispri(kt)) { 625 if (irt_ispri(kt)) {
621 emit_branch(as, MIPSI_BEQ, tmp1, type, l_end); 626 emit_branch(as, MIPSI_BEQ, tmp2, type, l_end);
622 } else { 627 } else {
623 emit_branch(as, MIPSI_BEQ, tmp2, key, l_end); 628 emit_branch(as, MIPSI_BEQ, tmp1, key, l_end);
624 emit_tsi(as, MIPSI_LW, tmp2, dest, (int32_t)offsetof(Node, key.gcr)); 629 emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, key.gcr));
625 emit_branch(as, MIPSI_BNE, tmp1, type, l_next); 630 emit_branch(as, MIPSI_BNE, tmp2, type, l_next);
626 } 631 }
627 } 632 }
628 emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, key.it)); 633 emit_tsi(as, MIPSI_LW, tmp2, dest, (int32_t)offsetof(Node, key.it));
629 *l_loop = MIPSI_BNE | MIPSF_S(tmp1) | ((as->mcp-l_loop-1) & 0xffffu); 634 *l_loop = MIPSI_BNE | MIPSF_S(tmp2) | ((as->mcp-l_loop-1) & 0xffffu);
630 635
631 /* Load main position relative to tab->node into dest. */ 636 /* Load main position relative to tab->node into dest. */
632 khash = irref_isk(refkey) ? ir_khash(irkey) : 1; 637 khash = irref_isk(refkey) ? ir_khash(irkey) : 1;
@@ -1694,7 +1699,14 @@ static void asm_ir(ASMState *as, IRIns *ir)
1694 case IR_GCSTEP: asm_gcstep(as, ir); break; 1699 case IR_GCSTEP: asm_gcstep(as, ir); break;
1695 1700
1696 /* Guarded assertions. */ 1701 /* Guarded assertions. */
1697 case IR_EQ: case IR_NE: asm_compeq(as, ir); break; 1702 case IR_EQ: case IR_NE:
1703 if ((ir-1)->o == IR_HREF && ir->op1 == as->curins-1) {
1704 as->curins--;
1705 asm_href(as, ir-1, (IROp)ir->o);
1706 break;
1707 }
1708 asm_compeq(as, ir);
1709 break;
1698 case IR_LT: case IR_GE: case IR_LE: case IR_GT: 1710 case IR_LT: case IR_GE: case IR_LE: case IR_GT:
1699 case IR_ULT: case IR_UGE: case IR_ULE: case IR_UGT: 1711 case IR_ULT: case IR_UGE: case IR_ULE: case IR_UGT:
1700 case IR_ABC: 1712 case IR_ABC:
@@ -1749,7 +1761,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
1749 1761
1750 /* Memory references. */ 1762 /* Memory references. */
1751 case IR_AREF: asm_aref(as, ir); break; 1763 case IR_AREF: asm_aref(as, ir); break;
1752 case IR_HREF: asm_href(as, ir); break; 1764 case IR_HREF: asm_href(as, ir, 0); break;
1753 case IR_HREFK: asm_hrefk(as, ir); break; 1765 case IR_HREFK: asm_hrefk(as, ir); break;
1754 case IR_NEWREF: asm_newref(as, ir); break; 1766 case IR_NEWREF: asm_newref(as, ir); break;
1755 case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break; 1767 case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break;
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h
index e79dca93..45fc7e85 100644
--- a/src/lj_asm_x86.h
+++ b/src/lj_asm_x86.h
@@ -947,23 +947,6 @@ static void asm_aref(ASMState *as, IRIns *ir)
947 emit_rr(as, XO_MOV, dest, as->mrm.base); 947 emit_rr(as, XO_MOV, dest, as->mrm.base);
948} 948}
949 949
950/* Merge NE(HREF, niltv) check. */
951static MCode *merge_href_niltv(ASMState *as, IRIns *ir)
952{
953 /* Assumes nothing else generates NE of HREF. */
954 if ((ir[1].o == IR_NE || ir[1].o == IR_EQ) && ir[1].op1 == as->curins &&
955 ra_hasreg(ir->r)) {
956 MCode *p = as->mcp;
957 p += (LJ_64 && *p != XI_ARITHi) ? 7+6 : 6+6;
958 /* Ensure no loop branch inversion happened. */
959 if (p[-6] == 0x0f && p[-5] == XI_JCCn+(CC_NE^(ir[1].o & 1))) {
960 as->mcp = p; /* Kill cmp reg, imm32 + jz exit. */
961 return p + *(int32_t *)(p-4); /* Return exit address. */
962 }
963 }
964 return NULL;
965}
966
967/* Inlined hash lookup. Specialized for key type and for const keys. 950/* Inlined hash lookup. Specialized for key type and for const keys.
968** The equivalent C code is: 951** The equivalent C code is:
969** Node *n = hashkey(t, key); 952** Node *n = hashkey(t, key);
@@ -972,10 +955,10 @@ static MCode *merge_href_niltv(ASMState *as, IRIns *ir)
972** } while ((n = nextnode(n))); 955** } while ((n = nextnode(n)));
973** return niltv(L); 956** return niltv(L);
974*/ 957*/
975static void asm_href(ASMState *as, IRIns *ir) 958static void asm_href(ASMState *as, IRIns *ir, IROp merge)
976{ 959{
977 MCode *nilexit = merge_href_niltv(as, ir); /* Do this before any restores. */
978 RegSet allow = RSET_GPR; 960 RegSet allow = RSET_GPR;
961 int destused = ra_used(ir);
979 Reg dest = ra_dest(as, ir, allow); 962 Reg dest = ra_dest(as, ir, allow);
980 Reg tab = ra_alloc1(as, ir->op1, rset_clear(allow, dest)); 963 Reg tab = ra_alloc1(as, ir->op1, rset_clear(allow, dest));
981 Reg key = RID_NONE, tmp = RID_NONE; 964 Reg key = RID_NONE, tmp = RID_NONE;
@@ -992,14 +975,12 @@ static void asm_href(ASMState *as, IRIns *ir)
992 tmp = ra_scratch(as, rset_exclude(allow, key)); 975 tmp = ra_scratch(as, rset_exclude(allow, key));
993 } 976 }
994 977
995 /* Key not found in chain: jump to exit (if merged with NE) or load niltv. */ 978 /* Key not found in chain: jump to exit (if merged) or load niltv. */
996 l_end = emit_label(as); 979 l_end = emit_label(as);
997 if (nilexit && ir[1].o == IR_NE) { 980 if (merge == IR_NE)
998 emit_jcc(as, CC_E, nilexit); /* XI_JMP is not found by lj_asm_patchexit. */ 981 asm_guardcc(as, CC_E); /* XI_JMP is not found by lj_asm_patchexit. */
999 nilexit = NULL; 982 else if (destused)
1000 } else {
1001 emit_loada(as, dest, niltvg(J2G(as->J))); 983 emit_loada(as, dest, niltvg(J2G(as->J)));
1002 }
1003 984
1004 /* Follow hash chain until the end. */ 985 /* Follow hash chain until the end. */
1005 l_loop = emit_sjcc_label(as, CC_NZ); 986 l_loop = emit_sjcc_label(as, CC_NZ);
@@ -1008,8 +989,8 @@ static void asm_href(ASMState *as, IRIns *ir)
1008 l_next = emit_label(as); 989 l_next = emit_label(as);
1009 990
1010 /* Type and value comparison. */ 991 /* Type and value comparison. */
1011 if (nilexit) 992 if (merge == IR_EQ)
1012 emit_jcc(as, CC_E, nilexit); 993 asm_guardcc(as, CC_E);
1013 else 994 else
1014 emit_sjcc(as, CC_E, l_end); 995 emit_sjcc(as, CC_E, l_end);
1015 if (irt_isnum(kt)) { 996 if (irt_isnum(kt)) {
@@ -2519,9 +2500,16 @@ static void asm_ir(ASMState *as, IRIns *ir)
2519 case IR_GCSTEP: asm_gcstep(as, ir); break; 2500 case IR_GCSTEP: asm_gcstep(as, ir); break;
2520 2501
2521 /* Guarded assertions. */ 2502 /* Guarded assertions. */
2503 case IR_EQ: case IR_NE:
2504 if ((ir-1)->o == IR_HREF && ir->op1 == as->curins-1) {
2505 as->curins--;
2506 asm_href(as, ir-1, (IROp)ir->o);
2507 break;
2508 }
2509 /* fallthrough */
2522 case IR_LT: case IR_GE: case IR_LE: case IR_GT: 2510 case IR_LT: case IR_GE: case IR_LE: case IR_GT:
2523 case IR_ULT: case IR_UGE: case IR_ULE: case IR_UGT: 2511 case IR_ULT: case IR_UGE: case IR_ULE: case IR_UGT:
2524 case IR_EQ: case IR_NE: case IR_ABC: 2512 case IR_ABC:
2525 asm_comp(as, ir, asm_compmap[ir->o]); 2513 asm_comp(as, ir, asm_compmap[ir->o]);
2526 break; 2514 break;
2527 2515
@@ -2615,7 +2603,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
2615 2603
2616 /* Memory references. */ 2604 /* Memory references. */
2617 case IR_AREF: asm_aref(as, ir); break; 2605 case IR_AREF: asm_aref(as, ir); break;
2618 case IR_HREF: asm_href(as, ir); break; 2606 case IR_HREF: asm_href(as, ir, 0); break;
2619 case IR_HREFK: asm_hrefk(as, ir); break; 2607 case IR_HREFK: asm_hrefk(as, ir); break;
2620 case IR_NEWREF: asm_newref(as, ir); break; 2608 case IR_NEWREF: asm_newref(as, ir); break;
2621 case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break; 2609 case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break;