aoptda.pas 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. {
  2. $Id$
  3. Copyright (c) 1999 by Jonas Maebe, member of the Free Pascal
  4. Development Team
  5. This unit contains the assembler optimizer data flow analyzer.
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. Unit aoptda;
  20. Interface
  21. uses aasm, aoptcpub, aoptcpu;
  22. Type TAsmDFA = Object(TAoptCpu)
  23. { uses the same constructor as TAoptCpu = constructor from TAoptObj }
  24. { gathers the information regarding the contents of every register }
  25. { at the end of every instruction }
  26. Procedure TAsmOptimizer.DoDFA;
  27. { handles the processor dependent dataflow analizing }
  28. Procedure CpuDFA(p: PInstr); Virtual;
  29. { How many instructions are between the current instruction and the }
  30. { last one that modified the register }
  31. NrOfInstrSinceLastMod: TInstrSinceLastMod;
  32. End;
  33. Implementation
  34. uses cpubase
  35. Procedure TAsmOptimizer.DoDFAPass2;
  36. { Analyzes the Data Flow of an assembler list. Analyses the reg contents }
  37. { for the instructions between blockstart and blockend. Returns the last pai }
  38. { which has been processed }
  39. Var
  40. CurProp: PPaiProp;
  41. UsedRegs: TUsedRegs;
  42. p, hp, NewBlockStart : Pai;
  43. TmpReg: TRegister;
  44. Begin
  45. p := BlockStart;
  46. UsedRegs.init;
  47. UsedRegs.Update(p);
  48. NewBlockStart := SkipHead(p);
  49. { done implicitely by the constructor
  50. FillChar(NrOfInstrSinceLastMod, SizeOf(NrOfInstrSinceLastMod), 0); }
  51. While (P <> BlockEnd) Do
  52. Begin
  53. CurProp := New(PPaiProp, init);
  54. If (p <> NewBlockStart) Then
  55. Begin
  56. GetLastInstruction(p, hp);
  57. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  58. CurProp^.CondRegs.Flags :=
  59. PPaiProp(hp^.OptInfo)^.CondRegs.Flags;
  60. End;
  61. CurProp^.UsedRegs.InitWithValue(UsedRegs.GetUsedRegs);
  62. UsedRegs.Update(Pai(p^.Next)));
  63. PPaiProp(p^.OptInfo) := CurProp;
  64. For TmpReg := R_EAX To R_EDI Do
  65. Inc(NrOfInstrSinceLastMod[TmpReg]);
  66. Case p^.typ Of
  67. ait_label:
  68. If (Pai_label(p)^.l^.is_used) Then
  69. CurProp^.DestroyAllRegs(NrOfInstrSinceLastMod);
  70. {$ifdef GDB}
  71. ait_stabs, ait_stabn, ait_stab_function_name:;
  72. {$endif GDB}
  73. ait_instruction:
  74. if not(pai386(p)^.is_jmp) then
  75. begin
  76. If IsLoadMemReg(p) Then
  77. Begin
  78. CurProp^.ReadRef(PInstr(p)^.oper[LoadSrc].ref);
  79. TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
  80. If RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^) And
  81. (CurProp^.Regs[TmpReg].Typ = Con_Ref) Then
  82. Begin
  83. { a load based on the value this register already }
  84. { contained }
  85. With CurProp^.Regs[TmpReg] Do
  86. Begin
  87. IncWState;
  88. {also store how many instructions are part of the }
  89. { sequence in the first instruction's PPaiProp, so }
  90. { it can be easily accessed from within }
  91. { CheckSequence }
  92. Inc(NrOfMods, NrOfInstrSinceLastMod[TmpReg]);
  93. PPaiProp(Pai(StartMod)^.OptInfo)^.Regs[TmpReg].NrOfMods := NrOfMods;
  94. NrOfInstrSinceLastMod[TmpReg] := 0
  95. End
  96. End
  97. Else
  98. Begin
  99. { load of a register with a completely new value }
  100. CurProp^.DestroyReg(TmpReg, NrOfInstrSinceLastMod);
  101. If Not(RegInRef(TmpReg, Pai386(p)^.oper[LoadSrc].ref^)) Then
  102. With CurProp^.Regs[TmpReg] Do
  103. Begin
  104. Typ := Con_Ref;
  105. StartMod := p;
  106. NrOfMods := 1;
  107. End
  108. End;
  109. {$ifdef StateDebug}
  110. hp := new(pai_asm_comment,init(strpnew(att_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].WState))));
  111. InsertLLItem(AsmL, p, p^.next, hp);
  112. {$endif StateDebug}
  113. End
  114. Else if IsLoadConstReg(p) Then
  115. Begin
  116. TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
  117. With CurProp^.Regs[TmpReg] Do
  118. Begin
  119. CurProp^.DestroyReg(TmpReg, NrOfInstrSinceLastMod);
  120. typ := Con_Const;
  121. StartMod := Pointer(PInstr(p)^.oper[LoadSrc].val);
  122. End
  123. End
  124. Else CpuDFA(Pinstr(p));
  125. End;
  126. Else CurProp^.DestroyAllRegs(NrOfInstrSinceLastMod);
  127. End;
  128. Inc(InstrCnt);
  129. GetNextInstruction(p, p);
  130. End;
  131. End;
  132. End.