mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-08 01:08:07 +02:00
* split the optimizer
This commit is contained in:
parent
2bfc4fa33d
commit
892964eaf2
1961
compiler/aopt386.pas
1961
compiler/aopt386.pas
File diff suppressed because it is too large
Load Diff
397
compiler/csopt386.pas
Normal file
397
compiler/csopt386.pas
Normal file
@ -0,0 +1,397 @@
|
||||
{
|
||||
$Id$
|
||||
Copyright (c) 1997-98 by Jonas Maebe
|
||||
|
||||
This unit contains the common subexpression elimination procedure.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
****************************************************************************
|
||||
}
|
||||
Unit CSOpt386;
|
||||
|
||||
Interface
|
||||
|
||||
Uses aasm;
|
||||
|
||||
{Procedure CSOpt386(First, Last: Pai);}
|
||||
Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
|
||||
|
||||
Implementation
|
||||
|
||||
Uses CObjects, globals, systems, verbose, hcodegen
|
||||
{$ifdef i386}
|
||||
,i386, cgi386, DAOpt386
|
||||
{$endif i386}
|
||||
;
|
||||
|
||||
Function CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint): Boolean;
|
||||
{checks whether the current instruction sequence (starting with p) and the
|
||||
one between StartMod and EndMod of Reg are the same. If so, the number of
|
||||
instructions that match is stored in Found and true is returned, otherwise
|
||||
Found holds the number of instructions between StartMod and EndMod and false
|
||||
is returned}
|
||||
Var hp2, hp3, EndMod: Pai;
|
||||
TmpResult: Boolean;
|
||||
RegsNotYetChecked: Set Of TRegister;
|
||||
Counter: Byte;
|
||||
|
||||
Function NoChangedRegInRef(oldp, newp: Pai): Boolean;
|
||||
Var TmpP: Pai;
|
||||
{checks if the first operator of newp is a reference and in that case checks
|
||||
whether that reference includes regs that have been changed since oldp. This
|
||||
to avoid wrong optimizations like
|
||||
|
||||
movl 8(%epb), %eax movl 8(%epb), %eax
|
||||
movl 12(%epb), %edx movl 12(%epb), %edx
|
||||
movl (%eax,%edx,1), %edi movl (%eax,%edx,1), %edi
|
||||
pushl %edi being converted to pushl %edi
|
||||
movl 8(%epb), %eax movl 16(%ebp), %edx
|
||||
movl 16(%epb), %edx pushl %edi
|
||||
movl (%eax,%edx,1), %edi
|
||||
pushl %edi
|
||||
|
||||
because first is checked whether %eax isn't changed (it isn't) and
|
||||
consequently all instructions containg %eax are removed}
|
||||
Begin
|
||||
TmpResult := True;
|
||||
If (Pai(oldp)^.typ = ait_instruction) Then {oldp and newp are the same instruction}
|
||||
Case Pai386(oldp)^.op1t Of
|
||||
Top_Reg:
|
||||
If (Reg32(TRegister(Pai386(oldp)^.op1)) in RegsNotYetChecked) Then
|
||||
Begin
|
||||
RegsNotYetChecked := RegsNotYetChecked - [Reg32(TRegister(Pai386(oldp)^.op1))];
|
||||
If Assigned(newp^.previous)
|
||||
Then
|
||||
Begin
|
||||
TmpP := Pai(newp^.previous);
|
||||
While Assigned (TmpP^.previous) And
|
||||
PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do
|
||||
TmpP := Pai(TmpP^.previous);
|
||||
TmpResult := Assigned(TmpP) And
|
||||
RegsSameContent(oldp, TmpP, Reg32(TRegister(Pai386(oldp)^.op1)))
|
||||
End
|
||||
Else TmpResult := False;
|
||||
End;
|
||||
Top_Ref:
|
||||
With TReference(Pai386(oldp)^.op1^) Do
|
||||
Begin
|
||||
If (Base in RegsNotYetChecked) And
|
||||
(Base <> R_NO) Then
|
||||
Begin
|
||||
RegsNotYetChecked := RegsNotYetChecked - [Base];
|
||||
If Assigned(newp^.previous)
|
||||
Then
|
||||
Begin
|
||||
TmpP := Pai(newp^.previous);
|
||||
While Assigned (TmpP^.previous) And
|
||||
PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do
|
||||
TmpP := Pai(TmpP^.previous);
|
||||
TmpResult := Assigned(TmpP) And
|
||||
RegsSameContent(oldp, TmpP, Base)
|
||||
End
|
||||
Else TmpResult := False;
|
||||
End;
|
||||
If TmpResult And
|
||||
(Index <> R_NO) And
|
||||
(Index in RegsNotYetChecked) Then
|
||||
Begin
|
||||
RegsNotYetChecked := RegsNotYetChecked - [Index];
|
||||
If Assigned(newp^.previous)
|
||||
Then
|
||||
Begin
|
||||
TmpP := Pai(newp^.previous);
|
||||
While Assigned (TmpP^.previous) And
|
||||
PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do
|
||||
TmpP := Pai(TmpP^.previous);
|
||||
TmpResult := Assigned(TmpP) And
|
||||
RegsSameContent(oldp, TmpP, Index)
|
||||
End
|
||||
Else TmpResult := False;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
NoChangedRegInRef := TmpResult;
|
||||
End;
|
||||
|
||||
Begin {CheckSequence}
|
||||
Reg := Reg32(Reg);
|
||||
Found := 0;
|
||||
hp2 := PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].StartMod;
|
||||
hp3 := p;
|
||||
EndMod := PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].StartMod;
|
||||
RegsNotYetChecked := [R_EAX..R_EDI];
|
||||
For Counter := 2 to PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods Do
|
||||
EndMod := Pai(EndMod^.Next);
|
||||
While (Found <> PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods) And
|
||||
InstructionsEqual(hp2, hp3) And
|
||||
NoChangedRegInRef(EndMod, hp3) Do
|
||||
Begin
|
||||
hp2 := Pai(hp2^.next);
|
||||
hp3 := Pai(hp3^.next);
|
||||
Inc(Found)
|
||||
End;
|
||||
If (Found <> PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods)
|
||||
Then
|
||||
Begin
|
||||
If ((Found+1) = PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods) And
|
||||
Assigned(hp2) And
|
||||
(Pai(hp2)^.typ = ait_instruction) And
|
||||
(Pai386(hp2)^._operator In [A_MOV, A_MOVZX]) And
|
||||
(Pai386(hp2)^.op1t = top_ref) And
|
||||
(Pai386(hp2)^.op2t = top_reg) And
|
||||
Assigned(hp3) And
|
||||
(Pai(hp3)^.typ = ait_instruction) And
|
||||
(Pai386(hp3)^._operator In [A_MOV, A_MOVZX]) And
|
||||
(Pai386(hp3)^.op1t = top_ref) And
|
||||
(Pai386(hp3)^.op2t = top_reg) And
|
||||
(Pai386(hp2)^._operator <> Pai386(hp3)^._operator) And
|
||||
RefsEqual(TReference(Pai386(hp2)^.op1^),TReference(Pai386(hp3)^.op1^)) And
|
||||
NoChangedRegInRef(EndMod, hp3)
|
||||
Then
|
||||
If (Pai386(hp2)^._operator = A_MOV)
|
||||
Then
|
||||
Begin
|
||||
If (Pai386(hp2)^.Size = S_B) And
|
||||
(Reg8toReg32(TRegister(Pai386(hp2)^.op2)) =
|
||||
TRegister(Pai386(hp3)^.op2))
|
||||
Then
|
||||
Begin
|
||||
Pai386(hp2)^._operator := A_MOVZX;
|
||||
Pai386(hp2)^.op2 := Pai386(hp3)^.op2;
|
||||
Pai386(hp2)^.Size := S_BL;
|
||||
Inc(Found);
|
||||
CheckSequence := True;
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
CheckSequence := False;
|
||||
If (Found > 0) Then
|
||||
Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
|
||||
End
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
If (Pai386(hp3)^.Size = S_B) And
|
||||
(Reg8toReg32(TRegister(Pai386(hp3)^.op2)) =
|
||||
TRegister(Pai386(hp2)^.op2))
|
||||
Then
|
||||
Begin
|
||||
CheckSequence := True;
|
||||
Inc(Found)
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
CheckSequence := False;
|
||||
If (Found > 0) Then
|
||||
Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
|
||||
End
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
CheckSequence := False;
|
||||
If (found > 0) then
|
||||
{this is correct because we only need to turn off the CanBeRemoved flag
|
||||
when an instruction has already been processed by CheckSequence
|
||||
(otherwise CanBeRemoved can't be true, or can't have to be turned off).
|
||||
If it has already been processed by checkSequence and flagged to be
|
||||
removed, it means that it has been checked against a previous sequence
|
||||
and that it was equal (otherwise CheckSequence would have returned false
|
||||
and the instruction wouldn't have been removed). If this "If found > 0"
|
||||
check is left out, incorrect optimizations are performed.}
|
||||
Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
|
||||
End
|
||||
End
|
||||
Else CheckSequence := True;
|
||||
End; {CheckSequence}
|
||||
|
||||
Procedure DoCSE(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
|
||||
two different sequences}
|
||||
Var Cnt, Cnt2: Longint;
|
||||
p, hp1, hp2: Pai;
|
||||
Begin
|
||||
p := First;
|
||||
While (p <> Pai(Last^.Next)) Do
|
||||
Begin
|
||||
Case p^.typ Of
|
||||
ait_label, ait_labeled_instruction:;
|
||||
ait_instruction:
|
||||
Begin
|
||||
Case Pai386(p)^._operator Of
|
||||
A_CLD: If Assigned(p^.previous) And
|
||||
(PPaiProp(Pai(p^.previous)^.fileinfo.line)^.DirFlag = F_NotSet) Then
|
||||
PPaiProp(Pai(p)^.fileinfo.line)^.CanBeRemoved := True;
|
||||
A_MOV, A_MOVZX, A_MOVSX:
|
||||
Begin
|
||||
Case Pai386(p)^.op1t Of
|
||||
{ Top_Reg:
|
||||
Case Pai386(p)^.op2t Of
|
||||
Top_Reg:;
|
||||
Top_Ref:;
|
||||
End;}
|
||||
Top_Ref:
|
||||
Begin {destination is always a register in this case}
|
||||
With PPaiProp(p^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op2))] Do
|
||||
Begin
|
||||
If Assigned(p^.previous) And
|
||||
(PPaiProp(Pai(p^.previous)^.fileinfo.line)^.
|
||||
Regs[Reg32(TRegister(Pai386(p)^.op2))].typ = con_ref) Then
|
||||
{so we don't try to check a sequence when the register only contains a constant}
|
||||
If CheckSequence(p, TRegister(Pai386(p)^.op2), Cnt) And
|
||||
(Cnt > 0)
|
||||
Then
|
||||
Begin
|
||||
hp1 := nil;
|
||||
{although it's perfectly ok to remove an instruction which doesn't contain
|
||||
the register that we've just checked (CheckSequence takes care of that),
|
||||
the sequence containing this other register should also be completely
|
||||
checked and removed, otherwise we may get situations like this:
|
||||
|
||||
movl 12(%ebp), %edx movl 12(%ebp), %edx
|
||||
movl 16(%ebp), %eax movl 16(%ebp), %eax
|
||||
movl 8(%edx), %edx movl 8(%edx), %edx
|
||||
movl (%eax), eax movl (%eax), eax
|
||||
cmpl %eax, %edx cmpl %eax, %edx
|
||||
jnz l123 getting converted to jnz l123
|
||||
movl 12(%ebp), %edx movl 4(%eax), eax
|
||||
movl 16(%ebp), %eax
|
||||
movl 8(%edx), %edx
|
||||
movl 4(%eax), eax}
|
||||
hp2 := p;
|
||||
For Cnt2 := 1 to Cnt Do
|
||||
Begin
|
||||
{ Note to Jonas :
|
||||
ait_stab_function_name is only at the begin of one function
|
||||
ait_stabn is only inserted in ag so you should not see any
|
||||
ait_stabs are only in head and tail of procs
|
||||
so you should no have problems with those neither !! (PM)
|
||||
Tell me if I am wrong
|
||||
If Not(Pai(p)^.typ In [ait_stabs, ait_stabn, ait_stab_function_name]) Then }
|
||||
Begin
|
||||
If (hp1 = nil) And
|
||||
Not(RegInInstruction(Tregister(Pai386(hp2)^.op2), p))
|
||||
Then hp1 := p;
|
||||
PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True;
|
||||
End;
|
||||
p := Pai(p^.next);
|
||||
End;
|
||||
If hp1 <> nil Then p := hp1;
|
||||
Continue;
|
||||
End
|
||||
Else
|
||||
If (Cnt > 0) And
|
||||
(PPaiProp(p^.fileinfo.line)^.CanBeRemoved) Then
|
||||
Begin
|
||||
hp2 := p;
|
||||
For Cnt2 := 1 to Cnt Do
|
||||
Begin
|
||||
If RegInInstruction(Tregister(Pai386(hp2)^.op2), p)
|
||||
Then PPaiProp(p^.fileinfo.line)^.CanBeRemoved := False;
|
||||
p := Pai(p^.Next)
|
||||
End;
|
||||
Continue;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
Top_Const:
|
||||
Begin
|
||||
Case Pai386(p)^.op2t Of
|
||||
Top_Reg:
|
||||
Begin
|
||||
If Assigned(p^.previous) Then
|
||||
With PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg32(TRegister(Pai386(p)^.op2))] Do
|
||||
If (Typ = Con_Const) And
|
||||
(StartMod = Pai386(p)^.op1) Then
|
||||
PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True;
|
||||
End;
|
||||
Top_Ref:;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
A_STD: If Assigned(p^.previous) And
|
||||
(PPaiProp(Pai(p^.previous)^.fileinfo.line)^.DirFlag = F_Set) Then
|
||||
PPaiProp(Pai(p)^.fileinfo.line)^.CanBeRemoved := True;
|
||||
A_XOR:
|
||||
Begin
|
||||
If (Pai386(p)^.op1t = top_reg) And
|
||||
(Pai386(p)^.op2t = top_reg) And
|
||||
(Pai386(p)^.op1 = Pai386(p)^.op2) And
|
||||
Assigned(p^.previous) And
|
||||
(PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].typ = con_const) And
|
||||
(PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].StartMod = Pointer(0))
|
||||
Then PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True
|
||||
End
|
||||
End
|
||||
End;
|
||||
End;
|
||||
p := Pai(p^.next);
|
||||
End;
|
||||
End;
|
||||
|
||||
Procedure RemoveInstructs(AsmL: PAasmOutput; First, Last: Pai);
|
||||
{Removes the marked instructions and disposes the PPaiProps of the other
|
||||
instructions, restoring theirline number}
|
||||
Var p, hp1: Pai;
|
||||
TmpLine, InstrCnt: Longint;
|
||||
Begin
|
||||
p := First;
|
||||
InstrCnt := 1;
|
||||
While (p <> Pai(Last^.Next)) Do
|
||||
If PPaiProp(p^.fileinfo.line)^.CanBeRemoved
|
||||
Then
|
||||
Begin
|
||||
If (InstrCnt > NrOfPaiFast) Then
|
||||
Dispose(PPaiProp(p^.fileinfo.line));
|
||||
hp1 := Pai(p^.Next);
|
||||
AsmL^.Remove(p);
|
||||
Dispose(p, Done);
|
||||
p := hp1;
|
||||
Inc(InstrCnt)
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
If (InstrCnt > NrOfPaiFast)
|
||||
Then
|
||||
Begin
|
||||
TmpLine := PPaiProp(p^.fileinfo.line)^.linesave;
|
||||
Dispose(PPaiProp(p^.fileinfo.line));
|
||||
p^.fileinfo.line := TmpLine;
|
||||
End
|
||||
Else p^.fileinfo.line := PPaiProp(p^.fileinfo.line)^.linesave;
|
||||
p := Pai(p^.Next);
|
||||
Inc(InstrCnt)
|
||||
End;
|
||||
If (NrOfPaiFast > 0) Then
|
||||
{$IfDef TP}
|
||||
Freemem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+1)div 2)*2))
|
||||
{$Else}
|
||||
FreeMem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+3)div 4)*4))
|
||||
{$EndIf TP}
|
||||
End;
|
||||
|
||||
Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
|
||||
Begin
|
||||
DoCSE(First, Last);
|
||||
RemoveInstructs(AsmL, First, Last);
|
||||
End;
|
||||
|
||||
End.
|
||||
|
||||
{
|
||||
$log$
|
||||
}
|
1208
compiler/daopt386.pas
Normal file
1208
compiler/daopt386.pas
Normal file
File diff suppressed because it is too large
Load Diff
1376
compiler/popt386.pas
Normal file
1376
compiler/popt386.pas
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user