aoptcpu.pas 13 KB

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