aoptcpu.pas 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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, aasmtai, aopt, aoptcpub;
  22. Type
  23. { TCpuAsmOptimizer }
  24. TCpuAsmOptimizer = class(TAsmOptimizer)
  25. { uses the same constructor as TAopObj }
  26. function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
  27. End;
  28. Implementation
  29. uses
  30. verbose,
  31. aasmbase,aasmcpu,
  32. cgbase;
  33. { TCpuAsmOptimizer }
  34. function Test_Set(const RegSet,t: tcpuregisterset): boolean;
  35. begin
  36. result := ((RegSet*t) = []) or ((RegSet*t) = t);
  37. end;
  38. function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
  39. var
  40. v: LongInt;
  41. hp1: tai;
  42. begin
  43. result := false;
  44. case p.typ of
  45. ait_instruction:
  46. begin
  47. { Collapse ADD r0,r0,r1 -> ADD r0,r1 }
  48. if (taicpu(p).opcode in [A_ADD,A_SUB,A_AND,A_EOR,A_OR,A_MUL]) and
  49. (taicpu(p).ops = 3) and
  50. (taicpu(p).oper[0]^.typ = top_reg) and
  51. (taicpu(p).oper[1]^.typ = top_reg) and
  52. (taicpu(p).oper[2]^.typ = top_reg) and
  53. (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
  54. begin
  55. hp1:=taicpu.op_reg_reg(taicpu(p).opcode,taicpu(p).oper[0]^.reg,taicpu(p).oper[2]^.reg);
  56. AsmL.InsertBefore(hp1,p);
  57. //InsertLLItem(p.Previous,p.Next,hp1);
  58. AsmL.Remove(p);
  59. p.Free;
  60. p:=hp1;
  61. result:=true;
  62. end
  63. { Collapse ADD r0,r1,r0 -> ADD r0,r1
  64. SUB needs RSUB }
  65. else if (taicpu(p).opcode in [A_ADD,A_AND,A_EOR,A_OR,A_MUL]) and
  66. (taicpu(p).ops = 3) and
  67. (taicpu(p).oper[0]^.typ = top_reg) and
  68. (taicpu(p).oper[1]^.typ = top_reg) and
  69. (taicpu(p).oper[2]^.typ = top_reg) and
  70. (taicpu(p).oper[0]^.reg = taicpu(p).oper[2]^.reg) then
  71. begin
  72. hp1:=taicpu.op_reg_reg(taicpu(p).opcode,taicpu(p).oper[0]^.reg,taicpu(p).oper[1]^.reg);
  73. AsmL.InsertBefore(hp1,p);
  74. //InsertLLItem(p.Previous,p.Next,hp1);
  75. AsmL.Remove(p);
  76. p.Free;
  77. p:=hp1;
  78. result:=true;
  79. end
  80. else
  81. case taicpu(p).opcode of
  82. { Collapse instructions into a compact format }
  83. A_SUB:
  84. begin
  85. { SUB r0,r0,imm8 -> SUB r0,imm8 }
  86. if (taicpu(p).ops=3) and
  87. (taicpu(p).oper[0]^.typ = top_reg) and
  88. (taicpu(p).oper[1]^.typ = top_reg) and
  89. (taicpu(p).oper[2]^.typ = top_const) and
  90. (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) and
  91. in_signed_bits(taicpu(p).oper[2]^.val, 8) then
  92. begin
  93. hp1:=taicpu.op_reg_const(taicpu(p).opcode,taicpu(p).oper[0]^.reg,taicpu(p).oper[2]^.val);
  94. AsmL.InsertBefore(hp1,p);
  95. //InsertLLItem(p.Previous,p.Next,hp1);
  96. AsmL.Remove(p);
  97. p.Free;
  98. p:=hp1;
  99. result:=true;
  100. end
  101. { SUB r0,r1,r0 -> RSUB r0,r1 }
  102. else if (taicpu(p).ops=3) and
  103. (taicpu(p).oper[0]^.typ = top_reg) and
  104. (taicpu(p).oper[1]^.typ = top_reg) and
  105. (taicpu(p).oper[2]^.typ = top_reg) and
  106. (taicpu(p).oper[0]^.reg = taicpu(p).oper[2]^.reg) then
  107. begin
  108. hp1:=taicpu.op_reg_reg(A_RSUB,taicpu(p).oper[0]^.reg,taicpu(p).oper[1]^.reg);
  109. AsmL.InsertBefore(hp1,p);
  110. //InsertLLItem(p.Previous,p.Next,hp1);
  111. AsmL.Remove(p);
  112. p.Free;
  113. p:=hp1;
  114. result:=true;
  115. end;
  116. end;
  117. A_LSL,
  118. A_LSR,
  119. A_ASR:
  120. begin
  121. { LSL r0,r0,imm8 -> LSL r0,imm8 }
  122. if (taicpu(p).ops=3) and
  123. (taicpu(p).oper[0]^.typ = top_reg) and
  124. (taicpu(p).oper[1]^.typ = top_reg) and
  125. (taicpu(p).oper[2]^.typ = top_const) and
  126. (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
  127. begin
  128. hp1:=taicpu.op_reg_const(taicpu(p).opcode,taicpu(p).oper[0]^.reg,taicpu(p).oper[2]^.val);
  129. AsmL.InsertBefore(hp1,p);
  130. //InsertLLItem(p.Previous,p.Next,hp1);
  131. AsmL.Remove(p);
  132. p.Free;
  133. p:=hp1;
  134. result:=true;
  135. end
  136. end;
  137. A_STM:
  138. begin
  139. { Try to compress STM --sp, LIST down to PUSHM LIST }
  140. if (taicpu(p).oper[0]^.ref^.base = NR_STACK_POINTER_REG) and
  141. (taicpu(p).oper[0]^.ref^.addressmode = AM_PREINDEXED) and
  142. (taicpu(p).oper[1]^.regset^ <> []) then
  143. begin
  144. if test_set(taicpu(p).oper[1]^.regset^, [0..3]) and
  145. test_set(taicpu(p).oper[1]^.regset^, [4..7]) and
  146. test_set(taicpu(p).oper[1]^.regset^, [8..9]) and
  147. test_set(taicpu(p).oper[1]^.regset^, [10]) and
  148. test_set(taicpu(p).oper[1]^.regset^, [11]) and
  149. test_set(taicpu(p).oper[1]^.regset^, [12]) and
  150. test_set(taicpu(p).oper[1]^.regset^, [14]) and
  151. test_set(taicpu(p).oper[1]^.regset^, [15]) and
  152. ((taicpu(p).oper[1]^.regset^ * [13]) = []) then
  153. begin
  154. hp1:=taicpu.op_regset(A_PUSHM,taicpu(p).oper[1]^.regtyp,taicpu(p).oper[1]^.subreg,taicpu(p).oper[1]^.regset^);
  155. AsmL.InsertBefore(hp1,p);
  156. //InsertLLItem(p.Previous,p.Next,hp1);
  157. AsmL.Remove(p);
  158. p.Free;
  159. p:=hp1;
  160. result:=true;
  161. exit;
  162. end;
  163. end;
  164. end;
  165. A_LDM:
  166. begin
  167. { Try to compress LDM sp++, LIST down to POPM LIST }
  168. if (taicpu(p).oper[0]^.ref^.base = NR_STACK_POINTER_REG) and
  169. ((taicpu(p).oper[0]^.ref^.addressmode = AM_POSTINDEXED) or
  170. (RS_STACK_POINTER_REG in taicpu(p).oper[1]^.regset^)) and
  171. (taicpu(p).oper[1]^.regset^ <> []) then
  172. begin
  173. if test_set(taicpu(p).oper[1]^.regset^, [0..3]) and
  174. test_set(taicpu(p).oper[1]^.regset^, [4..7]) and
  175. test_set(taicpu(p).oper[1]^.regset^, [8..9]) and
  176. test_set(taicpu(p).oper[1]^.regset^, [10]) and
  177. test_set(taicpu(p).oper[1]^.regset^, [11]) and
  178. test_set(taicpu(p).oper[1]^.regset^, [12]) and
  179. test_set(taicpu(p).oper[1]^.regset^, [14]) and
  180. test_set(taicpu(p).oper[1]^.regset^, [15]) and
  181. ((taicpu(p).oper[1]^.regset^ * [13]) = []) then
  182. begin
  183. hp1:=taicpu.op_regset(A_POPM,taicpu(p).oper[1]^.regtyp,taicpu(p).oper[1]^.subreg,taicpu(p).oper[1]^.regset^);
  184. AsmL.InsertBefore(hp1,p);
  185. //InsertLLItem(p.Previous,p.Next,hp1);
  186. AsmL.Remove(p);
  187. p.Free;
  188. p:=hp1;
  189. result:=true;
  190. exit;
  191. end;
  192. end;
  193. end;
  194. end;
  195. end;
  196. end;
  197. end;
  198. begin
  199. casmoptimizer:=TCpuAsmOptimizer;
  200. End.