From b33e3f2d441590f4de0d189bd9a65661824a48f6 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Mon, 4 Feb 2019 23:04:48 +0100 Subject: ARM64: Avoid side-effects of constant rematerialization. Thanks to Patrick Galizia. --- src/lj_asm_arm64.h | 46 +++++++++++++++++++++++++++++----------------- 1 file 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, } else if (asm_isk32(as, ir->op1, &ofs)) { ref = ir->op2; } else { - Reg rn = ra_alloc1(as, ir->op1, allow); - IRIns *irr = IR(ir->op2); + Reg refk = irref_isk(ir->op1) ? ir->op1 : ir->op2; + Reg refv = irref_isk(ir->op1) ? ir->op2 : ir->op1; + Reg rn = ra_alloc1(as, refv, allow); + IRIns *irr = IR(refk); uint32_t m; if (irr+1 == ir && !ra_used(irr) && irr->o == IR_ADD && irref_isk(irr->op2)) { @@ -307,7 +309,7 @@ static void asm_fusexref(ASMState *as, A64Ins ai, Reg rd, IRRef ref, goto skipopm; } } - m = asm_fuseopm(as, 0, ir->op2, rset_exclude(allow, rn)); + m = asm_fuseopm(as, 0, refk, rset_exclude(allow, rn)); ofs = sizeof(GCstr); skipopm: emit_lso(as, ai, rd, rd, ofs); @@ -722,6 +724,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) Reg dest = ra_dest(as, ir, allow); Reg tab = ra_alloc1(as, ir->op1, rset_clear(allow, dest)); Reg key = 0, tmp = RID_TMP; + Reg ftmp = RID_NONE, type = RID_NONE, scr = RID_NONE, tisnum = RID_NONE; IRRef refkey = ir->op2; IRIns *irkey = IR(refkey); int isk = irref_isk(ir->op2); @@ -751,6 +754,28 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) } } + /* Allocate constants early. */ + if (irt_isnum(kt)) { + if (!isk) { + tisnum = ra_allock(as, LJ_TISNUM << 15, allow); + ftmp = ra_scratch(as, rset_exclude(RSET_FPR, key)); + rset_clear(allow, tisnum); + } + } else if (irt_isaddr(kt)) { + if (isk) { + int64_t kk = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64; + scr = ra_allock(as, kk, allow); + } else { + scr = ra_scratch(as, allow); + } + rset_clear(allow, scr); + } else { + lua_assert(irt_ispri(kt) && !irt_isnil(kt)); + type = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow); + scr = ra_scratch(as, rset_clear(allow, type)); + rset_clear(allow, scr); + } + /* Key not found in chain: jump to exit (if merged) or load niltv. */ l_end = emit_label(as); as->invmcp = NULL; @@ -780,9 +805,6 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) emit_nm(as, A64I_CMPx, key, tmp); emit_lso(as, A64I_LDRx, tmp, dest, offsetof(Node, key.u64)); } else { - Reg tisnum = ra_allock(as, LJ_TISNUM << 15, allow); - Reg ftmp = ra_scratch(as, rset_exclude(RSET_FPR, key)); - rset_clear(allow, tisnum); emit_nm(as, A64I_FCMPd, key, ftmp); emit_dn(as, A64I_FMOV_D_R, (ftmp & 31), (tmp & 31)); emit_cond_branch(as, CC_LO, l_next); @@ -790,31 +812,21 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) emit_lso(as, A64I_LDRx, tmp, dest, offsetof(Node, key.n)); } } else if (irt_isaddr(kt)) { - Reg scr; if (isk) { - int64_t kk = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64; - scr = ra_allock(as, kk, allow); emit_nm(as, A64I_CMPx, scr, tmp); emit_lso(as, A64I_LDRx, tmp, dest, offsetof(Node, key.u64)); } else { - scr = ra_scratch(as, allow); emit_nm(as, A64I_CMPx, tmp, scr); emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key.u64)); } - rset_clear(allow, scr); } else { - Reg type, scr; - lua_assert(irt_ispri(kt) && !irt_isnil(kt)); - type = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow); - scr = ra_scratch(as, rset_clear(allow, type)); - rset_clear(allow, scr); emit_nm(as, A64I_CMPw, scr, type); emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key)); } *l_loop = A64I_BCC | A64F_S19(as->mcp - l_loop) | CC_NE; if (!isk && irt_isaddr(kt)) { - Reg type = ra_allock(as, (int32_t)irt_toitype(kt), allow); + type = ra_allock(as, (int32_t)irt_toitype(kt), allow); emit_dnm(as, A64I_ADDx | A64F_SH(A64SH_LSL, 47), tmp, key, type); rset_clear(allow, type); } -- cgit v1.2.3-55-g6feb