aoptcpu.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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, cgbase, aasmtai, aopt, aoptcpub;
  22. Type
  23. TCpuAsmOptimizer = class(TAsmOptimizer)
  24. Function GetNextInstructionUsingReg(Current: tai; Var Next: tai;reg : TRegister): Boolean;
  25. { uses the same constructor as TAopObj }
  26. function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
  27. procedure PeepHoleOptPass2;override;
  28. End;
  29. Implementation
  30. uses
  31. aasmbase,aasmcpu,
  32. globals,globtype;
  33. function CanBeCond(p : tai) : boolean;
  34. begin
  35. result:=(p.typ=ait_instruction) and (taicpu(p).condition=C_None);
  36. end;
  37. function TCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai;
  38. var Next: tai; reg: TRegister): Boolean;
  39. begin
  40. Next:=Current;
  41. repeat
  42. Result:=GetNextInstruction(Next,Next);
  43. until not(cs_opt_level3 in current_settings.optimizerswitches) or not(Result) or (Next.typ<>ait_instruction) or (RegInInstruction(reg,Next)) or
  44. (is_calljmp(taicpu(Next).opcode));
  45. end;
  46. function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
  47. var
  48. hp1,hp2,hp3: tai;
  49. alloc, dealloc: tai_regalloc;
  50. i: integer;
  51. begin
  52. result := false;
  53. case p.typ of
  54. ait_instruction:
  55. begin
  56. case taicpu(p).opcode of
  57. A_LDI:
  58. begin
  59. { turn
  60. ldi reg0, imm
  61. cp reg1, reg0
  62. dealloc reg0
  63. into
  64. cpi reg1, imm
  65. }
  66. if (taicpu(p).ops=2) and
  67. (taicpu(p).oper[0]^.typ=top_reg) and
  68. (taicpu(p).oper[1]^.typ=top_const) and
  69. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  70. (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
  71. (taicpu(hp1).opcode=A_CP) and
  72. (taicpu(hp1).ops=2) and
  73. (taicpu(hp1).oper[1]^.typ=top_reg) and
  74. (getsupreg(taicpu(hp1).oper[0]^.reg) in [16..31]) and
  75. (taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
  76. assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
  77. begin
  78. taicpu(hp1).opcode:=A_CPI;
  79. taicpu(hp1).loadconst(1, taicpu(p).oper[1]^.val);
  80. alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
  81. dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
  82. if assigned(alloc) and assigned(dealloc) then
  83. begin
  84. asml.Remove(alloc);
  85. alloc.Free;
  86. asml.Remove(dealloc);
  87. dealloc.Free;
  88. end;
  89. GetNextInstruction(p,hp1);
  90. asml.Remove(p);
  91. p.Free;
  92. p:=hp1;
  93. result:=true;
  94. end;
  95. end;
  96. A_CLR:
  97. begin
  98. { turn the common
  99. clr rX
  100. mov/ld rX, rY
  101. into
  102. mov/ld rX, rY
  103. }
  104. if (taicpu(p).ops=1) and
  105. (taicpu(p).oper[0]^.typ=top_reg) and
  106. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  107. (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
  108. (hp1.typ=ait_instruction) and
  109. (taicpu(hp1).opcode in [A_MOV,A_LD]) and
  110. (taicpu(hp1).ops>0) and
  111. (taicpu(hp1).oper[0]^.typ=top_reg) and
  112. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) then
  113. begin
  114. asml.Remove(p);
  115. p.Free;
  116. p:=hp1;
  117. result:=true;
  118. end
  119. { turn
  120. clr rX
  121. ...
  122. adc rY, rX
  123. into
  124. ...
  125. adc rY, r1
  126. }
  127. else if (taicpu(p).ops=1) and
  128. (taicpu(p).oper[0]^.typ=top_reg) and
  129. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  130. (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
  131. (hp1.typ=ait_instruction) and
  132. (taicpu(hp1).opcode in [A_ADC,A_SBC]) and
  133. (taicpu(hp1).ops=2) and
  134. (taicpu(hp1).oper[1]^.typ=top_reg) and
  135. (taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
  136. (taicpu(hp1).oper[0]^.reg<>taicpu(p).oper[0]^.reg) and
  137. assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
  138. begin
  139. taicpu(hp1).oper[1]^.reg:=NR_R1;
  140. alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
  141. dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
  142. if assigned(alloc) and assigned(dealloc) then
  143. begin
  144. asml.Remove(alloc);
  145. alloc.Free;
  146. asml.Remove(dealloc);
  147. dealloc.Free;
  148. end;
  149. GetNextInstruction(p,hp1);
  150. asml.Remove(p);
  151. p.free;
  152. p:=hp1;
  153. result:=true;
  154. end;
  155. end;
  156. A_PUSH:
  157. begin
  158. { turn
  159. push reg0
  160. push reg1
  161. pop reg3
  162. pop reg2
  163. into
  164. movw reg2,reg0
  165. }
  166. if (taicpu(p).ops=1) and
  167. (taicpu(p).oper[0]^.typ=top_reg) and
  168. GetNextInstruction(p,hp1) and
  169. (hp1.typ=ait_instruction) and
  170. (taicpu(hp1).opcode=A_PUSH) and
  171. (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
  172. ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
  173. GetNextInstruction(hp1,hp2) and
  174. (hp2.typ=ait_instruction) and
  175. (taicpu(hp2).opcode=A_POP) and
  176. GetNextInstruction(hp2,hp3) and
  177. (hp3.typ=ait_instruction) and
  178. (taicpu(hp3).opcode=A_POP) and
  179. (getsupreg(taicpu(hp2).oper[0]^.reg)=getsupreg(taicpu(hp3).oper[0]^.reg)+1) and
  180. ((getsupreg(taicpu(hp3).oper[0]^.reg) mod 2)=0) then
  181. begin
  182. taicpu(p).ops:=2;
  183. taicpu(p).opcode:=A_MOVW;
  184. taicpu(p).loadreg(1, taicpu(p).oper[0]^.reg);
  185. taicpu(p).loadreg(0, taicpu(hp3).oper[0]^.reg);
  186. asml.Remove(hp1);
  187. hp1.Free;
  188. asml.Remove(hp2);
  189. hp2.Free;
  190. asml.Remove(hp3);
  191. hp3.Free;
  192. result:=true;
  193. end;
  194. end;
  195. A_MOV:
  196. begin
  197. { turn
  198. mov reg0, reg1
  199. push reg0
  200. dealloc reg0
  201. into
  202. push reg1
  203. }
  204. if (taicpu(p).ops=2) and
  205. (taicpu(p).oper[0]^.typ = top_reg) and
  206. (taicpu(p).oper[1]^.typ = top_reg) and
  207. GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
  208. (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
  209. (hp1.typ = ait_instruction) and
  210. (taicpu(hp1).opcode in [A_PUSH,A_MOV,A_CP,A_CPC,A_ADD,A_SUB,A_EOR,A_AND,A_OR]) and
  211. RegInInstruction(taicpu(p).oper[0]^.reg, hp1) and
  212. (not RegModifiedByInstruction(taicpu(p).oper[0]^.reg, hp1)) and
  213. {(taicpu(hp1).ops=1) and
  214. (taicpu(hp1).oper[0]^.typ = top_reg) and
  215. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and }
  216. assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
  217. begin
  218. for i := 0 to taicpu(hp1).ops-1 do
  219. if taicpu(hp1).oper[i]^.typ=top_reg then
  220. if taicpu(hp1).oper[i]^.reg=taicpu(p).oper[0]^.reg then
  221. taicpu(hp1).oper[i]^.reg:=taicpu(p).oper[1]^.reg;
  222. alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
  223. dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
  224. if assigned(alloc) and assigned(dealloc) then
  225. begin
  226. asml.Remove(alloc);
  227. alloc.Free;
  228. asml.Remove(dealloc);
  229. dealloc.Free;
  230. end;
  231. GetNextInstruction(p,hp1);
  232. asml.Remove(p);
  233. p.free;
  234. p:=hp1;
  235. result:=true;
  236. end
  237. { fold
  238. mov reg2,reg0
  239. mov reg3,reg1
  240. to
  241. movw reg2,reg0
  242. }
  243. else if (taicpu(p).ops=2) and
  244. (taicpu(p).oper[0]^.typ = top_reg) and
  245. (taicpu(p).oper[1]^.typ = top_reg) and
  246. getnextinstruction(p,hp1) and
  247. (hp1.typ = ait_instruction) and
  248. (taicpu(hp1).opcode = A_MOV) and
  249. (taicpu(hp1).ops=2) and
  250. (taicpu(hp1).oper[0]^.typ = top_reg) and
  251. (taicpu(hp1).oper[1]^.typ = top_reg) and
  252. (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
  253. ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
  254. ((getsupreg(taicpu(p).oper[1]^.reg) mod 2)=0) and
  255. (getsupreg(taicpu(hp1).oper[1]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)+1) then
  256. begin
  257. alloc:=FindRegAllocBackward(taicpu(hp1).oper[0]^.reg,tai(hp1.Previous));
  258. if assigned(alloc) then
  259. begin
  260. asml.Remove(alloc);
  261. asml.InsertBefore(alloc,p);
  262. end;
  263. taicpu(p).opcode:=A_MOVW;
  264. asml.remove(hp1);
  265. hp1.free;
  266. result := true;
  267. end;
  268. end;
  269. end;
  270. end;
  271. end;
  272. end;
  273. procedure TCpuAsmOptimizer.PeepHoleOptPass2;
  274. begin
  275. end;
  276. begin
  277. casmoptimizer:=TCpuAsmOptimizer;
  278. End.