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;
   GetLastInstruction(p, PrevNonRemovablePai);
   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);
   While (RegCounter <= R_EDI) Do
     Begin
@@ -140,7 +141,8 @@ Begin {CheckSequence}
       Repeat
         Inc(RegCounter);
       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
               Not(PaiInSequence(p, PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter]))) }
             );
@@ -385,7 +387,7 @@ begin
   while assigned(p^.previous) and
         ((Pai(p^.previous)^.typ in (skipinstr+[ait_align])) or
          ((Pai(p^.previous)^.typ = ait_label) and
-          not(Pai_Label(p^.previous)^.l^.is_used))) do
+          labelCanBeSkipped(pai_label(p^.previous)))) do
     begin
       p := pai(p^.previous);
       if (p^.typ = ait_regalloc) and
@@ -744,12 +746,13 @@ Begin
   Counter := R_NO;
   repeat
      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)^.oper[0].typ = top_const) and
        (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.oper[0].val = l);
 {$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
          hp := new(pai_asm_comment,init(strpnew(
            'checking const load of '+tostr(l)+' here...')));
@@ -765,6 +768,34 @@ Begin
   FindRegWithConst := tmpResult;
 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);
 {marks the instructions that can be removed by RemoveInstructs. They're not
  removed immediately because sometimes an instruction needs to be checked in
@@ -789,6 +820,9 @@ Begin
         ait_instruction:
           Begin
             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
                         (PPaiProp(hp1^.OptInfo)^.DirFlag = F_NotSet) Then
                        PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;
@@ -964,7 +998,8 @@ Begin
                                  End
                                Else
                                  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
                                    if (cnt > 0) then
                                      begin
@@ -998,6 +1033,10 @@ Begin
                                      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;
                     top_Reg:
                       { try to replace the new reg with the old reg }
@@ -1030,7 +1069,7 @@ Begin
                               regCounter := Reg32(Paicpu(p)^.oper[1].reg);
                               If GetLastInstruction(p, hp1) Then
                                 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
                                      opsequal(paicpu(StartMod)^.oper[0],paicpu(p)^.oper[0]) Then
                                     begin
@@ -1116,7 +1155,19 @@ End.
 
 {
   $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
 
   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 GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
 Procedure SkipHead(var P: Pai);
+function labelCanBeSkipped(p: pai_label): boolean;
 
 Procedure RemoveLastDeallocForFuncRes(asmL: PAasmOutput; p: pai);
 Function regLoadedWithNewValue(reg: tregister; canDependOnPrevValue: boolean;
@@ -94,6 +95,14 @@ Const
   con_Unknown = 0;
   con_ref = 1;
   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 *********************************}
 
@@ -268,7 +277,7 @@ Begin
     While Assigned(p) And
           ((p^.typ in (SkipInstr - [ait_RegAlloc])) or
            ((p^.typ = ait_label) And
-            Not(Pai_Label(p)^.l^.is_used))) Do
+            labelCanBeSkipped(pai_label(current)))) Do
          p := Pai(p^.next);
     While Assigned(p) And
           (p^.typ=ait_RegAlloc) Do
@@ -282,7 +291,7 @@ Begin
   Until Not(Assigned(p)) Or
         (Not(p^.typ in SkipInstr) And
          Not((p^.typ = ait_label) And
-            Not(Pai_Label(p)^.l^.is_used)));
+             labelCanBeSkipped(pai_label(current))));
 End;
 
 {$endif tempOpts}
@@ -302,7 +311,7 @@ Begin
   While Assigned(P) Do
     Begin
       If (Pai(p)^.typ = ait_label) Then
-        If (Pai_Label(p)^.l^.is_used)
+        If not labelCanBeSkipped(pai_label(p))
           Then
             Begin
               LabelFound := True;
@@ -332,7 +341,7 @@ Begin
     While Assigned(StartPai) And
           ((StartPai^.typ in (SkipInstr - [ait_regAlloc])) Or
            ((StartPai^.typ = ait_label) and
-            Not(Pai_Label(StartPai)^.l^.Is_Used))) Do
+            labelCanBeSkipped(pai_label(startPai)))) Do
       StartPai := Pai(StartPai^.Next);
     If Assigned(StartPai) And
        (StartPai^.typ = ait_regAlloc) and (PairegAlloc(StartPai)^.allocation = alloc) Then
@@ -474,7 +483,7 @@ Begin
     Begin
       Case p^.typ Of
         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;
         ait_regAlloc:
           { ESI and EDI are (de)allocated manually, don't mess with them }
@@ -961,9 +970,9 @@ Begin
       End;
     Current := Pai(Current^.Next);
     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);
     If Assigned(Current) And
        (Current^.typ = ait_Marker) And
@@ -981,7 +990,7 @@ Begin
   If Assigned(Current) And
      Not((Current^.typ In SkipInstr) or
          ((Current^.typ = ait_label) And
-          Not(Pai_Label(Current)^.l^.is_used)))
+          labelCanBeSkipped(pai_label(current))))
     Then
       GetNextInstruction :=
          not((current^.typ = ait_marker) and
@@ -1004,7 +1013,7 @@ Begin
             Not(Pai_Marker(Current)^.Kind in [AsmBlockEnd,NoPropInfoEnd])) or
            (Current^.typ In SkipInstr) or
            ((Current^.typ = ait_label) And
-             Not(Pai_Label(Current)^.l^.is_used))) Do
+            labelCanBeSkipped(pai_label(current)))) Do
       Current := Pai(Current^.previous);
     If Assigned(Current) And
        (Current^.typ = ait_Marker) And
@@ -1021,7 +1030,7 @@ Begin
   If Not(Assigned(Current)) or
      (Current^.typ In SkipInstr) or
      ((Current^.typ = ait_label) And
-      Not(Pai_Label(Current)^.l^.is_used)) or
+      labelCanBeSkipped(pai_label(current))) or
      ((Current^.typ = ait_Marker) And
       (Pai_Marker(Current)^.Kind = AsmBlockEnd))
     Then
@@ -1050,16 +1059,14 @@ Begin
    {a marker of the NoPropInfoStart can't 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;
+
+function labelCanBeSkipped(p: pai_label): boolean;
+begin
+  labelCanBeSkipped := not(p^.l^.is_used) or p^.l^.is_addr;
+end;
+
 {******************* The Data Flow Analyzer functions ********************}
 
 function regLoadedWithNewValue(reg: tregister; canDependOnPrevValue: boolean;
@@ -1091,7 +1098,7 @@ Begin
     While Assigned(p) And
           ((p^.typ in (SkipInstr - [ait_RegAlloc])) or
            ((p^.typ = ait_label) And
-            Not(Pai_Label(p)^.l^.is_used))) Do
+            labelCanBeSkipped(pai_label(p)))) Do
          p := Pai(p^.next);
     While Assigned(p) And
           (p^.typ=ait_RegAlloc) Do
@@ -1105,7 +1112,7 @@ Begin
   Until Not(Assigned(p)) Or
         (Not(p^.typ in SkipInstr) And
          Not((p^.typ = ait_label) And
-            Not(Pai_Label(p)^.l^.is_used)));
+             labelCanBeSkipped(pai_label(p))));
 End;
 
 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.
  doIncState is false when this register has to be destroyed not because
  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;
     Counter: TRegister;
 Begin
@@ -1244,26 +1251,22 @@ Begin
         With p1^.Regs[Reg] Do
           Begin
             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;
                 TmpRState := RState;
-                FillChar(p1^.Regs[Counter], SizeOf(TContent), 0);
+                FillChar(p1^.Regs[Reg], SizeOf(TContent), 0);
                 WState := TmpWState;
                 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;
 
@@ -1581,7 +1584,7 @@ Begin
       For Counter := R_EAX to R_EDI Do
         With PPaiProp(p^.OptInfo)^.Regs[Counter] Do
           Begin
-            If (typ = Con_Ref) And
+            if (typ in [con_ref,con_noRemoveRef]) and
                ((Not(cs_UncertainOpts in aktglobalswitches) And
                  (NrOfMods <> 1)
                 ) Or
@@ -1609,7 +1612,7 @@ Begin
       }
     For Counter := R_EAX to R_EDI 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
       {for movsl}
           (Ref.Base = R_EDI) Or
@@ -1681,7 +1684,7 @@ var hp: pai;
 Begin
   Reg := Reg32(Reg);
   With PPaiProp(p^.optinfo)^.Regs[reg] Do
-    If (Typ = Con_Ref)
+    if (typ in [con_ref,con_noRemoveRef])
       Then
         Begin
           IncState(WState);
@@ -1784,13 +1787,14 @@ Begin
       For TmpReg := R_EAX To R_EDI Do
         Inc(NrOfInstrSinceLastMod[TmpReg]);
       Case p^.typ Of
+        ait_marker:;
         ait_label:
 {$Ifndef JumpAnal}
-          If (Pai_label(p)^.l^.is_used) Then
+          If not labelCanBeSkipped(pai_label(p)) Then
             DestroyAllRegs(CurProp);
 {$Else JumpAnal}
           Begin
-           If (Pai_Label(p)^.is_used) Then
+           If not labelCanBeSkipped(pai_label(p)) Then
              With LTable^[Pai_Label(p)^.l^.labelnr-LoLab] Do
 {$IfDef AnalyzeLoops}
               If (RefsFound = Pai_Label(p)^.l^.RefCount)
@@ -1886,7 +1890,13 @@ Begin
             if paicpu(p)^.is_jmp then
              begin
 {$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}
           With LTable^[pasmlabel(paicpu(p)^.oper[0].sym)^.labelnr-LoLab] Do
             If (RefsFound = pasmlabel(paicpu(p)^.oper[0].sym)^.RefCount) Then
@@ -2007,7 +2017,7 @@ Begin
                         ReadRef(CurProp, Paicpu(p)^.oper[0].ref);
                         TmpReg := Reg32(Paicpu(p)^.oper[1].reg);
                         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
                             Begin
                               With CurProp^.Regs[TmpReg] Do
@@ -2231,7 +2241,7 @@ Begin
       Case P^.Typ Of
         ait_label:
           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
           End;
         ait_instruction:
@@ -2310,7 +2320,19 @@ End.
 
 {
   $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
 
   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}
 
 Var
-  l : longint;
+  l, l1 : longint;
   p,hp1,hp2 : pai;
   hp3,hp4: pai;
-  TmpBool1, TmpBool2: Boolean;
 
   TmpRef: TReference;
 
   UsedRegs, TmpUsedRegs: TRegSet;
 
+  TmpBool1, TmpBool2: Boolean;
+
   Function SkipLabels(hp: Pai; var hp2: pai): boolean;
   {skips all labels and returns the next "real" instruction}
   Begin
@@ -279,7 +280,7 @@ Begin
                    While GetNextInstruction(p, hp1) and
                          ((hp1^.typ <> ait_label) or
                    { 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
                        Begin
                          AsmL^.Remove(hp1);
@@ -1224,37 +1225,81 @@ Begin
                 End;
               A_POP:
                 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
                       GetNextInstruction(p, hp1) And
                       (pai(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(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;
               A_PUSH:
                 Begin
@@ -1523,7 +1568,7 @@ Begin
           End;
 {        ait_label:
           Begin
-            If Not(Pai_Label(p)^.l^.is_used)
+            If labelCanBeSkipped(pai_label(p))
               Then
                 Begin
                   hp1 := Pai(p^.next);
@@ -1538,7 +1583,6 @@ Begin
     end;
 end;
 
-{$ifdef foldArithOps}
 function isFoldableArithOp(hp1: paicpu; reg: tregister): boolean;
 begin
   IsFoldableArithOp := False;
@@ -1551,12 +1595,11 @@ begin
         (paicpu(hp1)^.oper[1].typ = top_reg) and
         (paicpu(hp1)^.oper[1].reg = reg);
     A_INC,A_DEC:
-      isFoldableArithOp := 
+      isFoldableArithOp :=
         (paicpu(hp1)^.oper[0].typ = top_reg) and
         (paicpu(hp1)^.oper[0].reg = reg);
   end;
 end;
-{$endif foldArithOps}
 
 
 Procedure PeepHoleOptPass2(AsmL: PAasmOutput; BlockStart, BlockEnd: Pai);
@@ -1578,20 +1621,14 @@ var
   condition : tasmcond;
   hp3: pai;
 {$endif USECMOV}
-{$ifdef foldArithOps}
   UsedRegs, TmpUsedRegs: TRegSet;
-{$endif foldArithOps}
 
 Begin
   P := BlockStart;
-{$ifdef foldArithOps}
   UsedRegs := [];
-{$endif foldArithOps}
   While (P <> BlockEnd) Do
     Begin
-{$ifdef foldArithOps}
       UpdateUsedRegs(UsedRegs, Pai(p^.next));
-{$endif foldArithOps}
       Case P^.Typ Of
         Ait_Instruction:
           Begin
@@ -1711,7 +1748,6 @@ Begin
               A_FSTP,A_FISTP:
                 if doFpuLoadStoreOpt(asmL,p) then
                   continue;
-{$ifdef foldArithOps}
               A_IMUL:
                 begin
                   if ((paicpu(p)^.oper[0].typ = top_const) or
@@ -1735,7 +1771,6 @@ Begin
                       dispose(hp1,done);
                     end;
                 end;
-{$endif foldArithOps}
               A_MOV:
                 Begin
                   If (Paicpu(p)^.oper[0].typ = top_reg) And
@@ -1762,7 +1797,6 @@ Begin
                       p := hp1;
                       Continue;
                     End
-{$ifdef foldArithOps}
                   Else If (Paicpu(p)^.oper[0].typ = top_ref) And
                     GetNextInstruction(p,hp1) And
                     (hp1^.typ = ait_instruction) And
@@ -1787,7 +1821,7 @@ Begin
   { to       add/sub/or/... reg2/$const, (ref)    }
                      Begin
                        case paicpu(hp1)^.opcode of
-                         A_INC,A_DEC: 
+                         A_INC,A_DEC:
                            paicpu(hp1)^.LoadRef(0,newreference(Paicpu(p)^.oper[0].ref^))
                          else
                            paicpu(hp1)^.LoadRef(1,newreference(Paicpu(p)^.oper[0].ref^));
@@ -1799,7 +1833,6 @@ Begin
                        p := hp1
                      End;
                    End
-{$endif foldArithOps}
                   else if (Paicpu(p)^.oper[0].typ = Top_Const) And
                      (Paicpu(p)^.oper[0].val = 0) And
                      (Paicpu(p)^.oper[1].typ = Top_Reg) Then
@@ -1913,7 +1946,19 @@ End.
 
 {
   $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
 
   Revision 1.2  2000/07/13 11:32:45  michael