Optimize 8/16 OP_NOT on ARM

This now generates:

mvn r0, r0, lsl #24/#16
mov r0, r0, lsr/asr #24/#16

The lsr/asr might be folded into a following instruction, making the
whole operation 1 cycle instead of 2-3 with the previous solution.

git-svn-id: trunk@21658 -
This commit is contained in:
masta 2012-06-20 12:39:09 +00:00
parent f90e686be2
commit 92c47148cc

View File

@ -581,23 +581,34 @@ unit cgcpu;
procedure tcgarm.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
var
so : tshifterop;
begin
case op of
OP_NEG:
list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0));
OP_NOT:
begin
if op = OP_NEG then
list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0))
else if op = OP_NOT then
begin
if size in [OS_8, OS_16, OS_S8, OS_S16] then
begin
shifterop_reset(so);
so.shiftmode:=SM_LSL;
if size in [OS_8, OS_S8] then
so.shiftimm:=24
else
so.shiftimm:=16;
list.concat(taicpu.op_reg_reg_shifterop(A_MVN,dst,src,so));
{Using a shift here allows this to be folded into another instruction}
if size in [OS_S8, OS_S16] then
so.shiftmode:=SM_ASR
else
so.shiftmode:=SM_LSR;
list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,dst,so));
end
else
list.concat(taicpu.op_reg_reg(A_MVN,dst,src));
case size of
OS_8 :
a_op_const_reg_reg(list,OP_AND,OS_INT,$ff,dst,dst);
OS_16 :
a_op_const_reg_reg(list,OP_AND,OS_INT,$ffff,dst,dst);
end;
end
else
end
else
a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
end;
end;
@ -2664,7 +2675,7 @@ unit cgcpu;
procedure tcgarm.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
const
overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NEG];
begin
if (op in overflowops) and
(size in [OS_8,OS_S8,OS_16,OS_S16]) then