Browse Source

* daopt386: changes to getnextinstruction/getlastinstruction so they
ignore labels who have is_addr set
+ daopt386/csopt386: remove loads of registers which are overwritten
before their contents are used (especially usefull for removing superfluous
maybe_loadesi outputs and push/pops transformed by below optimization
+ popt386: transform pop/pop/pop/.../push/push/push to sequences of
'movl x(%esp),%reg' (only active when compiling a go32v2 compiler
currently because I don't know whether it's safe to do this under Win32/
Linux (because of problems we had when using esp as frame pointer on
those os'es)

Jonas Maebe 25 years ago
parent
commit
ce46621762
3 changed files with 218 additions and 100 deletions
  1. 59 8
      compiler/csopt386.pas
  2. 70 48
      compiler/daopt386.pas
  3. 89 44
      compiler/popt386.pas

+ 59 - 8
compiler/csopt386.pas

@@ -81,7 +81,8 @@ Begin {CheckSequence}
   RegCounter := R_EAX;
   RegCounter := R_EAX;
   GetLastInstruction(p, PrevNonRemovablePai);
   GetLastInstruction(p, PrevNonRemovablePai);
   While (RegCounter <= R_EDI) And
   While (RegCounter <= R_EDI) And
-        (PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].Typ <> Con_Ref) Do
+        not(ppaiprop(prevNonRemovablePai^.optInfo)^.regs[regCounter].typ in
+          [con_ref,con_noRemoveRef]) do
     Inc(RegCounter);
     Inc(RegCounter);
   While (RegCounter <= R_EDI) Do
   While (RegCounter <= R_EDI) Do
     Begin
     Begin
@@ -140,7 +141,8 @@ Begin {CheckSequence}
       Repeat
       Repeat
         Inc(RegCounter);
         Inc(RegCounter);
       Until (RegCounter > R_EDI) or
       Until (RegCounter > R_EDI) or
-            ((PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].Typ = Con_Ref) {And
+            ((ppaiprop(prevNonRemovablePai^.optInfo)^.regs[regCounter].typ
+                in [con_ref,con_noRemoveRef]) {And
              ((Regcounter = Reg) Or
              ((Regcounter = Reg) Or
               Not(PaiInSequence(p, PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter]))) }
               Not(PaiInSequence(p, PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter]))) }
             );
             );
@@ -385,7 +387,7 @@ begin
   while assigned(p^.previous) and
   while assigned(p^.previous) and
         ((Pai(p^.previous)^.typ in (skipinstr+[ait_align])) or
         ((Pai(p^.previous)^.typ in (skipinstr+[ait_align])) or
          ((Pai(p^.previous)^.typ = ait_label) and
          ((Pai(p^.previous)^.typ = ait_label) and
-          not(Pai_Label(p^.previous)^.l^.is_used))) do
+          labelCanBeSkipped(pai_label(p^.previous)))) do
     begin
     begin
       p := pai(p^.previous);
       p := pai(p^.previous);
       if (p^.typ = ait_regalloc) and
       if (p^.typ = ait_regalloc) and
@@ -744,12 +746,13 @@ Begin
   Counter := R_NO;
   Counter := R_NO;
   repeat
   repeat
      inc(counter);
      inc(counter);
-     tmpresult := (PPaiProp(p^.OptInfo)^.Regs[Counter].Typ = Con_Const) and
+     tmpresult := (ppaiprop(p^.optInfo)^.regs[counter].typ in
+         [con_const,con_noRemoveConst]) and
        (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.opsize = size) and
        (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.opsize = size) and
        (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.oper[0].typ = top_const) and
        (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.oper[0].typ = top_const) and
        (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.oper[0].val = l);
        (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.oper[0].val = l);
 {$ifdef testing}
 {$ifdef testing}
-     if (PPaiProp(p^.OptInfo)^.Regs[Counter].Typ = Con_Const) then
+     if (ppaiprop(p^.optInfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) then
        begin
        begin
          hp := new(pai_asm_comment,init(strpnew(
          hp := new(pai_asm_comment,init(strpnew(
            'checking const load of '+tostr(l)+' here...')));
            'checking const load of '+tostr(l)+' here...')));
@@ -765,6 +768,34 @@ Begin
   FindRegWithConst := tmpResult;
   FindRegWithConst := tmpResult;
 End;
 End;
 
 
+procedure removePrevNotUsedLoad(p: pai; reg: tRegister; check: boolean);
+{ If check = true, it means the procedure has to check whether it isn't  }
+{ possible that the contents are still used after p (used when removing  }
+{ instructions because of a "call"), otherwise this is not necessary     }
+{ (e.g. when you have a "mov 8(%ebp),%eax", you can be sure the previous }
+{ value of %eax isn't used anymore later on)                             }
+var
+  hp1: pai;
+begin
+  if getLastInstruction(p,hp1) then
+    with ppaiprop(hp1^.optInfo)^.regs[reg] do
+      if (typ in [con_ref,con_invalid]) and
+         (nrOfMods = 1) and
+         (rState = ppaiprop(startmod^.optInfo)^.regs[reg].rState) and
+         (not(check) or
+          (not(regInInstruction(reg,p)) and
+           (not(reg in usableregs) and
+            (startmod^.typ = ait_instruction) and
+            ((paicpu(startmod)^.opcode = A_MOV) or
+             (paicpu(startmod)^.opcode = A_MOVZX) or
+             (paicpu(startmod)^.opcode = A_MOVSX)) and
+            (paicpu(startmod)^.oper[0].typ = top_ref) and
+            (paicpu(startmod)^.oper[0].ref^.base = stack_pointer)) or
+           not(reg in ppaiprop(hp1^.optInfo)^.usedRegs) or
+           findRegDealloc(reg,p))) then
+        ppaiprop(startMod^.optInfo)^.canBeRemoved := true;
+end;
+
 Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai);
 Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai);
 {marks the instructions that can be removed by RemoveInstructs. They're not
 {marks the instructions that can be removed by RemoveInstructs. They're not
  removed immediately because sometimes an instruction needs to be checked in
  removed immediately because sometimes an instruction needs to be checked in
@@ -789,6 +820,9 @@ Begin
         ait_instruction:
         ait_instruction:
           Begin
           Begin
             Case Paicpu(p)^.opcode Of
             Case Paicpu(p)^.opcode Of
+              A_CALL:
+                for regCounter := R_EAX to R_EBX do
+                  removePrevNotUsedLoad(p,regCounter,true);
               A_CLD: If GetLastInstruction(p, hp1) And
               A_CLD: If GetLastInstruction(p, hp1) And
                         (PPaiProp(hp1^.OptInfo)^.DirFlag = F_NotSet) Then
                         (PPaiProp(hp1^.OptInfo)^.DirFlag = F_NotSet) Then
                        PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;
                        PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;
@@ -964,7 +998,8 @@ Begin
                                  End
                                  End
                                Else
                                Else
                                  If (PPaiProp(p^.OptInfo)^.
                                  If (PPaiProp(p^.OptInfo)^.
-                                      Regs[Reg32(Paicpu(p)^.oper[1].reg)].Typ = Con_Ref) And
+                                      regs[reg32(paicpu(p)^.oper[1].reg)].typ
+                                        in [con_ref,con_noRemoveRef]) and
                                     (PPaiProp(p^.OptInfo)^.CanBeRemoved) Then
                                     (PPaiProp(p^.OptInfo)^.CanBeRemoved) Then
                                    if (cnt > 0) then
                                    if (cnt > 0) then
                                      begin
                                      begin
@@ -998,6 +1033,10 @@ Begin
                                      end;
                                      end;
                               End;
                               End;
                           End;
                           End;
+                        if not ppaiprop(p^.optinfo)^.canBeRemoved and
+                           not regInRef(reg32(paicpu(p)^.oper[1].reg),
+                                        paicpu(p)^.oper[0].ref^) then
+                          removePrevNotUsedLoad(p,reg32(paicpu(p)^.oper[1].reg),false);
                       End;
                       End;
                     top_Reg:
                     top_Reg:
                       { try to replace the new reg with the old reg }
                       { try to replace the new reg with the old reg }
@@ -1030,7 +1069,7 @@ Begin
                               regCounter := Reg32(Paicpu(p)^.oper[1].reg);
                               regCounter := Reg32(Paicpu(p)^.oper[1].reg);
                               If GetLastInstruction(p, hp1) Then
                               If GetLastInstruction(p, hp1) Then
                                 With PPaiProp(hp1^.OptInfo)^.Regs[regCounter] Do
                                 With PPaiProp(hp1^.OptInfo)^.Regs[regCounter] Do
-                                  If (Typ = Con_Const) And
+                                  if (typ in [con_const,con_noRemoveConst]) and
                                      (paicpu(startMod)^.opsize >= paicpu(p)^.opsize) and
                                      (paicpu(startMod)^.opsize >= paicpu(p)^.opsize) and
                                      opsequal(paicpu(StartMod)^.oper[0],paicpu(p)^.oper[0]) Then
                                      opsequal(paicpu(StartMod)^.oper[0],paicpu(p)^.oper[0]) Then
                                     begin
                                     begin
@@ -1116,7 +1155,19 @@ End.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.3  2000-07-14 05:11:48  michael
+  Revision 1.4  2000-07-21 15:19:54  jonas
+    * daopt386: changes to getnextinstruction/getlastinstruction so they
+      ignore labels who have is_addr set
+    + daopt386/csopt386: remove loads of registers which are overwritten
+       before their contents are used (especially usefull for removing superfluous
+      maybe_loadesi outputs and push/pops transformed by below optimization
+    + popt386: transform pop/pop/pop/.../push/push/push to sequences of
+      'movl x(%esp),%reg' (only active when compiling a go32v2 compiler
+      currently because I don't know whether it's safe to do this under Win32/
+      Linux (because of problems we had when using esp as frame pointer on
+      those os'es)
+
+  Revision 1.3  2000/07/14 05:11:48  michael
   + Patch to 1.1
   + Patch to 1.1
 
 
   Revision 1.2  2000/07/13 11:32:39  michael
   Revision 1.2  2000/07/13 11:32:39  michael

+ 70 - 48
compiler/daopt386.pas

@@ -65,6 +65,7 @@ function RegInOp(Reg: TRegister; const o:toper): Boolean;
 Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
 Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
 Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
 Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
 Procedure SkipHead(var P: Pai);
 Procedure SkipHead(var P: Pai);
+function labelCanBeSkipped(p: pai_label): boolean;
 
 
 Procedure RemoveLastDeallocForFuncRes(asmL: PAasmOutput; p: pai);
 Procedure RemoveLastDeallocForFuncRes(asmL: PAasmOutput; p: pai);
 Function regLoadedWithNewValue(reg: tregister; canDependOnPrevValue: boolean;
 Function regLoadedWithNewValue(reg: tregister; canDependOnPrevValue: boolean;
@@ -94,6 +95,14 @@ Const
   con_Unknown = 0;
   con_Unknown = 0;
   con_ref = 1;
   con_ref = 1;
   con_const = 2;
   con_const = 2;
+  { The contents aren't usable anymore for CSE, but they may still be   }
+  { usefull for detecting whether the result of a load is actually used }
+  con_invalid = 3;
+  { the reverse of the above (in case a (conditional) jump is encountered): }
+  { CSE is still possible, but the original instruction can't be removed    }
+  con_noRemoveRef = 4;
+  { same, but for constants }
+  con_noRemoveConst = 5;
 
 
 {********************************* Types *********************************}
 {********************************* Types *********************************}
 
 
@@ -268,7 +277,7 @@ Begin
     While Assigned(p) And
     While Assigned(p) And
           ((p^.typ in (SkipInstr - [ait_RegAlloc])) or
           ((p^.typ in (SkipInstr - [ait_RegAlloc])) or
            ((p^.typ = ait_label) And
            ((p^.typ = ait_label) And
-            Not(Pai_Label(p)^.l^.is_used))) Do
+            labelCanBeSkipped(pai_label(current)))) Do
          p := Pai(p^.next);
          p := Pai(p^.next);
     While Assigned(p) And
     While Assigned(p) And
           (p^.typ=ait_RegAlloc) Do
           (p^.typ=ait_RegAlloc) Do
@@ -282,7 +291,7 @@ Begin
   Until Not(Assigned(p)) Or
   Until Not(Assigned(p)) Or
         (Not(p^.typ in SkipInstr) And
         (Not(p^.typ in SkipInstr) And
          Not((p^.typ = ait_label) And
          Not((p^.typ = ait_label) And
-            Not(Pai_Label(p)^.l^.is_used)));
+             labelCanBeSkipped(pai_label(current))));
 End;
 End;
 
 
 {$endif tempOpts}
 {$endif tempOpts}
@@ -302,7 +311,7 @@ Begin
   While Assigned(P) Do
   While Assigned(P) Do
     Begin
     Begin
       If (Pai(p)^.typ = ait_label) Then
       If (Pai(p)^.typ = ait_label) Then
-        If (Pai_Label(p)^.l^.is_used)
+        If not labelCanBeSkipped(pai_label(p))
           Then
           Then
             Begin
             Begin
               LabelFound := True;
               LabelFound := True;
@@ -332,7 +341,7 @@ Begin
     While Assigned(StartPai) And
     While Assigned(StartPai) And
           ((StartPai^.typ in (SkipInstr - [ait_regAlloc])) Or
           ((StartPai^.typ in (SkipInstr - [ait_regAlloc])) Or
            ((StartPai^.typ = ait_label) and
            ((StartPai^.typ = ait_label) and
-            Not(Pai_Label(StartPai)^.l^.Is_Used))) Do
+            labelCanBeSkipped(pai_label(startPai)))) Do
       StartPai := Pai(StartPai^.Next);
       StartPai := Pai(StartPai^.Next);
     If Assigned(StartPai) And
     If Assigned(StartPai) And
        (StartPai^.typ = ait_regAlloc) and (PairegAlloc(StartPai)^.allocation = alloc) Then
        (StartPai^.typ = ait_regAlloc) and (PairegAlloc(StartPai)^.allocation = alloc) Then
@@ -474,7 +483,7 @@ Begin
     Begin
     Begin
       Case p^.typ Of
       Case p^.typ Of
         ait_Label:
         ait_Label:
-          If Pai_Label(p)^.l^.is_used Then
+          If not labelCanBeSkipped(pai_label(p)) Then
             LabelTable^[Pai_Label(p)^.l^.labelnr-LowLabel].PaiObj := p;
             LabelTable^[Pai_Label(p)^.l^.labelnr-LowLabel].PaiObj := p;
         ait_regAlloc:
         ait_regAlloc:
           { ESI and EDI are (de)allocated manually, don't mess with them }
           { ESI and EDI are (de)allocated manually, don't mess with them }
@@ -961,9 +970,9 @@ Begin
       End;
       End;
     Current := Pai(Current^.Next);
     Current := Pai(Current^.Next);
     While Assigned(Current) And
     While Assigned(Current) And
-           ((Current^.typ In SkipInstr) or
-            ((Current^.typ = ait_label) And
-             Not(Pai_Label(Current)^.l^.is_used))) Do
+          ((current^.typ In skipInstr) or
+           ((current^.typ = ait_label) and
+            labelCanBeSkipped(pai_label(current)))) do
       Current := Pai(Current^.Next);
       Current := Pai(Current^.Next);
     If Assigned(Current) And
     If Assigned(Current) And
        (Current^.typ = ait_Marker) And
        (Current^.typ = ait_Marker) And
@@ -981,7 +990,7 @@ Begin
   If Assigned(Current) And
   If Assigned(Current) And
      Not((Current^.typ In SkipInstr) or
      Not((Current^.typ In SkipInstr) or
          ((Current^.typ = ait_label) And
          ((Current^.typ = ait_label) And
-          Not(Pai_Label(Current)^.l^.is_used)))
+          labelCanBeSkipped(pai_label(current))))
     Then
     Then
       GetNextInstruction :=
       GetNextInstruction :=
          not((current^.typ = ait_marker) and
          not((current^.typ = ait_marker) and
@@ -1004,7 +1013,7 @@ Begin
             Not(Pai_Marker(Current)^.Kind in [AsmBlockEnd,NoPropInfoEnd])) or
             Not(Pai_Marker(Current)^.Kind in [AsmBlockEnd,NoPropInfoEnd])) or
            (Current^.typ In SkipInstr) or
            (Current^.typ In SkipInstr) or
            ((Current^.typ = ait_label) And
            ((Current^.typ = ait_label) And
-             Not(Pai_Label(Current)^.l^.is_used))) Do
+            labelCanBeSkipped(pai_label(current)))) Do
       Current := Pai(Current^.previous);
       Current := Pai(Current^.previous);
     If Assigned(Current) And
     If Assigned(Current) And
        (Current^.typ = ait_Marker) And
        (Current^.typ = ait_Marker) And
@@ -1021,7 +1030,7 @@ Begin
   If Not(Assigned(Current)) or
   If Not(Assigned(Current)) or
      (Current^.typ In SkipInstr) or
      (Current^.typ In SkipInstr) or
      ((Current^.typ = ait_label) And
      ((Current^.typ = ait_label) And
-      Not(Pai_Label(Current)^.l^.is_used)) or
+      labelCanBeSkipped(pai_label(current))) or
      ((Current^.typ = ait_Marker) And
      ((Current^.typ = ait_Marker) And
       (Pai_Marker(Current)^.Kind = AsmBlockEnd))
       (Pai_Marker(Current)^.Kind = AsmBlockEnd))
     Then
     Then
@@ -1050,16 +1059,14 @@ Begin
    {a marker of the NoPropInfoStart can't be the first instruction of a
    {a marker of the NoPropInfoStart can't be the first instruction of a
     paasmoutput list}
     paasmoutput list}
       GetNextInstruction(Pai(P^.Previous),P);
       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
     Until P = OldP
 End;
 End;
+
+function labelCanBeSkipped(p: pai_label): boolean;
+begin
+  labelCanBeSkipped := not(p^.l^.is_used) or p^.l^.is_addr;
+end;
+
 {******************* The Data Flow Analyzer functions ********************}
 {******************* The Data Flow Analyzer functions ********************}
 
 
 function regLoadedWithNewValue(reg: tregister; canDependOnPrevValue: boolean;
 function regLoadedWithNewValue(reg: tregister; canDependOnPrevValue: boolean;
@@ -1091,7 +1098,7 @@ Begin
     While Assigned(p) And
     While Assigned(p) And
           ((p^.typ in (SkipInstr - [ait_RegAlloc])) or
           ((p^.typ in (SkipInstr - [ait_RegAlloc])) or
            ((p^.typ = ait_label) And
            ((p^.typ = ait_label) And
-            Not(Pai_Label(p)^.l^.is_used))) Do
+            labelCanBeSkipped(pai_label(p)))) Do
          p := Pai(p^.next);
          p := Pai(p^.next);
     While Assigned(p) And
     While Assigned(p) And
           (p^.typ=ait_RegAlloc) Do
           (p^.typ=ait_RegAlloc) Do
@@ -1105,7 +1112,7 @@ Begin
   Until Not(Assigned(p)) Or
   Until Not(Assigned(p)) Or
         (Not(p^.typ in SkipInstr) And
         (Not(p^.typ in SkipInstr) And
          Not((p^.typ = ait_label) And
          Not((p^.typ = ait_label) And
-            Not(Pai_Label(p)^.l^.is_used)));
+             labelCanBeSkipped(pai_label(p))));
 End;
 End;
 
 
 Procedure AllocRegBetween(AsmL: PAasmOutput; Reg: TRegister; p1, p2: Pai);
 Procedure AllocRegBetween(AsmL: PAasmOutput; Reg: TRegister; p1, p2: Pai);
@@ -1227,8 +1234,8 @@ Procedure DestroyReg(p1: PPaiProp; Reg: TRegister; doIncState:Boolean);
  contents of registers are loaded with a memory location based on Reg.
  contents of registers are loaded with a memory location based on Reg.
  doIncState is false when this register has to be destroyed not because
  doIncState is false when this register has to be destroyed not because
  it's contents are directly modified/overwritten, but because of an indirect
  it's contents are directly modified/overwritten, but because of an indirect
- action (ie. this register holds the contents of a variable and the value
- of the variable in memory is changed }
+ action (e.g. this register holds the contents of a variable and the value
+ of the variable in memory is changed) }
 Var TmpWState, TmpRState: Byte;
 Var TmpWState, TmpRState: Byte;
     Counter: TRegister;
     Counter: TRegister;
 Begin
 Begin
@@ -1244,26 +1251,22 @@ Begin
         With p1^.Regs[Reg] Do
         With p1^.Regs[Reg] Do
           Begin
           Begin
             if doIncState then
             if doIncState then
-              IncState(WState);
-            TmpWState := WState;
-            TmpRState := RState;
-            FillChar(p1^.Regs[Reg], SizeOf(TContent), 0);
-            WState := TmpWState;
-            RState := TmpRState;
-          End;
-        For counter := R_EAX to R_EDI Do
-          With p1^.Regs[counter] Do
-            If (Typ = Con_Ref) And
-               sequenceDependsOnReg(p1^.Regs[counter],counter,reg) Then
-              Begin
-                if doIncState then
-                  IncState(WState);
+              begin
+                IncState(WState);
                 TmpWState := WState;
                 TmpWState := WState;
                 TmpRState := RState;
                 TmpRState := RState;
-                FillChar(p1^.Regs[Counter], SizeOf(TContent), 0);
+                FillChar(p1^.Regs[Reg], SizeOf(TContent), 0);
                 WState := TmpWState;
                 WState := TmpWState;
                 RState := TmpRState;
                 RState := TmpRState;
-              End;
+              end
+            else
+              typ := con_invalid;
+          End;
+        For counter := R_EAX to R_EDI Do
+          With p1^.Regs[counter] Do
+            if (typ in [con_ref,con_noRemoveRef]) and
+               sequenceDependsOnReg(p1^.Regs[counter],counter,reg) Then
+              typ := con_invalid;
        End;
        End;
 End;
 End;
 
 
@@ -1581,7 +1584,7 @@ Begin
       For Counter := R_EAX to R_EDI Do
       For Counter := R_EAX to R_EDI Do
         With PPaiProp(p^.OptInfo)^.Regs[Counter] Do
         With PPaiProp(p^.OptInfo)^.Regs[Counter] Do
           Begin
           Begin
-            If (typ = Con_Ref) And
+            if (typ in [con_ref,con_noRemoveRef]) and
                ((Not(cs_UncertainOpts in aktglobalswitches) And
                ((Not(cs_UncertainOpts in aktglobalswitches) And
                  (NrOfMods <> 1)
                  (NrOfMods <> 1)
                 ) Or
                 ) Or
@@ -1609,7 +1612,7 @@ Begin
       }
       }
     For Counter := R_EAX to R_EDI Do
     For Counter := R_EAX to R_EDI Do
       With PPaiProp(p^.OptInfo)^.Regs[Counter] Do
       With PPaiProp(p^.OptInfo)^.Regs[Counter] Do
-      If (typ = Con_Ref) And
+      if (typ in [con_ref,con_noRemoveRef]) And
          (Not(cs_UncertainOpts in aktglobalswitches) Or
          (Not(cs_UncertainOpts in aktglobalswitches) Or
       {for movsl}
       {for movsl}
           (Ref.Base = R_EDI) Or
           (Ref.Base = R_EDI) Or
@@ -1681,7 +1684,7 @@ var hp: pai;
 Begin
 Begin
   Reg := Reg32(Reg);
   Reg := Reg32(Reg);
   With PPaiProp(p^.optinfo)^.Regs[reg] Do
   With PPaiProp(p^.optinfo)^.Regs[reg] Do
-    If (Typ = Con_Ref)
+    if (typ in [con_ref,con_noRemoveRef])
       Then
       Then
         Begin
         Begin
           IncState(WState);
           IncState(WState);
@@ -1784,13 +1787,14 @@ Begin
       For TmpReg := R_EAX To R_EDI Do
       For TmpReg := R_EAX To R_EDI Do
         Inc(NrOfInstrSinceLastMod[TmpReg]);
         Inc(NrOfInstrSinceLastMod[TmpReg]);
       Case p^.typ Of
       Case p^.typ Of
+        ait_marker:;
         ait_label:
         ait_label:
 {$Ifndef JumpAnal}
 {$Ifndef JumpAnal}
-          If (Pai_label(p)^.l^.is_used) Then
+          If not labelCanBeSkipped(pai_label(p)) Then
             DestroyAllRegs(CurProp);
             DestroyAllRegs(CurProp);
 {$Else JumpAnal}
 {$Else JumpAnal}
           Begin
           Begin
-           If (Pai_Label(p)^.is_used) Then
+           If not labelCanBeSkipped(pai_label(p)) Then
              With LTable^[Pai_Label(p)^.l^.labelnr-LoLab] Do
              With LTable^[Pai_Label(p)^.l^.labelnr-LoLab] Do
 {$IfDef AnalyzeLoops}
 {$IfDef AnalyzeLoops}
               If (RefsFound = Pai_Label(p)^.l^.RefCount)
               If (RefsFound = Pai_Label(p)^.l^.RefCount)
@@ -1886,7 +1890,13 @@ Begin
             if paicpu(p)^.is_jmp then
             if paicpu(p)^.is_jmp then
              begin
              begin
 {$IfNDef JumpAnal}
 {$IfNDef JumpAnal}
-  ;
+                for tmpReg := R_EAX to R_EDI do
+                  with curProp^.regs[tmpReg] do
+                    case typ of
+                      con_ref: typ := con_noRemoveRef;
+                      con_const: typ := con_noRemoveConst;
+                      con_invalid: typ := con_unknown;
+                    end;
 {$Else JumpAnal}
 {$Else JumpAnal}
           With LTable^[pasmlabel(paicpu(p)^.oper[0].sym)^.labelnr-LoLab] Do
           With LTable^[pasmlabel(paicpu(p)^.oper[0].sym)^.labelnr-LoLab] Do
             If (RefsFound = pasmlabel(paicpu(p)^.oper[0].sym)^.RefCount) Then
             If (RefsFound = pasmlabel(paicpu(p)^.oper[0].sym)^.RefCount) Then
@@ -2007,7 +2017,7 @@ Begin
                         ReadRef(CurProp, Paicpu(p)^.oper[0].ref);
                         ReadRef(CurProp, Paicpu(p)^.oper[0].ref);
                         TmpReg := Reg32(Paicpu(p)^.oper[1].reg);
                         TmpReg := Reg32(Paicpu(p)^.oper[1].reg);
                         If RegInRef(TmpReg, Paicpu(p)^.oper[0].ref^) And
                         If RegInRef(TmpReg, Paicpu(p)^.oper[0].ref^) And
-                           (CurProp^.Regs[TmpReg].Typ = Con_Ref)
+                           (curProp^.regs[tmpReg].typ in [con_ref,con_noRemoveRef])
                           Then
                           Then
                             Begin
                             Begin
                               With CurProp^.Regs[TmpReg] Do
                               With CurProp^.Regs[TmpReg] Do
@@ -2231,7 +2241,7 @@ Begin
       Case P^.Typ Of
       Case P^.Typ Of
         ait_label:
         ait_label:
           Begin
           Begin
-            If (Pai_Label(p)^.l^.is_used) Then
+            If not labelCanBeSkipped(pai_label(p)) Then
               LTable^[Pai_Label(P)^.l^.labelnr-LoLab].InstrNr := NrOfPaiObjs
               LTable^[Pai_Label(P)^.l^.labelnr-LoLab].InstrNr := NrOfPaiObjs
           End;
           End;
         ait_instruction:
         ait_instruction:
@@ -2310,7 +2320,19 @@ End.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.3  2000-07-14 05:11:48  michael
+  Revision 1.4  2000-07-21 15:19:54  jonas
+    * daopt386: changes to getnextinstruction/getlastinstruction so they
+      ignore labels who have is_addr set
+    + daopt386/csopt386: remove loads of registers which are overwritten
+       before their contents are used (especially usefull for removing superfluous
+      maybe_loadesi outputs and push/pops transformed by below optimization
+    + popt386: transform pop/pop/pop/.../push/push/push to sequences of
+      'movl x(%esp),%reg' (only active when compiling a go32v2 compiler
+      currently because I don't know whether it's safe to do this under Win32/
+      Linux (because of problems we had when using esp as frame pointer on
+      those os'es)
+
+  Revision 1.3  2000/07/14 05:11:48  michael
   + Patch to 1.1
   + Patch to 1.1
 
 
   Revision 1.2  2000/07/13 11:32:40  michael
   Revision 1.2  2000/07/13 11:32:40  michael

+ 89 - 44
compiler/popt386.pas

@@ -101,15 +101,16 @@ Procedure PeepHoleOptPass1(Asml: PAasmOutput; BlockStart, BlockEnd: Pai);
 {First pass of peepholeoptimizations}
 {First pass of peepholeoptimizations}
 
 
 Var
 Var
-  l : longint;
+  l, l1 : longint;
   p,hp1,hp2 : pai;
   p,hp1,hp2 : pai;
   hp3,hp4: pai;
   hp3,hp4: pai;
-  TmpBool1, TmpBool2: Boolean;
 
 
   TmpRef: TReference;
   TmpRef: TReference;
 
 
   UsedRegs, TmpUsedRegs: TRegSet;
   UsedRegs, TmpUsedRegs: TRegSet;
 
 
+  TmpBool1, TmpBool2: Boolean;
+
   Function SkipLabels(hp: Pai; var hp2: pai): boolean;
   Function SkipLabels(hp: Pai; var hp2: pai): boolean;
   {skips all labels and returns the next "real" instruction}
   {skips all labels and returns the next "real" instruction}
   Begin
   Begin
@@ -279,7 +280,7 @@ Begin
                    While GetNextInstruction(p, hp1) and
                    While GetNextInstruction(p, hp1) and
                          ((hp1^.typ <> ait_label) or
                          ((hp1^.typ <> ait_label) or
                    { skip unused labels, they're not referenced anywhere }
                    { skip unused labels, they're not referenced anywhere }
-                          Not(Pai_Label(hp1)^.l^.is_used)) Do
+                          labelCanBeSkipped(pai_label(hp1))) Do
                      If not(hp1^.typ in ([ait_label,ait_align]+skipinstr)) Then
                      If not(hp1^.typ in ([ait_label,ait_align]+skipinstr)) Then
                        Begin
                        Begin
                          AsmL^.Remove(hp1);
                          AsmL^.Remove(hp1);
@@ -1224,37 +1225,81 @@ Begin
                 End;
                 End;
               A_POP:
               A_POP:
                 Begin
                 Begin
+{$ifdef go32v2}
+                   { Transform a series of pop/pop/pop/push/push/push to }
+                   { 'movl x(%esp),%reg' for go32v2 (not for the rest,   }
+                   { because I'm not sure whether they can cope with     }
+                   { 'movl x(%esp),%reg' with x > 0, I believe we had    }
+                   { such a problem when using esp as frame pointer (JM) }
+                   if (Paicpu(p)^.oper[0].typ = top_reg) then
+                     begin
+                       hp1 := p;
+                       hp2 := p;
+                       l := 0;
+                       while getNextInstruction(hp1,hp1) and
+                             (hp1^.typ = ait_instruction) and
+                             (paicpu(hp1)^.opcode = A_POP) and
+                             (paicpu(hp1)^.oper[0].typ = top_reg) do
+                         begin
+                           hp2 := hp1;
+                           inc(l,4);
+                         end;
+                       getLastInstruction(p,hp3);
+                       l1 := 0;
+                       while (hp2 <> hp3) and
+                             assigned(hp1) and
+                             (hp1^.typ = ait_instruction) and
+                             (paicpu(hp1)^.opcode = A_PUSH) and
+                             (paicpu(hp1)^.oper[0].typ = top_reg) and
+                             (paicpu(hp1)^.oper[0].reg = paicpu(hp2)^.oper[0].reg) do
+                         begin
+                           { change it to a two op operation }
+                           paicpu(hp2)^.oper[1].typ:=top_none;
+                           paicpu(hp2)^.ops:=2;
+                           paicpu(hp2)^.opcode := A_MOV;
+                           paicpu(hp2)^.Loadoper(1,paicpu(hp1)^.oper[0]);
+                           reset_reference(tmpref);
+                           tmpRef.base := stack_pointer;
+                           tmpRef.offset := l;
+                           paicpu(hp2)^.loadRef(0,newReference(tmpRef));
+                           hp4 := hp1;
+                           getNextInstruction(hp1,hp1);
+                           asmL^.remove(hp4);
+                           dispose(hp4,done);
+                           getLastInstruction(hp2,hp2);
+                           dec(l,4);
+                           inc(l1);
+                         end;
+                       if l <> -4 then
+                         begin
+                           inc(l,4);
+                           for l1 := l1 downto 1 do
+                             begin
+                               getNextInstruction(hp2,hp2);
+                               dec(paicpu(hp2)^.oper[0].ref^.offset,l);
+                             end
+                         end
+                     end
+{$else go32v2}
                    if (Paicpu(p)^.oper[0].typ = top_reg) And
                    if (Paicpu(p)^.oper[0].typ = top_reg) And
                       GetNextInstruction(p, hp1) And
                       GetNextInstruction(p, hp1) And
                       (pai(hp1)^.typ=ait_instruction) and
                       (pai(hp1)^.typ=ait_instruction) and
                       (Paicpu(hp1)^.opcode=A_PUSH) and
                       (Paicpu(hp1)^.opcode=A_PUSH) and
                       (Paicpu(hp1)^.oper[0].typ = top_reg) And
                       (Paicpu(hp1)^.oper[0].typ = top_reg) And
                       (Paicpu(hp1)^.oper[0].reg=Paicpu(p)^.oper[0].reg) then
                       (Paicpu(hp1)^.oper[0].reg=Paicpu(p)^.oper[0].reg) then
-                  { This can't be done, because the register which is popped
-                    can still be used after the push (PFV)
-                     If (Not(cs_regalloc in aktglobalswitches)) Then
-                       Begin
-                         hp2:=pai(hp1^.next);
-                         asml^.remove(p);
-                         asml^.remove(hp1);
-                         dispose(p,done);
-                         dispose(hp1,done);
-                         p:=hp2;
-                         continue
-                       End
-                     Else }
-                       Begin
-                         { change it to a two op operation }
-                         Paicpu(p)^.oper[1].typ:=top_none;
-                         Paicpu(p)^.ops:=2;
-                         Paicpu(p)^.opcode := A_MOV;
-                         Paicpu(p)^.Loadoper(1,Paicpu(p)^.oper[0]);
-                         Reset_reference(tmpref);
-                         TmpRef.base := R_ESP;
-                         Paicpu(p)^.LoadRef(0,newReference(TmpRef));
-                         AsmL^.Remove(hp1);
-                         Dispose(hp1, Done)
-                       End;
+                     Begin
+                       { change it to a two op operation }
+                       Paicpu(p)^.oper[1].typ:=top_none;
+                       Paicpu(p)^.ops:=2;
+                       Paicpu(p)^.opcode := A_MOV;
+                       Paicpu(p)^.Loadoper(1,Paicpu(p)^.oper[0]);
+                       Reset_reference(tmpref);
+                       TmpRef.base := R_ESP;
+                       Paicpu(p)^.LoadRef(0,newReference(TmpRef));
+                       AsmL^.Remove(hp1);
+                       Dispose(hp1, Done)
+                     End;
+{$endif go32v2}
                 end;
                 end;
               A_PUSH:
               A_PUSH:
                 Begin
                 Begin
@@ -1523,7 +1568,7 @@ Begin
           End;
           End;
 {        ait_label:
 {        ait_label:
           Begin
           Begin
-            If Not(Pai_Label(p)^.l^.is_used)
+            If labelCanBeSkipped(pai_label(p))
               Then
               Then
                 Begin
                 Begin
                   hp1 := Pai(p^.next);
                   hp1 := Pai(p^.next);
@@ -1538,7 +1583,6 @@ Begin
     end;
     end;
 end;
 end;
 
 
-{$ifdef foldArithOps}
 function isFoldableArithOp(hp1: paicpu; reg: tregister): boolean;
 function isFoldableArithOp(hp1: paicpu; reg: tregister): boolean;
 begin
 begin
   IsFoldableArithOp := False;
   IsFoldableArithOp := False;
@@ -1551,12 +1595,11 @@ begin
         (paicpu(hp1)^.oper[1].typ = top_reg) and
         (paicpu(hp1)^.oper[1].typ = top_reg) and
         (paicpu(hp1)^.oper[1].reg = reg);
         (paicpu(hp1)^.oper[1].reg = reg);
     A_INC,A_DEC:
     A_INC,A_DEC:
-      isFoldableArithOp := 
+      isFoldableArithOp :=
         (paicpu(hp1)^.oper[0].typ = top_reg) and
         (paicpu(hp1)^.oper[0].typ = top_reg) and
         (paicpu(hp1)^.oper[0].reg = reg);
         (paicpu(hp1)^.oper[0].reg = reg);
   end;
   end;
 end;
 end;
-{$endif foldArithOps}
 
 
 
 
 Procedure PeepHoleOptPass2(AsmL: PAasmOutput; BlockStart, BlockEnd: Pai);
 Procedure PeepHoleOptPass2(AsmL: PAasmOutput; BlockStart, BlockEnd: Pai);
@@ -1578,20 +1621,14 @@ var
   condition : tasmcond;
   condition : tasmcond;
   hp3: pai;
   hp3: pai;
 {$endif USECMOV}
 {$endif USECMOV}
-{$ifdef foldArithOps}
   UsedRegs, TmpUsedRegs: TRegSet;
   UsedRegs, TmpUsedRegs: TRegSet;
-{$endif foldArithOps}
 
 
 Begin
 Begin
   P := BlockStart;
   P := BlockStart;
-{$ifdef foldArithOps}
   UsedRegs := [];
   UsedRegs := [];
-{$endif foldArithOps}
   While (P <> BlockEnd) Do
   While (P <> BlockEnd) Do
     Begin
     Begin
-{$ifdef foldArithOps}
       UpdateUsedRegs(UsedRegs, Pai(p^.next));
       UpdateUsedRegs(UsedRegs, Pai(p^.next));
-{$endif foldArithOps}
       Case P^.Typ Of
       Case P^.Typ Of
         Ait_Instruction:
         Ait_Instruction:
           Begin
           Begin
@@ -1711,7 +1748,6 @@ Begin
               A_FSTP,A_FISTP:
               A_FSTP,A_FISTP:
                 if doFpuLoadStoreOpt(asmL,p) then
                 if doFpuLoadStoreOpt(asmL,p) then
                   continue;
                   continue;
-{$ifdef foldArithOps}
               A_IMUL:
               A_IMUL:
                 begin
                 begin
                   if ((paicpu(p)^.oper[0].typ = top_const) or
                   if ((paicpu(p)^.oper[0].typ = top_const) or
@@ -1735,7 +1771,6 @@ Begin
                       dispose(hp1,done);
                       dispose(hp1,done);
                     end;
                     end;
                 end;
                 end;
-{$endif foldArithOps}
               A_MOV:
               A_MOV:
                 Begin
                 Begin
                   If (Paicpu(p)^.oper[0].typ = top_reg) And
                   If (Paicpu(p)^.oper[0].typ = top_reg) And
@@ -1762,7 +1797,6 @@ Begin
                       p := hp1;
                       p := hp1;
                       Continue;
                       Continue;
                     End
                     End
-{$ifdef foldArithOps}
                   Else If (Paicpu(p)^.oper[0].typ = top_ref) And
                   Else If (Paicpu(p)^.oper[0].typ = top_ref) And
                     GetNextInstruction(p,hp1) And
                     GetNextInstruction(p,hp1) And
                     (hp1^.typ = ait_instruction) And
                     (hp1^.typ = ait_instruction) And
@@ -1787,7 +1821,7 @@ Begin
   { to       add/sub/or/... reg2/$const, (ref)    }
   { to       add/sub/or/... reg2/$const, (ref)    }
                      Begin
                      Begin
                        case paicpu(hp1)^.opcode of
                        case paicpu(hp1)^.opcode of
-                         A_INC,A_DEC: 
+                         A_INC,A_DEC:
                            paicpu(hp1)^.LoadRef(0,newreference(Paicpu(p)^.oper[0].ref^))
                            paicpu(hp1)^.LoadRef(0,newreference(Paicpu(p)^.oper[0].ref^))
                          else
                          else
                            paicpu(hp1)^.LoadRef(1,newreference(Paicpu(p)^.oper[0].ref^));
                            paicpu(hp1)^.LoadRef(1,newreference(Paicpu(p)^.oper[0].ref^));
@@ -1799,7 +1833,6 @@ Begin
                        p := hp1
                        p := hp1
                      End;
                      End;
                    End
                    End
-{$endif foldArithOps}
                   else if (Paicpu(p)^.oper[0].typ = Top_Const) And
                   else if (Paicpu(p)^.oper[0].typ = Top_Const) And
                      (Paicpu(p)^.oper[0].val = 0) And
                      (Paicpu(p)^.oper[0].val = 0) And
                      (Paicpu(p)^.oper[1].typ = Top_Reg) Then
                      (Paicpu(p)^.oper[1].typ = Top_Reg) Then
@@ -1913,7 +1946,19 @@ End.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.3  2000-07-14 05:11:49  michael
+  Revision 1.4  2000-07-21 15:19:55  jonas
+    * daopt386: changes to getnextinstruction/getlastinstruction so they
+      ignore labels who have is_addr set
+    + daopt386/csopt386: remove loads of registers which are overwritten
+       before their contents are used (especially usefull for removing superfluous
+      maybe_loadesi outputs and push/pops transformed by below optimization
+    + popt386: transform pop/pop/pop/.../push/push/push to sequences of
+      'movl x(%esp),%reg' (only active when compiling a go32v2 compiler
+      currently because I don't know whether it's safe to do this under Win32/
+      Linux (because of problems we had when using esp as frame pointer on
+      those os'es)
+
+  Revision 1.3  2000/07/14 05:11:49  michael
   + Patch to 1.1
   + Patch to 1.1
 
 
   Revision 1.2  2000/07/13 11:32:45  michael
   Revision 1.2  2000/07/13 11:32:45  michael