aoptcpurv.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  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 OptPass1Add(var p: tai): boolean;
  39. procedure RemoveInstr(var orig: tai; moveback: boolean=true);
  40. end;
  41. implementation
  42. uses
  43. cutils;
  44. function MatchInstruction(const instr: tai; const op: TCommonAsmOps; const AConditions: TAsmConds = []): boolean;
  45. begin
  46. result :=
  47. (instr.typ = ait_instruction) and
  48. (taicpu(instr).opcode in op) and
  49. ((AConditions=[]) or (taicpu(instr).condition in AConditions));
  50. end;
  51. function MatchInstruction(const instr: tai; const op: TAsmOp; const AConditions: TAsmConds = []): boolean;
  52. begin
  53. result :=
  54. (instr.typ = ait_instruction) and
  55. (taicpu(instr).opcode = op) and
  56. ((AConditions=[]) or (taicpu(instr).condition in AConditions));
  57. end;
  58. function MatchOperand(const oper1: TOper; const oper2: TOper): boolean; inline;
  59. begin
  60. result := oper1.typ = oper2.typ;
  61. if result then
  62. case oper1.typ of
  63. top_const:
  64. Result:=oper1.val = oper2.val;
  65. top_reg:
  66. Result:=oper1.reg = oper2.reg;
  67. {top_ref:
  68. Result:=RefsEqual(oper1.ref^, oper2.ref^);}
  69. else Result:=false;
  70. end
  71. end;
  72. function MatchOperand(const oper: TOper; const reg: TRegister): boolean; inline;
  73. begin
  74. result := (oper.typ = top_reg) and (oper.reg = reg);
  75. end;
  76. {$ifdef DEBUG_AOPTCPU}
  77. procedure TRVCpuAsmOptimizer.DebugMsg(const s: string;p : tai);
  78. begin
  79. asml.insertbefore(tai_comment.Create(strpnew(s)), p);
  80. end;
  81. {$else DEBUG_AOPTCPU}
  82. procedure TRVCpuAsmOptimizer.DebugMsg(const s: string;p : tai);inline;
  83. begin
  84. end;
  85. {$endif DEBUG_AOPTCPU}
  86. function TRVCpuAsmOptimizer.InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;
  87. var
  88. p: taicpu;
  89. i: longint;
  90. begin
  91. result:=false;
  92. if not (assigned(hp) and (hp.typ=ait_instruction)) then
  93. exit;
  94. p:=taicpu(hp);
  95. i:=0;
  96. while(i<p.ops) do
  97. begin
  98. case p.oper[I]^.typ of
  99. top_reg:
  100. result:=(p.oper[I]^.reg=reg) and (p.spilling_get_operation_type(i)<>operand_write);
  101. top_ref:
  102. result:=
  103. (p.oper[I]^.ref^.base=reg);
  104. else
  105. ;
  106. end;
  107. if result then exit; {Bailout if we found something}
  108. Inc(I);
  109. end;
  110. end;
  111. function TRVCpuAsmOptimizer.RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;
  112. begin
  113. result:=
  114. (hp.typ=ait_instruction) and
  115. (taicpu(hp).ops>1) and
  116. (taicpu(hp).oper[0]^.typ=top_reg) and
  117. (taicpu(hp).oper[0]^.reg=reg) and
  118. (taicpu(hp).spilling_get_operation_type(0)<>operand_read);
  119. end;
  120. function TRVCpuAsmOptimizer.RegModifiedByInstruction(Reg: TRegister; p1: tai): boolean;
  121. var
  122. i : Longint;
  123. begin
  124. result:=false;
  125. for i:=0 to taicpu(p1).ops-1 do
  126. case taicpu(p1).oper[i]^.typ of
  127. top_reg:
  128. if (taicpu(p1).oper[i]^.reg=Reg) and (taicpu(p1).spilling_get_operation_type(i) in [operand_write,operand_readwrite]) then
  129. exit(true);
  130. else
  131. ;
  132. end;
  133. end;
  134. function TRVCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai; out Next: tai; reg: TRegister): Boolean;
  135. begin
  136. Next:=Current;
  137. repeat
  138. Result:=GetNextInstruction(Next,Next);
  139. until not (Result) or
  140. not(cs_opt_level3 in current_settings.optimizerswitches) or
  141. (Next.typ<>ait_instruction) or
  142. RegInInstruction(reg,Next) or
  143. is_calljmp(taicpu(Next).opcode);
  144. end;
  145. function TRVCpuAsmOptimizer.OptPass1OP(var p : tai) : boolean;
  146. var
  147. hp1 : tai;
  148. begin
  149. result:=false;
  150. { replace
  151. <Op> %reg3,%reg2,%reg1
  152. addi %reg4,%reg3,0
  153. dealloc %reg3
  154. by
  155. <Op> %reg4,%reg2,%reg1
  156. ?
  157. }
  158. if GetNextInstruction(p,hp1) and
  159. MatchInstruction(hp1,A_ADDI) and
  160. (taicpu(hp1).oper[2]^.val=0) and
  161. MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^) then
  162. begin
  163. TransferUsedRegs(TmpUsedRegs);
  164. UpdateUsedRegs(TmpUsedRegs, tai(p.next));
  165. if not(RegUsedAfterInstruction(taicpu(hp1).oper[1]^.reg,hp1,TmpUsedRegs)) then
  166. begin
  167. taicpu(p).loadoper(0,taicpu(hp1).oper[0]^);
  168. DebugMsg('Peephole OpAddi02Op done',p);
  169. RemoveInstruction(hp1);
  170. result:=true;
  171. end;
  172. end;
  173. end;
  174. procedure TRVCpuAsmOptimizer.RemoveInstr(var orig: tai; moveback: boolean = true);
  175. var
  176. n: tai;
  177. begin
  178. if moveback and (not GetLastInstruction(orig,n)) then
  179. GetNextInstruction(orig,n);
  180. AsmL.Remove(orig);
  181. orig.Free;
  182. orig:=n;
  183. end;
  184. function TRVCpuAsmOptimizer.OptPass1Add(var p: tai): boolean;
  185. var
  186. hp1: tai;
  187. begin
  188. result:=false;
  189. {
  190. Changes
  191. addi x, y, #
  192. addi/addiw z, x, #
  193. dealloc x
  194. To
  195. addi z, y, #+#
  196. }
  197. if (taicpu(p).ops=3) and
  198. (taicpu(p).oper[2]^.typ=top_const) and
  199. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  200. MatchInstruction(hp1,[A_ADDI{$ifdef riscv64},A_ADDIW{$endif}]) and
  201. (taicpu(hp1).ops=3) and
  202. MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^) and
  203. (taicpu(hp1).oper[2]^.typ=top_const) and
  204. is_imm12(taicpu(p).oper[2]^.val+taicpu(hp1).oper[2]^.val) and
  205. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  206. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  207. begin
  208. taicpu(hp1).loadreg(1,taicpu(p).oper[1]^.reg);
  209. taicpu(hp1).loadconst(2, taicpu(p).oper[2]^.val+taicpu(hp1).oper[2]^.val);
  210. DebugMsg('Peephole AddiAddi2Addi performed', hp1);
  211. RemoveInstr(p);
  212. result:=true;
  213. end
  214. {
  215. Changes
  216. addi x, z, (ref)
  217. ld/sd y, 0(x)
  218. dealloc x
  219. To
  220. ld/sd y, 0(ref)(x)
  221. }
  222. else if (taicpu(p).ops=3) and
  223. (taicpu(p).oper[2]^.typ=top_ref) and
  224. MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) and
  225. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  226. MatchInstruction(hp1, [A_LB,A_LBU,A_LH,A_LHU,A_LW,
  227. A_SB,A_SH,A_SW{$ifdef riscv64},A_LD,A_LWU,A_SD{$endif}]) and
  228. (taicpu(hp1).ops=2) and
  229. (taicpu(hp1).oper[1]^.typ=top_ref) and
  230. (taicpu(hp1).oper[1]^.ref^.base=taicpu(p).oper[0]^.reg) and
  231. (taicpu(hp1).oper[1]^.ref^.offset=0) and
  232. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  233. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  234. begin
  235. taicpu(hp1).loadref(1,taicpu(p).oper[2]^.ref^);
  236. taicpu(hp1).oper[1]^.ref^.base:=taicpu(p).oper[1]^.reg;
  237. DebugMsg('Peephole AddiMem2Mem performed', hp1);
  238. RemoveInstr(p);
  239. result:=true;
  240. end
  241. {
  242. Changes
  243. addi x, z, #w
  244. ld/sd y, 0(x)
  245. dealloc x
  246. To
  247. ld/sd y, #w(z)
  248. }
  249. else if (taicpu(p).ops=3) and
  250. (taicpu(p).oper[2]^.typ=top_const) and
  251. //MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) and
  252. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  253. MatchInstruction(hp1, [A_LB,A_LBU,A_LH,A_LHU,A_LW,
  254. A_SB,A_SH,A_SW{$ifdef riscv64},A_LWU,A_LD,A_SD{$endif}]) and
  255. (taicpu(hp1).ops=2) and
  256. (taicpu(hp1).oper[1]^.typ=top_ref) and
  257. (taicpu(hp1).oper[1]^.ref^.base=taicpu(p).oper[0]^.reg) and
  258. (taicpu(hp1).oper[1]^.ref^.offset=0) and
  259. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  260. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  261. begin
  262. //taicpu(hp1).loadconst(1,taicpu(p).oper[2]^.ref^);
  263. taicpu(hp1).oper[1]^.ref^.offset:=taicpu(p).oper[2]^.val;
  264. taicpu(hp1).oper[1]^.ref^.base:=taicpu(p).oper[1]^.reg;
  265. DebugMsg('Peephole AddiMem2Mem performed', hp1);
  266. RemoveInstr(p);
  267. result:=true;
  268. end
  269. else
  270. result:=OptPass1OP(p);
  271. end;
  272. function TRVCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
  273. var
  274. hp1: tai;
  275. begin
  276. result:=false;
  277. case p.typ of
  278. ait_instruction:
  279. begin
  280. case taicpu(p).opcode of
  281. A_ADDI:
  282. result:=OptPass1Add(p);
  283. A_SUB:
  284. begin
  285. {
  286. Turn
  287. sub x,y,z
  288. bgeu X0,x,...
  289. dealloc x
  290. Into
  291. bne y,x,...
  292. }
  293. if (taicpu(p).ops=3) and
  294. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  295. MatchInstruction(hp1,A_Bxx,[C_GEU,C_EQ]) and
  296. (taicpu(hp1).ops=3) and
  297. MatchOperand(taicpu(hp1).oper[0]^,NR_X0) and
  298. MatchOperand(taicpu(hp1).oper[1]^,taicpu(p).oper[0]^) and
  299. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  300. (not RegModifiedBetween(taicpu(p).oper[2]^.reg, p,hp1)) and
  301. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  302. begin
  303. taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg);
  304. taicpu(hp1).loadreg(1,taicpu(p).oper[2]^.reg);
  305. taicpu(hp1).condition:=C_EQ;
  306. DebugMsg('Peephole SubBxx2Beq performed', hp1);
  307. RemoveInstr(p);
  308. result:=true;
  309. end
  310. else
  311. result:=OptPass1OP(p);
  312. end;
  313. A_ANDI:
  314. begin
  315. {
  316. Changes
  317. andi x, y, #
  318. andi z, x, #
  319. dealloc x
  320. To
  321. andi z, y, # and #
  322. }
  323. if (taicpu(p).ops=3) and
  324. (taicpu(p).oper[2]^.typ=top_const) and
  325. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) then
  326. begin
  327. if MatchInstruction(hp1,A_ANDI) and
  328. (taicpu(hp1).ops=3) and
  329. MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^) and
  330. (taicpu(hp1).oper[2]^.typ=top_const) and
  331. is_imm12(taicpu(p).oper[2]^.val and taicpu(hp1).oper[2]^.val) and
  332. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  333. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  334. begin
  335. taicpu(hp1).loadreg(1,taicpu(p).oper[1]^.reg);
  336. taicpu(hp1).loadconst(2, taicpu(p).oper[2]^.val and taicpu(hp1).oper[2]^.val);
  337. DebugMsg('Peephole AndiAndi2Andi performed', hp1);
  338. RemoveInstr(p);
  339. result:=true;
  340. end
  341. {$ifndef RISCV32}
  342. else if MatchInstruction(hp1,A_ADDIW) and
  343. (taicpu(hp1).ops=3) and
  344. MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^) and
  345. (taicpu(hp1).oper[2]^.typ=top_const) and
  346. (taicpu(hp1).oper[2]^.val=0) and
  347. is_imm12(taicpu(p).oper[2]^.val) and
  348. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  349. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  350. begin
  351. taicpu(p).loadreg(0,taicpu(hp1).oper[0]^.reg);
  352. DebugMsg('Peephole AndiAddwi02Andi performed', hp1);
  353. RemoveInstr(hp1);
  354. result:=true;
  355. end
  356. {$endif RISCV32}
  357. else
  358. result:=OptPass1OP(p);
  359. end
  360. else
  361. result:=OptPass1OP(p);
  362. end;
  363. A_SLT,
  364. A_SLTU:
  365. begin
  366. {
  367. Turn
  368. sltu x,X0,y
  369. beq/bne x, X0, ...
  370. dealloc x
  371. Into
  372. bltu/geu X0, y, ...
  373. }
  374. if (taicpu(p).ops=3) and
  375. MatchOperand(taicpu(p).oper[1]^,NR_X0) and
  376. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  377. MatchInstruction(hp1,A_Bxx,[C_NE,C_EQ]) and
  378. (taicpu(hp1).ops=3) and
  379. MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) and
  380. MatchOperand(taicpu(hp1).oper[1]^,NR_X0) and
  381. (not RegModifiedBetween(taicpu(p).oper[2]^.reg, p,hp1)) and
  382. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  383. begin
  384. taicpu(hp1).loadreg(0,NR_X0);
  385. taicpu(hp1).loadreg(1,taicpu(p).oper[2]^.reg);
  386. if taicpu(p).opcode=A_SLTU then
  387. begin
  388. if taicpu(hp1).condition=C_NE then
  389. taicpu(hp1).condition:=C_LTU
  390. else
  391. taicpu(hp1).condition:=C_GEU;
  392. end
  393. else
  394. begin
  395. if taicpu(hp1).condition=C_NE then
  396. taicpu(hp1).condition:=C_LT
  397. else
  398. taicpu(hp1).condition:=C_GE;
  399. end;
  400. DebugMsg('Peephole SltuB2B performed', hp1);
  401. RemoveInstr(p);
  402. result:=true;
  403. end
  404. {
  405. Turn
  406. sltu x,y,z
  407. beq/bne x, X0, ...
  408. dealloc x
  409. Into
  410. bltu/geu y, z, ...
  411. }
  412. else if (taicpu(p).ops=3) and
  413. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  414. MatchInstruction(hp1,A_Bxx,[C_NE,C_EQ]) and
  415. (taicpu(hp1).ops=3) and
  416. MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) and
  417. MatchOperand(taicpu(hp1).oper[1]^,NR_X0) and
  418. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  419. (not RegModifiedBetween(taicpu(p).oper[2]^.reg, p,hp1)) and
  420. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  421. begin
  422. taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg);
  423. taicpu(hp1).loadreg(1,taicpu(p).oper[2]^.reg);
  424. if taicpu(p).opcode=A_SLTU then
  425. begin
  426. if taicpu(hp1).condition=C_NE then
  427. taicpu(hp1).condition:=C_LTU
  428. else
  429. taicpu(hp1).condition:=C_GEU;
  430. end
  431. else
  432. begin
  433. if taicpu(hp1).condition=C_NE then
  434. taicpu(hp1).condition:=C_LT
  435. else
  436. taicpu(hp1).condition:=C_GE;
  437. end;
  438. DebugMsg('Peephole SltuB2B performed', hp1);
  439. RemoveInstr(p);
  440. result:=true;
  441. end;
  442. end;
  443. A_SLTIU:
  444. begin
  445. {
  446. Turn
  447. sltiu x,y,1
  448. beq/ne x,x0,...
  449. dealloc x
  450. Into
  451. bne y,x0,...
  452. }
  453. if (taicpu(p).ops=3) and
  454. (taicpu(p).oper[2]^.typ=top_const) and
  455. (taicpu(p).oper[2]^.val=1) and
  456. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  457. MatchInstruction(hp1,A_Bxx,[C_NE,C_EQ]) and
  458. (taicpu(hp1).ops=3) and
  459. MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) and
  460. MatchOperand(taicpu(hp1).oper[1]^,NR_X0) and
  461. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  462. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  463. begin
  464. taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg);
  465. taicpu(hp1).condition:=inverse_cond(taicpu(hp1).condition);
  466. DebugMsg('Peephole Sltiu0B2B performed', hp1);
  467. RemoveInstr(p);
  468. result:=true;
  469. end;
  470. end;
  471. A_LUI,
  472. A_LB,
  473. A_LBU,
  474. A_LH,
  475. A_LHU,
  476. A_LW,
  477. {$ifdef riscv64}
  478. A_LWU,
  479. A_LD,
  480. {$endif riscv64}
  481. A_ADD,
  482. A_DIV,
  483. A_DIVU,
  484. {$ifdef riscv64}
  485. A_DIVW,
  486. A_DIVUW,
  487. {$endif riscv64}
  488. A_REM,
  489. A_REMU,
  490. {$ifdef riscv64}
  491. A_REMW,
  492. A_REMUW,
  493. {$endif riscv64}
  494. A_MUL,
  495. A_MULH,
  496. A_MULHSU,
  497. A_MULHU,
  498. A_XORI,
  499. A_ORI,
  500. A_AND,
  501. A_OR,
  502. A_XOR,
  503. A_SLL,
  504. A_SRL,
  505. A_SRA,
  506. A_NEG,
  507. A_NOT:
  508. result:=OptPass1OP(p);
  509. A_SRAI,
  510. A_SRLI,
  511. A_SLLI:
  512. begin
  513. if (taicpu(p).oper[2]^.val=0) and
  514. MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) then
  515. begin
  516. DebugMsg('Peephole S*LI x,x,0 to nop performed', p);
  517. RemoveInstr(p);
  518. result:=true;
  519. end
  520. else
  521. result:=OptPass1OP(p);
  522. end;
  523. A_SLTI:
  524. begin
  525. {
  526. Turn
  527. slti x,y,0
  528. beq/ne x,x0,...
  529. dealloc x
  530. Into
  531. bge/lt y,x0,...
  532. }
  533. if (taicpu(p).ops=3) and
  534. (taicpu(p).oper[2]^.typ=top_const) and
  535. (taicpu(p).oper[2]^.val=0) and
  536. GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
  537. (hp1.typ=ait_instruction) and
  538. (taicpu(hp1).opcode=A_Bxx) and
  539. (taicpu(hp1).ops=3) and
  540. (taicpu(hp1).oper[0]^.typ=top_reg) and
  541. (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
  542. (taicpu(hp1).oper[1]^.typ=top_reg) and
  543. (taicpu(hp1).oper[1]^.reg=NR_X0) and
  544. (taicpu(hp1).condition in [C_NE,C_EQ]) and
  545. (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
  546. RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
  547. begin
  548. taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg);
  549. taicpu(hp1).loadreg(1,NR_X0);
  550. if taicpu(hp1).condition=C_NE then
  551. taicpu(hp1).condition:=C_LT
  552. else
  553. taicpu(hp1).condition:=C_GE;
  554. DebugMsg('Peephole Slti0B2B performed', hp1);
  555. RemoveInstr(p);
  556. result:=true;
  557. end;
  558. end;
  559. else
  560. ;
  561. end;
  562. end;
  563. else
  564. ;
  565. end;
  566. end;
  567. end.