ARM64: Don't fuse sign extensions into logical operands.

Thanks to Peter Cawley. #1076
This commit is contained in:
Mike Pall 2023-09-09 20:57:46 +02:00
parent ba2b34f5e8
commit 90742d91c2

View File

@ -216,16 +216,13 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow,
static uint32_t asm_fuseopm(ASMState *as, A64Ins ai, IRRef ref, RegSet allow) static uint32_t asm_fuseopm(ASMState *as, A64Ins ai, IRRef ref, RegSet allow)
{ {
IRIns *ir = IR(ref); IRIns *ir = IR(ref);
int logical = (ai & 0x1f000000) == 0x0a000000;
if (ra_hasreg(ir->r)) { if (ra_hasreg(ir->r)) {
ra_noweak(as, ir->r); ra_noweak(as, ir->r);
return A64F_M(ir->r); return A64F_M(ir->r);
} else if (irref_isk(ref)) { } else if (irref_isk(ref)) {
uint32_t m;
int64_t k = get_k64val(as, ref); int64_t k = get_k64val(as, ref);
if ((ai & 0x1f000000) == 0x0a000000) uint32_t m = logical ? emit_isk13(k, irt_is64(ir->t)) : emit_isk12(k);
m = emit_isk13(k, irt_is64(ir->t));
else
m = emit_isk12(k);
if (m) if (m)
return m; return m;
} else if (mayfuse(as, ref)) { } else if (mayfuse(as, ref)) {
@ -237,7 +234,7 @@ static uint32_t asm_fuseopm(ASMState *as, A64Ins ai, IRRef ref, RegSet allow)
(IR(ir->op2)->i & (irt_is64(ir->t) ? 63 : 31)); (IR(ir->op2)->i & (irt_is64(ir->t) ? 63 : 31));
IRIns *irl = IR(ir->op1); IRIns *irl = IR(ir->op1);
if (sh == A64SH_LSL && if (sh == A64SH_LSL &&
irl->o == IR_CONV && irl->o == IR_CONV && !logical &&
irl->op2 == ((IRT_I64<<IRCONV_DSH)|IRT_INT|IRCONV_SEXT) && irl->op2 == ((IRT_I64<<IRCONV_DSH)|IRT_INT|IRCONV_SEXT) &&
shift <= 4 && shift <= 4 &&
canfuse(as, irl)) { canfuse(as, irl)) {
@ -247,7 +244,7 @@ static uint32_t asm_fuseopm(ASMState *as, A64Ins ai, IRRef ref, RegSet allow)
Reg m = ra_alloc1(as, ir->op1, allow); Reg m = ra_alloc1(as, ir->op1, allow);
return A64F_M(m) | A64F_SH(sh, shift); return A64F_M(m) | A64F_SH(sh, shift);
} }
} else if (ir->o == IR_CONV && } else if (ir->o == IR_CONV && !logical &&
ir->op2 == ((IRT_I64<<IRCONV_DSH)|IRT_INT|IRCONV_SEXT)) { ir->op2 == ((IRT_I64<<IRCONV_DSH)|IRT_INT|IRCONV_SEXT)) {
Reg m = ra_alloc1(as, ir->op1, allow); Reg m = ra_alloc1(as, ir->op1, allow);
return A64F_M(m) | A64F_EX(A64EX_SXTW); return A64F_M(m) | A64F_EX(A64EX_SXTW);