* made 'mod powerof2' -> 'and' optimization processor independent

This commit is contained in:
Jonas Maebe 2001-12-29 15:27:24 +00:00
parent 599a68f8c9
commit 928493e3ba
2 changed files with 103 additions and 78 deletions

View File

@ -68,7 +68,7 @@ implementation
usablecount, regstopush : byte; usablecount, regstopush : byte;
hreg1 : tregister; hreg1 : tregister;
hreg2 : tregister; hreg2 : tregister;
shrdiv, andmod, pushed,popeax,popedx : boolean; shrdiv, pushed,popeax,popedx : boolean;
power : longint; power : longint;
hl : tasmlabel; hl : tasmlabel;
@ -78,7 +78,6 @@ implementation
begin begin
shrdiv := false; shrdiv := false;
andmod := false;
secondpass(left); secondpass(left);
pushed:=maybe_push(right.registers32,left,is_64bitint(left.resulttype.def)); pushed:=maybe_push(right.registers32,left,is_64bitint(left.resulttype.def));
secondpass(right); secondpass(right);
@ -171,14 +170,6 @@ implementation
Else Else
emit_const_reg(A_SHR,S_L,power,hreg1); emit_const_reg(A_SHR,S_L,power,hreg1);
End End
else
if (nodetype=modn) and (right.nodetype=ordconstn) and
ispowerof2(tordconstnode(right).value,power) and Not(is_signed(left.resulttype.def)) Then
{is there a similar trick for MOD'ing signed numbers? (JM)}
Begin
emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg1);
andmod := true;
End
else else
begin begin
{ bring denominator to EDI } { bring denominator to EDI }
@ -265,33 +256,30 @@ implementation
end; end;
end end
else else
{if we did the mod by an "and", the result is in hreg1 and begin
EDX certainly hasn't been pushed (JM)} if not popeax and (hreg1 <> R_EAX)then
if not(andmod) Then ungetregister(R_EAX);
begin if popedx then
if not popeax and (hreg1 <> R_EAX)then {the mod was done by an (i)div (so the result is now in
ungetregister(R_EAX); edx), but edx was occupied prior to the division, so
if popedx then move the result into a safe place (JM)}
{the mod was done by an (i)div (so the result is now in emit_reg_reg(A_MOV,S_L,R_EDX,hreg1)
edx), but edx was occupied prior to the division, so else
move the result into a safe place (JM)} Begin
emit_reg_reg(A_MOV,S_L,R_EDX,hreg1) if hreg1 <> R_EDX then
else ungetregister32(hreg1);
Begin hreg1 := R_EDX
if hreg1 <> R_EDX then End;
ungetregister32(hreg1); end;
hreg1 := R_EDX
End;
end;
if popeax then if popeax then
emit_reg(A_POP,S_L,R_EAX); emit_reg(A_POP,S_L,R_EAX);
if popedx then if popedx then
emit_reg(A_POP,S_L,R_EDX); emit_reg(A_POP,S_L,R_EDX);
end; end;
If not(andmod or shrdiv) then If not(shrdiv) then
{andmod and shrdiv only use hreg1 (which is already in usedinproc, { shrdiv only use hreg1 (which is already in usedinproc, }
since it was acquired with getregister), the others also use both { since it was acquired with getregister), the others also }
EAX and EDX (JM)} { use both EAX and EDX (JM) }
Begin Begin
usedinproc:=usedinproc or ($80 shr byte(R_EAX)); usedinproc:=usedinproc or ($80 shr byte(R_EAX));
usedinproc:=usedinproc or ($80 shr byte(R_EDX)); usedinproc:=usedinproc or ($80 shr byte(R_EDX));
@ -312,7 +300,7 @@ implementation
hregister1,hregister2,hregister3, hregister1,hregister2,hregister3,
hregisterhigh,hregisterlow : tregister; hregisterhigh,hregisterlow : tregister;
pushed,popecx : boolean; pushed,popecx : boolean;
op : tasmop; op,opd : tasmop;
l1,l2,l3 : tasmlabel; l1,l2,l3 : tasmlabel;
begin begin
@ -324,8 +312,18 @@ implementation
if pushed then if pushed then
restore(left,is_64bitint(left.resulttype.def)); restore(left,is_64bitint(left.resulttype.def));
{ determine operator }
case nodetype of
shln: op:=A_SHL;
shrn: op:=A_SHR;
end;
if is_64bitint(left.resulttype.def) then if is_64bitint(left.resulttype.def) then
begin begin
if nodetype = shln then
opd:=A_SHLD
else opd:=A_SHRD;
{ load left operator in a register } { load left operator in a register }
if left.location.loc<>LOC_REGISTER then if left.location.loc<>LOC_REGISTER then
begin begin
@ -546,12 +544,6 @@ implementation
else else
hregister1:=left.location.register; hregister1:=left.location.register;
{ determine operator }
if nodetype=shln then
op:=A_SHL
else
op:=A_SHR;
{ shifting by a constant directly coded: } { shifting by a constant directly coded: }
if (right.nodetype=ordconstn) then if (right.nodetype=ordconstn) then
begin begin
@ -871,27 +863,14 @@ implementation
end; end;
LOC_FLAGS : LOC_FLAGS :
location.resflags:=flagsinvers[left.location.resflags]; location.resflags:=flagsinvers[left.location.resflags];
LOC_REGISTER : LOC_REGISTER, LOC_CREGISTER :
begin begin
{location.register:=left.location.register;
emit_const_reg(A_XOR,opsize,1,location.register);}
location.loc:=LOC_FLAGS; location.loc:=LOC_FLAGS;
location.resflags:=F_E; location.resflags:=F_E;
emit_reg_reg(A_TEST,opsize, emit_reg_reg(A_TEST,opsize,
left.location.register,left.location.register); left.location.register,left.location.register);
ungetregister(left.location.register); ungetregister(left.location.register);
end; end;
LOC_CREGISTER :
begin
clear_location(location);
location.loc:=LOC_REGISTER;
location.register:=def_getreg(resulttype.def);
emit_reg_reg(A_MOV,opsize,left.location.register,location.register);
emit_reg_reg(A_TEST,opsize,location.register,location.register);
ungetregister(location.register);
location.loc:=LOC_FLAGS;
location.resflags:=F_E;
end;
LOC_REFERENCE, LOC_REFERENCE,
LOC_MEM : LOC_MEM :
begin begin
@ -1020,7 +999,10 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.20 2001-12-27 15:33:58 jonas Revision 1.21 2001-12-29 15:27:24 jonas
* made 'mod powerof2' -> 'and' optimization processor independent
Revision 1.20 2001/12/27 15:33:58 jonas
* fixed fpuregister counting errors ("merged") * fixed fpuregister counting errors ("merged")
Revision 1.19 2001/12/07 13:03:49 jonas Revision 1.19 2001/12/07 13:03:49 jonas

View File

@ -37,6 +37,7 @@ interface
{ override the following if you want to implement } { override the following if you want to implement }
{ parts explicitely in the code generator (JM) } { parts explicitely in the code generator (JM) }
function first_moddiv64bitint: tnode; virtual; function first_moddiv64bitint: tnode; virtual;
function firstoptimize: tnode; virtual;
end; end;
tmoddivnodeclass = class of tmoddivnode; tmoddivnodeclass = class of tmoddivnode;
@ -195,32 +196,9 @@ implementation
function tmoddivnode.first_moddiv64bitint: tnode; function tmoddivnode.first_moddiv64bitint: tnode;
var var
procname: string[31]; procname: string[31];
power: longint;
begin begin
result := nil; result := nil;
{ divide/mod an unsigned number by a constant which is a power of 2? }
if (right.nodetype = ordconstn) and
not is_signed(resulttype.def) and
ispowerof2(tordconstnode(right).value,power) then
begin
if nodetype = divn then
begin
tordconstnode(right).value := power;
result := cshlshrnode.create(shrn,left,right)
end
else
begin
dec(tordconstnode(right).value);
result := caddnode.create(andn,left,right);
end;
{ left and right are reused }
left := nil;
right := nil;
firstpass(result);
exit;
end;
{ otherwise create a call to a helper } { otherwise create a call to a helper }
if nodetype = divn then if nodetype = divn then
procname := 'fpc_div_' procname := 'fpc_div_'
@ -238,6 +216,65 @@ implementation
firstpass(result); firstpass(result);
end; end;
function tmoddivnode.firstoptimize: tnode;
var
power, shiftval : longint;
newtype: tnodetype;
begin
result := nil;
{ divide/mod a number by a constant which is a power of 2? }
if (cs_optimize in aktglobalswitches) and
(right.nodetype = ordconstn) and
{ ((nodetype = divn) or
not is_signed(resulttype.def)) and}
(not is_signed(resulttype.def)) and
ispowerof2(tordconstnode(right).value,power) then
begin
if nodetype = divn then
begin
(*
if is_signed(resulttype.def) then
begin
if is_64bitint(left.resulttype.def) then
if not (cs_littlesize in aktglobalswitches) then
shiftval := 63
else
{ the shift code is a lot bigger than the call to }
{ the divide helper }
exit
else
shiftval := 31;
{ we reuse left twice, so create once a copy of it }
{ !!! if left is a call is -> call gets executed twice }
left := caddnode.create(addn,left,
caddnode.create(andn,
cshlshrnode.create(sarn,left.getcopy,
cordconstnode.create(shiftval,s32bittype)),
cordconstnode.create(tordconstnode(right).value-1,
right.resulttype)));
newtype := sarn;
end
else
*)
newtype := shrn;
tordconstnode(right).value := power;
result := cshlshrnode.create(newtype,left,right)
end
else
begin
dec(tordconstnode(right).value);
result := caddnode.create(andn,left,right);
end;
{ left and right are reused }
left := nil;
right := nil;
firstpass(result);
exit;
end;
end;
function tmoddivnode.pass_1 : tnode; function tmoddivnode.pass_1 : tnode;
begin begin
result:=nil; result:=nil;
@ -246,6 +283,9 @@ implementation
if codegenerror then if codegenerror then
exit; exit;
result := firstoptimize;
if assigned(result) then
exit;
{ 64bit } { 64bit }
if (left.resulttype.def.deftype=orddef) and (right.resulttype.def.deftype=orddef) and if (left.resulttype.def.deftype=orddef) and (right.resulttype.def.deftype=orddef) and
(is_64bitint(left.resulttype.def) or is_64bitint(right.resulttype.def)) then (is_64bitint(left.resulttype.def) or is_64bitint(right.resulttype.def)) then
@ -640,7 +680,10 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.26 2001-12-27 15:33:58 jonas Revision 1.27 2001-12-29 15:27:24 jonas
* made 'mod powerof2' -> 'and' optimization processor independent
Revision 1.26 2001/12/27 15:33:58 jonas
* fixed fpuregister counting errors ("merged") * fixed fpuregister counting errors ("merged")
Revision 1.25 2001/11/02 22:58:02 peter Revision 1.25 2001/11/02 22:58:02 peter