AVR: Add optimizations for sign testing, and a better Abs() implementation.

git-svn-id: trunk@42510 -
This commit is contained in:
Jeppe Johansen 2019-07-28 11:16:37 +00:00
parent bf71795324
commit 91016c97a4
3 changed files with 71 additions and 11 deletions

View File

@ -1606,7 +1606,7 @@ unit cgcpu;
procedure tcgavr.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;
cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);
var
swapped : boolean;
swapped , test_msb: boolean;
tmpreg : tregister;
i : byte;
begin
@ -1637,18 +1637,31 @@ unit cgcpu;
end;
end;
if swapped then
list.concat(taicpu.op_reg_reg(A_CP,NR_R1,reg))
else
list.concat(taicpu.op_reg_reg(A_CP,reg,NR_R1));
for i:=2 to tcgsize2size[size] do
{ If doing a signed test for x<0, we can simply test the sign bit
of the most significant byte }
if (cmp_op in [OC_LT,OC_GTE]) and
(not swapped) then
begin
for i:=2 to tcgsize2size[size] do
reg:=GetNextReg(reg);
list.concat(taicpu.op_reg_reg(A_CP,reg,NR_R1));
end
else
begin
reg:=GetNextReg(reg);
if swapped then
list.concat(taicpu.op_reg_reg(A_CPC,NR_R1,reg))
list.concat(taicpu.op_reg_reg(A_CP,NR_R1,reg))
else
list.concat(taicpu.op_reg_reg(A_CPC,reg,NR_R1));
list.concat(taicpu.op_reg_reg(A_CP,reg,NR_R1));
for i:=2 to tcgsize2size[size] do
begin
reg:=GetNextReg(reg);
if swapped then
list.concat(taicpu.op_reg_reg(A_CPC,NR_R1,reg))
else
list.concat(taicpu.op_reg_reg(A_CPC,reg,NR_R1));
end;
end;
a_jmp_cond(list,cmp_op,l);

View File

@ -202,6 +202,29 @@ interface
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
end;
if (not unsigned) and
(right.location.loc=LOC_CONSTANT) and
(right.location.value=0) and
(getresflags(unsigned) in [F_LT,F_GE]) then
begin
{ This is a simple sign test, where we can just test the msb }
tmpreg1:=left.location.register;
for i:=2 to tcgsize2size[left.location.size] do
begin
if i=5 then
tmpreg1:=left.location.registerhi
else
tmpreg1:=cg.GetNextReg(tmpreg1);
end;
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,tmpreg1,NR_R1));
location_reset(location,LOC_FLAGS,OS_NO);
location.resflags:=getresflags(unsigned);
exit;
end;
if right.location.loc=LOC_CONSTANT then
begin
{ decrease register pressure on registers >= r16 }

View File

@ -26,10 +26,12 @@ unit navrinl;
interface
uses
node,ninl,ncginl;
node,ninl,ncginl, aasmbase;
type
tavrinlinenode = class(tcginlinenode)
procedure second_abs_long; override;
function pass_typecheck_cpu:tnode;override;
function first_cpu : tnode;override;
procedure pass_generate_code_cpu;override;
@ -42,11 +44,33 @@ unit navrinl;
aasmdata,
aasmcpu,
symdef,
defutil,
hlcgobj,
pass_2,
cgbase, cgobj, cgutils,
cpubase;
procedure tavrinlinenode.second_abs_long;
var
hl: TAsmLabel;
size: TCgSize;
begin
secondpass(left);
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
location:=left.location;
location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,left.resultdef);
size:=def_cgsize(left.resultdef);
current_asmdata.getjumplabel(hl);
cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,size,OC_GTE,0,left.location.register,hl);
cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,size,left.location.register,location.register);
cg.a_label(current_asmdata.CurrAsmList,hl);
end;
function tavrinlinenode.pass_typecheck_cpu : tnode;
begin
Result:=nil;