aoptcpu.pas 13 KB

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