mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-25 01:51:41 +02:00
+ 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:
parent
edb86ee95f
commit
db196d76c2
@ -56,10 +56,10 @@ interface
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
tcgvecnode = class(tvecnode)
|
tcgvecnode = class(tvecnode)
|
||||||
|
function get_mul_size : aint;
|
||||||
private
|
private
|
||||||
procedure rangecheck_array;
|
procedure rangecheck_array;
|
||||||
protected
|
protected
|
||||||
function get_mul_size : aint;
|
|
||||||
{# This routine is used to calculate the address of the reference.
|
{# This routine is used to calculate the address of the reference.
|
||||||
On entry reg contains the index in the array,
|
On entry reg contains the index in the array,
|
||||||
and l contains the size of each element in the array.
|
and l contains the size of each element in the array.
|
||||||
|
|||||||
@ -791,6 +791,8 @@ implementation
|
|||||||
typecheckpass(right);
|
typecheckpass(right);
|
||||||
typecheckpass(t1);
|
typecheckpass(t1);
|
||||||
|
|
||||||
|
set_varstate(left,vs_written,[]);
|
||||||
|
|
||||||
{ loop unrolling }
|
{ loop unrolling }
|
||||||
if cs_opt_loopunroll in current_settings.optimizerswitches then
|
if cs_opt_loopunroll in current_settings.optimizerswitches then
|
||||||
begin
|
begin
|
||||||
|
|||||||
@ -449,7 +449,7 @@ implementation
|
|||||||
CGMessage(type_e_variable_id_expected);
|
CGMessage(type_e_variable_id_expected);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (mark_read_written) then
|
if mark_read_written then
|
||||||
begin
|
begin
|
||||||
{ This is actually only "read", but treat it nevertheless as }
|
{ This is actually only "read", but treat it nevertheless as }
|
||||||
{ modified due to the possible use of pointers }
|
{ modified due to the possible use of pointers }
|
||||||
|
|||||||
@ -34,12 +34,14 @@ unit optloop;
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
cclasses,
|
cutils,cclasses,
|
||||||
globtype,globals,constexp,
|
globtype,globals,constexp,
|
||||||
symdef,symsym,
|
symdef,symsym,
|
||||||
|
defutil,
|
||||||
cpuinfo,
|
cpuinfo,
|
||||||
nutils,
|
nutils,
|
||||||
nadd,nbas,nflw,ncon,ninl,ncal,nld,
|
nadd,nbas,nflw,ncon,ninl,ncal,nld,nmem,ncnv,
|
||||||
|
ncgmem,
|
||||||
pass_1,
|
pass_1,
|
||||||
optbase,optutils,
|
optbase,optutils,
|
||||||
procinfo;
|
procinfo;
|
||||||
@ -205,6 +207,13 @@ unit optloop;
|
|||||||
{ no definition in the loop? }
|
{ no definition in the loop? }
|
||||||
not(DFASetIn(loop.optinfo^.defsum,expr.optinfo^.index));
|
not(DFASetIn(loop.optinfo^.defsum,expr.optinfo^.index));
|
||||||
end;
|
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;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -223,7 +232,15 @@ unit optloop;
|
|||||||
if tnode(inductionexprs[i]).isequal(n) then
|
if tnode(inductionexprs[i]).isequal(n) then
|
||||||
begin
|
begin
|
||||||
n.free;
|
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;
|
result:=true;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@ -243,6 +260,7 @@ unit optloop;
|
|||||||
|
|
||||||
var
|
var
|
||||||
tempnode : ttempcreatenode;
|
tempnode : ttempcreatenode;
|
||||||
|
dummy : longint;
|
||||||
begin
|
begin
|
||||||
result:=fen_false;
|
result:=fen_false;
|
||||||
case n.nodetype of
|
case n.nodetype of
|
||||||
@ -289,6 +307,7 @@ unit optloop;
|
|||||||
addstatement(calccodestatements,
|
addstatement(calccodestatements,
|
||||||
geninlinenode(in_inc_x,false,
|
geninlinenode(in_inc_x,false,
|
||||||
ccallparanode.create(ctemprefnode.create(tempnode),ccallparanode.create(taddnode(n).right.getcopy,nil))));
|
ccallparanode.create(ctemprefnode.create(tempnode),ccallparanode.create(taddnode(n).right.getcopy,nil))));
|
||||||
|
|
||||||
addstatement(initcodestatements,tempnode);
|
addstatement(initcodestatements,tempnode);
|
||||||
addstatement(initcodestatements,cassignmentnode.create(ctemprefnode.create(tempnode),
|
addstatement(initcodestatements,cassignmentnode.create(ctemprefnode.create(tempnode),
|
||||||
caddnode.create(muln,
|
caddnode.create(muln,
|
||||||
@ -308,6 +327,66 @@ unit optloop;
|
|||||||
result:=fen_norecurse_false;
|
result:=fen_norecurse_false;
|
||||||
end;
|
end;
|
||||||
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;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
@ -211,7 +211,7 @@ unit optutils;
|
|||||||
Breakstack.Add(succ);
|
Breakstack.Add(succ);
|
||||||
Continuestack.Add(p);
|
Continuestack.Add(p);
|
||||||
result:=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);
|
DoSet(twhilerepeatnode(p).right,p);
|
||||||
p.successor:=succ;
|
p.successor:=succ;
|
||||||
Breakstack.Delete(Breakstack.Count-1);
|
Breakstack.Delete(Breakstack.Count-1);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user