Jelajahi Sumber

* 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 -

svenbarth 7 tahun lalu
induk
melakukan
199b5809a3
4 mengubah file dengan 107 tambahan dan 1 penghapusan
  1. 1 0
      .gitattributes
  2. 69 0
      compiler/nadd.pas
  3. 36 0
      tests/test/tarray17.pp
  4. 1 1
      tests/webtbs/tw30463.pp

+ 1 - 0
.gitattributes

@@ -12504,6 +12504,7 @@ tests/test/tarray13.pp svneol=native#text/pascal
 tests/test/tarray14.pp svneol=native#text/pascal
 tests/test/tarray14.pp svneol=native#text/pascal
 tests/test/tarray15.pp svneol=native#text/pascal
 tests/test/tarray15.pp svneol=native#text/pascal
 tests/test/tarray16.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/tarray2.pp svneol=native#text/plain
 tests/test/tarray3.pp svneol=native#text/plain
 tests/test/tarray3.pp svneol=native#text/plain
 tests/test/tarray4.pp svneol=native#text/plain
 tests/test/tarray4.pp svneol=native#text/plain

+ 69 - 0
compiler/nadd.pas

@@ -1205,6 +1205,72 @@ implementation
               inserttypeconv(n,adef);
               inserttypeconv(n,adef);
           end;
           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
       begin
          result:=nil;
          result:=nil;
          rlow:=0;
          rlow:=0;
@@ -2124,6 +2190,9 @@ implementation
          { <dyn. array>+<dyn. array> ? }
          { <dyn. array>+<dyn. array> ? }
          else if (nodetype=addn) and (is_dynamic_array(ld) or is_dynamic_array(rd)) then
          else if (nodetype=addn) and (is_dynamic_array(ld) or is_dynamic_array(rd)) then
            begin
            begin
+              result:=maybe_convert_to_insert;
+              if assigned(result) then
+                exit;
               if not(is_dynamic_array(ld)) then
               if not(is_dynamic_array(ld)) then
                 inserttypeconv(left,rd);
                 inserttypeconv(left,rd);
               if not(is_dynamic_array(rd)) then
               if not(is_dynamic_array(rd)) then

+ 36 - 0
tests/test/tarray17.pp

@@ -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.

+ 1 - 1
tests/webtbs/tw30463.pp

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