Преглед на файлове

+ first node cse implementation

git-svn-id: branches/fpc_2_3@6444 -
florian преди 18 години
родител
ревизия
0c8844463c
променени са 5 файла, в които са добавени 164 реда и са изтрити 8 реда
  1. 2 2
      compiler/globtype.pas
  2. 0 1
      compiler/nopt.pas
  3. 0 1
      compiler/nutils.pas
  4. 156 2
      compiler/optcse.pas
  5. 6 2
      compiler/psub.pas

+ 2 - 2
compiler/globtype.pas

@@ -153,7 +153,7 @@ interface
        toptimizerswitch = (cs_opt_none,
          cs_opt_level1,cs_opt_level2,cs_opt_level3,
          cs_opt_regvar,cs_opt_uncertain,cs_opt_size,cs_opt_stackframe,
-         cs_opt_peephole,cs_opt_asmcse,cs_opt_loopunroll,cs_opt_tailrecursion
+         cs_opt_peephole,cs_opt_asmcse,cs_opt_loopunroll,cs_opt_tailrecursion,cs_opt_nodecse
        );
        toptimizerswitches = set of toptimizerswitch;
 
@@ -161,7 +161,7 @@ interface
        OptimizerSwitchStr : array[toptimizerswitch] of string[10] = ('',
          'LEVEL1','LEVEL2','LEVEL3',
          'REGVAR','UNCERTAIN','SIZE','STACKFRAME',
-         'PEEPHOLE','ASMCSE','LOOPUNROLL','TAILREC'
+         'PEEPHOLE','ASMCSE','LOOPUNROLL','TAILREC','CSE'
        );
 
        { switches being applied to all CPUs at the given level }

+ 0 - 1
compiler/nopt.pas

@@ -359,7 +359,6 @@ begin
     end;
 end;
 
-
 begin
   caddsstringcharoptnode := taddsstringcharoptnode;
   caddsstringcsstringoptnode := taddsstringcsstringoptnode;

+ 0 - 1
compiler/nutils.pas

@@ -47,7 +47,6 @@ interface
 
     tforeachprocmethod = (pm_preprocess,pm_postprocess);
 
-
     foreachnodefunction = function(var n: tnode; arg: pointer): foreachnoderesult of object;
     staticforeachnodefunction = function(var n: tnode; arg: pointer): foreachnoderesult;
 

+ 156 - 2
compiler/optcse.pas

@@ -23,14 +23,167 @@ unit optcse;
 
 {$i fpcdefs.inc}
 
+{ $define csedebug}
+
   interface
 
-    procedure docse(rootnode : tnode);
+    uses
+      node;
+
+    function do_optcse(var rootnode : tnode) : tnode;
 
   implementation
 
-    procedure docse(rootnode : tnode);
+    uses
+      globtype,
+      cclasses,
+      nutils,
+      nbas,nld,
+      pass_1,
+      symtype,symdef;
+
+    const
+      cseinvariant : set of tnodetype = [loadn,addn,muln,subn,divn,andn,orn,xorn,notn,vecn,derefn];
+
+    function searchsubdomain(var n:tnode; arg: pointer) : foreachnoderesult;
+      begin
+        if not(n.nodetype in cseinvariant) then
+          begin
+            pboolean(arg)^:=false;
+            result:=fen_norecurse_true;
+          end
+        else
+          result:=fen_true;
+      end;
+
+    type
+      tlists = record
+        nodelist : tfplist;
+        locationlist : tfplist;
+      end;
+
+      plists = ^tlists;
+      pnode = ^tnode;
+
+
+    function collectnodes(var n:tnode; arg: pointer) : foreachnoderesult;
+      begin
+        { node worth to add? }
+        if node_complexity(n)>1 then
+          begin
+            plists(arg)^.nodelist.Add(n);
+            plists(arg)^.locationlist.Add(@n);
+            result:=fen_false;
+          end
+        else
+          result:=fen_norecurse_false;
+      end;
+
+
+    function searchcsedomain(var n: tnode; arg: pointer) : foreachnoderesult;
+      var
+        csedomain : boolean;
+        lists : tlists;
+        templist : tfplist;
+        i,j : aint;
+        def : tstoreddef;
+        nodes : tblocknode;
+        statements : tstatementnode;
+      begin
+        result:=fen_false;
+        if n.nodetype in cseinvariant then
+          begin
+            csedomain:=true;
+            foreachnodestatic(pm_postprocess,n,@searchsubdomain,@csedomain);
+            { found a cse domain }
+            if csedomain then
+              begin
+                statements:=nil;
+                result:=fen_norecurse_true;
+{$ifdef csedebug}
+                writeln('============ cse domain ==================');
+                printnode(output,n);
+{$endif csedebug}
+
+                lists.nodelist:=tfplist.create;
+                lists.locationlist:=tfplist.create;
+                foreachnodestatic(pm_postprocess,n,@collectnodes,@lists);
+
+                templist:=tfplist.create;
+                templist.count:=lists.nodelist.count;
+
+                { 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
+                    begin
+                      if tnode(lists.nodelist[i]).isequal(tnode(lists.nodelist[j])) then
+                        begin
+                          if not(assigned(statements)) then
+                            nodes:=internalstatements(statements);
+{$ifdef csedebug}
+                          writeln('    ====     ');
+                          printnode(output,tnode(lists.nodelist[i]));
+                          writeln('    equals   ');
+                          printnode(output,tnode(lists.nodelist[j]));
+                          writeln('    ====     ');
+{$endif csedebug}
+
+                          def:=tstoreddef(tnode(lists.nodelist[i]).resultdef);
+                          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
+                            begin
+                              templist[i]:=ctempcreatenode.create(def,def.size,tt_persistent,
+                                def.is_intregable or def.is_fpuregable);
+                              addstatement(statements,tnode(templist[i]));
+
+                              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])^);
+{$ifdef csedebug}
+                              printnode(output,statements);
+{$endif csedebug}
+                            end;
+                        end;
+                    end;
+                if assigned(statements) then
+                  begin
+                    addstatement(statements,n);
+                    n:=nodes;
+                    do_firstpass(n);
+{$ifdef csedebug}
+                    printnode(output,nodes);
+{$endif csedebug}
+                  end;
+{$ifdef csedebug}
+                writeln('nodes: ',lists.nodelist.count);
+                writeln('==========================================');
+{$endif csedebug}
+                lists.nodelist.free;
+                lists.locationlist.free;
+                templist.free;
+              end
+          end;
+      end;
+
+
+    function do_optcse(var rootnode : tnode) : tnode;
       begin
+        foreachnodestatic(pm_postprocess,rootnode,@searchcsedomain,nil);
+        result:=nil;
+(*
         { create a linear list of nodes }
 
         { create hash values }
@@ -74,6 +227,7 @@ unit optcse;
                   delete the temp. }
               end;
           end;
+*)
       end;
 
 end.

+ 6 - 2
compiler/psub.pas

@@ -102,7 +102,8 @@ implementation
        { codegen }
        tgobj,cgbase,cgobj,dbgbase,
        ncgutil,regvars,
-       opttail
+       opttail,
+       optcse
 {$if defined(arm) or defined(powerpc) or defined(powerpc64)}
        ,aasmcpu
 {$endif arm}
@@ -754,6 +755,9 @@ implementation
           (pi_is_recursive in flags) then
           do_opttail(code,procdef);
 
+        if cs_opt_nodecse in current_settings.optimizerswitches then
+          do_optcse(code);
+
         { add implicit entry and exit code }
         add_entry_exit_code;
 
@@ -816,7 +820,7 @@ implementation
                      tg.direction:=1;
                    end;
                end;
-            
+
 {$endif}
             { Create register allocator }
             cg.init_register_allocators;