aoptcpu.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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_STS:
  108. if (taicpu(p).oper[0]^.ref^.symbol=nil) and
  109. (taicpu(p).oper[0]^.ref^.relsymbol=nil) and
  110. (getsupreg(taicpu(p).oper[0]^.ref^.base)=RS_NO) and
  111. (getsupreg(taicpu(p).oper[0]^.ref^.index)=RS_NO) and
  112. (taicpu(p).oper[0]^.ref^.addressmode=AM_UNCHANGED) and
  113. (taicpu(p).oper[0]^.ref^.offset>=32) and
  114. (taicpu(p).oper[0]^.ref^.offset<=95) then
  115. begin
  116. taicpu(p).opcode:=A_OUT;
  117. taicpu(p).loadconst(0,taicpu(p).oper[0]^.ref^.offset-32);
  118. end;
  119. A_LDS:
  120. if (taicpu(p).oper[1]^.ref^.symbol=nil) and
  121. (taicpu(p).oper[1]^.ref^.relsymbol=nil) and
  122. (getsupreg(taicpu(p).oper[1]^.ref^.base)=RS_NO) and
  123. (getsupreg(taicpu(p).oper[1]^.ref^.index)=RS_NO) and
  124. (taicpu(p).oper[1]^.ref^.addressmode=AM_UNCHANGED) and
  125. (taicpu(p).oper[1]^.ref^.offset>=32) and
  126. (taicpu(p).oper[1]^.ref^.offset<=95) then
  127. begin
  128. taicpu(p).opcode:=A_IN;
  129. taicpu(p).loadconst(1,taicpu(p).oper[1]^.ref^.offset-32);
  130. end;
  131. A_CLR:
  132. begin
  133. { turn the common
  134. clr rX
  135. mov/ld rX, rY
  136. into
  137. mov/ld rX, rY
  138. }
  139. if (taicpu(p).ops=1) and
  140. (taicpu(p).oper[0]^.typ=top_reg) and
  141. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  142. (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
  143. (hp1.typ=ait_instruction) and
  144. (taicpu(hp1).opcode in [A_MOV,A_LD]) and
  145. (taicpu(hp1).ops>0) and
  146. (taicpu(hp1).oper[0]^.typ=top_reg) and
  147. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) then
  148. begin
  149. asml.Remove(p);
  150. p.Free;
  151. p:=hp1;
  152. result:=true;
  153. end
  154. { turn
  155. clr rX
  156. ...
  157. adc rY, rX
  158. into
  159. ...
  160. adc rY, r1
  161. }
  162. else if (taicpu(p).ops=1) and
  163. (taicpu(p).oper[0]^.typ=top_reg) and
  164. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  165. (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
  166. (hp1.typ=ait_instruction) and
  167. (taicpu(hp1).opcode in [A_ADC,A_SBC]) and
  168. (taicpu(hp1).ops=2) and
  169. (taicpu(hp1).oper[1]^.typ=top_reg) and
  170. (taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
  171. (taicpu(hp1).oper[0]^.reg<>taicpu(p).oper[0]^.reg) and
  172. assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
  173. begin
  174. taicpu(hp1).oper[1]^.reg:=NR_R1;
  175. alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
  176. dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
  177. if assigned(alloc) and assigned(dealloc) then
  178. begin
  179. asml.Remove(alloc);
  180. alloc.Free;
  181. asml.Remove(dealloc);
  182. dealloc.Free;
  183. end;
  184. GetNextInstruction(p,hp1);
  185. asml.Remove(p);
  186. p.free;
  187. p:=hp1;
  188. result:=true;
  189. end;
  190. end;
  191. A_PUSH:
  192. begin
  193. { turn
  194. push reg0
  195. push reg1
  196. pop reg3
  197. pop reg2
  198. into
  199. movw reg2,reg0
  200. }
  201. if (taicpu(p).ops=1) and
  202. (taicpu(p).oper[0]^.typ=top_reg) and
  203. GetNextInstruction(p,hp1) and
  204. (hp1.typ=ait_instruction) and
  205. (taicpu(hp1).opcode=A_PUSH) and
  206. (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
  207. ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
  208. GetNextInstruction(hp1,hp2) and
  209. (hp2.typ=ait_instruction) and
  210. (taicpu(hp2).opcode=A_POP) and
  211. GetNextInstruction(hp2,hp3) and
  212. (hp3.typ=ait_instruction) and
  213. (taicpu(hp3).opcode=A_POP) and
  214. (getsupreg(taicpu(hp2).oper[0]^.reg)=getsupreg(taicpu(hp3).oper[0]^.reg)+1) and
  215. ((getsupreg(taicpu(hp3).oper[0]^.reg) mod 2)=0) then
  216. begin
  217. taicpu(p).ops:=2;
  218. taicpu(p).opcode:=A_MOVW;
  219. taicpu(p).loadreg(1, taicpu(p).oper[0]^.reg);
  220. taicpu(p).loadreg(0, taicpu(hp3).oper[0]^.reg);
  221. asml.Remove(hp1);
  222. hp1.Free;
  223. asml.Remove(hp2);
  224. hp2.Free;
  225. asml.Remove(hp3);
  226. hp3.Free;
  227. result:=true;
  228. end;
  229. end;
  230. A_MOV:
  231. begin
  232. { turn
  233. mov reg0, reg1
  234. push reg0
  235. dealloc reg0
  236. into
  237. push reg1
  238. }
  239. if (taicpu(p).ops=2) and
  240. (taicpu(p).oper[0]^.typ = top_reg) and
  241. (taicpu(p).oper[1]^.typ = top_reg) and
  242. GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
  243. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p, hp1)) and
  244. (hp1.typ = ait_instruction) and
  245. (taicpu(hp1).opcode in [A_PUSH,A_MOV,A_CP,A_CPC,A_ADD,A_SUB,A_EOR,A_AND,A_OR]) and
  246. RegInInstruction(taicpu(p).oper[0]^.reg, hp1) and
  247. (not RegModifiedByInstruction(taicpu(p).oper[0]^.reg, hp1)) and
  248. {(taicpu(hp1).ops=1) and
  249. (taicpu(hp1).oper[0]^.typ = top_reg) and
  250. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and }
  251. assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
  252. begin
  253. for i := 0 to taicpu(hp1).ops-1 do
  254. if taicpu(hp1).oper[i]^.typ=top_reg then
  255. if taicpu(hp1).oper[i]^.reg=taicpu(p).oper[0]^.reg then
  256. taicpu(hp1).oper[i]^.reg:=taicpu(p).oper[1]^.reg;
  257. alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
  258. dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
  259. if assigned(alloc) and assigned(dealloc) then
  260. begin
  261. asml.Remove(alloc);
  262. alloc.Free;
  263. asml.Remove(dealloc);
  264. dealloc.Free;
  265. end;
  266. GetNextInstruction(p,hp1);
  267. asml.Remove(p);
  268. p.free;
  269. p:=hp1;
  270. result:=true;
  271. end
  272. { remove
  273. mov reg0,reg0
  274. }
  275. else if (taicpu(p).ops=2) and
  276. (taicpu(p).oper[0]^.typ = top_reg) and
  277. (taicpu(p).oper[1]^.typ = top_reg) and
  278. (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
  279. begin
  280. GetNextInstruction(p,hp1);
  281. asml.remove(p);
  282. p.free;
  283. p:=hp1;
  284. result:=true;
  285. end
  286. { fold
  287. mov reg2,reg0
  288. mov reg3,reg1
  289. to
  290. movw reg2,reg0
  291. }
  292. else if (CPUAVR_HAS_MOVW in cpu_capabilities[current_settings.cputype]) and
  293. (taicpu(p).ops=2) and
  294. (taicpu(p).oper[0]^.typ = top_reg) and
  295. (taicpu(p).oper[1]^.typ = top_reg) and
  296. getnextinstruction(p,hp1) and
  297. (hp1.typ = ait_instruction) and
  298. (taicpu(hp1).opcode = A_MOV) and
  299. (taicpu(hp1).ops=2) and
  300. (taicpu(hp1).oper[0]^.typ = top_reg) and
  301. (taicpu(hp1).oper[1]^.typ = top_reg) and
  302. (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
  303. ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
  304. ((getsupreg(taicpu(p).oper[1]^.reg) mod 2)=0) and
  305. (getsupreg(taicpu(hp1).oper[1]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)+1) then
  306. begin
  307. alloc:=FindRegAllocBackward(taicpu(hp1).oper[0]^.reg,tai(hp1.Previous));
  308. if assigned(alloc) then
  309. begin
  310. asml.Remove(alloc);
  311. asml.InsertBefore(alloc,p);
  312. end;
  313. taicpu(p).opcode:=A_MOVW;
  314. asml.remove(hp1);
  315. hp1.free;
  316. result:=true;
  317. end;
  318. end;
  319. end;
  320. end;
  321. end;
  322. end;
  323. procedure TCpuAsmOptimizer.PeepHoleOptPass2;
  324. begin
  325. end;
  326. begin
  327. casmoptimizer:=TCpuAsmOptimizer;
  328. End.