mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-17 04:59:33 +02:00
+ 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:
parent
b1feaa9458
commit
aca9727418
compiler
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user