+ 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:
sergei 2014-06-07 22:19:10 +00:00
parent da91ac9726
commit c184d9740c

View File

@ -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);