summaryrefslogtreecommitdiff
path: root/compiler/aoptda.pas
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/aoptda.pas')
-rw-r--r--compiler/aoptda.pas183
1 files changed, 183 insertions, 0 deletions
diff --git a/compiler/aoptda.pas b/compiler/aoptda.pas
new file mode 100644
index 0000000000..25bc035898
--- /dev/null
+++ b/compiler/aoptda.pas
@@ -0,0 +1,183 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the data flow analyzer object of the assembler
+ optimizer.
+
+ 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 aoptda;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ cpubase,cgbase,
+ aasmbase,aasmtai,aasmcpu,
+ aoptcpub, aoptbase;
+
+ Type
+ TAOptDFA = class
+ { uses the same constructor as TAoptCpu = constructor from TAoptObj }
+
+ { gathers the information regarding the contents of every register }
+ { at the end of every instruction }
+ Procedure DoDFA;
+
+ { handles the processor dependent dataflow analizing }
+ Procedure CpuDFA(p: PInstr); Virtual;
+
+ { How many instructions are between the current instruction and the }
+ { last one that modified the register }
+ InstrSinceLastMod: TInstrSinceLastMod;
+
+ { convert a TInsChange value into the corresponding register }
+ //!!!!!!!!!! Function TCh2Reg(Ch: TInsChange): TRegister; Virtual;
+ { returns whether the instruction P reads from register Reg }
+ Function RegReadByInstr(Reg: TRegister; p: tai): Boolean; Virtual;
+ End;
+
+ Implementation
+
+ uses
+ globals, aoptobj;
+
+ Procedure TAOptDFA.DoDFA;
+ { Analyzes the Data Flow of an assembler list. Analyses the reg contents }
+ { for the instructions between blockstart and blockend. Returns the last pai }
+ { which has been processed }
+ Var
+ CurProp: TPaiProp;
+ UsedRegs: TUsedRegs;
+ p, hp, NewBlockStart : tai;
+ TmpReg: TRegister;
+ Begin
+ {!!!!!!!!!!
+ p := BlockStart;
+ UsedRegs.Create;
+ UsedRegs.Update(p);
+ NewBlockStart := SkipHead(p);
+ { done implicitely by the constructor
+ FillChar(InstrSinceLastMod, SizeOf(InstrSinceLastMod), 0); }
+ While (P <> BlockEnd) Do
+ Begin
+ CurProp:=TPaiProp.Create;
+ If (p <> NewBlockStart) Then
+ Begin
+ GetLastInstruction(p, hp);
+ CurProp.Regs := TPaiProp(hp.OptInfo).Regs;
+ { !!!!!!!!!!!! }
+ {$ifdef x86}
+ CurProp.CondRegs.Flags :=
+ TPaiProp(hp.OptInfo).CondRegs.Flags;
+ {$endif}
+ End;
+ CurProp.UsedRegs.InitWithValue(UsedRegs.GetUsedRegs);
+ UsedRegs.Update(tai(p.Next));
+ TPaiProp(p.OptInfo) := CurProp;
+ For TmpReg := LoGPReg To HiGPReg Do
+ Inc(InstrSinceLastMod[TmpReg]);
+ Case p^.typ Of
+ ait_label:
+ If (Pai_label(p)^.l^.is_used) Then
+ CurProp^.DestroyAllRegs(InstrSinceLastMod);
+ ait_stab, ait_force_line, ait_function_name:;
+ ait_instruction:
+ if not(PInstr(p)^.is_jmp) then
+ begin
+ If IsLoadMemReg(p) Then
+ Begin
+ CurProp^.ReadRef(PInstr(p)^.oper[LoadSrc].ref);
+ TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
+ If RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^) And
+ (CurProp^.GetRegContentType(TmpReg) = Con_Ref) Then
+ Begin
+ { a load based on the value this register already }
+ { contained }
+ With CurProp^.Regs[TmpReg] Do
+ Begin
+ CurProp^.IncWState(TmpReg);
+ {also store how many instructions are part of the }
+ { sequence in the first instruction's PPaiProp, so }
+ { it can be easily accessed from within }
+ { CheckSequence }
+ Inc(NrOfMods, InstrSinceLastMod[TmpReg]);
+ PPaiProp(Pai(StartMod)^.OptInfo)^.Regs[TmpReg].NrOfMods := NrOfMods;
+ InstrSinceLastMod[TmpReg] := 0
+ End
+ End
+ Else
+ Begin
+ { load of a register with a completely new value }
+ CurProp^.DestroyReg(TmpReg, InstrSinceLastMod);
+ If Not(RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^)) Then
+ With CurProp^.Regs[TmpReg] Do
+ Begin
+ Typ := Con_Ref;
+ StartMod := p;
+ NrOfMods := 1;
+ End
+ End;
+ {$ifdef StateDebug}
+ hp := new(pai_asm_comment,init(strpnew(std_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].WState))));
+ InsertLLItem(AsmL, p, p^.next, hp);
+ {$endif StateDebug}
+
+ End
+ Else if IsLoadConstReg(p) Then
+ Begin
+ TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
+ With CurProp^.Regs[TmpReg] Do
+ Begin
+ CurProp^.DestroyReg(TmpReg, InstrSinceLastMod);
+ typ := Con_Const;
+ StartMod := Pointer(PInstr(p)^.oper[LoadSrc].val);
+ End
+ End
+ Else CpuDFA(Pinstr(p));
+ End;
+ Else CurProp^.DestroyAllRegs(InstrSinceLastMod);
+ End;
+ { Inc(InstrCnt);}
+ GetNextInstruction(p, p);
+ End;
+ }
+ End;
+
+ Procedure TAoptDFA.CpuDFA(p: PInstr);
+ Begin
+ Abstract;
+ End;
+
+ {!!!!!!!
+ Function TAOptDFA.TCh2Reg(Ch: TInsChange): TRegister;
+ Begin
+ TCh2Reg:=R_NO;
+ Abstract;
+ End;
+ }
+
+ Function TAOptDFA.RegReadByInstr(Reg: TRegister; p: tai): Boolean;
+ Begin
+ RegReadByInstr:=false;
+ Abstract;
+ End;
+
+
+End.