mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 13:28:05 +02:00
* Fixed the strength reduction optimization for loops containing 'continue'.
The compiler now cycles properly with -O3 -OoSTRENGTH.
This commit is contained in:
parent
b8befe3d1f
commit
bd4c206472
@ -256,7 +256,17 @@ unit optloop;
|
||||
templist : tfplist;
|
||||
inductionexprs : tfplist;
|
||||
changedforloop,
|
||||
containsnestedforloop : boolean;
|
||||
containsnestedforloop,
|
||||
docalcatend: boolean;
|
||||
|
||||
function checkcontinue(var n:tnode; arg: pointer): foreachnoderesult;
|
||||
begin
|
||||
if n.nodetype=continuen then
|
||||
result:=fen_norecurse_true
|
||||
else
|
||||
result:=fen_false;
|
||||
end;
|
||||
|
||||
|
||||
function is_loop_invariant(loop : tnode;expr : tnode) : boolean;
|
||||
begin
|
||||
@ -330,9 +340,20 @@ unit optloop;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure CheckCalcAtEnd;
|
||||
begin
|
||||
if not assigned(initcode) then
|
||||
docalcatend:=not(foreachnodestatic(tfornode(arg).t2,@checkcontinue,nil)) and
|
||||
not(assigned(tfornode(arg).entrylabel));
|
||||
end;
|
||||
|
||||
|
||||
var
|
||||
tempnode : ttempcreatenode;
|
||||
dummy : longint;
|
||||
nn : tnode;
|
||||
nt : tnodetype;
|
||||
begin
|
||||
result:=fen_false;
|
||||
case n.nodetype of
|
||||
@ -346,9 +367,7 @@ unit optloop;
|
||||
{ plain read of the loop variable? }
|
||||
not(nf_write in taddnode(n).right.flags) and
|
||||
not(nf_modify in taddnode(n).right.flags) and
|
||||
is_loop_invariant(tfornode(arg),taddnode(n).left) and
|
||||
{ for now, we can handle only constant lower borders }
|
||||
is_constnode(tfornode(arg).right) then
|
||||
is_loop_invariant(tfornode(arg),taddnode(n).left) then
|
||||
taddnode(n).swapleftright;
|
||||
|
||||
if (taddnode(n).left.nodetype=loadn) and
|
||||
@ -356,14 +375,19 @@ unit optloop;
|
||||
{ plain read of the loop variable? }
|
||||
not(nf_write in taddnode(n).left.flags) and
|
||||
not(nf_modify in taddnode(n).left.flags) and
|
||||
is_loop_invariant(tfornode(arg),taddnode(n).right) and
|
||||
{ for now, we can handle only constant lower borders }
|
||||
is_constnode(tfornode(arg).right) then
|
||||
is_loop_invariant(tfornode(arg),taddnode(n).right) then
|
||||
begin
|
||||
changedforloop:=true;
|
||||
{ did we use the same expression before already? }
|
||||
if not(findpreviousstrengthreduction) then
|
||||
begin
|
||||
{$ifdef DEBUG_OPTSTRENGTH}
|
||||
writeln('**********************************************************************************');
|
||||
writeln(parser_current_file, ': Found expression for strength reduction (MUL): ');
|
||||
printnode(n);
|
||||
writeln('**********************************************************************************');
|
||||
{$endif DEBUG_OPTSTRENGTH}
|
||||
CheckCalcAtEnd;
|
||||
tempnode:=ctempcreatenode.create(n.resultdef,n.resultdef.size,tt_persistent,
|
||||
tstoreddef(n.resultdef).is_intregable or tstoreddef(n.resultdef).is_fpuregable);
|
||||
|
||||
@ -381,11 +405,23 @@ unit optloop;
|
||||
ccallparanode.create(ctemprefnode.create(tempnode),ccallparanode.create(taddnode(n).right.getcopy,nil))));
|
||||
|
||||
addstatement(initcodestatements,tempnode);
|
||||
nn:=tfornode(arg).right.getcopy;
|
||||
{ If the calculation is not performed at the end
|
||||
it is needed to adjust the starting value }
|
||||
if not docalcatend then
|
||||
begin
|
||||
if lnf_backward in tfornode(arg).loopflags then
|
||||
nt:=addn
|
||||
else
|
||||
nt:=subn;
|
||||
nn:=caddnode.create_internal(nt,nn,
|
||||
cordconstnode.create(1,nn.resultdef,false));
|
||||
end;
|
||||
addstatement(initcodestatements,cassignmentnode.create(ctemprefnode.create(tempnode),
|
||||
caddnode.create(muln,tfornode(arg).right.getcopy,
|
||||
taddnode(n).right.getcopy)
|
||||
)
|
||||
);
|
||||
caddnode.create(muln,nn,
|
||||
taddnode(n).right.getcopy)
|
||||
)
|
||||
);
|
||||
|
||||
{ finally replace the node by a temp. ref }
|
||||
n:=ctemprefnode.create(tempnode);
|
||||
@ -426,10 +462,11 @@ unit optloop;
|
||||
begin
|
||||
{$ifdef DEBUG_OPTSTRENGTH}
|
||||
writeln('**********************************************************************************');
|
||||
writeln('Found expression for strength reduction: ');
|
||||
writeln(parser_current_file,': Found expression for strength reduction (VEC): ');
|
||||
printnode(n);
|
||||
writeln('**********************************************************************************');
|
||||
{$endif DEBUG_OPTSTRENGTH}
|
||||
CheckCalcAtEnd;
|
||||
tempnode:=ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
|
||||
|
||||
templist.Add(tempnode);
|
||||
@ -448,11 +485,22 @@ unit optloop;
|
||||
cordconstnode.create(tcgvecnode(n).get_mul_size,sizeuinttype,false),nil))));
|
||||
|
||||
addstatement(initcodestatements,tempnode);
|
||||
addstatement(initcodestatements,cassignmentnode.create(ctemprefnode.create(tempnode),
|
||||
caddrnode.create(
|
||||
nn:=caddrnode.create(
|
||||
cvecnode.create(tvecnode(n).left.getcopy,tfornode(arg).right.getcopy)
|
||||
)
|
||||
));
|
||||
);
|
||||
{ If the calculation is not performed at the end
|
||||
it is needed to adjust the starting value }
|
||||
if not docalcatend then
|
||||
begin
|
||||
if lnf_backward in tfornode(arg).loopflags then
|
||||
nt:=addn
|
||||
else
|
||||
nt:=subn;
|
||||
nn:=caddnode.create_internal(nt,
|
||||
ctypeconvnode.create_internal(nn,voidpointertype),
|
||||
cordconstnode.create(tcgvecnode(n).get_mul_size,sizeuinttype,false));
|
||||
end;
|
||||
addstatement(initcodestatements,cassignmentnode.create(ctemprefnode.create(tempnode),nn));
|
||||
|
||||
{ finally replace the node by a temp. ref }
|
||||
n:=ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),n.resultdef);
|
||||
@ -489,6 +537,7 @@ unit optloop;
|
||||
initcodestatements:=nil;
|
||||
calccodestatements:=nil;
|
||||
deletecodestatements:=nil;
|
||||
docalcatend:=false;
|
||||
{ find all expressions being candidates for strength reduction
|
||||
and replace them }
|
||||
foreachnodestatic(pm_postprocess,node,@dostrengthreductiontest,node);
|
||||
@ -511,8 +560,11 @@ unit optloop;
|
||||
node:=fornode;
|
||||
|
||||
loopcode:=internalstatements(loopcodestatements);
|
||||
if not docalcatend then
|
||||
addstatement(loopcodestatements,calccode);
|
||||
addstatement(loopcodestatements,tfornode(node).t2);
|
||||
addstatement(loopcodestatements,calccode);
|
||||
if docalcatend then
|
||||
addstatement(loopcodestatements,calccode);
|
||||
tfornode(node).t2:=loopcode;
|
||||
do_firstpass(node);
|
||||
|
||||
@ -556,6 +608,9 @@ unit optloop;
|
||||
|
||||
function OptimizeInductionVariables(node : tnode) : boolean;
|
||||
begin
|
||||
Result:=false;
|
||||
if not(pi_dfaavailable in current_procinfo.flags) then
|
||||
exit;
|
||||
changedforloop:=false;
|
||||
foreachnodestatic(pm_postprocess,node,@OptimizeInductionVariables_iterforloops,nil);
|
||||
Result:=changedforloop;
|
||||
|
Loading…
Reference in New Issue
Block a user