diff options
author | Mike Pall <mike> | 2019-02-04 23:04:48 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2019-02-04 23:04:48 +0100 |
commit | b33e3f2d441590f4de0d189bd9a65661824a48f6 (patch) | |
tree | e7236f72cd3bc740a9850ca6ed6eb7f018f1f0b1 /src | |
parent | f0e865dd4861520258299d0f2a56491bd9d602e1 (diff) | |
download | luajit-b33e3f2d441590f4de0d189bd9a65661824a48f6.tar.gz luajit-b33e3f2d441590f4de0d189bd9a65661824a48f6.tar.bz2 luajit-b33e3f2d441590f4de0d189bd9a65661824a48f6.zip |
ARM64: Avoid side-effects of constant rematerialization.
Thanks to Patrick Galizia.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_asm_arm64.h | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h index baafa21a..ebe2e359 100644 --- a/src/lj_asm_arm64.h +++ b/src/lj_asm_arm64.h | |||
@@ -295,8 +295,10 @@ static void asm_fusexref(ASMState *as, A64Ins ai, Reg rd, IRRef ref, | |||
295 | } else if (asm_isk32(as, ir->op1, &ofs)) { | 295 | } else if (asm_isk32(as, ir->op1, &ofs)) { |
296 | ref = ir->op2; | 296 | ref = ir->op2; |
297 | } else { | 297 | } else { |
298 | Reg rn = ra_alloc1(as, ir->op1, allow); | 298 | Reg refk = irref_isk(ir->op1) ? ir->op1 : ir->op2; |
299 | IRIns *irr = IR(ir->op2); | 299 | Reg refv = irref_isk(ir->op1) ? ir->op2 : ir->op1; |
300 | Reg rn = ra_alloc1(as, refv, allow); | ||
301 | IRIns *irr = IR(refk); | ||
300 | uint32_t m; | 302 | uint32_t m; |
301 | if (irr+1 == ir && !ra_used(irr) && | 303 | if (irr+1 == ir && !ra_used(irr) && |
302 | irr->o == IR_ADD && irref_isk(irr->op2)) { | 304 | irr->o == IR_ADD && irref_isk(irr->op2)) { |
@@ -307,7 +309,7 @@ static void asm_fusexref(ASMState *as, A64Ins ai, Reg rd, IRRef ref, | |||
307 | goto skipopm; | 309 | goto skipopm; |
308 | } | 310 | } |
309 | } | 311 | } |
310 | m = asm_fuseopm(as, 0, ir->op2, rset_exclude(allow, rn)); | 312 | m = asm_fuseopm(as, 0, refk, rset_exclude(allow, rn)); |
311 | ofs = sizeof(GCstr); | 313 | ofs = sizeof(GCstr); |
312 | skipopm: | 314 | skipopm: |
313 | emit_lso(as, ai, rd, rd, ofs); | 315 | emit_lso(as, ai, rd, rd, ofs); |
@@ -722,6 +724,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
722 | Reg dest = ra_dest(as, ir, allow); | 724 | Reg dest = ra_dest(as, ir, allow); |
723 | Reg tab = ra_alloc1(as, ir->op1, rset_clear(allow, dest)); | 725 | Reg tab = ra_alloc1(as, ir->op1, rset_clear(allow, dest)); |
724 | Reg key = 0, tmp = RID_TMP; | 726 | Reg key = 0, tmp = RID_TMP; |
727 | Reg ftmp = RID_NONE, type = RID_NONE, scr = RID_NONE, tisnum = RID_NONE; | ||
725 | IRRef refkey = ir->op2; | 728 | IRRef refkey = ir->op2; |
726 | IRIns *irkey = IR(refkey); | 729 | IRIns *irkey = IR(refkey); |
727 | int isk = irref_isk(ir->op2); | 730 | int isk = irref_isk(ir->op2); |
@@ -751,6 +754,28 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
751 | } | 754 | } |
752 | } | 755 | } |
753 | 756 | ||
757 | /* Allocate constants early. */ | ||
758 | if (irt_isnum(kt)) { | ||
759 | if (!isk) { | ||
760 | tisnum = ra_allock(as, LJ_TISNUM << 15, allow); | ||
761 | ftmp = ra_scratch(as, rset_exclude(RSET_FPR, key)); | ||
762 | rset_clear(allow, tisnum); | ||
763 | } | ||
764 | } else if (irt_isaddr(kt)) { | ||
765 | if (isk) { | ||
766 | int64_t kk = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64; | ||
767 | scr = ra_allock(as, kk, allow); | ||
768 | } else { | ||
769 | scr = ra_scratch(as, allow); | ||
770 | } | ||
771 | rset_clear(allow, scr); | ||
772 | } else { | ||
773 | lua_assert(irt_ispri(kt) && !irt_isnil(kt)); | ||
774 | type = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow); | ||
775 | scr = ra_scratch(as, rset_clear(allow, type)); | ||
776 | rset_clear(allow, scr); | ||
777 | } | ||
778 | |||
754 | /* Key not found in chain: jump to exit (if merged) or load niltv. */ | 779 | /* Key not found in chain: jump to exit (if merged) or load niltv. */ |
755 | l_end = emit_label(as); | 780 | l_end = emit_label(as); |
756 | as->invmcp = NULL; | 781 | as->invmcp = NULL; |
@@ -780,9 +805,6 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
780 | emit_nm(as, A64I_CMPx, key, tmp); | 805 | emit_nm(as, A64I_CMPx, key, tmp); |
781 | emit_lso(as, A64I_LDRx, tmp, dest, offsetof(Node, key.u64)); | 806 | emit_lso(as, A64I_LDRx, tmp, dest, offsetof(Node, key.u64)); |
782 | } else { | 807 | } else { |
783 | Reg tisnum = ra_allock(as, LJ_TISNUM << 15, allow); | ||
784 | Reg ftmp = ra_scratch(as, rset_exclude(RSET_FPR, key)); | ||
785 | rset_clear(allow, tisnum); | ||
786 | emit_nm(as, A64I_FCMPd, key, ftmp); | 808 | emit_nm(as, A64I_FCMPd, key, ftmp); |
787 | emit_dn(as, A64I_FMOV_D_R, (ftmp & 31), (tmp & 31)); | 809 | emit_dn(as, A64I_FMOV_D_R, (ftmp & 31), (tmp & 31)); |
788 | emit_cond_branch(as, CC_LO, l_next); | 810 | emit_cond_branch(as, CC_LO, l_next); |
@@ -790,31 +812,21 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
790 | emit_lso(as, A64I_LDRx, tmp, dest, offsetof(Node, key.n)); | 812 | emit_lso(as, A64I_LDRx, tmp, dest, offsetof(Node, key.n)); |
791 | } | 813 | } |
792 | } else if (irt_isaddr(kt)) { | 814 | } else if (irt_isaddr(kt)) { |
793 | Reg scr; | ||
794 | if (isk) { | 815 | if (isk) { |
795 | int64_t kk = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64; | ||
796 | scr = ra_allock(as, kk, allow); | ||
797 | emit_nm(as, A64I_CMPx, scr, tmp); | 816 | emit_nm(as, A64I_CMPx, scr, tmp); |
798 | emit_lso(as, A64I_LDRx, tmp, dest, offsetof(Node, key.u64)); | 817 | emit_lso(as, A64I_LDRx, tmp, dest, offsetof(Node, key.u64)); |
799 | } else { | 818 | } else { |
800 | scr = ra_scratch(as, allow); | ||
801 | emit_nm(as, A64I_CMPx, tmp, scr); | 819 | emit_nm(as, A64I_CMPx, tmp, scr); |
802 | emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key.u64)); | 820 | emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key.u64)); |
803 | } | 821 | } |
804 | rset_clear(allow, scr); | ||
805 | } else { | 822 | } else { |
806 | Reg type, scr; | ||
807 | lua_assert(irt_ispri(kt) && !irt_isnil(kt)); | ||
808 | type = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow); | ||
809 | scr = ra_scratch(as, rset_clear(allow, type)); | ||
810 | rset_clear(allow, scr); | ||
811 | emit_nm(as, A64I_CMPw, scr, type); | 823 | emit_nm(as, A64I_CMPw, scr, type); |
812 | emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key)); | 824 | emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key)); |
813 | } | 825 | } |
814 | 826 | ||
815 | *l_loop = A64I_BCC | A64F_S19(as->mcp - l_loop) | CC_NE; | 827 | *l_loop = A64I_BCC | A64F_S19(as->mcp - l_loop) | CC_NE; |
816 | if (!isk && irt_isaddr(kt)) { | 828 | if (!isk && irt_isaddr(kt)) { |
817 | Reg type = ra_allock(as, (int32_t)irt_toitype(kt), allow); | 829 | type = ra_allock(as, (int32_t)irt_toitype(kt), allow); |
818 | emit_dnm(as, A64I_ADDx | A64F_SH(A64SH_LSL, 47), tmp, key, type); | 830 | emit_dnm(as, A64I_ADDx | A64F_SH(A64SH_LSL, 47), tmp, key, type); |
819 | rset_clear(allow, type); | 831 | rset_clear(allow, type); |
820 | } | 832 | } |