Browse Source

* Pass 2 can now be run multiple times when
under -O3 and above.

J. Gareth "Curious Kit" Moreton 3 years ago
parent
commit
47825610b8
3 changed files with 37 additions and 18 deletions
  1. 30 14
      compiler/aoptobj.pas
  2. 3 2
      compiler/i386/aoptcpu.pas
  3. 4 2
      compiler/x86_64/aoptcpu.pas

+ 30 - 14
compiler/aoptobj.pas

@@ -2523,7 +2523,7 @@ Unit AoptObj;
 
     procedure TAOptObj.PeepHoleOptPass1;
       const
-        MaxPasses: array[1..3] of Cardinal = (1, 2, 8);
+        MaxPasses_Pass1: array[1..3] of Cardinal = (1, 2, 8);
       var
         p : tai;
         stoploop, FirstInstruction, JumpOptsAvailable: boolean;
@@ -2537,11 +2537,11 @@ Unit AoptObj;
         { Determine the maximum number of passes allowed based on the compiler switches }
         if (cs_opt_level3 in current_settings.optimizerswitches) then
           { it should never take more than 8 passes, but the limit is finite to protect against faulty optimisations }
-          MaxCount := MaxPasses[3]
+          MaxCount := MaxPasses_Pass1[3]
         else if (cs_opt_level2 in current_settings.optimizerswitches) then
-          MaxCount := MaxPasses[2] { The original double run of Pass 1 }
+          MaxCount := MaxPasses_Pass1[2] { The original double run of Pass 1 }
         else
-          MaxCount := MaxPasses[1];
+          MaxCount := MaxPasses_Pass1[1];
 
         NotFirstIteration := False;
         repeat
@@ -2606,19 +2606,35 @@ Unit AoptObj;
 
 
     procedure TAOptObj.PeepHoleOptPass2;
+      const
+        MaxPasses_Pass2 = 8;
       var
         p: tai;
+        stoploop: Boolean;
+        PassCount: Cardinal;
       begin
-        p := BlockStart;
-        ClearUsedRegs;
-        while (p <> BlockEnd) Do
-          begin
-            prefetch(pointer(p.Next)^);
-            if PeepHoleOptPass2Cpu(p) then
-              continue;
-            if assigned(p) then
-              p := tai(UpdateUsedRegsAndOptimize(p).Next);
-          end;
+        PassCount := 0;
+
+        { Pass 2 is only executed multiple times under -O3 and above }
+        repeat
+          stoploop := True;
+          p := BlockStart;
+          ClearUsedRegs;
+          while (p <> BlockEnd) Do
+            begin
+              prefetch(pointer(p.Next)^);
+              if PeepHoleOptPass2Cpu(p) then
+                begin
+                  stoploop := False;
+                  continue;
+                end;
+              if assigned(p) then
+                p := tai(UpdateUsedRegsAndOptimize(p).Next);
+            end;
+
+          Inc(PassCount);
+
+        until stoploop or not (cs_opt_level3 in current_settings.optimizerswitches) or (PassCount >= MaxPasses_Pass2);
       end;
 
 

+ 3 - 2
compiler/i386/aoptcpu.pas

@@ -316,8 +316,9 @@ unit aoptcpu;
           else
             ;
         end;
-        { If this flag is set, something was optimised ahead of p, so move
-          ahead by 1 instruction but treat as if Result was set to True }
+        { If this flag is set, force another run of pass 2 even if p wasn't
+          changed (-O3 only), but otherwise move p ahead by 1 instruction
+          and treat as if Result was set to True }
         if aoc_ForceNewIteration in OptsToCheck then
           begin
             Exclude(OptsToCheck, aoc_ForceNewIteration);

+ 4 - 2
compiler/x86_64/aoptcpu.pas

@@ -41,6 +41,7 @@ implementation
 
 uses
   globals,
+  globtype,
   aasmcpu;
 
     function TCpuAsmOptimizer.PrePeepHoleOptsCpu(var p : tai) : boolean;
@@ -234,8 +235,9 @@ uses
           else
             ;
         end;
-        { If this flag is set, something was optimised ahead of p, so move
-          ahead by 1 instruction but treat as if Result was set to True }
+        { If this flag is set, force another run of pass 2 even if p wasn't
+          changed (-O3 only), but otherwise move p ahead by 1 instruction
+          and treat as if Result was set to True }
         if aoc_ForceNewIteration in OptsToCheck then
           begin
             Exclude(OptsToCheck, aoc_ForceNewIteration);