From 91016c97a43192836780f6bd5b1c0da01f1d4b6b Mon Sep 17 00:00:00 2001 From: Jeppe Johansen Date: Sun, 28 Jul 2019 11:16:37 +0000 Subject: [PATCH] AVR: Add optimizations for sign testing, and a better Abs() implementation. git-svn-id: trunk@42510 - --- compiler/avr/cgcpu.pas | 33 +++++++++++++++++++++++---------- compiler/avr/navradd.pas | 23 +++++++++++++++++++++++ compiler/avr/navrinl.pas | 26 +++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 11 deletions(-) diff --git a/compiler/avr/cgcpu.pas b/compiler/avr/cgcpu.pas index b3e7238c14..f9e9133d0b 100644 --- a/compiler/avr/cgcpu.pas +++ b/compiler/avr/cgcpu.pas @@ -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); diff --git a/compiler/avr/navradd.pas b/compiler/avr/navradd.pas index 84a3342631..8c9e9b5066 100644 --- a/compiler/avr/navradd.pas +++ b/compiler/avr/navradd.pas @@ -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 } diff --git a/compiler/avr/navrinl.pas b/compiler/avr/navrinl.pas index 4b8662f502..0158a5b8a5 100644 --- a/compiler/avr/navrinl.pas +++ b/compiler/avr/navrinl.pas @@ -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;