[fpc-devel] Kit's ambitions!

Florian Klämpfl florian at freepascal.org
Thu Jun 14 22:58:43 CEST 2018


Am 13.06.2018 um 20:50 schrieb J. Gareth Moreton:
> I haven't fully uncovered the secrets of
> the compiler yet, but I did notice "pre-
> peephole pass" under x86, but I think the
> only functions it touched was one of the
> bit shifts. Does this occur before
> register allocation or was it just
> something that had to be done before Pass
> 1?

It is only before pass 1.

I attached a patch I once started which shows the idea.
-------------- next part --------------
From 7c679b8365e7819f1c39e57c2c222b08bc935f72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20Kl=C3=A4mpfl?= <florian at freepascal.org>
Date: Sat, 11 Jun 2016 13:15:55 +0200
Subject: [PATCH] unfinished: + new pass to carry out peep hole optimizations
 before register allocation, this might reduce register pressure + x86:
 optmize LeaMov2Mov

---
 compiler/aopt.pas        | 32 ++++++++++++++++++++++++++++----
 compiler/aoptobj.pas     | 25 +++++++++++++++++++++++++
 compiler/psub.pas        |  4 ++++
 compiler/x86/aoptx86.pas | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/compiler/aopt.pas b/compiler/aopt.pas
index fde868713e..ad3590e1a1 100644
--- a/compiler/aopt.pas
+++ b/compiler/aopt.pas
@@ -39,9 +39,11 @@ Unit aopt;
         { _AsmL is the PAasmOutpout list that has to be optimized }
         Constructor create(_AsmL: TAsmList); virtual; reintroduce;
 
+        Destructor destroy;override;
+
         { call the necessary optimizer procedures }
         Procedure Optimize;virtual;
-        Destructor destroy;override;
+        procedure PreRegallocOptimize;virtual;
 
       private
         procedure FindLoHiLabels;
@@ -68,6 +70,7 @@ Unit aopt;
       casmoptimizer : TAsmOptimizerClass;
       cpreregallocscheduler : TAsmSchedulerClass;
 
+    procedure PreRegallocOptimize(AsmL:TAsmList);
     procedure Optimize(AsmL:TAsmList);
     procedure PreRegallocSchedule(AsmL:TAsmList);
 
@@ -86,6 +89,7 @@ Unit aopt;
         inherited create(_asml,nil,nil,nil);
         { setup labeltable, always necessary }
         New(LabelInfo);
+        LabelInfo^.LabelTable:=nil;
       End;
 
     procedure TAsmOptimizer.FindLoHiLabels;
@@ -315,11 +319,21 @@ Unit aopt;
       End;
 
 
+    Procedure TAsmOptimizer.PreRegallocOptimize;
+      begin
+        BlockStart := tai(AsmL.First);
+        PreRegAllocPeepHoleOptPass;
+      end;
+
+
     Destructor TAsmOptimizer.Destroy;
       Begin
-        if assigned(LabelInfo^.LabelTable) then
-          Freemem(LabelInfo^.LabelTable);
-        Dispose(LabelInfo);
+        if assigned(LabelInfo) then
+          begin
+            if assigned(LabelInfo^.LabelTable) then
+              Freemem(LabelInfo^.LabelTable);
+            Dispose(LabelInfo);
+          end;
         inherited Destroy;
       End;
 
@@ -375,6 +389,16 @@ Unit aopt;
       End;
 
 
+    procedure PreRegallocOptimize(AsmL:TAsmList);
+      var
+        p : TAsmOptimizer;
+      begin
+        p:=casmoptimizer.Create(AsmL);
+        p.PreRegallocOptimize;
+        p.free;
+      end;
+
+
     procedure Optimize(AsmL:TAsmList);
       var
         p : TAsmOptimizer;
diff --git a/compiler/aoptobj.pas b/compiler/aoptobj.pas
index 02fc330167..985c03ec2b 100644
--- a/compiler/aoptobj.pas
+++ b/compiler/aoptobj.pas
@@ -344,12 +344,16 @@ Unit AoptObj;
         procedure PeepHoleOptPass2; virtual;
         procedure PostPeepHoleOpts; virtual;
 
+        procedure PreRegAllocPeepHoleOptPass; virtual;
+
         { processor dependent methods }
         // if it returns true, perform a "continue"
         function PrePeepHoleOptsCpu(var p: tai): boolean; virtual;
         function PeepHoleOptPass1Cpu(var p: tai): boolean; virtual;
         function PeepHoleOptPass2Cpu(var p: tai): boolean; virtual;
         function PostPeepHoleOptsCpu(var p: tai): boolean; virtual;
+
+        function PreRegAllocPeepHoleOptPassCpu(var p : tai) : boolean; virtual;
       End;
 
        Function ArrayRefsEq(const r1, r2: TReference): Boolean;
@@ -1572,4 +1576,25 @@ Unit AoptObj;
         result := false;
       end;
 
+
+    procedure TAOptObj.PreRegAllocPeepHoleOptPass;
+      var
+        p: tai;
+      begin
+        p := BlockStart;
+        while (p <> BlockEnd) Do
+          begin
+            if PreRegAllocPeepHoleOptPassCPU(p) then
+              continue;
+            p:=tai(p.next);
+          end;
+      end;
+
+
+    function TAOptObj.PreRegAllocPeepHoleOptPassCpu(var p: tai): boolean;
+      begin
+        result := false;
+      end;
+
+
 End.
diff --git a/compiler/psub.pas b/compiler/psub.pas
index 95e5030631..b070145d77 100644
--- a/compiler/psub.pas
+++ b/compiler/psub.pas
@@ -1585,6 +1585,10 @@ implementation
             }
 
 
+            if (cs_opt_level1 in current_settings.optimizerswitches) and
+               { do not optimize pure assembler procedures }
+               not(pi_is_assembler in flags)  then
+              PreRegallocOptimize(aktproccode);
 {$ifndef NoOpt}
 {$ifndef i386}
             if (cs_opt_scheduler in current_settings.optimizerswitches) and
diff --git a/compiler/x86/aoptx86.pas b/compiler/x86/aoptx86.pas
index 01605a1a96..fcf7521613 100644
--- a/compiler/x86/aoptx86.pas
+++ b/compiler/x86/aoptx86.pas
@@ -37,6 +37,8 @@ unit aoptx86;
     type
       TX86AsmOptimizer = class(TAsmOptimizer)
         function RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean; override;
+      private
+       function PreRegAllocPeepHoleOptLea(var p : tai) : boolean;
       protected
         procedure PostPeepholeOptMov(const p : tai);
 
@@ -53,6 +55,8 @@ unit aoptx86;
         class function IsExitCode(p : tai) : boolean;
         class function isFoldableArithOp(hp1 : taicpu; reg : tregister) : boolean;
         procedure RemoveLastDeallocForFuncRes(p : tai);
+
+        function PreRegAllocPeepHoleOptPassCpu(var p : tai) : boolean; override;
       end;
 
     function MatchInstruction(const instr: tai; const op: TAsmOp; const opsize: topsizes): boolean;
@@ -75,7 +79,7 @@ unit aoptx86;
     uses
       cutils,
       verbose,
-      procinfo,
+      cgobj,procinfo,
       symconst,symsym,
       itcpugas;
 
@@ -1245,5 +1249,46 @@ unit aoptx86;
          end;
       end;
 
+
+    function TX86AsmOptimizer.PreRegAllocPeepHoleOptLea(var p : tai) : boolean;
+      var
+        hp1 : tai;
+      begin
+        Result:=false;
+        if GetNextInstruction(p,hp1) and
+          (hp1.typ=ait_instruction) and
+          MatchInstruction(hp1,A_MOV,[S_L]) and
+          MatchOpType(hp1,top_reg,top_reg) and
+          MatchOperand(taicpu(p).oper[1]^,taicpu(hp1).oper[0]^) and
+          (cg.rg[getregtype(taicpu(p).oper[1]^.reg)].live_start[getsupreg(taicpu(p).oper[1]^.reg)]=p) and
+          (cg.rg[getregtype(taicpu(p).oper[1]^.reg)].live_end[getsupreg(taicpu(p).oper[1]^.reg)]=hp1) then
+          begin
+            taicpu(p).oper[1]^.reg:=taicpu(hp1).oper[0]^.reg;
+
+            if cg.rg[getregtype(taicpu(hp1).oper[1]^.reg)].live_end[getsupreg(taicpu(hp1).oper[1]^.reg)]=hp1 then
+              cg.rg[getregtype(taicpu(hp1).oper[1]^.reg)].live_end[getsupreg(taicpu(p).oper[1]^.reg)]:=p;
+
+            if cg.rg[getregtype(taicpu(hp1).oper[1]^.reg)].live_start[getsupreg(taicpu(hp1).oper[1]^.reg)]=hp1 then
+              cg.rg[getregtype(taicpu(hp1).oper[1]^.reg)].live_start[getsupreg(taicpu(p).oper[1]^.reg)]:=p;
+
+            AsmL.Remove(hp1);
+            hp1.Free;
+            cg.rg[getregtype(taicpu(p).oper[1]^.reg)].live_start[getsupreg(taicpu(p).oper[1]^.reg)]:=nil;
+            cg.rg[getregtype(taicpu(p).oper[1]^.reg)].live_end[getsupreg(taicpu(p).oper[1]^.reg)]:=nil;
+          end;
+      end;
+
+
+    function TX86AsmOptimizer.PreRegAllocPeepHoleOptPassCpu(var p : tai) : boolean;
+      begin
+        Result:=false;
+        case p.typ of
+          ait_instruction:
+            case taicpu(p).opcode of
+              A_LEA:
+                Result:=PreRegAllocPeepHoleOptLea(p);
+            end;
+        end;
+      end;
 end.
 
-- 
2.13.3.windows.1



More information about the fpc-devel mailing list