+ strength reduction for array accesses inside for loops

* export get_mul_size so we can use it for strength reduction
* ensure loop counter is marked as being written
* typos fixed

git-svn-id: trunk@11825 -
This commit is contained in:
florian 2008-09-26 18:23:31 +00:00
parent edb86ee95f
commit db196d76c2
5 changed files with 87 additions and 6 deletions

View File

@ -56,10 +56,10 @@ interface
end;
tcgvecnode = class(tvecnode)
function get_mul_size : aint;
private
procedure rangecheck_array;
protected
function get_mul_size : aint;
{# This routine is used to calculate the address of the reference.
On entry reg contains the index in the array,
and l contains the size of each element in the array.

View File

@ -791,6 +791,8 @@ implementation
typecheckpass(right);
typecheckpass(t1);
set_varstate(left,vs_written,[]);
{ loop unrolling }
if cs_opt_loopunroll in current_settings.optimizerswitches then
begin

View File

@ -449,7 +449,7 @@ implementation
CGMessage(type_e_variable_id_expected);
end;
if (mark_read_written) then
if mark_read_written then
begin
{ This is actually only "read", but treat it nevertheless as }
{ modified due to the possible use of pointers }

View File

@ -34,12 +34,14 @@ unit optloop;
implementation
uses
cclasses,
cutils,cclasses,
globtype,globals,constexp,
symdef,symsym,
defutil,
cpuinfo,
nutils,
nadd,nbas,nflw,ncon,ninl,ncal,nld,
nadd,nbas,nflw,ncon,ninl,ncal,nld,nmem,ncnv,
ncgmem,
pass_1,
optbase,optutils,
procinfo;
@ -205,6 +207,13 @@ unit optloop;
{ no definition in the loop? }
not(DFASetIn(loop.optinfo^.defsum,expr.optinfo^.index));
end;
vecn:
begin
result:=((tvecnode(expr).left.nodetype=loadn) or is_loop_invariant(loop,tvecnode(expr).left)) and
is_loop_invariant(loop,tvecnode(expr).right);
end;
typeconvn:
result:=is_loop_invariant(loop,ttypeconvnode(expr).left);
end;
end;
@ -223,7 +232,15 @@ unit optloop;
if tnode(inductionexprs[i]).isequal(n) then
begin
n.free;
n:=ctemprefnode.create(ttempcreatenode(templist[i]));
case n.nodetype of
muln:
n:=ctemprefnode.create(ttempcreatenode(templist[i]));
vecn:
n:=ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(
ttempcreatenode(templist[i]))),n.resultdef);
else
internalerror(200809211);
end;
result:=true;
exit;
end;
@ -243,6 +260,7 @@ unit optloop;
var
tempnode : ttempcreatenode;
dummy : longint;
begin
result:=fen_false;
case n.nodetype of
@ -289,6 +307,7 @@ unit optloop;
addstatement(calccodestatements,
geninlinenode(in_inc_x,false,
ccallparanode.create(ctemprefnode.create(tempnode),ccallparanode.create(taddnode(n).right.getcopy,nil))));
addstatement(initcodestatements,tempnode);
addstatement(initcodestatements,cassignmentnode.create(ctemprefnode.create(tempnode),
caddnode.create(muln,
@ -308,6 +327,66 @@ unit optloop;
result:=fen_norecurse_false;
end;
end;
vecn:
begin
{ is the index the counter variable? }
if not(is_special_array(tvecnode(n).left.resultdef)) and
(tvecnode(n).right.isequal(tfornode(arg).left) or
{ fpc usually creates a type cast to access an array }
((tvecnode(n).right.nodetype=typeconvn) and
ttypeconvnode(tvecnode(n).right).left.isequal(tfornode(arg).left)
)
) and
{ plain read of the loop variable? }
not(nf_write in tvecnode(n).right.flags) and
not(nf_modify in tvecnode(n).right.flags) and
{ direct array access? }
((tvecnode(n).left.nodetype=loadn) or
{ ... or loop invariant expression? }
is_loop_invariant(tfornode(arg),tvecnode(n).left)) and
{ removing the multiplication is only worth the
effort if it's not a simple shift }
not(ispowerof2(tcgvecnode(n).get_mul_size,dummy)) then
begin
changedforloop:=true;
{ did we use the same expression before already? }
if not(findpreviousstrengthreduction) then
begin
tempnode:=ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
templist.Add(tempnode);
inductionexprs.Add(n);
CreateNodes;
if lnf_backward in tfornode(arg).loopflags then
addstatement(calccodestatements,
geninlinenode(in_dec_x,false,
ccallparanode.create(ctemprefnode.create(tempnode),ccallparanode.create(
cordconstnode.create(tcgvecnode(n).get_mul_size,tfornode(arg).right.resultdef,false),nil))))
else
addstatement(calccodestatements,
geninlinenode(in_inc_x,false,
ccallparanode.create(ctemprefnode.create(tempnode),ccallparanode.create(
cordconstnode.create(tcgvecnode(n).get_mul_size,tfornode(arg).right.resultdef,false),nil))));
addstatement(initcodestatements,tempnode);
addstatement(initcodestatements,cassignmentnode.create(ctemprefnode.create(tempnode),
caddrnode.create(
cvecnode.create(tvecnode(n).left.getcopy,tfornode(arg).right.getcopy)
)
));
{ finally replace the node by a temp. ref }
n:=ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),n.resultdef);
{ ... and add a temp. release node }
addstatement(deletecodestatements,ctempdeletenode.create(tempnode));
end;
{ set types }
do_firstpass(n);
result:=fen_norecurse_false;
end;
end;
end;
end;

View File

@ -211,7 +211,7 @@ unit optutils;
Breakstack.Add(succ);
Continuestack.Add(p);
result:=p;
{ the successor of the last node of the for body is the while node itself }
{ the successor of the last node of the while body is the while node itself }
DoSet(twhilerepeatnode(p).right,p);
p.successor:=succ;
Breakstack.Delete(Breakstack.Count-1);