aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2023-09-09 20:57:46 +0200
committerMike Pall <mike>2023-09-09 20:57:46 +0200
commit90742d91c27d185b70d1b4a6343fb6b7c26002db (patch)
tree3b99bd38d581fdd74d440054befeb111b90b4342 /src
parentba2b34f5e82baec5f925fa89b7bf4f88ae376da9 (diff)
downloadluajit-90742d91c27d185b70d1b4a6343fb6b7c26002db.tar.gz
luajit-90742d91c27d185b70d1b4a6343fb6b7c26002db.tar.bz2
luajit-90742d91c27d185b70d1b4a6343fb6b7c26002db.zip
ARM64: Don't fuse sign extensions into logical operands.
Thanks to Peter Cawley. #1076
Diffstat (limited to 'src')
-rw-r--r--src/lj_asm_arm64.h11
1 files changed, 4 insertions, 7 deletions
diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h
index 05bdc78a..04834f57 100644
--- a/src/lj_asm_arm64.h
+++ b/src/lj_asm_arm64.h
@@ -216,16 +216,13 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow,
216static uint32_t asm_fuseopm(ASMState *as, A64Ins ai, IRRef ref, RegSet allow) 216static uint32_t asm_fuseopm(ASMState *as, A64Ins ai, IRRef ref, RegSet allow)
217{ 217{
218 IRIns *ir = IR(ref); 218 IRIns *ir = IR(ref);
219 int logical = (ai & 0x1f000000) == 0x0a000000;
219 if (ra_hasreg(ir->r)) { 220 if (ra_hasreg(ir->r)) {
220 ra_noweak(as, ir->r); 221 ra_noweak(as, ir->r);
221 return A64F_M(ir->r); 222 return A64F_M(ir->r);
222 } else if (irref_isk(ref)) { 223 } else if (irref_isk(ref)) {
223 uint32_t m;
224 int64_t k = get_k64val(as, ref); 224 int64_t k = get_k64val(as, ref);
225 if ((ai & 0x1f000000) == 0x0a000000) 225 uint32_t m = logical ? emit_isk13(k, irt_is64(ir->t)) : emit_isk12(k);
226 m = emit_isk13(k, irt_is64(ir->t));
227 else
228 m = emit_isk12(k);
229 if (m) 226 if (m)
230 return m; 227 return m;
231 } else if (mayfuse(as, ref)) { 228 } else if (mayfuse(as, ref)) {
@@ -237,7 +234,7 @@ static uint32_t asm_fuseopm(ASMState *as, A64Ins ai, IRRef ref, RegSet allow)
237 (IR(ir->op2)->i & (irt_is64(ir->t) ? 63 : 31)); 234 (IR(ir->op2)->i & (irt_is64(ir->t) ? 63 : 31));
238 IRIns *irl = IR(ir->op1); 235 IRIns *irl = IR(ir->op1);
239 if (sh == A64SH_LSL && 236 if (sh == A64SH_LSL &&
240 irl->o == IR_CONV && 237 irl->o == IR_CONV && !logical &&
241 irl->op2 == ((IRT_I64<<IRCONV_DSH)|IRT_INT|IRCONV_SEXT) && 238 irl->op2 == ((IRT_I64<<IRCONV_DSH)|IRT_INT|IRCONV_SEXT) &&
242 shift <= 4 && 239 shift <= 4 &&
243 canfuse(as, irl)) { 240 canfuse(as, irl)) {
@@ -247,7 +244,7 @@ static uint32_t asm_fuseopm(ASMState *as, A64Ins ai, IRRef ref, RegSet allow)
247 Reg m = ra_alloc1(as, ir->op1, allow); 244 Reg m = ra_alloc1(as, ir->op1, allow);
248 return A64F_M(m) | A64F_SH(sh, shift); 245 return A64F_M(m) | A64F_SH(sh, shift);
249 } 246 }
250 } else if (ir->o == IR_CONV && 247 } else if (ir->o == IR_CONV && !logical &&
251 ir->op2 == ((IRT_I64<<IRCONV_DSH)|IRT_INT|IRCONV_SEXT)) { 248 ir->op2 == ((IRT_I64<<IRCONV_DSH)|IRT_INT|IRCONV_SEXT)) {
252 Reg m = ra_alloc1(as, ir->op1, allow); 249 Reg m = ra_alloc1(as, ir->op1, allow);
253 return A64F_M(m) | A64F_EX(A64EX_SXTW); 250 return A64F_M(m) | A64F_EX(A64EX_SXTW);