aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2019-02-04 23:04:48 +0100
committerMike Pall <mike>2019-02-04 23:04:48 +0100
commitb33e3f2d441590f4de0d189bd9a65661824a48f6 (patch)
treee7236f72cd3bc740a9850ca6ed6eb7f018f1f0b1 /src
parentf0e865dd4861520258299d0f2a56491bd9d602e1 (diff)
downloadluajit-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.h46
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 }