aoptcpurv.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. {
  2. Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
  3. Development Team
  4. This unit implements the common RiscV 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 aoptcpurv;
  19. interface
  20. {$I fpcdefs.inc}
  21. { $define DEBUG_AOPTCPU}
  22. uses
  23. cpubase,
  24. globals, globtype,
  25. cgbase,
  26. aoptobj, aoptcpub, aopt,
  27. aasmtai, aasmcpu;
  28. type
  29. TRVCpuAsmOptimizer = class(TAsmOptimizer)
  30. function InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean; override;
  31. function RegLoadedWithNewValue(reg: tregister; hp: tai): boolean; override;
  32. function RegModifiedByInstruction(Reg: TRegister; p1: tai): boolean; override;
  33. Function GetNextInstructionUsingReg(Current: tai; Out Next: tai; reg: TRegister): Boolean;
  34. { outputs a debug message into the assembler file }
  35. procedure DebugMsg(const s: string; p: tai);
  36. function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
  37. function OptPass1OP(var p: tai): boolean;
  38. function OptPass1FOP(var p: tai;mvop: tasmop): boolean;
  39. function OptPass1Add(var p: tai): boolean;
  40. procedure RemoveInstr(var orig: tai; moveback: boolean=true);
  41. end;
  42. implementation
  43. uses
  44. cutils,
  45. verbose;
  46. function MatchInstruction(const instr: tai; const op: TCommonAsmOps; const AConditions: TAsmConds = []): boolean;
  47. begin
  48. result :=
  49. (instr.typ = ait_instruction) and
  50. (taicpu(instr).opcode in op) and
  51. ((AConditions=[]) or (taicpu(instr).condition in AConditions));
  52. end;
  53. function MatchInstruction(const instr: tai; const op: TAsmOp; const AConditions: TAsmConds = []): boolean;
  54. begin
  55. result :=
  56. (instr.typ = ait_instruction) and
  57. (taicpu(instr).opcode = op) and
  58. ((AConditions=[]) or (taicpu(instr).condition in AConditions));
  59. end;
  60. function MatchOperand(const oper1: TOper; const oper2: TOper): boolean; inline;
  61. begin
  62. result := oper1.typ = oper2.typ;
  63. if result then
  64. case oper1.typ of
  65. top_const:
  66. Result:=oper1.val = oper2.val;
  67. top_reg:
  68. Result:=oper1.reg = oper2.reg;
  69. {top_ref:
  70. Result:=RefsEqual(oper1.ref^, oper2.ref^);}
  71. else Result:=false;
  72. end
  73. end;
  74. function MatchOperand(const oper: TOper; const reg: TRegister): boolean; inline;
  75. begin
  76. result := (oper.typ = top_reg) and (oper.reg = reg);
  77. end;
  78. {$ifdef DEBUG_AOPTCPU}
  79. procedure TRVCpuAsmOptimizer.DebugMsg(const s: string;p : tai);
  80. begin
  81. asml.insertbefore(tai_comment.Create(strpnew(s)), p);
  82. end;
  83. {$else DEBUG_AOPTCPU}
  84. procedure TRVCpuAsmOptimizer.DebugMsg(const s: string;p : tai);inline;
  85. begin
  86. end;
  87. {$endif DEBUG_AOPTCPU}
  88. function TRVCpuAsmOptimizer.InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;
  89. var
  90. p: taicpu;
  91. i: longint;
  92. begin
  93. result:=false;
  94. if not (assigned(hp) and (hp.typ=ait_instruction)) then
  95. exit;
  96. p:=taicpu(hp);
  97. i:=0;
  98. while(i<p.ops) do
  99. begin
  100. case p.oper[I]^.typ of
  101. top_reg:
  102. result:=(p.oper[I]^.reg=reg) and (p.spilling_get_operation_type(i)<>operand_write);
  103. top_ref:
  104. result:=
  105. (p.oper[I]^.ref^.base=reg);
  106. else
  107. ;
  108. end;
  109. if result then exit; {Bailout if we found something}
  110. Inc(I);
  111. end;
  112. end;
  113. function TRVCpuAsmOptimizer.RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;
  114. begin
  115. result:=
  116. (hp.typ=ait_instruction) and
  117. (taicpu(hp).ops>1) and
  118. (taicpu(hp).oper[0]^.typ=top_reg) and
  119. (taicpu(hp).oper[0]^.reg=reg) and
  120. (taicpu(hp).spilling_get_operation_type(0)<>operand_read);
  121. end;
  122. function TRVCpuAsmOptimizer.RegModifiedByInstruction(Reg: TRegister; p1: tai): boolean;
  123. var
  124. i : Longint;
  125. begin
  126. result:=false;
  127. for i:=0 to taicpu(p1).ops-1 do
  128. case taicpu(p1).oper[i]^.typ of
  129. top_reg:
  130. if (taicpu(p1).oper[i]^.reg=Reg) and (taicpu(p1).spilling_get_operation_type(i) in [operand_write,operand_readwrite]) then
  131. exit(true);
  132. else
  133. ;
  134. end;
  135. end;
  136. function TRVCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai; out Next: tai; reg: TRegister): Boolean;
  137. begin
  138. Next:=Current;
  139. repeat
  140. Result:=GetNextInstruction(Next,Next);
  141. until not (Result) or
  142. not(cs_opt_level3 in current_settings.optimizerswitches) or
  143. (Next.typ<>ait_instruction) or
  144. RegInInstruction(reg,Next) or
  145. is_calljmp(taicpu(Next).opcode);
  146. end;
  147. function TRVCpuAsmOptimizer.OptPass1OP(var p : tai) : boolean;
  148. var
  149. hp1 : tai;
  150. begin
  151. result:=false;
  152. { replace
  153. <Op> %reg3,%reg2,%reg1
  154. addi %reg4,%reg3,0
  155. dealloc %reg3
  156. by
  157. <Op> %reg4,%reg2,%reg1
  158. ?
  159. }
  160. if GetNextInstruction(p,hp1) and
  161. MatchInstruction(hp1,A_ADDI) and
  162. (taicpu(hp1).oper[2]^.val=0) and
  163. MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^) then
  164. begin
  165. TransferUsedRegs(TmpUsedRegs);
  166. UpdateUsedRegs(TmpUsedRegs, tai(p.next));
  167. if not(RegUsedAfterInstruction(taicpu(hp1).oper[1]^.reg,hp1,TmpUsedRegs)) then
  168. begin
  169. taicpu(p).loadoper(0,taicpu(hp1).oper[0]^);
  170. DebugMsg('Peephole OpAddi02Op done',p);
  171. RemoveInstruction(hp1);
  172. result:=true;
  173. end;
  174. end;
  175. end;
  176. function TRVCpuAsmOptimizer.OptPass1FOP(var p: tai;mvop: tasmop) : boolean;
  177. var
  178. hp1 : tai;
  179. begin
  180. result:=false;
  181. { replace
  182. <FOp> %reg3,%reg2,%reg1
  183. <mvop> %reg4,%reg3,%reg3
  184. dealloc %reg3
  185. by
  186. <FOp> %reg4,%reg2,%reg1
  187. ?
  188. }
  189. if GetNextInstruction(p,hp1) and
  190. MatchInstruction(hp1,mvop) and
  191. MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^) and
  192. MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[2]^) then
  193. begin
  194. TransferUsedRegs(TmpUsedRegs);
  195. UpdateUsedRegs(TmpUsedRegs, tai(p.next));
  196. if not(RegUsedAfterInstruction(taicpu(hp1).oper[1]^.reg,hp1,TmpUsedRegs)) then
  197. begin
  198. taicpu(p).loadoper(0,taicpu(hp1).oper[0]^);
  199. DebugMsg('Peephole FOpFsgnj02FOp done',p);
  200. RemoveInstruction(hp1);
  201. result:=true;
  202. end;
  203. end;
  204. end;
  205. procedure TRVCpuAsmOptimizer.RemoveInstr(var orig: tai; moveback: boolean = true);
  206. var
  207. n: tai;
  208. begin
  209. if moveback and (not GetLastInstruction(orig,n)) then
  210. GetNextInstruction(orig,n);
  211. AsmL.Remove(orig);
  212. orig.Free;
  213. orig:=n;
  214. end;
  215. function TRVCpuAsmOptimizer.OptPass1Add(var p: tai): boolean;
  216. var
  217. hp1: tai;
  218. begin
  219. result:=false;
  220. {
  221. Get rid of
  222. addi x, x, 0
  223. }
  224. if (taicpu(p).ops=3) and
  225. (taicpu(p).oper[2]^.typ=top_const) and
  226. (taicpu(p).oper[2]^.val=0) and
  227. MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) then
  228. begin
  229. DebugMsg('Peephole Addi2Nop performed', p);
  230. RemoveInstr(p);
  231. result:=true;
  232. end
  233. {
  234. Changes
  235. addi x, y, #
  236. addi/addiw z, x, #
  237. dealloc x
  238. To
  239. addi z, y, #+#
  240. }
  241. else if (taicpu(p).ops=3) and
  242. (taicpu(p).oper[2]^.typ=top_const) and
  243. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  244. MatchInstruction(hp1,[A_ADDI{$ifdef riscv64},A_ADDIW{$endif}]) and
  245. (taicpu(hp1).ops=3) and
  246. MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^) and
  247. (taicpu(hp1).oper[2]^.typ=top_const) and
  248. is_imm12(taicpu(p).oper[2]^.val+taicpu(hp1).oper[2]^.val) and
  249. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  250. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  251. begin
  252. taicpu(hp1).loadreg(1,taicpu(p).oper[1]^.reg);
  253. taicpu(hp1).loadconst(2, taicpu(p).oper[2]^.val+taicpu(hp1).oper[2]^.val);
  254. DebugMsg('Peephole AddiAddi2Addi performed', hp1);
  255. RemoveInstr(p);
  256. result:=true;
  257. end
  258. {
  259. Changes
  260. addi x, z, (ref)
  261. ld/sd y, 0(x)
  262. dealloc x
  263. To
  264. ld/sd y, 0(ref)(x)
  265. }
  266. else if (taicpu(p).ops=3) and
  267. (taicpu(p).oper[2]^.typ=top_ref) and
  268. MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) and
  269. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  270. MatchInstruction(hp1, [A_LB,A_LBU,A_LH,A_LHU,A_LW,
  271. A_SB,A_SH,A_SW{$ifdef riscv64},A_LD,A_LWU,A_SD{$endif}]) and
  272. (taicpu(hp1).ops=2) and
  273. (taicpu(hp1).oper[1]^.typ=top_ref) and
  274. (taicpu(hp1).oper[1]^.ref^.base=taicpu(p).oper[0]^.reg) and
  275. (taicpu(hp1).oper[1]^.ref^.offset=0) and
  276. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  277. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  278. begin
  279. taicpu(hp1).loadref(1,taicpu(p).oper[2]^.ref^);
  280. taicpu(hp1).oper[1]^.ref^.base:=taicpu(p).oper[1]^.reg;
  281. DebugMsg('Peephole AddiMem2Mem performed', hp1);
  282. RemoveInstr(p);
  283. result:=true;
  284. end
  285. {
  286. Changes
  287. addi x, z, #w
  288. ld/sd y, 0(x)
  289. dealloc x
  290. To
  291. ld/sd y, #w(z)
  292. }
  293. else if (taicpu(p).ops=3) and
  294. (taicpu(p).oper[2]^.typ=top_const) and
  295. //MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) and
  296. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  297. MatchInstruction(hp1, [A_LB,A_LBU,A_LH,A_LHU,A_LW,
  298. A_SB,A_SH,A_SW{$ifdef riscv64},A_LWU,A_LD,A_SD{$endif}]) and
  299. (taicpu(hp1).ops=2) and
  300. (taicpu(hp1).oper[1]^.typ=top_ref) and
  301. (taicpu(hp1).oper[1]^.ref^.base=taicpu(p).oper[0]^.reg) and
  302. (taicpu(hp1).oper[1]^.ref^.offset=0) and
  303. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  304. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  305. begin
  306. //taicpu(hp1).loadconst(1,taicpu(p).oper[2]^.ref^);
  307. taicpu(hp1).oper[1]^.ref^.offset:=taicpu(p).oper[2]^.val;
  308. taicpu(hp1).oper[1]^.ref^.base:=taicpu(p).oper[1]^.reg;
  309. DebugMsg('Peephole AddiMem2Mem performed', hp1);
  310. RemoveInstr(p);
  311. result:=true;
  312. end
  313. {
  314. Changes
  315. addi w, z, 0
  316. op x, y, w
  317. dealloc w
  318. To
  319. op x, y, z
  320. }
  321. else if (taicpu(p).ops=3) and
  322. (taicpu(p).oper[2]^.typ=top_const) and
  323. (taicpu(p).oper[2]^.val=0) and
  324. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  325. ((MatchInstruction(hp1, [A_SUB,A_ADD,A_SLL,A_SRL,A_SLT,A_AND,A_OR,
  326. A_ADDI,A_ANDI,A_ORI,A_SRAI,A_SRLI,A_SLLI,A_XORI,A_MUL,
  327. A_DIV,A_DIVU,A_REM,A_REMU
  328. {$ifdef riscv64},A_ADDIW,A_SLLIW,A_SRLIW,A_SRAIW,
  329. A_ADDW,A_SLLW,A_SRLW,A_SUBW,A_SRAW,
  330. A_DIVUW,A_DIVW,A_REMW,A_REMUW{$endif}]
  331. ) and
  332. (taicpu(hp1).ops=3) and
  333. (MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[2]^) or MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^))) {or
  334. This is not possible yet as the deallocation after the jump could also mean that the register is in use at the
  335. jump target.
  336. (MatchInstruction(hp1, [A_Bxx]) and
  337. (taicpu(hp1).ops=3) and
  338. (MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[0]^) or MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^))) }
  339. ) and
  340. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  341. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  342. begin
  343. { if MatchInstruction(hp1, [A_Bxx]) and MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[0]^) then
  344. taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg); }
  345. if MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^) then
  346. taicpu(hp1).loadreg(1,taicpu(p).oper[1]^.reg);
  347. if MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[2]^) then
  348. taicpu(hp1).loadreg(2,taicpu(p).oper[1]^.reg);
  349. AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,UsedRegs);
  350. DebugMsg('Peephole Addi0Op2Op performed', hp1);
  351. RemoveInstr(p);
  352. result:=true;
  353. end
  354. else
  355. result:=OptPass1OP(p);
  356. end;
  357. function TRVCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
  358. var
  359. hp1: tai;
  360. begin
  361. result:=false;
  362. case p.typ of
  363. ait_instruction:
  364. begin
  365. case taicpu(p).opcode of
  366. A_ADDI:
  367. result:=OptPass1Add(p);
  368. A_SUB:
  369. begin
  370. {
  371. Turn
  372. sub x,y,z
  373. bgeu X0,x,...
  374. dealloc x
  375. Into
  376. bne y,x,...
  377. }
  378. if (taicpu(p).ops=3) and
  379. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  380. MatchInstruction(hp1,A_Bxx,[C_GEU,C_EQ]) and
  381. (taicpu(hp1).ops=3) and
  382. MatchOperand(taicpu(hp1).oper[0]^,NR_X0) and
  383. MatchOperand(taicpu(hp1).oper[1]^,taicpu(p).oper[0]^) and
  384. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  385. (not RegModifiedBetween(taicpu(p).oper[2]^.reg, p,hp1)) and
  386. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  387. begin
  388. taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg);
  389. taicpu(hp1).loadreg(1,taicpu(p).oper[2]^.reg);
  390. taicpu(hp1).condition:=C_EQ;
  391. DebugMsg('Peephole SubBxx2Beq performed', hp1);
  392. RemoveInstr(p);
  393. result:=true;
  394. end
  395. else
  396. result:=OptPass1OP(p);
  397. end;
  398. A_ANDI:
  399. begin
  400. {
  401. Changes
  402. andi x, y, #
  403. andi z, x, #
  404. dealloc x
  405. To
  406. andi z, y, # and #
  407. }
  408. if (taicpu(p).ops=3) and
  409. (taicpu(p).oper[2]^.typ=top_const) and
  410. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) then
  411. begin
  412. if MatchInstruction(hp1,A_ANDI) and
  413. (taicpu(hp1).ops=3) and
  414. MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^) and
  415. (taicpu(hp1).oper[2]^.typ=top_const) and
  416. is_imm12(taicpu(p).oper[2]^.val and taicpu(hp1).oper[2]^.val) and
  417. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  418. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  419. begin
  420. taicpu(hp1).loadreg(1,taicpu(p).oper[1]^.reg);
  421. taicpu(hp1).loadconst(2, taicpu(p).oper[2]^.val and taicpu(hp1).oper[2]^.val);
  422. DebugMsg('Peephole AndiAndi2Andi performed', hp1);
  423. RemoveInstr(p);
  424. result:=true;
  425. end
  426. {$ifndef RISCV32}
  427. else if MatchInstruction(hp1,A_ADDIW) and
  428. (taicpu(hp1).ops=3) and
  429. MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^) and
  430. (taicpu(hp1).oper[2]^.typ=top_const) and
  431. (taicpu(hp1).oper[2]^.val=0) and
  432. is_imm12(taicpu(p).oper[2]^.val) and
  433. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  434. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  435. begin
  436. taicpu(p).loadreg(0,taicpu(hp1).oper[0]^.reg);
  437. DebugMsg('Peephole AndiAddwi02Andi performed', hp1);
  438. RemoveInstr(hp1);
  439. result:=true;
  440. end
  441. {$endif RISCV32}
  442. else
  443. result:=OptPass1OP(p);
  444. end
  445. else
  446. result:=OptPass1OP(p);
  447. end;
  448. A_SLT,
  449. A_SLTU:
  450. begin
  451. {
  452. Turn
  453. sltu x,X0,y
  454. beq/bne x, X0, ...
  455. dealloc x
  456. Into
  457. bltu/geu X0, y, ...
  458. }
  459. if (taicpu(p).ops=3) and
  460. MatchOperand(taicpu(p).oper[1]^,NR_X0) and
  461. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  462. MatchInstruction(hp1,A_Bxx,[C_NE,C_EQ]) and
  463. (taicpu(hp1).ops=3) and
  464. MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) and
  465. MatchOperand(taicpu(hp1).oper[1]^,NR_X0) and
  466. (not RegModifiedBetween(taicpu(p).oper[2]^.reg, p,hp1)) and
  467. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  468. begin
  469. taicpu(hp1).loadreg(0,NR_X0);
  470. taicpu(hp1).loadreg(1,taicpu(p).oper[2]^.reg);
  471. if taicpu(p).opcode=A_SLTU then
  472. begin
  473. if taicpu(hp1).condition=C_NE then
  474. taicpu(hp1).condition:=C_LTU
  475. else
  476. taicpu(hp1).condition:=C_GEU;
  477. end
  478. else
  479. begin
  480. if taicpu(hp1).condition=C_NE then
  481. taicpu(hp1).condition:=C_LT
  482. else
  483. taicpu(hp1).condition:=C_GE;
  484. end;
  485. DebugMsg('Peephole SltuB2B performed', hp1);
  486. RemoveInstr(p);
  487. result:=true;
  488. end
  489. {
  490. Turn
  491. sltu x,y,z
  492. beq/bne x, X0, ...
  493. dealloc x
  494. Into
  495. bltu/geu y, z, ...
  496. }
  497. else if (taicpu(p).ops=3) and
  498. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  499. MatchInstruction(hp1,A_Bxx,[C_NE,C_EQ]) and
  500. (taicpu(hp1).ops=3) and
  501. MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) and
  502. MatchOperand(taicpu(hp1).oper[1]^,NR_X0) and
  503. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  504. (not RegModifiedBetween(taicpu(p).oper[2]^.reg, p,hp1)) and
  505. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  506. begin
  507. taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg);
  508. taicpu(hp1).loadreg(1,taicpu(p).oper[2]^.reg);
  509. if taicpu(p).opcode=A_SLTU then
  510. begin
  511. if taicpu(hp1).condition=C_NE then
  512. taicpu(hp1).condition:=C_LTU
  513. else
  514. taicpu(hp1).condition:=C_GEU;
  515. end
  516. else
  517. begin
  518. if taicpu(hp1).condition=C_NE then
  519. taicpu(hp1).condition:=C_LT
  520. else
  521. taicpu(hp1).condition:=C_GE;
  522. end;
  523. DebugMsg('Peephole SltuB2B performed', hp1);
  524. RemoveInstr(p);
  525. result:=true;
  526. end;
  527. end;
  528. A_SLTIU:
  529. begin
  530. {
  531. Turn
  532. sltiu x,y,1
  533. beq/ne x,x0,...
  534. dealloc x
  535. Into
  536. bne y,x0,...
  537. }
  538. if (taicpu(p).ops=3) and
  539. (taicpu(p).oper[2]^.typ=top_const) and
  540. (taicpu(p).oper[2]^.val=1) and
  541. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  542. MatchInstruction(hp1,A_Bxx,[C_NE,C_EQ]) and
  543. (taicpu(hp1).ops=3) and
  544. MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) and
  545. MatchOperand(taicpu(hp1).oper[1]^,NR_X0) and
  546. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  547. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  548. begin
  549. taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg);
  550. taicpu(hp1).condition:=inverse_cond(taicpu(hp1).condition);
  551. DebugMsg('Peephole Sltiu0B2B performed', hp1);
  552. RemoveInstr(p);
  553. result:=true;
  554. end;
  555. end;
  556. A_LA,
  557. A_LUI,
  558. A_LB,
  559. A_LBU,
  560. A_LH,
  561. A_LHU,
  562. A_LW,
  563. {$ifdef riscv64}
  564. A_LWU,
  565. A_LD,
  566. {$endif riscv64}
  567. A_ADD,
  568. {$ifdef riscv64}
  569. A_ADDIW,
  570. A_SUBW,
  571. {$endif riscv64}
  572. A_DIV,
  573. A_DIVU,
  574. {$ifdef riscv64}
  575. A_DIVW,
  576. A_DIVUW,
  577. {$endif riscv64}
  578. A_REM,
  579. A_REMU,
  580. {$ifdef riscv64}
  581. A_REMW,
  582. A_REMUW,
  583. A_MULW,
  584. {$endif riscv64}
  585. A_MUL,
  586. A_MULH,
  587. A_MULHSU,
  588. A_MULHU,
  589. A_XORI,
  590. A_ORI,
  591. A_AND,
  592. A_OR,
  593. A_XOR,
  594. A_SLL,
  595. A_SRL,
  596. A_SRA,
  597. A_NEG,
  598. A_NOT:
  599. result:=OptPass1OP(p);
  600. A_SRAI,
  601. A_SRLI,
  602. A_SLLI:
  603. begin
  604. if (taicpu(p).oper[2]^.val=0) and
  605. MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) then
  606. begin
  607. DebugMsg('Peephole S*LI x,x,0 to nop performed', p);
  608. RemoveInstr(p);
  609. result:=true;
  610. end
  611. else if (taicpu(p).oper[2]^.val=0) then
  612. begin
  613. { this enables further optimizations }
  614. DebugMsg('Peephole S*LI x,y,0 to addi performed', p);
  615. taicpu(p).opcode:=A_ADDI;
  616. result:=true;
  617. end
  618. else
  619. result:=OptPass1OP(p);
  620. end;
  621. A_SLTI:
  622. begin
  623. {
  624. Turn
  625. slti x,y,0
  626. beq/ne x,x0,...
  627. dealloc x
  628. Into
  629. bge/lt y,x0,...
  630. }
  631. if (taicpu(p).ops=3) and
  632. (taicpu(p).oper[2]^.typ=top_const) and
  633. (taicpu(p).oper[2]^.val=0) and
  634. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  635. (hp1.typ=ait_instruction) and
  636. (taicpu(hp1).opcode=A_Bxx) and
  637. (taicpu(hp1).ops=3) and
  638. (taicpu(hp1).oper[0]^.typ=top_reg) and
  639. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
  640. (taicpu(hp1).oper[1]^.typ=top_reg) and
  641. (taicpu(hp1).oper[1]^.reg=NR_X0) and
  642. (taicpu(hp1).condition in [C_NE,C_EQ]) and
  643. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  644. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  645. begin
  646. taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg);
  647. taicpu(hp1).loadreg(1,NR_X0);
  648. if taicpu(hp1).condition=C_NE then
  649. taicpu(hp1).condition:=C_LT
  650. else
  651. taicpu(hp1).condition:=C_GE;
  652. DebugMsg('Peephole Slti0B2B performed', hp1);
  653. RemoveInstr(p);
  654. result:=true;
  655. end;
  656. end;
  657. A_FADD_S,
  658. A_FSUB_S,
  659. A_FMUL_S,
  660. A_FDIV_S,
  661. A_FSQRT_S,
  662. A_FNEG_S,
  663. A_FLW,
  664. A_FCVT_D_S,
  665. A_FMADD_S,A_FMSUB_S,A_FNMSUB_S,A_FNMADD_S:
  666. result:=OptPass1FOP(p,A_FSGNJ_S);
  667. A_FADD_D,
  668. A_FSUB_D,
  669. A_FMUL_D,
  670. A_FDIV_D,
  671. A_FSQRT_D,
  672. A_FNEG_D,
  673. A_FLD,
  674. A_FCVT_S_D,
  675. A_FMADD_D,A_FMSUB_D,A_FNMSUB_D,A_FNMADD_D:
  676. result:=OptPass1FOP(p,A_FSGNJ_D);
  677. else
  678. ;
  679. end;
  680. end;
  681. else
  682. ;
  683. end;
  684. end;
  685. end.