2
0
Эх сурвалжийг харах

+ very limited SSA support (only outside control flow
constructs for now)

git-svn-id: trunk@3671 -

Jonas Maebe 19 жил өмнө
parent
commit
e531c4f125

+ 10 - 2
compiler/ncgflw.pas

@@ -148,6 +148,7 @@ implementation
          oldflowcontrol:=flowcontrol;
          oldclabel:=current_procinfo.CurrContinueLabel;
          oldblabel:=current_procinfo.CurrBreakLabel;
+         include(flowcontrol,fc_inflowcontrol);
 
          sync_regvars(true);
 {$ifdef OLDREGVARS}
@@ -199,7 +200,7 @@ implementation
          current_procinfo.CurrContinueLabel:=oldclabel;
          current_procinfo.CurrBreakLabel:=oldblabel;
          { a break/continue in a while/repeat block can't be seen outside }
-         flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue]);
+         flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue,fc_inflowcontrol]);
       end;
 
 
@@ -211,6 +212,7 @@ implementation
 
       var
          hl,otlabel,oflabel : tasmlabel;
+         oldflowcontrol: tflowcontrol;
 (*
          org_regvar_loaded_other,
          then_regvar_loaded_other,
@@ -226,6 +228,8 @@ implementation
       begin
          location_reset(location,LOC_VOID,OS_NO);
 
+         oldflowcontrol := flowcontrol;
+         include(flowcontrol,fc_inflowcontrol);
          otlabel:=current_procinfo.CurrTrueLabel;
          oflabel:=current_procinfo.CurrFalseLabel;
          current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
@@ -359,6 +363,7 @@ implementation
 
          current_procinfo.CurrTrueLabel:=otlabel;
          current_procinfo.CurrFalseLabel:=oflabel;
+         flowcontrol := oldflowcontrol + (flowcontrol - [fc_inflowcontrol]);
       end;
 
 
@@ -416,6 +421,7 @@ implementation
       begin
          location_reset(location,LOC_VOID,OS_NO);
          oldflowcontrol:=flowcontrol;
+         include(flowcontrol,fc_inflowcontrol);
          oldclabel:=current_procinfo.CurrContinueLabel;
          oldblabel:=current_procinfo.CurrBreakLabel;
          current_asmdata.getjumplabel(current_procinfo.CurrContinueLabel);
@@ -759,7 +765,7 @@ implementation
          current_procinfo.CurrContinueLabel:=oldclabel;
          current_procinfo.CurrBreakLabel:=oldblabel;
          { a break/continue in a while/repeat block can't be seen outside }
-         flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue]);
+         flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue,fc_inflowcontrol]);
       end;
 
 
@@ -830,6 +836,7 @@ implementation
        begin
          location_reset(location,LOC_VOID,OS_NO);
 
+         include(flowcontrol,fc_gotolabel);
 {$ifdef OLDREGVARS}
          load_all_regvars(current_asmdata.CurrAsmList);
 {$endif OLDREGVARS}
@@ -853,6 +860,7 @@ implementation
       begin
          location_reset(location,LOC_VOID,OS_NO);
 
+         include(flowcontrol,fc_gotolabel);
 {$ifdef OLDREGVARS}
          load_all_regvars(current_asmdata.CurrAsmList);
 {$endif OLDREGVARS}

+ 2 - 0
compiler/ncgld.pas

@@ -557,6 +557,8 @@ implementation
           end
         else
           begin
+            { SSA support }
+            maybechangeloadnodereg(left);
             case right.location.loc of
               LOC_CONSTANT :
                 begin

+ 4 - 0
compiler/ncgset.pas

@@ -683,6 +683,7 @@ implementation
 
     procedure tcgcasenode.pass_2;
       var
+         oldflowcontrol: tflowcontrol;
          i : longint;
          lv,hv,
          max_label: tconstexprint;
@@ -695,6 +696,8 @@ implementation
       begin
          location_reset(location,LOC_VOID,OS_NO);
 
+         oldflowcontrol := flowcontrol;
+         include(flowcontrol,fc_inflowcontrol);
          { Allocate labels }
          current_asmdata.getjumplabel(endlabel);
          current_asmdata.getjumplabel(elselabel);
@@ -862,6 +865,7 @@ implementation
          { Reset labels }
          for i:=0 to blocks.count-1 do
            pcaseblock(blocks[i])^.blocklabel:=nil;
+         flowcontrol := oldflowcontrol + (flowcontrol - [fc_inflowcontrol]);
       end;
 
 

+ 135 - 0
compiler/ncgutil.pas

@@ -101,6 +101,9 @@ interface
 //    procedure get_used_regvars_common(n: tnode; var rv: tusedregvarscommon);
     procedure gen_sync_regvars(list:TAsmList; var rv: tusedregvars);
 
+    { if the result of n is a LOC_C(..)REGISTER, try to find the corresponding }
+    { loadn and change its location to a new register (= SSA)                  }
+    procedure maybechangeloadnodereg(var n: tnode);
 
    {#
       Allocate the buffers for exception management and setjmp environment.
@@ -167,6 +170,9 @@ implementation
 {$ifdef powerpc64}
     , cpupi
 {$endif}
+{$ifdef SUPPORT_MMX}
+    , cgx86
+{$endif SUPPORT_MMX}
 ;
 
 
@@ -2240,6 +2246,135 @@ implementation
       end;
 
 
+{*****************************************************************************
+                              SSA support
+*****************************************************************************}
+
+    type
+      preplaceregrec = ^treplaceregrec;
+      treplaceregrec = record
+        old, new: tregister;
+{$ifndef cpu64bit}
+        oldhi, newhi: tregister;    
+{$endif cpu64bit}
+        ressym: tsym;
+      end;
+
+
+    function doreplace(var n: tnode; para: pointer): foreachnoderesult;
+      var
+        rr: preplaceregrec absolute para;
+      begin
+        result := fen_false;
+        case n.nodetype of
+          loadn:
+            begin
+              if (tabstractvarsym(tloadnode(n).symtableentry).varoptions * [vo_is_dll_var, vo_is_thread_var] = []) and
+                 not assigned(tloadnode(n).left) and
+                 (((tloadnode(n).symtableentry <> rr^.ressym) and
+                   not(vo_is_funcret in tabstractvarsym(tloadnode(n).symtableentry).varoptions)) or
+                  not(fc_exit in flowcontrol)) and
+                 (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
+                 (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register = rr^.old) then
+                begin
+{$ifndef cpu64bit}
+                  { it's possible a 64 bit location was shifted and/xor typecasted }
+                  { in a 32 bit value, so only 1 register was left in the location }
+                  if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_64,OS_S64]) then
+                    if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi = rr^.oldhi) then
+                      tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi := rr^.newhi
+                    else
+                      exit;
+{$endif cpu64bit}
+                  tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register := rr^.new;
+                  result := fen_norecurse_true;
+                end;
+            end;
+          temprefn:
+            begin
+              if (ttemprefnode(n).tempinfo^.valid) and
+                 (ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
+                 (ttemprefnode(n).tempinfo^.location.register = rr^.old) then
+                begin
+{$ifndef cpu64bit}
+                  { it's possible a 64 bit location was shifted and/xor typecasted }
+                  { in a 32 bit value, so only 1 register was left in the location }
+                  if (ttemprefnode(n).tempinfo^.location.size in [OS_64,OS_S64]) then
+                    if (ttemprefnode(n).tempinfo^.location.register64.reghi = rr^.oldhi) then
+                      ttemprefnode(n).tempinfo^.location.register64.reghi := rr^.newhi
+                    else
+                      exit;
+{$endif cpu64bit}
+                  ttemprefnode(n).tempinfo^.location.register := rr^.new;
+                  result := fen_norecurse_true;
+                end;
+            end;
+        end;  
+      end;
+
+
+    procedure maybechangeloadnodereg(var n: tnode);
+      var
+        rr: treplaceregrec;
+      begin
+        if not (n.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) or
+           ([fc_inflowcontrol,fc_gotolabel] * flowcontrol <> []) then
+          exit;
+        rr.old := n.location.register;
+        rr.ressym := nil;
+      {$ifndef cpu64bit}
+        rr.oldhi := NR_NO;
+      {$endif cpu64bit}
+        case n.location.loc of
+          LOC_CREGISTER:
+            begin
+      {$ifndef cpu64bit}
+              if (n.location.size in [OS_64,OS_S64]) then
+                begin
+                  rr.oldhi := n.location.register64.reghi;
+                  rr.new := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+                  rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+                end
+              else
+      {$endif cpu64bit}
+                rr.new := cg.getintregister(current_asmdata.CurrAsmList,n.location.size);
+            end;
+          LOC_CFPUREGISTER:
+            rr.new := cg.getfpuregister(current_asmdata.CurrAsmList,n.location.size);
+      {$ifdef SUPPORT_MMX}
+          LOC_CMMXREGISTER:
+            rr.new := tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
+      {$endif SUPPORT_MMX}
+          LOC_CMMREGISTER:
+            rr.new := cg.getmmregister(current_asmdata.CurrAsmList,n.location.size);
+          else
+            exit;
+        end;
+
+        if (current_procinfo.procdef.funcretloc[calleeside].loc<>LOC_VOID) and
+           assigned(current_procinfo.procdef.funcretsym) and
+           (tabstractvarsym(current_procinfo.procdef.funcretsym).refs <> 0) then
+          if (current_procinfo.procdef.proctypeoption=potype_constructor) then
+            rr.ressym:=tsym(current_procinfo.procdef.parast.search('self'))
+         else
+            rr.ressym:=current_procinfo.procdef.funcretsym;
+
+        if not foreachnodestatic(n,@doreplace,@rr) then
+          exit;
+
+        { now that we've change the loadn/temp, also change the node result location }  
+      {$ifndef cpu64bit}
+        if (n.location.size in [OS_64,OS_S64]) then
+          begin
+            n.location.register64.reglo := rr.new;
+            n.location.register64.reghi := rr.newhi;
+          end
+        else
+      {$endif cpu64bit}
+          n.location.register := rr.new;
+      end;
+
+
     procedure gen_free_symtable(list:TAsmList;st:tsymtable);
       var
         sym : tsym;

+ 1 - 1
compiler/pass_2.pas

@@ -29,7 +29,7 @@ uses
    node;
 
     type
-       tenumflowcontrol = (fc_exit,fc_break,fc_continue);
+       tenumflowcontrol = (fc_exit,fc_break,fc_continue,fc_inflowcontrol,fc_gotolabel);
        tflowcontrol = set of tenumflowcontrol;
 
     var