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 /src/lj_asm_x86.h | |
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.
Diffstat (limited to 'src/lj_asm_x86.h')
-rw-r--r-- | src/lj_asm_x86.h | 46 |
1 files changed, 17 insertions, 29 deletions
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; |