+ OptimizeForLoop: convert for-loops into zero-based backward for-loops if possible, for most architectures, this results in simpler code

git-svn-id: trunk@44287 -
This commit is contained in:
florian 2020-03-08 14:30:59 +00:00
parent b1feaa9458
commit aca9727418
3 changed files with 90 additions and 4 deletions

View File

@ -46,7 +46,10 @@ interface
{ Should the value of the loop variable on exit be correct. }
lnf_dont_mind_loopvar_on_exit,
{ Loop simplify flag }
lnf_simplify_processing);
lnf_simplify_processing,
{ set if in a for loop the counter is not used, so an easier exit check
can be carried out }
lnf_counter_not_used);
tloopflags = set of tloopflag;
const
@ -1957,7 +1960,12 @@ implementation
end
else
begin
addstatement(ifstatements,cwhilerepeatnode.create(caddnode.create_internal(cond,left.getcopy,t1.getcopy),loopblock,false,true));
{ is a simple comparision for equality sufficient? }
if do_loopvar_at_end and (lnf_backward in loopflags) and (lnf_counter_not_used in loopflags) then
addstatement(ifstatements,cwhilerepeatnode.create(caddnode.create_internal(equaln,left.getcopy,
caddnode.create_internal(subn,t1.getcopy,cordconstnode.create(1,t1.resultdef,false))),loopblock,false,true))
else
addstatement(ifstatements,cwhilerepeatnode.create(caddnode.create_internal(cond,left.getcopy,t1.getcopy),loopblock,false,true));
addstatement(statements,ifblock);
end;
current_filepos:=storefilepos;

View File

@ -24,6 +24,7 @@ unit optloop;
{$i fpcdefs.inc}
{ $define DEBUG_OPTSTRENGTH}
{ $define DEBUG_OPTFORLOOP}
interface
@ -32,6 +33,7 @@ unit optloop;
function unroll_loop(node : tnode) : tnode;
function OptimizeInductionVariables(node : tnode) : boolean;
function OptimizeForLoop(var node : tnode) : boolean;
implementation
@ -523,7 +525,7 @@ unit optloop;
end;
function iterforloops(var n: tnode; arg: pointer): foreachnoderesult;
function OptimizeInductionVariables_iterforloops(var n: tnode; arg: pointer): foreachnoderesult;
var
hp : tnode;
begin
@ -553,7 +555,74 @@ unit optloop;
function OptimizeInductionVariables(node : tnode) : boolean;
begin
changedforloop:=false;
foreachnodestatic(pm_postprocess,node,@iterforloops,nil);
foreachnodestatic(pm_postprocess,node,@OptimizeInductionVariables_iterforloops,nil);
Result:=changedforloop;
end;
function OptimizeForLoop_iterforloops(var n: tnode; arg: pointer): foreachnoderesult;
var
hp : tnode;
begin
Result:=fen_false;
if (n.nodetype=forn) and
not(lnf_backward in tfornode(n).loopflags) and
(lnf_dont_mind_loopvar_on_exit in tfornode(n).loopflags) and
is_constintnode(tfornode(n).right) and
{ this is not strictly necessary, but we do it for now }
is_constnode(tfornode(n).t1) and
(([cs_check_overflow,cs_check_range]*n.localswitches)=[]) and
(([cs_check_overflow,cs_check_range]*tfornode(n).left.localswitches)=[]) and
((tfornode(n).left.nodetype=loadn) and (tloadnode(tfornode(n).left).symtableentry is tabstractvarsym) and
not(tabstractvarsym(tloadnode(tfornode(n).left).symtableentry).addr_taken) and
not(tabstractvarsym(tloadnode(tfornode(n).left).symtableentry).different_scope)) then
begin
{ do we have DFA available? }
if pi_dfaavailable in current_procinfo.flags then
begin
CalcUseSum(tfornode(n).t2);
CalcDefSum(tfornode(n).t2);
end
else
Internalerror(2017122801);
if not(assigned(tfornode(n).left.optinfo)) then
exit;
if not(DFASetIn(tfornode(n).t2.optinfo^.usesum,tfornode(n).left.optinfo^.index)) and
not(DFASetIn(tfornode(n).t2.optinfo^.defsum,tfornode(n).left.optinfo^.index)) then
begin
{ convert the loop from i:=a to b into i:=b-a+1 to 1 as this simplifies the
abort condition }
{$ifdef DEBUG_OPTFORLOOP}
writeln('**********************************************************************************');
writeln('Found loop for reverting: ');
printnode(n);
writeln('**********************************************************************************');
{$endif DEBUG_OPTFORLOOP}
include(tfornode(n).loopflags,lnf_backward);
tfornode(n).right:=caddnode.create_internal(addn,caddnode.create_internal(subn,tfornode(n).t1,tfornode(n).right),
cordconstnode.create(1,tfornode(n).left.resultdef,false));
tfornode(n).t1:=cordconstnode.create(1,tfornode(n).left.resultdef,false);
include(tfornode(n).loopflags,lnf_counter_not_used);
exclude(n.flags,nf_pass1_done);
do_firstpass(n);
{$ifdef DEBUG_OPTFORLOOP}
writeln('Loop reverted: ');
printnode(n);
writeln('**********************************************************************************');
{$endif DEBUG_OPTFORLOOP}
changedforloop:=true;
end;
end;
end;
function OptimizeForLoop(var node : tnode) : boolean;
begin
Result:=false;
if not(pi_dfaavailable in current_procinfo.flags) then
exit;
changedforloop:=false;
foreachnodestatic(pm_postprocess,node,@OptimizeForLoop_iterforloops,nil);
Result:=changedforloop;
end;

View File

@ -1179,6 +1179,15 @@ implementation
RedoDFA:=OptimizeInductionVariables(code);
end;
if RedoDFA then
begin
dfabuilder.resetdfainfo(code);
dfabuilder.createdfainfo(code);
include(flags,pi_dfaavailable);
end;
RedoDFA:=OptimizeForLoop(code);
RedoDFA:=ConvertForLoops(code) or RedoDFA;
if RedoDFA then