ARM64: Fuse BOR(BSHL, BSHR) into EXTR/ROR.

Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
This commit is contained in:
Mike Pall 2016-12-09 18:16:12 +01:00
parent ec2756ba78
commit 44b99ff14d

View File

@ -378,6 +378,34 @@ static int asm_fuseandshift(ASMState *as, IRIns *ir)
return 0;
}
/* Fuse BOR(BSHL, BSHR) into EXTR/ROR. */
static int asm_fuseorshift(ASMState *as, IRIns *ir)
{
IRIns *irl = IR(ir->op1), *irr = IR(ir->op2);
lua_assert(ir->o == IR_BOR);
if (!neverfuse(as) && ((irl->o == IR_BSHR && irr->o == IR_BSHL) ||
(irl->o == IR_BSHL && irr->o == IR_BSHR))) {
if (irref_isk(irl->op2) && irref_isk(irr->op2)) {
IRRef lref = irl->op1, rref = irr->op1;
uint32_t lshift = IR(irl->op2)->i, rshift = IR(irr->op2)->i;
if (irl->o == IR_BSHR) { /* BSHR needs to be the right operand. */
uint32_t tmp2;
IRRef tmp1 = lref; lref = rref; rref = tmp1;
tmp2 = lshift; lshift = rshift; rshift = tmp2;
}
if (rshift + lshift == (irt_is64(ir->t) ? 64 : 32)) {
A64Ins ai = irt_is64(ir->t) ? A64I_EXTRx : A64I_EXTRw;
Reg dest = ra_dest(as, ir, RSET_GPR);
Reg left = ra_alloc1(as, lref, RSET_GPR);
Reg right = ra_alloc1(as, rref, rset_exclude(RSET_GPR, left));
emit_dnm(as, ai | A64F_IMMS(rshift), dest, left, right);
return 1;
}
}
}
return 0;
}
/* -- Calls --------------------------------------------------------------- */
/* Generate a call to a C function. */
@ -1460,8 +1488,14 @@ static void asm_band(ASMState *as, IRIns *ir)
asm_bitop(as, ir, A64I_ANDw);
}
static void asm_bor(ASMState *as, IRIns *ir)
{
if (asm_fuseorshift(as, ir))
return;
asm_bitop(as, ir, A64I_ORRw);
}
#define asm_bnot(as, ir) asm_bitop(as, ir, A64I_MVNw)
#define asm_bor(as, ir) asm_bitop(as, ir, A64I_ORRw)
#define asm_bxor(as, ir) asm_bitop(as, ir, A64I_EORw)
static void asm_bswap(ASMState *as, IRIns *ir)