mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-17 13:39:36 +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;
|
||||
{ divide/mod a number by a constant which is a power of 2? }
|
||||
if (right.nodetype = ordconstn) and
|
||||
ispowerof2(tordconstnode(right).value,power) and
|
||||
{$ifdef cpu64bitalu}
|
||||
{ for 64 bit, we leave the optimization to the cg }
|
||||
(not is_signed(resultdef)) and
|
||||
(not is_signed(resultdef)) then
|
||||
{$else cpu64bitalu}
|
||||
(((nodetype=divn) and is_64bit(resultdef)) or
|
||||
not is_signed(resultdef)) and
|
||||
(nodetype=modn) or
|
||||
not is_signed(resultdef)) then
|
||||
{$endif cpu64bitalu}
|
||||
ispowerof2(tordconstnode(right).value,power) then
|
||||
begin
|
||||
if nodetype=divn then
|
||||
begin
|
||||
@ -530,6 +531,49 @@ implementation
|
||||
result:=cshlshrnode.create(shrn,left,right)
|
||||
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
|
||||
begin
|
||||
dec(tordconstnode(right).value.uvalue);
|
||||
|
Loading…
Reference in New Issue
Block a user