mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 02:29:19 +02:00
+ Implemented target-independent optimization of signed "mod 2**N" as
"sign:=left sar sizeof(left)*8-1; result:=(((left xor sign)-sign) and 2**N-1) xor sign)-sign;" This solution yields larger code than one suggested by Mantis #21152, however its speed on i386 is approximately the same, and it is also suitable for all operand sizes, all powers of two and all targets. git-svn-id: trunk@27891 -
This commit is contained in:
parent
da91ac9726
commit
c184d9740c
@ -474,14 +474,15 @@ implementation
|
|||||||
result := nil;
|
result := nil;
|
||||||
{ divide/mod a number by a constant which is a power of 2? }
|
{ divide/mod a number by a constant which is a power of 2? }
|
||||||
if (right.nodetype = ordconstn) and
|
if (right.nodetype = ordconstn) and
|
||||||
|
ispowerof2(tordconstnode(right).value,power) and
|
||||||
{$ifdef cpu64bitalu}
|
{$ifdef cpu64bitalu}
|
||||||
{ for 64 bit, we leave the optimization to the cg }
|
{ for 64 bit, we leave the optimization to the cg }
|
||||||
(not is_signed(resultdef)) and
|
(not is_signed(resultdef)) then
|
||||||
{$else cpu64bitalu}
|
{$else cpu64bitalu}
|
||||||
(((nodetype=divn) and is_64bit(resultdef)) or
|
(((nodetype=divn) and is_64bit(resultdef)) or
|
||||||
not is_signed(resultdef)) and
|
(nodetype=modn) or
|
||||||
|
not is_signed(resultdef)) then
|
||||||
{$endif cpu64bitalu}
|
{$endif cpu64bitalu}
|
||||||
ispowerof2(tordconstnode(right).value,power) then
|
|
||||||
begin
|
begin
|
||||||
if nodetype=divn then
|
if nodetype=divn then
|
||||||
begin
|
begin
|
||||||
@ -530,6 +531,49 @@ implementation
|
|||||||
result:=cshlshrnode.create(shrn,left,right)
|
result:=cshlshrnode.create(shrn,left,right)
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
|
else if is_signed(resultdef) then { signed modulus }
|
||||||
|
begin
|
||||||
|
if (cs_opt_size in current_settings.optimizerswitches) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
shiftval:=left.resultdef.size*8-1;
|
||||||
|
dec(tordconstnode(right).value.uvalue);
|
||||||
|
|
||||||
|
result:=internalstatements(statements);
|
||||||
|
temp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,true);
|
||||||
|
resulttemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
|
||||||
|
addstatement(statements,resulttemp);
|
||||||
|
addstatement(statements,temp);
|
||||||
|
addstatement(statements,cassignmentnode.create(ctemprefnode.create(temp),left));
|
||||||
|
{ sign:=sar(left,sizeof(left)*8-1); }
|
||||||
|
addstatement(statements,cassignmentnode.create(ctemprefnode.create(resulttemp),
|
||||||
|
cinlinenode.create(in_sar_x_y,false,
|
||||||
|
ccallparanode.create(cordconstnode.create(shiftval,u8inttype,false),
|
||||||
|
ccallparanode.create(ctemprefnode.create(temp),nil)
|
||||||
|
)
|
||||||
|
)));
|
||||||
|
|
||||||
|
{ result:=((((left xor sign)-sign) and right) xor sign)-sign; }
|
||||||
|
addstatement(statements,cassignmentnode.create(ctemprefnode.create(resulttemp),
|
||||||
|
caddnode.create(subn,
|
||||||
|
caddnode.create(xorn,
|
||||||
|
caddnode.create(andn,
|
||||||
|
right,
|
||||||
|
caddnode.create(subn,
|
||||||
|
caddnode.create(xorn,
|
||||||
|
ctemprefnode.create(resulttemp),
|
||||||
|
ctemprefnode.create(temp)),
|
||||||
|
ctemprefnode.create(resulttemp))
|
||||||
|
),
|
||||||
|
ctemprefnode.create(resulttemp)
|
||||||
|
),
|
||||||
|
ctemprefnode.create(resulttemp))
|
||||||
|
));
|
||||||
|
|
||||||
|
addstatement(statements,ctempdeletenode.create(temp));
|
||||||
|
addstatement(statements,ctempdeletenode.create_normal_temp(resulttemp));
|
||||||
|
addstatement(statements,ctemprefnode.create(resulttemp));
|
||||||
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
dec(tordconstnode(right).value.uvalue);
|
dec(tordconstnode(right).value.uvalue);
|
||||||
|
Loading…
Reference in New Issue
Block a user