mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-19 20:39:25 +02:00
* make use of lea if possible
git-svn-id: trunk@25898 -
This commit is contained in:
parent
945b318012
commit
3c58cad96b
@ -70,6 +70,9 @@ unit cgx86;
|
||||
procedure a_op_ref_reg(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
|
||||
procedure a_op_reg_ref(list : TAsmList; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
|
||||
|
||||
procedure a_op_const_reg_reg(list : TAsmList; op : Topcg; size : Tcgsize; a : tcgint; src,dst : Tregister); override;
|
||||
procedure a_op_reg_reg_reg(list : TAsmList; op : TOpCg; size : tcgsize; src1,src2,dst : tregister); override;
|
||||
|
||||
{ move instructions }
|
||||
procedure a_load_const_reg(list : TAsmList; tosize: tcgsize; a : tcgint;reg : tregister);override;
|
||||
procedure a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;const ref : treference);override;
|
||||
@ -1547,11 +1550,71 @@ unit cgx86;
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgx86.a_op_const_reg_reg(list:TAsmList;op:Topcg;size:Tcgsize;
|
||||
a:tcgint;src,dst:Tregister);
|
||||
var
|
||||
power : longint;
|
||||
href : treference;
|
||||
begin
|
||||
{ if (op in [OP_MUL,OP_IMUL]) and (size in [OS_32,OS_S32,OS_64,OS_S64]) and
|
||||
not(cs_check_overflow in current_settings.localswitches) and
|
||||
(a>1) and ispowerof2(int64(a-1),power) and (power in [1..3]) then
|
||||
begin
|
||||
reference_reset_base(href,src,0,0);
|
||||
href.index:=src;
|
||||
href.scalefactor:=a-1;
|
||||
list.concat(taicpu.op_ref_reg(A_LEA,TCgSize2OpSize[size],href,dst));
|
||||
end
|
||||
else } if (op=OP_ADD) and
|
||||
((size in [OS_32,OS_S32]) or
|
||||
{ lea supports only 32 bit signed displacments }
|
||||
((size=OS_64) and (a>=0) and (a<=maxLongint)) or
|
||||
((size=OS_S64) and (a>=-maxLongint) and (a<=maxLongint))
|
||||
) and
|
||||
not(cs_check_overflow in current_settings.localswitches) then
|
||||
begin
|
||||
reference_reset_base(href,src,a,0);
|
||||
list.concat(taicpu.op_ref_reg(A_LEA,TCgSize2OpSize[size],href,dst));
|
||||
end
|
||||
else if (op=OP_SUB) and
|
||||
((size in [OS_32,OS_S32]) or
|
||||
{ lea supports only 32 bit signed displacments }
|
||||
((size=OS_64) and (a>=0) and (a<=maxLongint)) or
|
||||
((size=OS_S64) and (a>=-maxLongint) and (a<=maxLongint))
|
||||
) and
|
||||
not(cs_check_overflow in current_settings.localswitches) then
|
||||
begin
|
||||
reference_reset_base(href,src,-a,0);
|
||||
list.concat(taicpu.op_ref_reg(A_LEA,TCgSize2OpSize[size],href,dst));
|
||||
end
|
||||
else
|
||||
inherited a_op_const_reg_reg(list,op,size,a,src,dst);
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgx86.a_op_reg_reg_reg(list: TAsmList; op: TOpCg;
|
||||
size: tcgsize; src1, src2, dst: tregister);
|
||||
var
|
||||
href : treference;
|
||||
begin
|
||||
if (op=OP_ADD) and (size in [OS_32,OS_S32,OS_64,OS_S64]) and
|
||||
not(cs_check_overflow in current_settings.localswitches) then
|
||||
begin
|
||||
reference_reset_base(href,src1,0,0);
|
||||
href.index:=src2;
|
||||
list.concat(taicpu.op_ref_reg(A_LEA,TCgSize2OpSize[size],href,dst));
|
||||
end
|
||||
else
|
||||
inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgx86.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
|
||||
|
||||
var
|
||||
opcode : tasmop;
|
||||
power : longint;
|
||||
href : treference;
|
||||
{$ifdef x86_64}
|
||||
tmpreg : tregister;
|
||||
{$endif x86_64}
|
||||
@ -1605,6 +1668,7 @@ unit cgx86;
|
||||
list.concat(taicpu.op_const_reg(A_SHL,TCgSize2OpSize[size],power,reg));
|
||||
exit;
|
||||
end;
|
||||
|
||||
if op = OP_IMUL then
|
||||
list.concat(taicpu.op_const_reg(A_IMUL,TCgSize2OpSize[size],a,reg))
|
||||
else
|
||||
|
@ -85,6 +85,7 @@ unit nx86add;
|
||||
power : longint;
|
||||
hl4 : tasmlabel;
|
||||
r : Tregister;
|
||||
href : treference;
|
||||
begin
|
||||
{ at this point, left.location.loc should be LOC_REGISTER }
|
||||
if right.location.loc=LOC_REGISTER then
|
||||
@ -156,6 +157,18 @@ unit nx86add;
|
||||
begin
|
||||
emit_const_reg(A_SHL,TCGSize2Opsize[opsize],power,left.location.register);
|
||||
end
|
||||
else if (op=A_IMUL) and
|
||||
(right.location.loc=LOC_CONSTANT) and
|
||||
(right.location.value>1) and (ispowerof2(int64(right.location.value)-1,power)) and
|
||||
(power in [1..3]) and
|
||||
not(cs_check_overflow in current_settings.localswitches) then
|
||||
begin
|
||||
reference_reset_base(href,left.location.register,0,0);
|
||||
href.index:=left.location.register;
|
||||
href.scalefactor:=int64(right.location.value)-1;
|
||||
left.location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_LEA,TCgSize2OpSize[opsize],href,left.location.register));
|
||||
end
|
||||
else
|
||||
begin
|
||||
if extra_not then
|
||||
@ -210,7 +223,7 @@ unit nx86add;
|
||||
{ maybe we can reuse a constant register when the
|
||||
operation is a comparison that doesn't change the
|
||||
value of the register }
|
||||
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]));
|
||||
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]));
|
||||
end;
|
||||
end;
|
||||
if (right.location.loc<>LOC_CONSTANT) and
|
||||
|
Loading…
Reference in New Issue
Block a user