* optimize "dynarr := dynarr + [elem]" to "Insert(elem, dynarr, High(SizeInt))" and "dynarr := [elem] + dynarr" to "Insert(elem, dynarr, 0)" (we need to do this in the typecheck of taddnode as otherwise the array constructor is already converted)

+ added test
* adjusted test for Mantis #30463 as p1 triggers the optimization as well

git-svn-id: trunk@39119 -
This commit is contained in:
svenbarth 2018-05-25 16:03:56 +00:00
parent 85439a0fa0
commit 199b5809a3
4 changed files with 107 additions and 1 deletions

1
.gitattributes vendored
View File

@ -12504,6 +12504,7 @@ tests/test/tarray13.pp svneol=native#text/pascal
tests/test/tarray14.pp svneol=native#text/pascal
tests/test/tarray15.pp svneol=native#text/pascal
tests/test/tarray16.pp svneol=native#text/pascal
tests/test/tarray17.pp svneol=native#text/pascal
tests/test/tarray2.pp svneol=native#text/plain
tests/test/tarray3.pp svneol=native#text/plain
tests/test/tarray4.pp svneol=native#text/plain

View File

@ -1205,6 +1205,72 @@ implementation
inserttypeconv(n,adef);
end;
function maybe_convert_to_insert:tnode;
function element_count(arrconstr: tarrayconstructornode):asizeint;
begin
result:=0;
while assigned(arrconstr) do
begin
if arrconstr.nodetype=arrayconstructorrangen then
internalerror(2018052501);
inc(result);
arrconstr:=tarrayconstructornode(tarrayconstructornode(arrconstr).right);
end;
end;
var
elem : tnode;
para : tcallparanode;
isarrconstrl,
isarrconstrr : boolean;
index : asizeint;
begin
result:=nil;
isarrconstrl:=left.nodetype=arrayconstructorn;
isarrconstrr:=right.nodetype=arrayconstructorn;
if not assigned(aktassignmentnode) or
(aktassignmentnode.right<>self) or
not(
isarrconstrl or
isarrconstrr
) or
not(
left.isequal(aktassignmentnode.left) or
right.isequal(aktassignmentnode.left)
) or
not valid_for_var(aktassignmentnode.left,false) or
(isarrconstrl and (element_count(tarrayconstructornode(left))>1)) or
(isarrconstrr and (element_count(tarrayconstructornode(right))>1)) then
exit;
if isarrconstrl then
begin
index:=0;
elem:=tarrayconstructornode(left).left;
tarrayconstructornode(left).left:=nil;
end
else
begin
index:=high(asizeint);
elem:=tarrayconstructornode(right).left;
tarrayconstructornode(right).left:=nil;
end;
{ we use the fact that insert() caps the index to avoid a copy }
para:=ccallparanode.create(
cordconstnode.create(index,sizesinttype,false),
ccallparanode.create(
aktassignmentnode.left.getcopy,
ccallparanode.create(
elem,nil)));
result:=cinlinenode.create(in_insert_x_y_z,false,para);
include(aktassignmentnode.flags,nf_assign_done_in_right);
end;
begin
result:=nil;
rlow:=0;
@ -2124,6 +2190,9 @@ implementation
{ <dyn. array>+<dyn. array> ? }
else if (nodetype=addn) and (is_dynamic_array(ld) or is_dynamic_array(rd)) then
begin
result:=maybe_convert_to_insert;
if assigned(result) then
exit;
if not(is_dynamic_array(ld)) then
inserttypeconv(left,rd);
if not(is_dynamic_array(rd)) then

36
tests/test/tarray17.pp Normal file
View File

@ -0,0 +1,36 @@
program tarray17;
{$mode objfpc}
{$COperators on}
function CheckArray(aArr, aExpected: array of LongInt): Boolean;
var
i: LongInt;
begin
if Length(aArr) <> Length(aExpected) then
Exit(False);
for i := Low(aArr) to High(aArr) do
if aArr[i] <> aExpected[i] then
Exit(False);
Result := True;
end;
var
a: array of LongInt;
begin
a := [1, 2, 3];
a := a + [4];
if not CheckArray(a, [1, 2, 3, 4]) then
Halt(1);
a := [0] + a;
if not CheckArray(a, [0, 1, 2, 3, 4]) then
Halt(2);
a += [5];
if not CheckArray(a, [0, 1, 2, 3, 4, 5]) then
Halt(3);
Writeln('ok');
end.

View File

@ -39,7 +39,7 @@ procedure p2;
end;
begin
// p1;
p1;
p2;
writeln('ok');
end.