aoptcpu.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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. (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
  72. (taicpu(hp1).opcode=A_CP) and
  73. (taicpu(hp1).ops=2) and
  74. (taicpu(hp1).oper[1]^.typ=top_reg) and
  75. (getsupreg(taicpu(hp1).oper[0]^.reg) in [16..31]) and
  76. (taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
  77. assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
  78. begin
  79. taicpu(hp1).opcode:=A_CPI;
  80. taicpu(hp1).loadconst(1, taicpu(p).oper[1]^.val);
  81. alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
  82. dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
  83. if assigned(alloc) and assigned(dealloc) then
  84. begin
  85. asml.Remove(alloc);
  86. alloc.Free;
  87. asml.Remove(dealloc);
  88. dealloc.Free;
  89. end;
  90. GetNextInstruction(p,hp1);
  91. asml.Remove(p);
  92. p.Free;
  93. p:=hp1;
  94. result:=true;
  95. end;
  96. end;
  97. A_CLR:
  98. begin
  99. { turn the common
  100. clr rX
  101. mov/ld rX, rY
  102. into
  103. mov/ld rX, rY
  104. }
  105. if (taicpu(p).ops=1) and
  106. (taicpu(p).oper[0]^.typ=top_reg) and
  107. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  108. (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
  109. (hp1.typ=ait_instruction) and
  110. (taicpu(hp1).opcode in [A_MOV,A_LD]) and
  111. (taicpu(hp1).ops>0) and
  112. (taicpu(hp1).oper[0]^.typ=top_reg) and
  113. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) then
  114. begin
  115. asml.Remove(p);
  116. p.Free;
  117. p:=hp1;
  118. result:=true;
  119. end
  120. { turn
  121. clr rX
  122. ...
  123. adc rY, rX
  124. into
  125. ...
  126. adc rY, r1
  127. }
  128. else if (taicpu(p).ops=1) and
  129. (taicpu(p).oper[0]^.typ=top_reg) and
  130. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  131. (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
  132. (hp1.typ=ait_instruction) and
  133. (taicpu(hp1).opcode in [A_ADC,A_SBC]) and
  134. (taicpu(hp1).ops=2) and
  135. (taicpu(hp1).oper[1]^.typ=top_reg) and
  136. (taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
  137. (taicpu(hp1).oper[0]^.reg<>taicpu(p).oper[0]^.reg) and
  138. assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
  139. begin
  140. taicpu(hp1).oper[1]^.reg:=NR_R1;
  141. alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
  142. dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
  143. if assigned(alloc) and assigned(dealloc) then
  144. begin
  145. asml.Remove(alloc);
  146. alloc.Free;
  147. asml.Remove(dealloc);
  148. dealloc.Free;
  149. end;
  150. GetNextInstruction(p,hp1);
  151. asml.Remove(p);
  152. p.free;
  153. p:=hp1;
  154. result:=true;
  155. end;
  156. end;
  157. A_PUSH:
  158. begin
  159. { turn
  160. push reg0
  161. push reg1
  162. pop reg3
  163. pop reg2
  164. into
  165. movw reg2,reg0
  166. }
  167. if (taicpu(p).ops=1) and
  168. (taicpu(p).oper[0]^.typ=top_reg) and
  169. GetNextInstruction(p,hp1) and
  170. (hp1.typ=ait_instruction) and
  171. (taicpu(hp1).opcode=A_PUSH) and
  172. (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
  173. ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
  174. GetNextInstruction(hp1,hp2) and
  175. (hp2.typ=ait_instruction) and
  176. (taicpu(hp2).opcode=A_POP) and
  177. GetNextInstruction(hp2,hp3) and
  178. (hp3.typ=ait_instruction) and
  179. (taicpu(hp3).opcode=A_POP) and
  180. (getsupreg(taicpu(hp2).oper[0]^.reg)=getsupreg(taicpu(hp3).oper[0]^.reg)+1) and
  181. ((getsupreg(taicpu(hp3).oper[0]^.reg) mod 2)=0) then
  182. begin
  183. taicpu(p).ops:=2;
  184. taicpu(p).opcode:=A_MOVW;
  185. taicpu(p).loadreg(1, taicpu(p).oper[0]^.reg);
  186. taicpu(p).loadreg(0, taicpu(hp3).oper[0]^.reg);
  187. asml.Remove(hp1);
  188. hp1.Free;
  189. asml.Remove(hp2);
  190. hp2.Free;
  191. asml.Remove(hp3);
  192. hp3.Free;
  193. result:=true;
  194. end;
  195. end;
  196. A_MOV:
  197. begin
  198. { turn
  199. mov reg0, reg1
  200. push reg0
  201. dealloc reg0
  202. into
  203. push reg1
  204. }
  205. if (taicpu(p).ops=2) and
  206. (taicpu(p).oper[0]^.typ = top_reg) and
  207. (taicpu(p).oper[1]^.typ = top_reg) and
  208. GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
  209. (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
  210. (hp1.typ = ait_instruction) and
  211. (taicpu(hp1).opcode in [A_PUSH,A_MOV,A_CP,A_CPC,A_ADD,A_SUB,A_EOR,A_AND,A_OR]) and
  212. RegInInstruction(taicpu(p).oper[0]^.reg, hp1) and
  213. (not RegModifiedByInstruction(taicpu(p).oper[0]^.reg, hp1)) and
  214. {(taicpu(hp1).ops=1) and
  215. (taicpu(hp1).oper[0]^.typ = top_reg) and
  216. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and }
  217. assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
  218. begin
  219. for i := 0 to taicpu(hp1).ops-1 do
  220. if taicpu(hp1).oper[i]^.typ=top_reg then
  221. if taicpu(hp1).oper[i]^.reg=taicpu(p).oper[0]^.reg then
  222. taicpu(hp1).oper[i]^.reg:=taicpu(p).oper[1]^.reg;
  223. alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
  224. dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
  225. if assigned(alloc) and assigned(dealloc) then
  226. begin
  227. asml.Remove(alloc);
  228. alloc.Free;
  229. asml.Remove(dealloc);
  230. dealloc.Free;
  231. end;
  232. GetNextInstruction(p,hp1);
  233. asml.Remove(p);
  234. p.free;
  235. p:=hp1;
  236. result:=true;
  237. end
  238. { fold
  239. mov reg2,reg0
  240. mov reg3,reg1
  241. to
  242. movw reg2,reg0
  243. }
  244. else if (CPUAVR_HAS_MOVW in cpu_capabilities[current_settings.cputype]) and
  245. (taicpu(p).ops=2) and
  246. (taicpu(p).oper[0]^.typ = top_reg) and
  247. (taicpu(p).oper[1]^.typ = top_reg) and
  248. getnextinstruction(p,hp1) and
  249. (hp1.typ = ait_instruction) and
  250. (taicpu(hp1).opcode = A_MOV) and
  251. (taicpu(hp1).ops=2) and
  252. (taicpu(hp1).oper[0]^.typ = top_reg) and
  253. (taicpu(hp1).oper[1]^.typ = top_reg) and
  254. (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
  255. ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
  256. ((getsupreg(taicpu(p).oper[1]^.reg) mod 2)=0) and
  257. (getsupreg(taicpu(hp1).oper[1]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)+1) then
  258. begin
  259. alloc:=FindRegAllocBackward(taicpu(hp1).oper[0]^.reg,tai(hp1.Previous));
  260. if assigned(alloc) then
  261. begin
  262. asml.Remove(alloc);
  263. asml.InsertBefore(alloc,p);
  264. end;
  265. taicpu(p).opcode:=A_MOVW;
  266. asml.remove(hp1);
  267. hp1.free;
  268. result := true;
  269. end;
  270. end;
  271. end;
  272. end;
  273. end;
  274. end;
  275. procedure TCpuAsmOptimizer.PeepHoleOptPass2;
  276. begin
  277. end;
  278. begin
  279. casmoptimizer:=TCpuAsmOptimizer;
  280. End.