aoptcpu.pas 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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): 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): boolean;
  49. var
  50. next,hp1: tai;
  51. alloc,dealloc: tai_regalloc;
  52. begin
  53. { Fold
  54. op $reg1,...
  55. move $reg2,$reg1
  56. dealloc $reg1
  57. into
  58. op $reg2,...
  59. }
  60. result:=false;
  61. if GetNextInstruction(p,next) and
  62. MatchInstruction(next,A_MOVE) and
  63. MatchOperand(taicpu(next).oper[1]^,taicpu(p).oper[0]^.reg) then
  64. begin
  65. dealloc:=FindRegDealloc(taicpu(p).oper[0]^.reg,tai(next.Next));
  66. if assigned(dealloc) then
  67. begin
  68. { taicpu(p).oper[0]^.reg is not used anymore, try to find its allocation
  69. and remove it if possible }
  70. GetLastInstruction(p,hp1);
  71. asml.Remove(dealloc);
  72. alloc:=FindRegAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
  73. if assigned(alloc) then
  74. begin
  75. asml.Remove(alloc);
  76. alloc.free;
  77. dealloc.free;
  78. end
  79. else
  80. asml.InsertAfter(dealloc,p);
  81. { try to move the allocation of the target register }
  82. GetLastInstruction(next,hp1);
  83. alloc:=FindRegAlloc(taicpu(next).oper[0]^.reg,tai(hp1.Next));
  84. if assigned(alloc) then
  85. begin
  86. asml.Remove(alloc);
  87. asml.InsertBefore(alloc,p);
  88. { adjust used regs }
  89. IncludeRegInUsedRegs(taicpu(next).oper[0]^.reg,UsedRegs);
  90. end;
  91. { finally get rid of the mov }
  92. taicpu(p).loadreg(0,taicpu(next).oper[0]^.reg);
  93. asml.remove(next);
  94. next.free;
  95. end;
  96. end;
  97. end;
  98. function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
  99. var
  100. next,next2: tai;
  101. begin
  102. result:=false;
  103. case p.typ of
  104. ait_instruction:
  105. begin
  106. case taicpu(p).opcode of
  107. A_SRL:
  108. begin
  109. { Remove 'andi' in sequences
  110. srl Rx,Ry,16
  111. andi Rx,Rx,65535
  112. srl Rx,Ry,24
  113. andi Rx,Rx,255
  114. since 'srl' clears all relevant upper bits }
  115. if (taicpu(p).oper[2]^.typ=top_const) and
  116. GetNextInstruction(p,next) and
  117. MatchInstruction(next,A_ANDI) and
  118. IsSameReg(taicpu(p),taicpu(next)) and
  119. (taicpu(next).oper[2]^.typ=top_const) and
  120. ((
  121. (taicpu(p).oper[2]^.val>=16) and
  122. (taicpu(next).oper[2]^.val=65535)
  123. ) or (
  124. (taicpu(p).oper[2]^.val>=24) and
  125. (taicpu(next).oper[2]^.val=255)
  126. )) then
  127. begin
  128. asml.remove(next);
  129. next.free;
  130. end
  131. else
  132. TryRemoveMov(p);
  133. end;
  134. A_ANDI:
  135. begin
  136. { Remove sign extension after 'andi' if bit 7/15 of const operand is clear }
  137. if (taicpu(p).oper[2]^.typ=top_const) and
  138. GetNextInstruction(p,next) and
  139. MatchInstruction(next,A_SLL) and
  140. GetNextInstruction(next,next2) and
  141. MatchInstruction(next2,A_SRA) and
  142. IsSameReg(taicpu(p),taicpu(next)) and
  143. IsSameReg(taicpu(p),taicpu(next2)) and
  144. (taicpu(next).oper[2]^.typ=top_const) and
  145. (taicpu(next2).oper[2]^.typ=top_const) and
  146. (taicpu(next).oper[2]^.val=taicpu(next2).oper[2]^.val) and
  147. ((
  148. (taicpu(p).oper[2]^.val<=$7fff) and
  149. (taicpu(next).oper[2]^.val=16)
  150. ) or (
  151. (taicpu(p).oper[2]^.val<=$7f) and
  152. (taicpu(next).oper[2]^.val=24)
  153. )) then
  154. begin
  155. asml.remove(next);
  156. asml.remove(next2);
  157. next.free;
  158. next2.free;
  159. end
  160. else
  161. TryRemoveMov(p);
  162. end;
  163. A_ADD,A_ADDU,
  164. A_ADDI,A_ADDIU,
  165. A_SUB,A_SUBU,
  166. A_SRA,A_SRAV,
  167. A_SRLV,
  168. A_SLL,A_SLLV,
  169. A_AND,A_OR,A_XOR,A_ORI,A_XORI:
  170. TryRemoveMov(p);
  171. end;
  172. end;
  173. end;
  174. end;
  175. begin
  176. casmoptimizer:=TCpuAsmOptimizer;
  177. end.