aoptcpu.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. {
  2. Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
  3. Development Team
  4. This unit implements the ARM64 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
  23. globtype, globals,
  24. cutils,
  25. cgbase, cpubase, aasmtai, aasmcpu,
  26. aopt, aoptcpub, aoptarm;
  27. Type
  28. TCpuAsmOptimizer = class(TARMAsmOptimizer)
  29. { uses the same constructor as TAopObj }
  30. function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
  31. function PostPeepHoleOptsCpu(var p: tai): boolean; override;
  32. function RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;override;
  33. function InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;override;
  34. function LookForPostindexedPattern(p : taicpu) : boolean;
  35. private
  36. function OptPass1Shift(var p: tai): boolean;
  37. function OptPostCMP(var p: tai): boolean;
  38. function OptPass1Data(var p: tai): boolean;
  39. function RemoveSuperfluousFMov(const p: tai; movp: tai; const optimizer: string): boolean;
  40. function OptPass1STP(var p: tai): boolean;
  41. function OptPass1Mov(var p: tai): boolean;
  42. End;
  43. Implementation
  44. uses
  45. aasmbase,
  46. aoptutils,
  47. cgutils,
  48. verbose;
  49. function CanBeCond(p : tai) : boolean;
  50. begin
  51. result:=(p.typ=ait_instruction) and (taicpu(p).condition=C_None);
  52. end;
  53. function TCpuAsmOptimizer.RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;
  54. var
  55. p: taicpu;
  56. begin
  57. p := taicpu(hp);
  58. Result := false;
  59. if not ((assigned(hp)) and (hp.typ = ait_instruction)) then
  60. exit;
  61. case p.opcode of
  62. { These operands do not write into a register at all }
  63. A_CMP, A_CMN, A_TST, A_B, A_BL, A_MSR, A_FCMP:
  64. exit;
  65. {Take care of post/preincremented store and loads, they will change their base register}
  66. A_STR, A_LDR:
  67. begin
  68. Result := false;
  69. { actually, this does not apply here because post-/preindexed does not mean that a register
  70. is loaded with a new value, it is only modified
  71. (taicpu(p).oper[1]^.typ=top_ref) and
  72. (taicpu(p).oper[1]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and
  73. (taicpu(p).oper[1]^.ref^.base = reg);
  74. }
  75. { STR does not load into it's first register }
  76. if p.opcode = A_STR then
  77. exit;
  78. end;
  79. else
  80. ;
  81. end;
  82. if Result then
  83. exit;
  84. case p.oper[0]^.typ of
  85. top_reg:
  86. Result := (p.oper[0]^.reg = reg);
  87. top_ref:
  88. Result :=
  89. (taicpu(p).oper[0]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and
  90. (taicpu(p).oper[0]^.ref^.base = reg);
  91. else
  92. ;
  93. end;
  94. end;
  95. function TCpuAsmOptimizer.InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;
  96. var
  97. p: taicpu;
  98. i: longint;
  99. begin
  100. instructionLoadsFromReg := false;
  101. if not (assigned(hp) and (hp.typ = ait_instruction)) then
  102. exit;
  103. p:=taicpu(hp);
  104. i:=1;
  105. { Start on oper[0]? }
  106. if taicpu(hp).spilling_get_operation_type(0) in [operand_read, operand_readwrite] then
  107. i:=0;
  108. while(i<p.ops) do
  109. begin
  110. case p.oper[I]^.typ of
  111. top_reg:
  112. Result := (p.oper[I]^.reg = reg);
  113. top_ref:
  114. Result :=
  115. (p.oper[I]^.ref^.base = reg) or
  116. (p.oper[I]^.ref^.index = reg);
  117. else
  118. ;
  119. end;
  120. { Bailout if we found something }
  121. if Result then
  122. exit;
  123. Inc(I);
  124. end;
  125. end;
  126. {
  127. optimize
  128. ldr/str regX,[reg1]
  129. ...
  130. add/sub reg1,reg1,regY/const
  131. into
  132. ldr/str regX,[reg1], regY/const
  133. }
  134. function TCpuAsmOptimizer.LookForPostindexedPattern(p: taicpu) : boolean;
  135. var
  136. hp1 : tai;
  137. begin
  138. Result:=false;
  139. if (p.oper[1]^.typ = top_ref) and
  140. (p.oper[1]^.ref^.addressmode=AM_OFFSET) and
  141. (p.oper[1]^.ref^.index=NR_NO) and
  142. (p.oper[1]^.ref^.offset=0) and
  143. GetNextInstructionUsingReg(p, hp1, p.oper[1]^.ref^.base) and
  144. { we cannot check NR_DEFAULTFLAGS for modification yet so don't allow a condition }
  145. MatchInstruction(hp1, [A_ADD, A_SUB], [PF_None]) and
  146. (taicpu(hp1).oper[0]^.reg=p.oper[1]^.ref^.base) and
  147. (taicpu(hp1).oper[1]^.reg=p.oper[1]^.ref^.base) and
  148. (
  149. { valid offset? }
  150. (taicpu(hp1).oper[2]^.typ=top_const) and
  151. (taicpu(hp1).oper[2]^.val>=-256) and
  152. (abs(taicpu(hp1).oper[2]^.val)<256)
  153. ) and
  154. { don't apply the optimization if the base register is loaded }
  155. (getsupreg(p.oper[0]^.reg)<>getsupreg(p.oper[1]^.ref^.base)) and
  156. not(RegModifiedBetween(taicpu(hp1).oper[0]^.reg,p,hp1)) and
  157. not(RegModifiedBetween(taicpu(hp1).oper[2]^.reg,p,hp1)) then
  158. begin
  159. DebugMsg('Peephole Str/LdrAdd/Sub2Str/Ldr Postindex done', p);
  160. p.oper[1]^.ref^.addressmode:=AM_POSTINDEXED;
  161. if taicpu(hp1).opcode=A_ADD then
  162. p.oper[1]^.ref^.offset:=taicpu(hp1).oper[2]^.val
  163. else
  164. p.oper[1]^.ref^.offset:=-taicpu(hp1).oper[2]^.val;
  165. asml.Remove(hp1);
  166. hp1.Free;
  167. Result:=true;
  168. end;
  169. end;
  170. function TCpuAsmOptimizer.RemoveSuperfluousFMov(const p: tai; movp: tai; const optimizer: string):boolean;
  171. var
  172. alloc,
  173. dealloc : tai_regalloc;
  174. hp1 : tai;
  175. begin
  176. Result:=false;
  177. if ((MatchInstruction(movp, A_FMOV, [taicpu(p).condition], [taicpu(p).oppostfix]) and
  178. ((getregtype(taicpu(movp).oper[0]^.reg)=R_MMREGISTER) { or (taicpu(p).opcode in [A_LDUR])})
  179. ) { or
  180. (((taicpu(p).oppostfix in [PF_F64F32,PF_F64S16,PF_F64S32,PF_F64U16,PF_F64U32]) or (getsubreg(taicpu(p).oper[0]^.reg)=R_SUBFD)) and MatchInstruction(movp, A_VMOV, [taicpu(p).condition], [PF_F64])) or
  181. (((taicpu(p).oppostfix in [PF_F32F64,PF_F32S16,PF_F32S32,PF_F32U16,PF_F32U32]) or (getsubreg(taicpu(p).oper[0]^.reg)=R_SUBFS)) and MatchInstruction(movp, A_VMOV, [taicpu(p).condition], [PF_F32])) }
  182. ) and
  183. (taicpu(movp).ops=2) and
  184. MatchOperand(taicpu(movp).oper[1]^, taicpu(p).oper[0]^.reg) and
  185. { the destination register of the mov might not be used beween p and movp }
  186. not(RegUsedBetween(taicpu(movp).oper[0]^.reg,p,movp)) and
  187. { Take care to only do this for instructions which REALLY load to the first register.
  188. Otherwise
  189. str reg0, [reg1]
  190. fmov reg2, reg0
  191. will be optimized to
  192. str reg2, [reg1]
  193. }
  194. RegLoadedWithNewValue(taicpu(p).oper[0]^.reg, p) then
  195. begin
  196. dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(movp.Next));
  197. if assigned(dealloc) then
  198. begin
  199. DebugMsg('Peephole '+optimizer+' removed superfluous vmov', movp);
  200. result:=true;
  201. { taicpu(p).oper[0]^.reg is not used anymore, try to find its allocation
  202. and remove it if possible }
  203. asml.Remove(dealloc);
  204. alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.previous));
  205. if assigned(alloc) then
  206. begin
  207. asml.Remove(alloc);
  208. alloc.free;
  209. dealloc.free;
  210. end
  211. else
  212. asml.InsertAfter(dealloc,p);
  213. { try to move the allocation of the target register }
  214. GetLastInstruction(movp,hp1);
  215. alloc:=FindRegAlloc(taicpu(movp).oper[0]^.reg,tai(hp1.Next));
  216. if assigned(alloc) then
  217. begin
  218. asml.Remove(alloc);
  219. asml.InsertBefore(alloc,p);
  220. { adjust used regs }
  221. IncludeRegInUsedRegs(taicpu(movp).oper[0]^.reg,UsedRegs);
  222. end;
  223. { change
  224. vldr reg0,[reg1]
  225. vmov reg2,reg0
  226. into
  227. ldr reg2,[reg1]
  228. if reg2 is an int register
  229. if (taicpu(p).opcode=A_VLDR) and (getregtype(taicpu(movp).oper[0]^.reg)=R_INTREGISTER) then
  230. taicpu(p).opcode:=A_LDR;
  231. }
  232. { finally get rid of the mov }
  233. taicpu(p).loadreg(0,taicpu(movp).oper[0]^.reg);
  234. asml.remove(movp);
  235. movp.free;
  236. end;
  237. end;
  238. end;
  239. function TCpuAsmOptimizer.OptPass1Shift(var p : tai): boolean;
  240. var
  241. hp1,hp2: tai;
  242. I2, I: Integer;
  243. shifterop: tshifterop;
  244. begin
  245. Result:=false;
  246. { This folds shifterops into following instructions
  247. <shiftop> r0, r1, #imm
  248. <op> r2, r3, r0
  249. to
  250. <op> r2, r3, r1, <shiftop> #imm
  251. }
  252. { do not handle ROR yet, only part of the instructions below support ROR as shifter operand }
  253. if MatchInstruction(p,[A_LSL, A_LSR, A_ASR{, A_ROR}],[PF_None]) and
  254. MatchOpType(taicpu(p),top_reg,top_reg,top_const) and
  255. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  256. MatchInstruction(hp1, [A_ADD, A_AND, A_BIC, A_CMP, A_CMN,
  257. A_EON, A_EOR, A_NEG, A_ORN, A_ORR,
  258. A_SUB, A_TST], [PF_None]) and
  259. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) and
  260. (taicpu(hp1).ops >= 2) and
  261. { Currently we can't fold into another shifterop }
  262. (taicpu(hp1).oper[taicpu(hp1).ops-1]^.typ = top_reg) and
  263. { SP does not work completely with shifted registers, as I didn't find the exact rules,
  264. we do not operate on SP }
  265. (taicpu(hp1).oper[0]^.reg<>NR_SP) and
  266. (taicpu(hp1).oper[1]^.reg<>NR_SP) and
  267. (taicpu(hp1).oper[taicpu(hp1).ops-1]^.reg<>NR_SP) and
  268. { reg1 might not be modified inbetween }
  269. not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) and
  270. (
  271. { Only ONE of the two src operands is allowed to match }
  272. MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[taicpu(hp1).ops-2]^) xor
  273. MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[taicpu(hp1).ops-1]^)
  274. ) and
  275. { for SUB, the last operand must match, there is no RSB on AArch64 }
  276. ((taicpu(hp1).opcode<>A_SUB) or
  277. MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[taicpu(hp1).ops-1]^)) then
  278. begin
  279. { for the two operand instructions, start also at the second operand as they are not always commutative
  280. (depends on the flags tested laster on) and thus the operands cannot swapped }
  281. I2:=1;
  282. for I:=I2 to taicpu(hp1).ops-1 do
  283. if MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[I]^.reg) then
  284. begin
  285. { If the parameter matched on the second op from the RIGHT
  286. we have to switch the parameters, this will not happen for CMP
  287. were we're only evaluating the most right parameter
  288. }
  289. shifterop_reset(shifterop);
  290. case taicpu(p).opcode of
  291. A_LSL:
  292. shifterop.shiftmode:=SM_LSL;
  293. A_ROR:
  294. shifterop.shiftmode:=SM_ROR;
  295. A_LSR:
  296. shifterop.shiftmode:=SM_LSR;
  297. A_ASR:
  298. shifterop.shiftmode:=SM_ASR;
  299. else
  300. InternalError(2019090401);
  301. end;
  302. shifterop.shiftimm:=taicpu(p).oper[2]^.val;
  303. if I <> taicpu(hp1).ops-1 then
  304. begin
  305. if taicpu(hp1).ops = 3 then
  306. hp2:=taicpu.op_reg_reg_reg_shifterop(taicpu(hp1).opcode,
  307. taicpu(hp1).oper[0]^.reg, taicpu(hp1).oper[2]^.reg,
  308. taicpu(p).oper[1]^.reg, shifterop)
  309. else
  310. hp2:=taicpu.op_reg_reg_shifterop(taicpu(hp1).opcode,
  311. taicpu(hp1).oper[0]^.reg, taicpu(p).oper[1]^.reg,
  312. shifterop);
  313. end
  314. else
  315. if taicpu(hp1).ops = 3 then
  316. hp2:=taicpu.op_reg_reg_reg_shifterop(taicpu(hp1).opcode,
  317. taicpu(hp1).oper[0]^.reg, taicpu(hp1).oper[1]^.reg,
  318. taicpu(p).oper[1]^.reg,shifterop)
  319. else
  320. hp2:=taicpu.op_reg_reg_shifterop(taicpu(hp1).opcode,
  321. taicpu(hp1).oper[0]^.reg, taicpu(p).oper[1]^.reg,
  322. shifterop);
  323. taicpu(hp2).fileinfo:=taicpu(hp1).fileinfo;
  324. asml.insertbefore(hp2, hp1);
  325. GetNextInstruction(p, hp2);
  326. asml.remove(p);
  327. asml.remove(hp1);
  328. p.free;
  329. hp1.free;
  330. p:=hp2;
  331. DebugMsg('Peephole FoldShiftProcess done', p);
  332. Result:=true;
  333. break;
  334. end;
  335. end
  336. else if MatchInstruction(p,[A_LSL, A_LSR, A_ASR,A_ROR],[PF_None]) and
  337. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  338. RemoveSuperfluousMove(p, hp1, 'ShiftMov2Shift') then
  339. Result:=true;
  340. end;
  341. function TCpuAsmOptimizer.OptPass1Data(var p : tai): boolean;
  342. var
  343. hp1: tai;
  344. begin
  345. result:=false;
  346. if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  347. RemoveSuperfluousMove(p, hp1, 'DataMov2Data') then
  348. Result:=true;
  349. end;
  350. function TCpuAsmOptimizer.OptPass1STP(var p : tai): boolean;
  351. var
  352. hp1, hp2, hp3, hp4: tai;
  353. begin
  354. Result:=false;
  355. {
  356. change
  357. stp x29,x30,[sp, #-16]!
  358. mov x29,sp
  359. bl abc
  360. ldp x29,x30,[sp], #16
  361. ret
  362. into
  363. b abc
  364. }
  365. if MatchInstruction(p, A_STP, [C_None], [PF_None]) and
  366. MatchOpType(taicpu(p),top_reg,top_reg,top_ref) and
  367. (taicpu(p).oper[0]^.reg = NR_X29) and
  368. (taicpu(p).oper[1]^.reg = NR_X30) and
  369. (taicpu(p).oper[2]^.ref^.base=NR_STACK_POINTER_REG) and
  370. (taicpu(p).oper[2]^.ref^.index=NR_NO) and
  371. (taicpu(p).oper[2]^.ref^.offset=-16) and
  372. (taicpu(p).oper[2]^.ref^.addressmode=AM_PREINDEXED) and
  373. GetNextInstruction(p, hp1) and
  374. GetNextInstruction(hp1, hp2) and
  375. SkipEntryExitMarker(hp2, hp2) and
  376. GetNextInstruction(hp2, hp3) and
  377. SkipEntryExitMarker(hp3, hp3) and
  378. GetNextInstruction(hp3, hp4) and
  379. MatchInstruction(hp1, A_MOV, [C_None], [PF_NONE]) and
  380. MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) and
  381. (taicpu(hp1).oper[1]^.typ = top_reg) and
  382. (taicpu(hp1).oper[1]^.reg = NR_STACK_POINTER_REG) and
  383. MatchInstruction(hp2, A_BL, [C_None], [PF_NONE]) and
  384. (taicpu(hp2).oper[0]^.typ = top_ref) and
  385. MatchInstruction(hp3, A_LDP, [C_None], [PF_NONE]) and
  386. MatchOpType(taicpu(hp3),top_reg,top_reg,top_ref) and
  387. (taicpu(hp3).oper[0]^.reg = NR_X29) and
  388. (taicpu(hp3).oper[1]^.reg = NR_X30) and
  389. (taicpu(hp3).oper[2]^.ref^.base=NR_STACK_POINTER_REG) and
  390. (taicpu(hp3).oper[2]^.ref^.index=NR_NO) and
  391. (taicpu(hp3).oper[2]^.ref^.offset=16) and
  392. (taicpu(hp3).oper[2]^.ref^.addressmode=AM_POSTINDEXED) and
  393. MatchInstruction(hp4, A_RET, [C_None], [PF_None]) and
  394. (taicpu(hp4).ops = 0) then
  395. begin
  396. asml.Remove(p);
  397. asml.Remove(hp1);
  398. asml.Remove(hp3);
  399. asml.Remove(hp4);
  400. taicpu(hp2).opcode:=A_B;
  401. p.free;
  402. hp1.free;
  403. hp3.free;
  404. hp4.free;
  405. p:=hp2;
  406. DebugMsg('Peephole Bl2B done', p);
  407. Result:=true;
  408. end;
  409. end;
  410. function TCpuAsmOptimizer.OptPass1Mov(var p : tai): boolean;
  411. var
  412. hp1: tai;
  413. begin
  414. Result:=false;
  415. if MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) and
  416. (taicpu(p).oppostfix=PF_None) then
  417. begin
  418. RemoveCurrentP(p);
  419. DebugMsg('Peephole Mov2None done', p);
  420. Result:=true;
  421. end
  422. {
  423. optimize
  424. mov rX, yyyy
  425. ....
  426. }
  427. else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) then
  428. begin
  429. if RemoveSuperfluousMove(p, hp1, 'MovMov2Mov') then
  430. Result:=true
  431. else if (taicpu(p).ops = 2) and
  432. (tai(hp1).typ = ait_instruction) and
  433. RedundantMovProcess(p,hp1) then
  434. Result:=true;
  435. end;
  436. end;
  437. function TCpuAsmOptimizer.OptPostCMP(var p : tai): boolean;
  438. var
  439. hp1,hp2: tai;
  440. begin
  441. Result:=false;
  442. if MatchOpType(taicpu(p),top_reg,top_const) and
  443. (taicpu(p).oper[1]^.val=0) and
  444. GetNextInstruction(p,hp1) and
  445. MatchInstruction(hp1,A_B,[PF_None]) and
  446. (taicpu(hp1).condition in [C_EQ,C_NE]) then
  447. begin
  448. case taicpu(hp1).condition of
  449. C_NE:
  450. hp2:=taicpu.op_reg_sym_ofs(A_CBNZ,taicpu(p).oper[0]^.reg,taicpu(hp1).oper[0]^.ref^.symbol,taicpu(hp1).oper[0]^.ref^.offset);
  451. C_EQ:
  452. hp2:=taicpu.op_reg_sym_ofs(A_CBZ,taicpu(p).oper[0]^.reg,taicpu(hp1).oper[0]^.ref^.symbol,taicpu(hp1).oper[0]^.ref^.offset);
  453. else
  454. Internalerror(2019090801);
  455. end;
  456. taicpu(hp2).fileinfo:=taicpu(hp1).fileinfo;
  457. asml.insertbefore(hp2, hp1);
  458. asml.remove(p);
  459. asml.remove(hp1);
  460. p.free;
  461. hp1.free;
  462. p:=hp2;
  463. DebugMsg('Peephole CMPB.E/NE2CBNZ/CBZ done', p);
  464. Result:=true;
  465. end;
  466. end;
  467. function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
  468. var
  469. hp1: tai;
  470. begin
  471. result := false;
  472. if p.typ=ait_instruction then
  473. begin
  474. case taicpu(p).opcode of
  475. A_LDR:
  476. begin
  477. Result:=LookForPostindexedPattern(taicpu(p));
  478. end;
  479. A_STR:
  480. begin
  481. Result:=LookForPostindexedPattern(taicpu(p));
  482. end;
  483. A_MOV:
  484. Result:=OptPass1Mov(p);
  485. A_STP:
  486. Result:=OptPass1STP(p);
  487. A_LSR,
  488. A_ROR,
  489. A_ASR,
  490. A_LSL:
  491. Result:=OptPass1Shift(p);
  492. A_AND:
  493. Result:=OptPass1And(p);
  494. A_ADD,
  495. A_ADC,
  496. A_SUB,
  497. A_SBC,
  498. A_BIC,
  499. A_EOR,
  500. A_ORR,
  501. A_MUL:
  502. Result:=OptPass1Data(p);
  503. A_UXTB:
  504. Result:=OptPass1UXTB(p);
  505. A_UXTH:
  506. Result:=OptPass1UXTH(p);
  507. A_SXTB:
  508. Result:=OptPass1SXTB(p);
  509. A_SXTH:
  510. Result:=OptPass1SXTH(p);
  511. // A_VLDR,
  512. A_FADD,
  513. A_FMUL,
  514. A_FDIV,
  515. A_FSUB,
  516. A_FSQRT,
  517. A_FNEG,
  518. A_FCVT,
  519. A_FABS:
  520. begin
  521. if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  522. RemoveSuperfluousFMov(p, hp1, 'FOpFMov2FOp') then
  523. Result:=true;
  524. end
  525. else
  526. ;
  527. end;
  528. end;
  529. end;
  530. function TCpuAsmOptimizer.PostPeepHoleOptsCpu(var p: tai): boolean;
  531. begin
  532. result := false;
  533. if p.typ=ait_instruction then
  534. begin
  535. case taicpu(p).opcode of
  536. A_CMP:
  537. Result:=OptPostCMP(p);
  538. else
  539. ;
  540. end;
  541. end;
  542. end;
  543. begin
  544. casmoptimizer:=TCpuAsmOptimizer;
  545. End.