diff options
author | Mike Pall <mike> | 2013-04-22 20:47:39 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2013-04-22 20:47:39 +0200 |
commit | 2cd4ce614167804896c54e04d3d8a69ec16321c7 (patch) | |
tree | 24fdcebc4fac059abc3015114dffb01e75822028 | |
parent | 988e1839658523e772de53f89df389b568883fde (diff) | |
download | luajit-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.h | 48 | ||||
-rw-r--r-- | src/lj_asm_x86.h | 46 |
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 | */ |
573 | static void asm_href(ASMState *as, IRIns *ir) | 573 | static 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. */ | ||
951 | static 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 | */ |
975 | static void asm_href(ASMState *as, IRIns *ir) | 958 | static 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; |