aoptcpu.pas 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. {
  2. Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
  3. Development Team
  4. This unit implements the SPC32 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. {$define DEBUG_AOPTCPU}
  21. Interface
  22. uses cpubase, cgbase, aasmtai, aopt, aoptcpub;
  23. Type
  24. { TCpuAsmOptimizer }
  25. TCpuAsmOptimizer = class(TAsmOptimizer)
  26. private
  27. function SkipMarkers(var p: tai): boolean;
  28. public
  29. Function GetNextInstructionUsingReg(Current: tai; Var Next: tai;reg : TRegister): Boolean;
  30. { uses the same constructor as TAopObj }
  31. function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
  32. function PeepHoleOptPass2Cpu(var p: tai): boolean; override;
  33. function PostPeepHoleOptsCpu(var p: tai): boolean; override;
  34. procedure DebugMsg(const s: string; p: tai);
  35. End;
  36. Implementation
  37. uses
  38. cpuinfo,
  39. aasmbase,aasmcpu,
  40. globals,globtype,
  41. cutils;
  42. function CanBeCond(p : tai) : boolean;
  43. begin
  44. result:=(p.typ=ait_instruction) and (taicpu(p).condition=C_None);
  45. end;
  46. function TCpuAsmOptimizer.SkipMarkers(var p: tai): boolean;
  47. begin
  48. result:=assigned(p);
  49. while result and
  50. assigned(p) and
  51. (p.typ in [ait_marker,ait_force_line]) do
  52. begin
  53. p:=tai(p.next);
  54. result:=assigned(p);
  55. end;
  56. end;
  57. function TCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai;
  58. var Next: tai; reg: TRegister): Boolean;
  59. begin
  60. Next:=Current;
  61. repeat
  62. Result:=GetNextInstruction(Next,Next);
  63. until not(cs_opt_level3 in current_settings.optimizerswitches) or not(Result) or (Next.typ<>ait_instruction) or (RegInInstruction(reg,Next)) or
  64. (is_calljmp(taicpu(Next).opcode));
  65. end;
  66. {$ifdef DEBUG_AOPTCPU}
  67. procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);
  68. begin
  69. asml.insertbefore(tai_comment.Create(strpnew(s)), p);
  70. end;
  71. {$else DEBUG_AOPTCPU}
  72. procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);inline;
  73. begin
  74. end;
  75. {$endif DEBUG_AOPTCPU}
  76. function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
  77. var
  78. hp1,hp2,hp3: tai;
  79. alloc, dealloc: tai_regalloc;
  80. i: integer;
  81. begin
  82. result := false;
  83. case p.typ of
  84. ait_instruction:
  85. begin
  86. case taicpu(p).opcode of
  87. A_LD:
  88. begin
  89. {
  90. turn
  91. ld rx
  92. st rx
  93. into
  94. ld rx
  95. }
  96. if (taicpu(p).ops=1) and
  97. (taicpu(p).oper[0]^.typ=top_reg) and
  98. GetNextInstruction(p,hp1) and
  99. (hp1.typ=ait_instruction) and
  100. (taicpu(hp1).opcode=A_ST) and
  101. (taicpu(hp1).ops=1) and
  102. (taicpu(hp1).oper[0]^.typ=top_reg) and
  103. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) then
  104. begin
  105. DebugMsg('LdSt2Ld', p);
  106. AsmL.Remove(hp1);
  107. hp1.free;
  108. result:=true;
  109. end
  110. {
  111. turn
  112. ld *
  113. ld rx
  114. into
  115. ld rx
  116. }
  117. else if (taicpu(p).ops=1) and
  118. GetNextInstruction(p,hp1) and
  119. (hp1.typ=ait_instruction) and
  120. (taicpu(hp1).opcode in [A_LD,A_NUL,A_GS]) then
  121. begin
  122. DebugMsg('LdLd2Ld', p);
  123. AsmL.Remove(p);
  124. p.free;
  125. p:=hp1;
  126. result:=true;
  127. end
  128. {
  129. turn
  130. ld rx
  131. ldX #0
  132. into
  133. nul
  134. ldX rx
  135. }
  136. else if (taicpu(p).ops=1) and
  137. (taicpu(p).oper[0]^.typ=top_reg) and
  138. GetNextInstruction(p,hp1) and
  139. (hp1.typ=ait_instruction) and
  140. (taicpu(hp1).opcode in [A_LDB,A_LDH,A_LDW]) and
  141. (taicpu(hp1).ops=1) and
  142. (taicpu(hp1).oper[0]^.typ=top_const) and
  143. (taicpu(hp1).oper[0]^.val=0) then
  144. begin
  145. DebugMsg('LdLdx2Ldx', p);
  146. taicpu(hp1).loadreg(0,taicpu(p).oper[0]^.reg);
  147. taicpu(p).ops:=0;
  148. taicpu(p).opcode:=A_NUL;
  149. result:=true;
  150. end
  151. {
  152. turn
  153. ld rx
  154. alloc ry
  155. st ry
  156. ...
  157. op ry
  158. dealloc ry
  159. into
  160. ld rx
  161. ...
  162. op rx
  163. }
  164. else if (taicpu(p).ops=1) and
  165. (taicpu(p).oper[0]^.typ=top_reg) and
  166. GetNextInstruction(p,hp1) and
  167. (hp1.typ=ait_instruction) and
  168. (taicpu(hp1).opcode=A_ST) and
  169. (taicpu(hp1).ops=1) and
  170. (taicpu(hp1).oper[0]^.typ=top_reg) and
  171. GetNextInstructionUsingReg(hp1,hp2,taicpu(hp1).oper[0]^.reg) and
  172. (hp2.typ=ait_instruction) and
  173. (taicpu(hp2).ops=1) and
  174. (taicpu(hp2).opcode<>A_ST) and
  175. (taicpu(hp2).oper[0]^.typ=top_reg) and
  176. (taicpu(hp2).oper[0]^.reg=taicpu(hp1).oper[0]^.reg) and
  177. assigned(FindRegDeAlloc(taicpu(hp1).oper[0]^.reg,tai(hp2.Next))) and
  178. (not RegModifiedBetween(taicpu(p).oper[0]^.reg,p,hp2)) then
  179. begin
  180. DebugMsg('LdStOp2LdOp', p);
  181. alloc:=FindRegAllocBackward(taicpu(hp1).oper[0]^.reg, tai(hp1.Previous));
  182. dealloc:=FindRegDeAlloc(taicpu(hp1).oper[0]^.reg,tai(hp2.next));
  183. if assigned(alloc) and assigned(dealloc) then
  184. begin
  185. asml.Remove(alloc);
  186. alloc.free;
  187. asml.Remove(dealloc);
  188. dealloc.free;
  189. end;
  190. AsmL.Remove(hp1);
  191. hp1.free;
  192. taicpu(hp2).oper[0]^.reg:=taicpu(p).oper[0]^.reg;
  193. result:=true;
  194. end
  195. {
  196. turn
  197. ld rx
  198. stX *
  199. ld rx
  200. into
  201. ld rx
  202. stX *
  203. }
  204. else if (taicpu(p).ops=1) and
  205. (taicpu(p).oper[0]^.typ=top_reg) and
  206. GetNextInstruction(p,hp1) and
  207. (hp1.typ=ait_instruction) and
  208. (taicpu(hp1).opcode in [A_STB,A_STH,A_STW]) and
  209. (taicpu(hp1).ops=1) and
  210. GetNextInstruction(hp1,hp2) and
  211. (hp2.typ=ait_instruction) and
  212. (taicpu(hp2).opcode=A_LD) and
  213. (taicpu(hp2).ops=1) and
  214. (taicpu(hp2).oper[0]^.typ=top_reg) and
  215. (taicpu(hp2).oper[0]^.reg=taicpu(p).oper[0]^.reg) then
  216. begin
  217. DebugMsg('LdStxLd2LdStx', p);
  218. asml.remove(hp2);
  219. hp2.free;
  220. result:=true;
  221. end
  222. {
  223. turn
  224. ld #x
  225. ldu #y
  226. ldX #0
  227. into
  228. nul
  229. ldu #y+$8000
  230. ldX #x
  231. }
  232. else if (taicpu(p).ops=1) and
  233. (taicpu(p).oper[0]^.typ=top_ref) and
  234. (taicpu(p).oper[0]^.ref^.refaddr=addr_lo16) and
  235. GetNextInstruction(p,hp1) and
  236. (hp1.typ=ait_instruction) and
  237. (taicpu(hp1).opcode in [A_LDU]) and
  238. (taicpu(hp1).ops=1) and
  239. (taicpu(hp1).oper[0]^.typ=top_ref) and
  240. (taicpu(hp1).oper[0]^.ref^.refaddr=addr_hi16) and
  241. GetNextInstruction(hp1,hp2) and
  242. (hp2.typ=ait_instruction) and
  243. (taicpu(hp2).opcode in [A_LDB,A_LDH,A_LDW]) and
  244. (taicpu(hp2).ops=1) and
  245. (taicpu(hp2).oper[0]^.typ=top_const) and
  246. (taicpu(hp2).oper[0]^.val=0) then
  247. begin
  248. DebugMsg('LdLduLdx2NulLduLdx', p);
  249. inc(taicpu(hp1).oper[0]^.ref^.offset, $8000);
  250. taicpu(hp2).loadref(0, taicpu(p).oper[0]^.ref^);
  251. taicpu(p).ops:=0;
  252. taicpu(p).opcode:=A_NUL;
  253. result:=true;
  254. end
  255. {
  256. turn
  257. ld 0
  258. into
  259. nul
  260. }
  261. else if (taicpu(p).ops=1) and
  262. (taicpu(p).oper[0]^.typ=top_const) and
  263. (taicpu(p).oper[0]^.val=0) then
  264. begin
  265. DebugMsg('Ld2Nul', p);
  266. taicpu(p).ops:=0;
  267. taicpu(p).opcode:=A_NUL;
  268. result:=true;
  269. end
  270. {
  271. turn
  272. ld rX
  273. ss 6
  274. ...
  275. gs 6
  276. into
  277. ...
  278. ld rX
  279. }
  280. else if (taicpu(p).ops=1) and
  281. (taicpu(p).oper[0]^.typ=top_reg) and
  282. GetNextInstruction(p,hp1) and
  283. (hp1.typ=ait_instruction) and
  284. (taicpu(hp1).opcode=A_SS) and
  285. (taicpu(hp1).ops=1) and
  286. (taicpu(hp1).oper[0]^.typ=top_const) and
  287. (taicpu(hp1).oper[0]^.val=6) then
  288. begin
  289. hp2:=hp1;
  290. for i:=0 to 4 do
  291. begin
  292. if not GetNextInstruction(hp2,hp2) then
  293. exit;
  294. if (hp2.typ=ait_instruction) and
  295. taicpu(hp2).is_jmp then
  296. exit;
  297. if (hp2.typ=ait_instruction) and
  298. (taicpu(hp2).opcode=A_GS) and
  299. (taicpu(hp2).ops=1) and
  300. (taicpu(hp2).oper[0]^.typ=top_const) and
  301. (taicpu(hp2).oper[0]^.val=6) then
  302. begin
  303. DebugMsg('LdSS6_2_...Ld', p);
  304. if RegModifiedBetween(taicpu(p).oper[0]^.reg,hp1,hp2) then
  305. exit;
  306. asml.Remove(p);
  307. asml.InsertAfter(p,hp2);
  308. asml.Remove(hp2);
  309. hp2.Free;
  310. GetNextInstruction(hp1,p);
  311. asml.Remove(hp1);
  312. hp1.Free;
  313. result:=true;
  314. break;
  315. end;
  316. end;
  317. end;
  318. end;
  319. A_ST:
  320. begin
  321. {
  322. turn
  323. st rx
  324. ld rx
  325. dealloc rx
  326. into
  327. ...
  328. }
  329. if (taicpu(p).ops=1) and
  330. (taicpu(p).oper[0]^.typ=top_reg) and
  331. GetNextInstruction(p,hp1) and
  332. SkipMarkers(hp1) and
  333. (hp1.typ=ait_instruction) and
  334. (taicpu(hp1).opcode=A_LD) and
  335. (taicpu(hp1).ops=1) and
  336. (taicpu(hp1).oper[0]^.typ=top_reg) and
  337. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
  338. assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.next))) then
  339. begin
  340. DebugMsg('StLd2*', p);
  341. alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg, tai(p.Previous));
  342. dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.next));
  343. if assigned(alloc) and assigned(dealloc) then
  344. begin
  345. asml.Remove(alloc);
  346. alloc.free;
  347. asml.Remove(dealloc);
  348. dealloc.free;
  349. end;
  350. AsmL.Remove(hp1);
  351. hp1.free;
  352. GetNextInstruction(p,hp1);
  353. AsmL.Remove(p);
  354. p.free;
  355. p:=hp1;
  356. result:=true;
  357. end
  358. {
  359. turn
  360. st rx
  361. ld rx
  362. into
  363. st rx
  364. }
  365. else if (taicpu(p).ops=1) and
  366. (taicpu(p).oper[0]^.typ=top_reg) and
  367. GetNextInstruction(p,hp1) and
  368. SkipMarkers(hp1) and
  369. (hp1.typ=ait_instruction) and
  370. (taicpu(hp1).opcode=A_LD) and
  371. (taicpu(hp1).ops=1) and
  372. (taicpu(hp1).oper[0]^.typ=top_reg) and
  373. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) then
  374. begin
  375. DebugMsg('StLd2St', p);
  376. AsmL.Remove(hp1);
  377. hp1.free;
  378. result:=true;
  379. end
  380. {
  381. turn
  382. st rx
  383. st rx
  384. into
  385. st rx
  386. }
  387. else if (taicpu(p).ops=1) and
  388. (taicpu(p).oper[0]^.typ=top_reg) and
  389. GetNextInstruction(p,hp1) and
  390. SkipMarkers(hp1) and
  391. (hp1.typ=ait_instruction) and
  392. (taicpu(hp1).opcode=A_ST) and
  393. (taicpu(hp1).ops=1) and
  394. (taicpu(hp1).oper[0]^.typ=top_reg) and
  395. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) then
  396. begin
  397. DebugMsg('StSt2St', p);
  398. AsmL.Remove(hp1);
  399. hp1.free;
  400. result:=true;
  401. end
  402. {
  403. turn
  404. st rx
  405. ...
  406. st rx
  407. into
  408. st rx
  409. }
  410. else if (taicpu(p).ops=1) and
  411. (taicpu(p).oper[0]^.typ=top_reg) and
  412. GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
  413. SkipMarkers(hp1) and
  414. (hp1.typ=ait_instruction) and
  415. (taicpu(hp1).opcode=A_ST) and
  416. (taicpu(hp1).ops=1) and
  417. (taicpu(hp1).oper[0]^.typ=top_reg) and
  418. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
  419. (not RegModifiedBetween(taicpu(p).oper[0]^.reg,p,hp1)) and
  420. (not RegUsedBetween(taicpu(p).oper[0]^.reg,p,hp1)) then
  421. begin
  422. DebugMsg('St...St2...St', p);
  423. GetNextInstruction(p,hp1);
  424. AsmL.Remove(p);
  425. p.free;
  426. p:=hp1;
  427. result:=true;
  428. end
  429. {
  430. turn
  431. st rx
  432. nul
  433. ldw rx
  434. dealloc rx
  435. into
  436. ldw 0
  437. }
  438. else if (taicpu(p).ops=1) and
  439. (taicpu(p).oper[0]^.typ=top_reg) and
  440. GetNextInstruction(p,hp1) and
  441. (hp1.typ=ait_instruction) and
  442. (taicpu(hp1).opcode=A_NUL) and
  443. GetNextInstruction(hp1,hp2) and
  444. (hp1.typ=ait_instruction) and
  445. (taicpu(hp2).opcode in [A_LDW,A_LDH,A_LDB]) and
  446. (taicpu(hp2).ops=1) and
  447. (taicpu(hp2).oper[0]^.typ=top_reg) and
  448. (taicpu(hp2).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
  449. Assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp2.next))) then
  450. begin
  451. DebugMsg('StNulLdx2Ldx', p);
  452. alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg, tai(p.Previous));
  453. dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp2.next));
  454. if assigned(alloc) and assigned(dealloc) then
  455. begin
  456. asml.Remove(alloc);
  457. alloc.free;
  458. asml.Remove(dealloc);
  459. dealloc.free;
  460. end;
  461. AsmL.Remove(p);
  462. p.free;
  463. AsmL.Remove(hp1);
  464. hp1.free;
  465. taicpu(hp2).loadconst(0,0);
  466. p:=taicpu(hp2);
  467. if p.Previous<>nil then
  468. p:=tai(p.Previous); // try to enable some extra optimizations
  469. result:=true;
  470. end
  471. {
  472. turn
  473. st rx
  474. ld ry
  475. [dealloc ry]
  476. op rx
  477. dealloc rx
  478. into
  479. op ry
  480. [dealloc ry]
  481. }
  482. else if (taicpu(p).ops=1) and
  483. (taicpu(p).oper[0]^.typ=top_reg) and
  484. GetNextInstruction(p,hp1) and
  485. SkipMarkers(hp1) and
  486. (hp1.typ=ait_instruction) and
  487. (taicpu(hp1).opcode=A_LD) and
  488. (taicpu(hp1).ops=1) and
  489. (taicpu(hp1).oper[0]^.typ=top_reg) and
  490. GetNextInstruction(hp1,hp2) and
  491. SkipMarkers(hp2) and
  492. (hp2.typ=ait_instruction) and
  493. (taicpu(hp2).opcode in [A_ADD,A_ADC,A_MUL,
  494. A_AND,A_ORR,A_XOR]) and
  495. (taicpu(hp2).ops=1) and
  496. (taicpu(hp2).oper[0]^.typ=top_reg) and
  497. (taicpu(hp2).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
  498. assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp2.next))) then
  499. begin
  500. DebugMsg('StLdOp2Op', p);
  501. dealloc:=FindRegDeAlloc(taicpu(hp1).oper[0]^.reg,tai(hp1.next));
  502. if assigned(dealloc) then
  503. begin
  504. asml.Remove(dealloc);
  505. asml.InsertAfter(dealloc,hp2);
  506. end;
  507. alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg, tai(p.Previous));
  508. dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp2.next));
  509. if assigned(alloc) and assigned(dealloc) then
  510. begin
  511. asml.Remove(alloc);
  512. alloc.free;
  513. asml.Remove(dealloc);
  514. dealloc.free;
  515. end;
  516. taicpu(hp2).oper[0]^.reg:=taicpu(hp1).oper[0]^.reg;
  517. AsmL.Remove(hp1);
  518. hp1.free;
  519. AsmL.Remove(p);
  520. p.free;
  521. p:=hp2;
  522. result:=true;
  523. end;
  524. end;
  525. A_GS:
  526. begin
  527. {
  528. turn
  529. gs pc
  530. j...
  531. gs pc
  532. ...
  533. into
  534. gs pc
  535. j...
  536. ...
  537. }
  538. if (taicpu(p).ops=1) and
  539. (taicpu(p).oper[0]^.typ=top_const) and
  540. (taicpu(p).oper[0]^.val=SS_PC) then
  541. begin
  542. hp1:=p;
  543. {while GetNextInstruction(hp1,hp2) and
  544. (hp2.typ=ait_instruction) and
  545. (taicpu(hp2).is_jmp) do
  546. begin
  547. if GetNextInstruction(hp2,hp3) and
  548. (hp3.typ=ait_instruction) and
  549. (taicpu(hp3).opcode=A_GS) and
  550. (taicpu(hp3).ops=1) and
  551. (taicpu(hp3).oper[0]^.typ=top_const) and
  552. (taicpu(hp3).oper[0]^.val=SS_PC) then
  553. begin
  554. DebugMsg('GsJGs2GsJ', hp1);
  555. asml.Remove(hp3);
  556. hp3.free;
  557. result:=true;
  558. end
  559. else
  560. break;
  561. hp1:=hp2;
  562. end;}
  563. end;
  564. end;
  565. A_SS:
  566. begin
  567. {
  568. turn
  569. ss 6
  570. ...
  571. gs 6
  572. ld rX
  573. into
  574. ...
  575. ld rX
  576. }
  577. if (taicpu(p).opcode=A_SS) and
  578. (taicpu(p).ops=1) and
  579. (taicpu(p).oper[0]^.typ=top_const) and
  580. (taicpu(p).oper[0]^.val=6) then
  581. begin
  582. hp1:=p;
  583. hp2:=p;
  584. for i:=0 to 4 do
  585. begin
  586. if not GetNextInstruction(hp2,hp2) then
  587. exit;
  588. if (hp2.typ=ait_instruction) and
  589. taicpu(hp2).is_jmp then
  590. exit;
  591. if (hp2.typ=ait_instruction) and
  592. (taicpu(hp2).opcode=A_GS) and
  593. (taicpu(hp2).ops=1) and
  594. (taicpu(hp2).oper[0]^.typ=top_const) and
  595. (taicpu(hp2).oper[0]^.val=6) then
  596. begin
  597. if not GetNextInstruction(hp2,p) then
  598. exit;
  599. if (p.typ=ait_instruction) and
  600. (taicpu(p).opcode in [A_LD,A_NUL,A_GS]) then
  601. begin
  602. DebugMsg('Ss6 Removal', p);
  603. GetNextInstruction(hp1,p);
  604. asml.Remove(hp2);
  605. hp2.Free;
  606. asml.Remove(hp1);
  607. hp1.Free;
  608. result:=true;
  609. end;
  610. break;
  611. {if RegModifiedBetween(taicpu(p).oper[0]^.reg,hp1,hp2) then
  612. exit;
  613. asml.Remove(p);
  614. asml.InsertAfter(p,hp2);
  615. asml.Remove(hp2);
  616. hp2.Free;
  617. GetNextInstruction(hp1,p);
  618. asml.Remove(hp1);
  619. hp1.Free;
  620. break;}
  621. end;
  622. end;
  623. end;
  624. end;
  625. A_ADD:
  626. begin
  627. if (taicpu(p).ops=1) and
  628. (taicpu(p).oper[0]^.typ=top_reg) and
  629. GetNextInstruction(p,hp1) and
  630. (taicpu(hp1).opcode in [A_LDW,A_LDH,A_LDB]) and
  631. (taicpu(hp1).ops=1) and
  632. (taicpu(hp1).oper[0]^.typ=top_const) and
  633. (taicpu(hp1).oper[0]^.val=0) then
  634. begin
  635. DebugMsg('AddLdw2Ldw', p);
  636. taicpu(hp1).loadreg(0,taicpu(p).oper[0]^.reg);
  637. asml.remove(p);
  638. p.free;
  639. p:=hp1;
  640. result:=true;
  641. end;
  642. end;
  643. A_MOV:
  644. begin
  645. {
  646. turn
  647. mov rx,ry
  648. info
  649. ld ry
  650. st rx
  651. }
  652. dealloc:=FindRegDeAlloc(taicpu(p).oper[1]^.reg,tai(p.next));
  653. hp1:=taicpu.op_reg(A_ST,taicpu(p).oper[0]^.reg);
  654. if assigned(dealloc) then
  655. AsmL.InsertAfter(hp1, dealloc)
  656. else
  657. AsmL.InsertAfter(hp1, p);
  658. taicpu(p).loadreg(0,taicpu(p).oper[1]^.reg);
  659. taicpu(p).ops:=1;
  660. taicpu(p).opcode:=A_LD;
  661. result:=true;
  662. end;
  663. A_NUL:
  664. begin
  665. {
  666. turn
  667. nul
  668. alloc ry
  669. st ry
  670. ...
  671. op ry
  672. dealloc ry
  673. into
  674. ...
  675. op 0
  676. }
  677. if GetNextInstruction(p,hp1) and
  678. (hp1.typ=ait_instruction) and
  679. (taicpu(hp1).opcode=A_ST) and
  680. (taicpu(hp1).ops=1) and
  681. (taicpu(hp1).oper[0]^.typ=top_reg) and
  682. GetNextInstructionUsingReg(hp1,hp2,taicpu(hp1).oper[0]^.reg) and
  683. (hp2.typ=ait_instruction) and
  684. (taicpu(hp2).ops=1) and
  685. (taicpu(hp2).opcode<>A_ST) and
  686. (taicpu(hp2).oper[0]^.typ=top_reg) and
  687. (taicpu(hp2).oper[0]^.reg=taicpu(hp1).oper[0]^.reg) and
  688. assigned(FindRegDeAlloc(taicpu(hp1).oper[0]^.reg,tai(hp2.Next))) then
  689. begin
  690. alloc:=FindRegAllocBackward(taicpu(hp1).oper[0]^.reg, tai(hp1.Previous));
  691. dealloc:=FindRegDeAlloc(taicpu(hp1).oper[0]^.reg,tai(hp2.next));
  692. if assigned(alloc) and assigned(dealloc) then
  693. begin
  694. asml.Remove(alloc);
  695. alloc.free;
  696. asml.Remove(dealloc);
  697. dealloc.free;
  698. end;
  699. DebugMsg('NulStOp2Op0', p);
  700. AsmL.Remove(hp1);
  701. hp1.free;
  702. taicpu(hp2).loadconst(0,0);
  703. result:=true;
  704. end
  705. {
  706. turn
  707. nul
  708. ld/nul
  709. into
  710. ld/nul
  711. }
  712. else if GetNextInstruction(p,hp1) and
  713. (hp1.typ=ait_instruction) and
  714. (taicpu(hp1).opcode in [A_NUL,A_LD]) then
  715. begin
  716. DebugMsg('Dup nul removed', p);
  717. asml.remove(p);
  718. p.free;
  719. p:=hp1;
  720. result:=true;
  721. end
  722. {
  723. turn
  724. nul
  725. add *
  726. into
  727. ld *
  728. }
  729. else if GetNextInstruction(p,hp1) and
  730. (hp1.typ=ait_instruction) and
  731. (taicpu(hp1).opcode in [A_ADD]) then
  732. begin
  733. DebugMsg('NulAdd2Ld', p);
  734. asml.remove(p);
  735. p.free;
  736. p:=hp1;
  737. taicpu(p).opcode:=A_LD;
  738. result:=true;
  739. end
  740. {
  741. turn
  742. nul
  743. sub #x
  744. into
  745. ld #x
  746. }
  747. else if GetNextInstruction(p,hp1) and
  748. (hp1.typ=ait_instruction) and
  749. (taicpu(hp1).opcode in [A_SUB]) and
  750. (taicpu(hp1).ops=1) and
  751. (taicpu(hp1).oper[0]^.typ=top_const) and
  752. (abs(taicpu(hp1).oper[0]^.val)<$8000) then
  753. begin
  754. DebugMsg('NulSub2Ld', p);
  755. asml.remove(p);
  756. p.free;
  757. p:=hp1;
  758. taicpu(p).opcode:=A_LD;
  759. taicpu(p).oper[0]^.val:=-taicpu(p).oper[0]^.val;
  760. result:=true;
  761. end;
  762. end;
  763. A_LOAD:
  764. begin
  765. {
  766. ss 6
  767. ld ref.offset
  768. add ref.index
  769. ldw ref.base
  770. st reg
  771. gs 6
  772. ss 6
  773. ld ref.offset
  774. ldw ref.base
  775. st reg
  776. gs 6
  777. }
  778. if GetNextInstruction(p,hp1) and
  779. (tai(hp1).typ=ait_instruction) and
  780. (not (taicpu(hp1).opcode in [A_LD,A_NUL,A_GS])) then
  781. begin
  782. AsmL.InsertBefore(taicpu.op_const(A_SS,6),p);
  783. AsmL.InsertAfter(taicpu.op_const(A_GS,6),p);
  784. end;
  785. AsmL.InsertAfter(taicpu.op_reg(A_ST,taicpu(p).oper[0]^.reg),p);
  786. AsmL.InsertAfter(taicpu.op_reg(A_LDW,taicpu(p).oper[1]^.ref^.base),p);
  787. if taicpu(p).oper[1]^.ref^.index<>NR_NO then
  788. AsmL.InsertAfter(taicpu.op_reg(A_ADD,taicpu(p).oper[1]^.ref^.index),p);
  789. taicpu(p).opcode:=A_LD;
  790. taicpu(p).loadconst(0, taicpu(p).oper[1]^.ref^.offset);
  791. taicpu(p).ops:=1;
  792. result:=true;
  793. end;
  794. A_STORE:
  795. begin
  796. {
  797. ss 6
  798. ld ref.offset
  799. add ref.index
  800. add ref.base
  801. stw reg
  802. gs 6
  803. }
  804. if GetNextInstruction(p,hp1) and
  805. (tai(hp1).typ=ait_instruction) and
  806. (not (taicpu(hp1).opcode in [A_LD,A_NUL,A_GS])) then
  807. begin
  808. AsmL.InsertBefore(taicpu.op_const(A_SS,6),p);
  809. AsmL.InsertAfter(taicpu.op_const(A_GS,6),p);
  810. end;
  811. //AsmL.InsertBefore(taicpu.op_const(A_SS,6),p);
  812. //AsmL.InsertAfter(taicpu.op_const(A_GS,6),p);
  813. AsmL.InsertAfter(taicpu.op_reg(A_STW,taicpu(p).oper[0]^.reg),p);
  814. AsmL.InsertAfter(taicpu.op_reg(A_ADD,taicpu(p).oper[1]^.ref^.base),p);
  815. if taicpu(p).oper[1]^.ref^.index<>NR_NO then
  816. AsmL.InsertAfter(taicpu.op_reg(A_ADD,taicpu(p).oper[1]^.ref^.index),p);
  817. taicpu(p).opcode:=A_LD;
  818. taicpu(p).loadconst(0, taicpu(p).oper[1]^.ref^.offset);
  819. taicpu(p).ops:=1;
  820. result:=true;
  821. end;
  822. end;
  823. end;
  824. end;
  825. end;
  826. function TCpuAsmOptimizer.PeepHoleOptPass2Cpu(var p: tai): boolean;
  827. var
  828. hp1,hp2,hp3: tai;
  829. alloc, dealloc: tai_regalloc;
  830. i: integer;
  831. begin
  832. result := false;
  833. case p.typ of
  834. ait_instruction:
  835. begin
  836. case taicpu(p).opcode of
  837. A_PJMP:
  838. begin
  839. AsmL.InsertBefore(taicpu.op_const(A_GS,SS_PC),p);
  840. taicpu(p).opcode:=A_JMP;
  841. result:=true;
  842. end;
  843. A_PJxx:
  844. begin
  845. AsmL.InsertBefore(taicpu.op_const(A_GS,SS_PC),p);
  846. taicpu(p).opcode:=A_Jxx;
  847. result:=true;
  848. end;
  849. A_PCALL:
  850. begin
  851. AsmL.InsertBefore(taicpu.op_const(A_GS,SS_PC),p);
  852. taicpu(p).opcode:=A_CALL;
  853. result:=true;
  854. end;
  855. end;
  856. end;
  857. end;
  858. end;
  859. function TCpuAsmOptimizer.PostPeepHoleOptsCpu(var p: tai): boolean;
  860. var
  861. hp1,hp2,hp3, hp4: tai;
  862. alloc, dealloc: tai_regalloc;
  863. i: integer;
  864. begin
  865. result := false;
  866. case p.typ of
  867. ait_instruction:
  868. begin
  869. case taicpu(p).opcode of
  870. A_GS:
  871. begin
  872. if (taicpu(p).ops=1) and
  873. (taicpu(p).oper[0]^.typ=top_const) and
  874. (taicpu(p).oper[0]^.val=SS_PC) then
  875. begin
  876. hp1:=p;
  877. while GetNextInstruction(hp1,hp2) and
  878. (hp2.typ=ait_instruction) and
  879. (taicpu(hp2).is_jmp) do
  880. begin
  881. if GetNextInstruction(hp2,hp3) and
  882. (hp3.typ=ait_label) and
  883. GetNextInstruction(hp3,hp4) and
  884. (hp4.typ=ait_instruction) and
  885. (taicpu(hp4).opcode=A_GS) and
  886. (taicpu(hp4).ops=1) and
  887. (taicpu(hp4).oper[0]^.typ=top_const) and
  888. (taicpu(hp4).oper[0]^.val=SS_PC) then
  889. begin
  890. DebugMsg('GsJGs2GsJ', hp1);
  891. asml.Remove(hp3);
  892. asml.InsertBefore(hp3,p);
  893. asml.Remove(hp4);
  894. hp4.free;
  895. result:=true;
  896. end
  897. else
  898. break;
  899. hp1:=hp2;
  900. end;
  901. end;
  902. end;
  903. end;
  904. end;
  905. end;
  906. end;
  907. begin
  908. casmoptimizer:=TCpuAsmOptimizer;
  909. End.