aoptcpu.pas 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. {
  2. Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
  3. Development Team
  4. This unit implements the ARM optimizer object
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. Unit aoptcpu;
  19. {$i fpcdefs.inc}
  20. Interface
  21. uses cpubase, aopt, aoptcpub;
  22. Type
  23. TCpuAsmOptimizer = class(TAsmOptimizer)
  24. { uses the same constructor as TAopObj }
  25. procedure PeepHoleOptPass2;override;
  26. End;
  27. Implementation
  28. uses
  29. aasmbase,aasmtai,aasmcpu;
  30. function CanBeCond(p : tai) : boolean;
  31. begin
  32. result:=(p.typ=ait_instruction) and (taicpu(p).condition=C_None);
  33. end;
  34. { instructions modifying the CPSR can be only the last instruction }
  35. function MustBeLast(p : tai) : boolean;
  36. begin
  37. Result:=(p.typ=ait_instruction) and
  38. ((taicpu(p).opcode in [A_BL,A_BLX,A_CMP,A_CMN,A_SWI,A_TEQ,A_TST]) or
  39. (taicpu(p).oppostfix=PF_S));
  40. end;
  41. procedure TCpuAsmOptimizer.PeepHoleOptPass2;
  42. var
  43. p,hp1,hp2: tai;
  44. l : longint;
  45. condition : tasmcond;
  46. hp3: tai;
  47. { UsedRegs, TmpUsedRegs: TRegSet; }
  48. begin
  49. p := BlockStart;
  50. { UsedRegs := []; }
  51. while (p <> BlockEnd) Do
  52. begin
  53. { UpdateUsedRegs(UsedRegs, tai(p.next)); }
  54. case p.Typ Of
  55. Ait_Instruction:
  56. begin
  57. case taicpu(p).opcode Of
  58. A_B:
  59. if taicpu(p).condition<>C_None then
  60. begin
  61. { check for
  62. Bxx xxx
  63. <several instructions>
  64. xxx:
  65. }
  66. l:=0;
  67. GetNextInstruction(p, hp1);
  68. while assigned(hp1) and
  69. (l<=4) and
  70. CanBeCond(hp1) and
  71. { stop on labels }
  72. not(hp1.typ=ait_label) do
  73. begin
  74. inc(l);
  75. if MustBeLast(hp1) then
  76. begin
  77. GetNextInstruction(hp1,hp1);
  78. break;
  79. end
  80. else
  81. GetNextInstruction(hp1,hp1);
  82. end;
  83. if assigned(hp1) then
  84. begin
  85. if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol),hp1) then
  86. begin
  87. if (l<=4) and (l>0) then
  88. begin
  89. condition:=inverse_cond(taicpu(p).condition);
  90. hp2:=p;
  91. GetNextInstruction(p,hp1);
  92. p:=hp1;
  93. repeat
  94. if hp1.typ=ait_instruction then
  95. taicpu(hp1).condition:=condition;
  96. if MustBeLast(hp1) then
  97. begin
  98. GetNextInstruction(hp1,hp1);
  99. break;
  100. end
  101. else
  102. GetNextInstruction(hp1,hp1);
  103. until not(assigned(hp1)) or
  104. not(CanBeCond(hp1)) or
  105. (hp1.typ=ait_label);
  106. { wait with removing else GetNextInstruction could
  107. ignore the label if it was the only usage in the
  108. jump moved away }
  109. tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol).decrefs;
  110. asml.remove(hp2);
  111. hp2.free;
  112. continue;
  113. end;
  114. end
  115. else
  116. begin
  117. { check further for
  118. Bcc xxx
  119. <several movs 1>
  120. B yyy
  121. xxx:
  122. <several movs 2>
  123. yyy:
  124. }
  125. { hp2 points to jmp yyy }
  126. hp2:=hp1;
  127. { skip hp1 to xxx }
  128. GetNextInstruction(hp1, hp1);
  129. if assigned(hp2) and
  130. assigned(hp1) and
  131. (l<=3) and
  132. (hp2.typ=ait_instruction) and
  133. (taicpu(hp2).is_jmp) and
  134. (taicpu(hp2).condition=C_None) and
  135. { real label and jump, no further references to the
  136. label are allowed }
  137. (tasmlabel(taicpu(p).oper[0]^.ref^.symbol).getrefs=2) and
  138. FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol),hp1) then
  139. begin
  140. l:=0;
  141. { skip hp1 to <several moves 2> }
  142. GetNextInstruction(hp1, hp1);
  143. while assigned(hp1) and
  144. CanBeCond(hp1) do
  145. begin
  146. inc(l);
  147. GetNextInstruction(hp1, hp1);
  148. end;
  149. { hp1 points to yyy: }
  150. if assigned(hp1) and
  151. FindLabel(tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol),hp1) then
  152. begin
  153. condition:=inverse_cond(taicpu(p).condition);
  154. GetNextInstruction(p,hp1);
  155. hp3:=p;
  156. p:=hp1;
  157. repeat
  158. if hp1.typ=ait_instruction then
  159. taicpu(hp1).condition:=condition;
  160. GetNextInstruction(hp1,hp1);
  161. until not(assigned(hp1)) or
  162. not(CanBeCond(hp1));
  163. { hp2 is still at jmp yyy }
  164. GetNextInstruction(hp2,hp1);
  165. { hp2 is now at xxx: }
  166. condition:=inverse_cond(condition);
  167. GetNextInstruction(hp1,hp1);
  168. { hp1 is now at <several movs 2> }
  169. repeat
  170. taicpu(hp1).condition:=condition;
  171. GetNextInstruction(hp1,hp1);
  172. until not(assigned(hp1)) or
  173. not(CanBeCond(hp1)) or
  174. (hp1.typ=ait_label);
  175. {
  176. asml.remove(hp1.next)
  177. hp1.next.free;
  178. asml.remove(hp1);
  179. hp1.free;
  180. }
  181. { remove Bcc }
  182. tasmlabel(taicpu(hp3).oper[0]^.ref^.symbol).decrefs;
  183. asml.remove(hp3);
  184. hp3.free;
  185. { remove jmp }
  186. tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol).decrefs;
  187. asml.remove(hp2);
  188. hp2.free;
  189. continue;
  190. end;
  191. end;
  192. end;
  193. end;
  194. end;
  195. end;
  196. end;
  197. end;
  198. p := tai(p.next)
  199. end;
  200. end;
  201. begin
  202. casmoptimizer:=TCpuAsmOptimizer;
  203. End.