aoptcpu.pas 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. {
  2. Copyright (c) 1998-2004 by Jonas Maebe
  3. This unit calls the optimization procedures to optimize the assembler
  4. code for sparc
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit aoptcpu;
  19. {$i fpcdefs.inc}
  20. Interface
  21. uses
  22. cgbase, cpubase, aoptobj, aoptcpub, aopt, aasmtai;
  23. Type
  24. TCpuAsmOptimizer = class(TAsmOptimizer)
  25. function TryRemoveMov(var p: tai; opcode: TAsmOp): boolean;
  26. function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
  27. End;
  28. Implementation
  29. uses
  30. aasmcpu;
  31. function MatchInstruction(const instr: tai; const op: TAsmOp): boolean;
  32. begin
  33. result :=
  34. (instr.typ = ait_instruction) and
  35. (taicpu(instr).opcode = op);
  36. end;
  37. function MatchOperand(const oper: TOper; reg: TRegister): boolean;
  38. begin
  39. result:=(oper.typ=top_reg) and (oper.reg=reg);
  40. end;
  41. function IsSameReg(this,next: taicpu): boolean;
  42. begin
  43. result:=(next.oper[0]^.typ=top_reg) and
  44. (next.oper[1]^.typ=top_reg) and
  45. (next.oper[0]^.reg=next.oper[1]^.reg) and
  46. (next.oper[0]^.reg=this.oper[0]^.reg);
  47. end;
  48. function TCpuAsmOptimizer.TryRemoveMov(var p: tai; opcode: TAsmOp): boolean;
  49. var
  50. next,hp1: tai;
  51. alloc,dealloc: tai_regalloc;
  52. begin
  53. { Fold
  54. op $reg1,...
  55. opcode $reg2,$reg1
  56. dealloc $reg1
  57. into
  58. op $reg2,...
  59. opcode may be A_MOVE, A_MOV_s, A_MOV_d, etc.
  60. }
  61. result:=false;
  62. if GetNextInstruction(p,next) and
  63. MatchInstruction(next,opcode) and
  64. MatchOperand(taicpu(next).oper[1]^,taicpu(p).oper[0]^.reg) then
  65. begin
  66. dealloc:=FindRegDealloc(taicpu(p).oper[0]^.reg,tai(next.Next));
  67. if assigned(dealloc) then
  68. begin
  69. { taicpu(p).oper[0]^.reg is not used anymore, try to find its allocation
  70. and remove it if possible }
  71. GetLastInstruction(p,hp1);
  72. asml.Remove(dealloc);
  73. alloc:=FindRegAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
  74. if assigned(alloc) then
  75. begin
  76. asml.Remove(alloc);
  77. alloc.free;
  78. dealloc.free;
  79. end
  80. else
  81. asml.InsertAfter(dealloc,p);
  82. { try to move the allocation of the target register }
  83. GetLastInstruction(next,hp1);
  84. alloc:=FindRegAlloc(taicpu(next).oper[0]^.reg,tai(hp1.Next));
  85. if assigned(alloc) then
  86. begin
  87. asml.Remove(alloc);
  88. asml.InsertBefore(alloc,p);
  89. { adjust used regs }
  90. IncludeRegInUsedRegs(taicpu(next).oper[0]^.reg,UsedRegs);
  91. end;
  92. { finally get rid of the mov }
  93. taicpu(p).loadreg(0,taicpu(next).oper[0]^.reg);
  94. asml.remove(next);
  95. next.free;
  96. end;
  97. end;
  98. end;
  99. function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
  100. var
  101. next,next2: tai;
  102. begin
  103. result:=false;
  104. case p.typ of
  105. ait_instruction:
  106. begin
  107. case taicpu(p).opcode of
  108. A_SRL:
  109. begin
  110. { Remove 'andi' in sequences
  111. srl Rx,Ry,16
  112. andi Rx,Rx,65535
  113. srl Rx,Ry,24
  114. andi Rx,Rx,255
  115. since 'srl' clears all relevant upper bits }
  116. if (taicpu(p).oper[2]^.typ=top_const) and
  117. GetNextInstruction(p,next) and
  118. MatchInstruction(next,A_ANDI) and
  119. IsSameReg(taicpu(p),taicpu(next)) and
  120. (taicpu(next).oper[2]^.typ=top_const) and
  121. ((
  122. (taicpu(p).oper[2]^.val>=16) and
  123. (taicpu(next).oper[2]^.val=65535)
  124. ) or (
  125. (taicpu(p).oper[2]^.val>=24) and
  126. (taicpu(next).oper[2]^.val=255)
  127. )) then
  128. begin
  129. asml.remove(next);
  130. next.free;
  131. end
  132. else
  133. TryRemoveMov(p,A_MOVE);
  134. end;
  135. A_ANDI:
  136. begin
  137. { Remove sign extension after 'andi' if bit 7/15 of const operand is clear }
  138. if (taicpu(p).oper[2]^.typ=top_const) and
  139. GetNextInstruction(p,next) and
  140. MatchInstruction(next,A_SLL) and
  141. GetNextInstruction(next,next2) and
  142. MatchInstruction(next2,A_SRA) and
  143. IsSameReg(taicpu(p),taicpu(next)) and
  144. IsSameReg(taicpu(p),taicpu(next2)) and
  145. (taicpu(next).oper[2]^.typ=top_const) and
  146. (taicpu(next2).oper[2]^.typ=top_const) and
  147. (taicpu(next).oper[2]^.val=taicpu(next2).oper[2]^.val) and
  148. ((
  149. (taicpu(p).oper[2]^.val<=$7fff) and
  150. (taicpu(next).oper[2]^.val=16)
  151. ) or (
  152. (taicpu(p).oper[2]^.val<=$7f) and
  153. (taicpu(next).oper[2]^.val=24)
  154. )) then
  155. begin
  156. asml.remove(next);
  157. asml.remove(next2);
  158. next.free;
  159. next2.free;
  160. end
  161. else
  162. TryRemoveMov(p,A_MOVE);
  163. end;
  164. A_ADD,A_ADDU,
  165. A_ADDI,A_ADDIU,
  166. A_SUB,A_SUBU,
  167. A_SRA,A_SRAV,
  168. A_SRLV,
  169. A_SLL,A_SLLV,
  170. A_AND,A_OR,A_XOR,A_ORI,A_XORI:
  171. TryRemoveMov(p,A_MOVE);
  172. A_ADD_s, A_SUB_s, A_MUL_s, A_DIV_s,
  173. A_ABS_s, A_NEG_s, A_SQRT_s,
  174. A_CVT_s_w, A_CVT_s_l, A_CVT_s_d:
  175. TryRemoveMov(p,A_MOV_s);
  176. A_ADD_d, A_SUB_d, A_MUL_d, A_DIV_d,
  177. A_ABS_d, A_NEG_d, A_SQRT_d,
  178. A_CVT_d_w, A_CVT_d_l, A_CVT_d_s:
  179. TryRemoveMov(p,A_MOV_d);
  180. end;
  181. end;
  182. end;
  183. end;
  184. begin
  185. casmoptimizer:=TCpuAsmOptimizer;
  186. end.