Răsfoiți Sursa

* continued on node cse

git-svn-id: trunk@14496 -
florian 15 ani în urmă
părinte
comite
701d911f58
3 a modificat fișierele cu 120 adăugiri și 61 ștergeri
  1. 1 0
      .gitattributes
  2. 100 61
      compiler/optcse.pas
  3. 19 0
      tests/test/opt/tcse4.pp

+ 1 - 0
.gitattributes

@@ -8738,6 +8738,7 @@ tests/test/opt/tcmov.pp svneol=native#text/plain
 tests/test/opt/tcse1.pp svneol=native#text/plain
 tests/test/opt/tcse1.pp svneol=native#text/plain
 tests/test/opt/tcse2.pp svneol=native#text/plain
 tests/test/opt/tcse2.pp svneol=native#text/plain
 tests/test/opt/tcse3.pp svneol=native#text/plain
 tests/test/opt/tcse3.pp svneol=native#text/plain
+tests/test/opt/tcse4.pp svneol=native#text/pascal
 tests/test/opt/tdfa1.pp svneol=native#text/pascal
 tests/test/opt/tdfa1.pp svneol=native#text/pascal
 tests/test/opt/tdfa2.pp svneol=native#text/pascal
 tests/test/opt/tdfa2.pp svneol=native#text/pascal
 tests/test/opt/tgotoreg.pp svneol=native#text/plain
 tests/test/opt/tgotoreg.pp svneol=native#text/plain

+ 100 - 61
compiler/optcse.pas

@@ -31,6 +31,22 @@ unit optcse;
     uses
     uses
       node;
       node;
 
 
+
+    {
+      the function is not ready for use yet
+      - when handling short boolean evaluation, the cse's are evaluated before the
+        whole expression, this is wrong and can lead to crashes
+
+      further, it creates non optimal code:
+      - nested cse's in another cse are not recognized
+      - cse's in chained expressions are not recognized: the common subexpression
+        in (a1 and b and c) vs. (a2 and b and c) is not recognized because there is no common
+        subtree b and c
+      - the cse knows nothing about register pressure. In case of high register pressure, cse might
+        have a negative impact
+
+      - it could be done probably in a faster way, currently the complexity is approx. O(n^4)
+    }
     function do_optcse(var rootnode : tnode) : tnode;
     function do_optcse(var rootnode : tnode) : tnode;
 
 
   implementation
   implementation
@@ -48,7 +64,7 @@ unit optcse;
       cseinvariant : set of tnodetype = [loadn,addn,muln,subn,divn,slashn,modn,andn,orn,xorn,notn,vecn,
       cseinvariant : set of tnodetype = [loadn,addn,muln,subn,divn,slashn,modn,andn,orn,xorn,notn,vecn,
         derefn,equaln,unequaln,ltn,gtn,lten,gten,typeconvn,subscriptn,
         derefn,equaln,unequaln,ltn,gtn,lten,gten,typeconvn,subscriptn,
         inn,symdifn,shrn,shln,ordconstn,realconstn,unaryminusn,pointerconstn,stringconstn,setconstn,
         inn,symdifn,shrn,shln,ordconstn,realconstn,unaryminusn,pointerconstn,stringconstn,setconstn,
-        isn,asn,starstarn,nothingn];
+        isn,asn,starstarn,nothingn,temprefn];
 
 
     function searchsubdomain(var n:tnode; arg: pointer) : foreachnoderesult;
     function searchsubdomain(var n:tnode; arg: pointer) : foreachnoderesult;
       begin
       begin
@@ -89,6 +105,7 @@ unit optcse;
 
 
     function searchcsedomain(var n: tnode; arg: pointer) : foreachnoderesult;
     function searchcsedomain(var n: tnode; arg: pointer) : foreachnoderesult;
       var
       var
+        restart : boolean;
         csedomain : boolean;
         csedomain : boolean;
         lists : tlists;
         lists : tlists;
         templist : tfplist;
         templist : tfplist;
@@ -114,73 +131,102 @@ unit optcse;
                 printnode(output,n);
                 printnode(output,n);
                 writeln('Complexity: ',node_complexity(n));
                 writeln('Complexity: ',node_complexity(n));
 {$endif csedebug}
 {$endif csedebug}
+                repeat
+                  lists.nodelist:=tfplist.create;
+                  lists.locationlist:=tfplist.create;
+                  foreachnodestatic(pm_postprocess,n,@collectnodes,@lists);
+
+                  templist:=tfplist.create;
+                  templist.count:=lists.nodelist.count;
 
 
-                lists.nodelist:=tfplist.create;
-                lists.locationlist:=tfplist.create;
-                foreachnodestatic(pm_postprocess,n,@collectnodes,@lists);
+                  restart:=false;
 
 
-                templist:=tfplist.create;
-                templist.count:=lists.nodelist.count;
+                  { this is poorly coded, just comparing every node with all other nodes }
 
 
-                { this is poorly coded, just comparing every node with all other nodes }
-                for i:=0 to lists.nodelist.count-1 do
-                  for j:=i+1 to lists.nodelist.count-1 do
+                  { the nodes are sorted by size so we'll find the largest matching tree
+                    first }
+                  for i:=0 to lists.nodelist.count-1 do
                     begin
                     begin
-                      if not(tnode(lists.nodelist[i]).nodetype in [tempcreaten,temprefn]) and
-                        tnode(lists.nodelist[i]).isequal(tnode(lists.nodelist[j])) then
+                      for j:=lists.nodelist.count-1 downto i+1 do
                         begin
                         begin
-                          if not(assigned(statements)) then
+                        {
+                          writeln(i);
+                          writeln(j);
+                          writeln(dword(tnode(lists.nodelist[i]).nodetype));
+                          writeln(dword(tnode(lists.nodelist[j]).nodetype)); }
+                          if not(tnode(lists.nodelist[i]).nodetype in [tempcreaten,temprefn]) and
+                            not(tnode(lists.nodelist[j]).nodetype in [tempcreaten,temprefn]) and
+                            tnode(lists.nodelist[i]).isequal(tnode(lists.nodelist[j])) then
                             begin
                             begin
-                              nodes:=internalstatements(statements);
-                              addstatement(statements,internalstatements(creates));
-                            end;
+                              if not(assigned(statements)) then
+                                begin
+                                  nodes:=internalstatements(statements);
+                                  addstatement(statements,internalstatements(creates));
+                                end;
 {$if defined(csedebug) or defined(csestats)}
 {$if defined(csedebug) or defined(csestats)}
-                          writeln('    ====     ');
-                          printnode(output,tnode(lists.nodelist[i]));
-                          writeln('    equals   ');
-                          printnode(output,tnode(lists.nodelist[j]));
-                          writeln('    ====     ');
+                              writeln('    ====     ');
+                              printnode(output,tnode(lists.nodelist[i]));
+                              writeln('    equals   ');
+                              printnode(output,tnode(lists.nodelist[j]));
+                              writeln('    ====     ');
 {$endif defined(csedebug) or defined(csestats)}
 {$endif defined(csedebug) or defined(csestats)}
 
 
-                          def:=tstoreddef(tnode(lists.nodelist[i]).resultdef);
-                          if assigned(def) then
-                            begin
-                              if assigned(templist[i])  then
-                                begin
-                                  templist[j]:=templist[i];
-                                  pnode(lists.locationlist[j])^.free;
-                                  pnode(lists.locationlist[j])^:=ctemprefnode.create(ttempcreatenode(templist[j]));
-                                  do_firstpass(pnode(lists.locationlist[j])^);
-                                end
-                              else
+                              def:=tstoreddef(tnode(lists.nodelist[i]).resultdef);
+                              if assigned(def) then
                                 begin
                                 begin
-                                  templist[i]:=ctempcreatenode.create(def,def.size,tt_persistent,
-                                    def.is_intregable or def.is_fpuregable);
-                                  addstatement(creates,tnode(templist[i]));
-
-                                  { properties can't be passed by "var" }
-                                  hp:=ttempcreatenode(templist[i]);
-                                  do_firstpass(tnode(hp));
-
-                                  addstatement(statements,cassignmentnode.create(ctemprefnode.create(ttempcreatenode(templist[i])),
-                                    tnode(lists.nodelist[i])));
-                                  pnode(lists.locationlist[i])^:=ctemprefnode.create(ttempcreatenode(templist[i]));
-                                  do_firstpass(pnode(lists.locationlist[i])^);
-
-                                  templist[j]:=templist[i];
-
-                                  pnode(lists.locationlist[j])^.free;
-                                  pnode(lists.locationlist[j])^:=ctemprefnode.create(ttempcreatenode(templist[j]));
-                                  do_firstpass(pnode(lists.locationlist[j])^);
+                                  restart:=true;
+                                  if assigned(templist[i])  then
+                                    begin
+                                      templist[j]:=templist[i];
+                                      pnode(lists.locationlist[j])^.free;
+                                      pnode(lists.locationlist[j])^:=ctemprefnode.create(ttempcreatenode(templist[j]));
+                                      do_firstpass(pnode(lists.locationlist[j])^);
+                                      lists.nodelist[j]:=pnode(lists.locationlist[j])^;
+                                    end
+                                  else
+                                    begin
+                                      templist[i]:=ctempcreatenode.create(def,def.size,tt_persistent,
+                                        def.is_intregable or def.is_fpuregable);
+                                      addstatement(creates,tnode(templist[i]));
+
+                                      { properties can't be passed by "var" }
+                                      hp:=ttempcreatenode(templist[i]);
+                                      do_firstpass(tnode(hp));
+
+                                      addstatement(statements,cassignmentnode.create(ctemprefnode.create(ttempcreatenode(templist[i])),
+                                        tnode(lists.nodelist[i]).getcopy));
+                                      pnode(lists.locationlist[i])^:=ctemprefnode.create(ttempcreatenode(templist[i]));
+                                      do_firstpass(pnode(lists.locationlist[i])^);
+
+                                      templist[j]:=templist[i];
+
+                                      pnode(lists.locationlist[j])^.free;
+                                      pnode(lists.locationlist[j])^:=ctemprefnode.create(ttempcreatenode(templist[j]));
+                                      do_firstpass(pnode(lists.locationlist[j])^);
+                                      lists.nodelist[j]:=pnode(lists.locationlist[j])^;
 {$ifdef csedebug}
 {$ifdef csedebug}
-                                  printnode(output,statements);
+                                      printnode(output,statements);
 {$endif csedebug}
 {$endif csedebug}
-                                end;
-                              end
-                            else
-                              internalerror(2007091701);
+                                    end;
+                                  end
+                                else
+                                  internalerror(2007091701);
+                            end;
                         end;
                         end;
+                      { if a node in a cse domain has been replaced, we've to restart
+                        searching else we could find nested trees of the replaced node
+                      }
+                      if restart then
+                        break;
                     end;
                     end;
+{$ifdef csedebug}
+                  writeln('nodes: ',lists.nodelist.count);
+                  writeln('==========================================');
+{$endif csedebug}
+                  lists.nodelist.free;
+                  lists.locationlist.free;
+                  templist.free;
+                until not(restart);
                 if assigned(statements) then
                 if assigned(statements) then
                   begin
                   begin
                     addstatement(statements,n);
                     addstatement(statements,n);
@@ -190,13 +236,6 @@ unit optcse;
                     printnode(output,nodes);
                     printnode(output,nodes);
 {$endif csedebug}
 {$endif csedebug}
                   end;
                   end;
-{$ifdef csedebug}
-                writeln('nodes: ',lists.nodelist.count);
-                writeln('==========================================');
-{$endif csedebug}
-                lists.nodelist.free;
-                lists.locationlist.free;
-                templist.free;
               end
               end
           end;
           end;
       end;
       end;

+ 19 - 0
tests/test/opt/tcse4.pp

@@ -0,0 +1,19 @@
+{$mode objfpc}
+type
+  tr = record
+    data1 : longint;
+    data2 : longint;
+  end;
+
+  tc = class
+    r : ^tr;
+    function f : longint;
+  end;
+
+function tc.f : longint;
+  begin
+    result:=r^.data1+r^.data2*r^.data1;
+  end;
+
+begin
+end.