Browse Source

+ optimize pascal code surrounding assembler blocks

Jonas Maebe 26 years ago
parent
commit
8cf4da6d5e
7 changed files with 161 additions and 80 deletions
  1. 5 2
      compiler/aasm.pas
  2. 33 13
      compiler/aopt386.pas
  3. 11 9
      compiler/csopt386.pas
  4. 77 43
      compiler/daopt386.pas
  5. 6 2
      compiler/hcodegen.pas
  6. 13 10
      compiler/popt386.pas
  7. 16 1
      compiler/pstatmnt.pas

+ 5 - 2
compiler/aasm.pas

@@ -254,7 +254,7 @@ unit aasm;
           constructor init_end;
        end;
 
-       TMarker = (NoPropInfoStart, NoPropInfoEnd);
+       TMarker = (NoPropInfoStart, NoPropInfoEnd, AsmBlockStart, AsmBlockEnd);
        pai_marker = ^tai_marker;
        tai_marker = object(tai)
          Kind: TMarker;
@@ -912,7 +912,10 @@ uses
 end.
 {
   $Log$
-  Revision 1.28  1998-12-16 00:27:16  peter
+  Revision 1.29  1998-12-29 18:48:24  jonas
+    + optimize pascal code surrounding assembler blocks
+
+  Revision 1.28  1998/12/16 00:27:16  peter
     * removed some obsolete version checks
 
   Revision 1.27  1998/12/11 00:02:37  peter

+ 33 - 13
compiler/aopt386.pas

@@ -38,32 +38,52 @@ Uses
 
 
 Procedure Optimize(AsmL: PAasmOutput);
-Var BlockEnd: Pai;
+Var BlockStart, BlockEnd: Pai;
 Begin
 {setup labeltable, always necessary}
-  DFAPass1(AsmL);
+  BlockStart := Pai(AsmL^.First);
+  BlockEnd := DFAPass1(AsmL, BlockStart);
+{Blockend now either contains an ait_marker with Kind = AsmBlockStart, or nil}
+  While Assigned(BlockStart) Do
+    Begin
 {peephole optimizations}
-  PeepHoleOptPass1(AsmL);
-  PeepHoleOptPass1(AsmL);
+      PeepHoleOptPass1(AsmL, BlockStart, BlockEnd);
+      PeepHoleOptPass1(AsmL, BlockStart, BlockEnd);
 {data flow analyzer}
-  If (cs_slowoptimize in aktglobalswitches) Then
-    Begin
-      BlockEnd := DFAPass2(AsmL);
-      If BlockEnd <> Nil Then
+      If (cs_slowoptimize in aktglobalswitches) Then
+        Begin
+          If DFAPass2(AsmL, BlockStart, BlockEnd) Then
 {common subexpression elimination}
-        CSE(AsmL, Pai(AsmL^.First), BlockEnd);
-    End;
+            CSE(AsmL, BlockStart, BlockEnd);
+        End;
 {more peephole optimizations}
-  PeepHoleOptPass2(AsmL);
+      PeepHoleOptPass2(AsmL, BlockStart, BlockEnd);
 {dispose labeltabel}
-  ShutDownDFA;
+      ShutDownDFA;
+
+      If Assigned(BlockEnd) And
+         GetNextInstruction(BlockEnd, BlockStart) Then
+       {we stopped at an assmbler block, so skip it}
+        Begin
+          While GetNextInstruction(BlockStart, BlockStart) And
+                ((BlockStart^.Typ <> Ait_Marker) Or
+                 (Pai_Marker(Blockstart)^.Kind <> AsmBlockEnd)) Do;
+          If GetNextInstruction(BlockStart, BlockStart) Then
+            BlockEnd := DFAPass1(AsmL, BlockStart)
+          Else BlockStart := Nil
+        End
+      Else BlockStart := Nil;
+   End;
 End;
 
 End.
 
 {
  $Log$
- Revision 1.23  1998-12-11 00:02:43  peter
+ Revision 1.24  1998-12-29 18:48:23  jonas
+   + optimize pascal code surrounding assembler blocks
+
+ Revision 1.23  1998/12/11 00:02:43  peter
    + globtype,tokens,version unit splitted from globals
 
  Revision 1.22  1998/08/19 16:07:57  jonas

+ 11 - 9
compiler/csopt386.pas

@@ -240,10 +240,9 @@ Var Cnt, Cnt2: Longint;
     TmpState: Byte;
 Begin
   p := First;
-  If (p^.typ in (SkipInstr+[ait_marker])) Then
-    GetNextInstruction(p, p);
+  SkipHead(p);
   First := p;
-  While Assigned(p) Do
+  While (p <> Last) Do
     Begin
       Case p^.typ Of
         ait_instruction:
@@ -264,7 +263,8 @@ Begin
                       Begin {destination is always a register in this case}
                         With PPaiProp(p^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op2))] Do
                           Begin
-                            If GetLastInstruction (p, hp1) Then
+                            If GetLastInstruction (p, hp1) And
+                              (hp1^.typ <> ait_marker) Then
 {so we don't try to check a sequence when p is the first instruction of the block}
                                If CheckSequence(p, TRegister(Pai386(p)^.op2), Cnt, RegInfo) And
                                   (Cnt > 0)
@@ -498,7 +498,7 @@ End;
 
 Procedure RemoveInstructs(AsmL: PAasmOutput; First, Last: Pai);
 {Removes the marked instructions and disposes the PPaiProps of the other
- instructions, restoring theirline number}
+ instructions, restoring their line number}
 Var p, hp1: Pai;
 {$IfDef TP}
     TmpLine: Longint;
@@ -506,10 +506,9 @@ Var p, hp1: Pai;
     InstrCnt: Longint;
 Begin
   p := First;
-  If (p^.typ in (SkipInstr + [ait_marker])) Then
-    GetNextInstruction(p, p);
+  SkipHead(P);
   InstrCnt := 1;
-  While Assigned(p) Do
+  While (p <> Last) Do
     Begin
 {$ifndef noinstremove}
       If PPaiProp(p^.fileinfo.line)^.CanBeRemoved
@@ -553,7 +552,10 @@ End.
 
 {
  $Log$
- Revision 1.17  1998-12-17 16:37:39  jonas
+ Revision 1.18  1998-12-29 18:48:22  jonas
+   + optimize pascal code surrounding assembler blocks
+
+ Revision 1.17  1998/12/17 16:37:39  jonas
    + extra checks in RegsEquivalent so some more optimizations can be done (which
      where disabled by the second fix from revision 1.22)
 

+ 77 - 43
compiler/daopt386.pas

@@ -62,14 +62,15 @@ Function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
 
 Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
 Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
+Procedure SkipHead(var P: Pai);
 
 Procedure UpdateUsedRegs(Var UsedRegs: TRegSet; p: Pai);
 Function RegsEquivalent(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo; OpAct: TopAction): Boolean;
 Function InstructionsEquivalent(p1, p2: Pai; Var RegInfo: TRegInfo): Boolean;
 Function OpsEqual(typ: Longint; op1, op2: Pointer): Boolean;
 
-Procedure DFAPass1(AsmL: PAasmOutput);
-Function DFAPass2(AsmL: PAasmOutput): Pai;
+Function DFAPass1(AsmL: PAasmOutput; BlockStart: Pai): Pai;
+Function DFAPass2(AsmL: PAasmOutput; BlockStart, BlockEnd: Pai): Boolean;
 Procedure ShutDownDFA;
 
 Function FindLabel(L: PLabel; Var hp: Pai): Boolean;
@@ -611,17 +612,19 @@ Var
 
 {************************ Create the Label table ************************}
 
-Procedure FindLoHiLabels(AsmL: PAasmOutput; Var LowLabel, HighLabel, LabelDif: Longint);
+Function FindLoHiLabels(AsmL: PAasmOutput; Var LowLabel, HighLabel, LabelDif: Longint; BlockStart: Pai): Pai;
 {Walks through the paasmlist to find the lowest and highest label number;
  Since 0.9.3: also removes unused labels}
 Var LabelFound: Boolean;
-    P{, hp1}: Pai;
+    P: Pai;
 Begin
   LabelFound := False;
   LowLabel := MaxLongint;
   HighLabel := 0;
-  P := Pai(AsmL^.first);
-  While Assigned(p) Do
+  P := BlockStart;
+  While Assigned(P) And
+        ((P^.typ <> Ait_Marker) Or
+         (Pai_Marker(P)^.Kind <> AsmBlockStart)) Do
     Begin
       If (Pai(p)^.typ = ait_label) Then
         If (Pai_Label(p)^.l^.is_used)
@@ -643,6 +646,7 @@ Begin
             End};
       GetNextInstruction(p, p);
     End;
+  FindLoHiLabels := p;
   If LabelFound
     Then LabelDif := HighLabel+1-LowLabel
     Else LabelDif := 0;
@@ -672,7 +676,7 @@ Begin
 End;
 
 Procedure BuildLabelTableAndFixRegAlloc(AsmL: PAasmOutput; Var LabelTable: PLabelTable; LowLabel: Longint;
-            Var LabelDif: Longint);
+            Var LabelDif: Longint; BlockStart, BlockEnd: Pai);
 {Builds a table with the locations of the labels in the paasmoutput.
  Also fixes some RegDeallocs like "# %eax released; push (%eax)"}
 Var p, hp1, hp2: Pai;
@@ -688,8 +692,8 @@ Begin
 {$EndIf TP}
             GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
             FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
-            p := pai(AsmL^.first);
-            While Assigned(p) Do
+            p := BlockStart;
+            While (P <> BlockEnd) Do
               Begin
                 Case p^.typ Of
                   ait_Label:
@@ -1048,12 +1052,13 @@ Begin
        (Pai_Marker(Current)^.Kind = NoPropInfoStart) Then
       Begin
         While Assigned(Current) And
-              Not((Current^.typ = ait_Marker) And
-                  (Pai_Marker(Current)^.Kind = NoPropInfoEnd)) Do
-          Current := Pai(Current^.Next)
+              ((Current^.typ <> ait_Marker) Or
+               (Pai_Marker(Current)^.Kind <> NoPropInfoEnd)) Do
+          Current := Pai(Current^.Next);
       End;
   Until Not(Assigned(Current)) Or
-        (Current^.typ <> ait_Marker);
+        (Current^.typ <> ait_Marker) Or
+        (Pai_Marker(Current)^.Kind <> NoPropInfoEnd);
   Next := Current;
   If Assigned(Current) And
      Not((Current^.typ In SkipInstr) or
@@ -1083,12 +1088,13 @@ Begin
        (Pai_Marker(Current)^.Kind = NoPropInfoEnd) Then
       Begin
         While Assigned(Current) And
-              Not((Current^.typ = ait_Marker) And
-                  (Pai_Marker(Current)^.Kind = NoPropInfoStart)) Do
+              ((Current^.typ <> ait_Marker) Or
+               (Pai_Marker(Current)^.Kind <> NoPropInfoStart)) Do
           Current := Pai(Current^.previous);
       End;
   Until Not(Assigned(Current)) Or
-        (Current^.typ <> ait_Marker);
+        (Current^.typ <> ait_Marker) Or
+        (Pai_Marker(Current)^.Kind <> NoPropInfoStart);
  Last := Current;
   If Assigned(Current) And
      Not((Current^.typ In SkipInstr) or
@@ -1102,6 +1108,28 @@ Begin
       End;
 End;
 
+Procedure SkipHead(var P: Pai);
+Var OldP: Pai;
+Begin
+  Repeat
+    OldP := P;
+    If (P^.typ in SkipInstr) Then
+      GetNextInstruction(P, P)
+    Else If ((P^.Typ = Ait_Marker) And
+        (Pai_Marker(P)^.Kind = NoPropInfoStart)) Then
+   {a marker of the NoPropInfoStart can4t be the first instruction of a
+    paasmoutput list}
+      GetNextInstruction(Pai(P^.Previous),P);
+    If (P^.Typ = Ait_Marker) And
+       (Pai_Marker(P)^.Kind = AsmBlockStart) Then
+      Begin
+        P := Pai(P^.Next);
+        While (P^.typ <> Ait_Marker) Or
+              (Pai_Marker(P)^.Kind <> AsmBlockEnd) Do
+          P := Pai(P^.Next)
+      End;
+    Until P = OldP
+End;
 {******************* The Data Flow Analyzer functions ********************}
 
 Procedure UpdateUsedRegs(Var UsedRegs: TRegSet; p: Pai);
@@ -1561,18 +1589,21 @@ Begin
   End;
 End;
 
-Procedure DFAPass1(AsmL: PAasmOutput);
-{gathers the RegAlloc data... still need to think about where to store it}
+Function DFAPass1(AsmL: PAasmOutput; BlockStart: Pai): Pai;
+{gathers the RegAlloc data... still need to think about where to store it to
+ avoid global vars}
+Var BlockEnd: Pai;
 Begin
-  FindLoHiLabels(AsmL, LoLab, HiLab, LabDif);
-  BuildLabelTableAndFixRegAlloc(AsmL, LTable, LoLab, LabDif);
+  BlockEnd := FindLoHiLabels(AsmL, LoLab, HiLab, LabDif, BlockStart);
+  BuildLabelTableAndFixRegAlloc(AsmL, LTable, LoLab, LabDif, BlockStart, BlockEnd);
+  DFAPass1 := BlockEnd;
 End;
 
-Function DoDFAPass2(
+Procedure DoDFAPass2(
 {$Ifdef StateDebug}
 AsmL: PAasmOutput;
 {$endif statedebug}
-First: Pai): Pai;
+BlockStart, BlockEnd: Pai);
 {Analyzes the Data Flow of an assembler list. Starts creating the reg
  contents for the instructions starting with p. Returns the last pai which has
  been processed}
@@ -1588,23 +1619,22 @@ Var
     TmpRef: TReference;
     TmpReg: TRegister;
 Begin
-  p := First;
+  p := BlockStart;
   UsedRegs := [];
   UpdateUsedregs(UsedRegs, p);
-  If (First^.typ in SkipInstr) Then
+  If (BlockStart^.typ in SkipInstr) Then
     GetNextInstruction(p, p);
-  First := p;
+  BlockStart := p;
   InstrCnt := 1;
   FillChar(NrOfInstrSinceLastMod, SizeOf(NrOfInstrSinceLastMod), 0);
-  While Assigned(p) Do
+  While (P <> BlockEnd) Do
     Begin
-      DoDFAPass2 := p;
 {$IfDef TP}
       New(CurProp);
 {$Else TP}
       CurProp := @PaiPropBlock^[InstrCnt];
 {$EndIf TP}
-      If (p <> First)
+      If (p <> BlockStart)
         Then
           Begin
 {$ifdef JumpAnal}
@@ -2002,7 +2032,7 @@ Begin
     End;
 End;
 
-Function InitDFAPass2(AsmL: PAasmOutput): Boolean;
+Function InitDFAPass2(AsmL: PAasmOutput; BlockStart, BlockEnd: Pai): Boolean;
 {reserves memory for the PPaiProps in one big memory block when not using
  TP, returns False if not enough memory is available for the optimizer in all
  cases}
@@ -2010,11 +2040,10 @@ Var p: Pai;
     Count: Longint;
 {    TmpStr: String; }
 Begin
-  P := Pai(AsmL^.First);
-  If (p^.typ in SkipInstr) Then
-    GetNextInstruction(p, p);
+  P := BlockStart;
+  SkipHead(P);
   NrOfPaiObjs := 0;
-  While Assigned(P) Do
+  While (P <> BlockEnd) Do
     Begin
 {$IfDef JumpAnal}
       Case P^.Typ Of
@@ -2056,9 +2085,8 @@ Begin
     Begin
       InitDFAPass2 := True;
       GetMem(PaiPropBlock, NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4));
-      p := Pai(AsmL^.First);
-      If (p^.typ in SkipInstr) Then
-        GetNextInstruction(p, p);
+      p := BlockStart;
+      SkipHead(p);
       For Count := 1 To NrOfPaiObjs Do
         Begin
           PaiPropBlock^[Count].LineSave := p^.fileinfo.line;
@@ -2070,15 +2098,18 @@ Begin
  {$EndIf TP}
 End;
 
-Function DFAPass2(AsmL: PAasmOutPut): Pai;
+Function DFAPass2(AsmL: PAasmOutPut; BlockStart, BlockEnd: Pai): Boolean;
 Begin
-  If InitDFAPass2(AsmL)
-    Then DFAPass2 := DoDFAPass2(
+  If InitDFAPass2(AsmL, BlockStart, BlockEnd) Then
+    Begin
+      DoDFAPass2(
 {$ifdef statedebug}
- asml,
+         asml,
 {$endif statedebug}
-    Pai(AsmL^.First))
-    Else DFAPass2 := Nil;
+         BlockStart, BlockEnd);
+      DFAPass2 := True
+    End
+  Else DFAPass2 := False;
 End;
 
 Procedure ShutDownDFA;
@@ -2091,7 +2122,10 @@ End.
 
 {
  $Log$
- Revision 1.33  1998-12-17 16:37:38  jonas
+ Revision 1.34  1998-12-29 18:48:19  jonas
+   + optimize pascal code surrounding assembler blocks
+
+ Revision 1.33  1998/12/17 16:37:38  jonas
    + extra checks in RegsEquivalent so some more optimizations can be done (which
      where disabled by the second fix from revision 1.22)
 

+ 6 - 2
compiler/hcodegen.pas

@@ -42,7 +42,8 @@ unit hcodegen;
        pi_C_import  = $10;      { set, if the procedure is an external C function }
        pi_uses_exceptions = $20;{ set, if the procedure has a try statement => }
                                 { no register variables                        }
-
+       pi_is_assembler = $40;   { set if the procedure is declared as ASSEMBLER
+                                  => don't optimize}
     type
        pprocinfo = ^tprocinfo;
        tprocinfo = record
@@ -354,7 +355,10 @@ end.
 
 {
   $Log$
-  Revision 1.23  1998-11-27 14:50:38  peter
+  Revision 1.24  1998-12-29 18:48:18  jonas
+    + optimize pascal code surrounding assembler blocks
+
+  Revision 1.23  1998/11/27 14:50:38  peter
     + open strings, $P switch support
 
   Revision 1.22  1998/11/16 12:12:21  peter

+ 13 - 10
compiler/popt386.pas

@@ -26,8 +26,8 @@ Interface
 
 Uses Aasm;
 
-Procedure PeepHoleOptPass1(AsmL: PAasmOutput);
-Procedure PeepHoleOptPass2(AsmL: PAasmOutput);
+Procedure PeepHoleOptPass1(AsmL: PAasmOutput; BlockStart, BlockEnd: Pai);
+Procedure PeepHoleOptPass2(AsmL: PAasmOutput; BlockStart, BlockEnd: Pai);
 
 Implementation
 
@@ -42,7 +42,7 @@ Begin
   RegUsedAfterInstruction := Reg in UsedRegs
 End;
 
-Procedure PeepHoleOptPass1(Asml: PAasmOutput);
+Procedure PeepHoleOptPass1(Asml: PAasmOutput; BlockStart, BlockEnd: Pai);
 {First pass of peepholeoptimizations}
 
 Var
@@ -79,7 +79,7 @@ Var
 
   Begin
     If (hp^.lab^.nb >= LoLab) and
-       (hp^.lab^.nb <= HiLab) and   {range check, necessary?}
+       (hp^.lab^.nb <= HiLab) and   {range check, a jump can go past an assembler block!}
        Assigned(LTable^[hp^.lab^.nb-LoLab].PaiObj) Then
       Begin
         p1 := LTable^[hp^.lab^.nb-LoLab].PaiObj; {the jump's destination}
@@ -100,9 +100,9 @@ Var
   End;
 
 Begin
-  P := Pai(AsmL^.First);
+  P := BlockStart;
   UsedRegs := [];
-  While Assigned(P) Do
+  While (P <> BlockEnd) Do
     Begin
       UpDateUsedRegs(UsedRegs, Pai(p^.next));
       Case P^.Typ Of
@@ -1476,13 +1476,13 @@ Begin
     end;
 end;
 
-Procedure PeepHoleOptPass2(AsmL: PAasmOutput);
+Procedure PeepHoleOptPass2(AsmL: PAasmOutput; BlockStart, BlockEnd: Pai);
 
 var
   p,hp1,hp2: pai;
 Begin
-  P := Pai(AsmL^.First);
-  While Assigned(p) Do
+  P := BlockStart;
+  While (P <> BlockEnd) Do
     Begin
       Case P^.Typ Of
         Ait_Instruction:
@@ -1590,7 +1590,10 @@ End.
 
 {
  $Log$
- Revision 1.33  1998-12-23 15:16:21  jonas
+ Revision 1.34  1998-12-29 18:48:17  jonas
+   + optimize pascal code surrounding assembler blocks
+
+ Revision 1.33  1998/12/23 15:16:21  jonas
    * change "inc x/dec x; test x, x"  to "add 1, x/sub 1,x" because inc and dec
      don't affect the carry flag (test does). This *doesn't* fix the problem with
     cardinal, that's a cg issue.

+ 16 - 1
compiler/pstatmnt.pas

@@ -680,6 +680,7 @@ unit pstatmnt;
     function _asm_statement : ptree;
       var
         asmstat : ptree;
+        Marker : Pai;
       begin
          if (aktprocsym^.definition^.options and poinline)<>0 then
            Begin
@@ -762,6 +763,16 @@ unit pstatmnt;
               consume(RECKKLAMMER);
            end
          else usedinproc:=$ff;
+
+{ mark the start and the end of the assembler block for the optimizer }
+
+         If Assigned(AsmStat^.p_asm) Then
+           Begin
+             Marker := New(Pai_Marker, Init(AsmBlockStart));
+             AsmStat^.p_asm^.Insert(Marker);
+             Marker := New(Pai_Marker, Init(AsmBlockEnd));
+             AsmStat^.p_asm^.Concat(Marker);
+           End;
          _asm_statement:=asmstat;
       end;
 
@@ -1236,6 +1247,7 @@ unit pstatmnt;
           { force the asm statement }
             if token<>_ASM then
              consume(_ASM);
+            Procinfo.Flags := ProcInfo.Flags Or pi_is_assembler;
             assembler_block:=_asm_statement;
           { becuase the END is already read we need to get the
             last_endtoken_filepos here (PFV) }
@@ -1245,7 +1257,10 @@ unit pstatmnt;
 end.
 {
   $Log$
-  Revision 1.56  1998-12-23 22:52:56  peter
+  Revision 1.57  1998-12-29 18:48:15  jonas
+    + optimize pascal code surrounding assembler blocks
+
+  Revision 1.56  1998/12/23 22:52:56  peter
     * fixed new(x) crash if x contains an error
 
   Revision 1.55  1998/12/16 12:30:59  jonas