aoptcpu.pas 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. {
  2. Copyright (c) 1998-2014 by the Free Pascal development team
  3. This unit calls the optimization procedures to optimize the assembler
  4. code for m68k
  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. cpubase, aoptobj, aoptcpub, aopt, aasmtai;
  24. Type
  25. TCpuAsmOptimizer = class(TAsmOptimizer)
  26. function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
  27. { outputs a debug message into the assembler file }
  28. procedure DebugMsg(const s: string; p: tai);
  29. End;
  30. Implementation
  31. uses
  32. cutils, aasmcpu, cgutils, globals, cpuinfo;
  33. {$ifdef DEBUG_AOPTCPU}
  34. procedure TCpuAsmOptimizer.DebugMsg(const s: string; p : tai);
  35. begin
  36. asml.insertbefore(tai_comment.Create(strpnew(s)), p);
  37. end;
  38. {$else DEBUG_AOPTCPU}
  39. procedure TCpuAsmOptimizer.DebugMsg(const s: string; p : tai);inline;
  40. begin
  41. end;
  42. {$endif DEBUG_AOPTCPU}
  43. function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
  44. var
  45. next: tai;
  46. tmpref: treference;
  47. tmpsingle: single;
  48. begin
  49. result:=false;
  50. case p.typ of
  51. ait_instruction:
  52. begin
  53. //asml.insertbefore(tai_comment.Create(strpnew('pass1 called for instr')), p);
  54. case taicpu(p).opcode of
  55. { LEA (Ax),Ax is a NOP if src and dest reg is equal, so remove it. }
  56. A_LEA:
  57. if GetNextInstruction(p,next) and not assigned(taicpu(p).oper[0]^.ref^.symbol) and
  58. (((taicpu(p).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) and
  59. (taicpu(p).oper[0]^.ref^.index = NR_NO)) or
  60. ((taicpu(p).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg) and
  61. (taicpu(p).oper[0]^.ref^.base = NR_NO))) and
  62. (taicpu(p).oper[0]^.ref^.offset = 0) then
  63. begin
  64. DebugMsg('Optimizer: LEA 0(Ax),Ax removed',p);
  65. asml.remove(p);
  66. p.free;
  67. p:=next;
  68. result:=true;
  69. end;
  70. { Address register sub/add can be replaced with ADDQ/SUBQ or LEA if the value is in the
  71. SmallInt range, which is shorter to encode and faster to execute on most 68k }
  72. A_SUB,A_SUBA,A_ADD,A_ADDA:
  73. if (taicpu(p).oper[1]^.typ = top_reg) and isaddressregister(taicpu(p).oper[1]^.reg) and
  74. (taicpu(p).oper[0]^.typ = top_const) then
  75. begin
  76. if isvalueforaddqsubq(taicpu(p).oper[0]^.val) then
  77. begin
  78. DebugMsg('Optimizer: SUB/ADD #val,Ax to SUBQ/ADDQ',p);
  79. taicpu(p).opsize:=S_L; // this is safe, because we're targetting an address reg
  80. if taicpu(p).opcode in [A_ADD,A_ADDA] then
  81. taicpu(p).opcode:=A_ADDQ
  82. else
  83. taicpu(p).opcode:=A_SUBQ;
  84. result:=true;
  85. end
  86. else
  87. if isvalue16bit(abs(taicpu(p).oper[0]^.val)) then
  88. begin
  89. DebugMsg('Optimizer: SUB/ADD #val,Ax to LEA val(Ax),Ax',p);
  90. if taicpu(p).opcode in [A_SUB,A_SUBA] then
  91. reference_reset_base(tmpref,taicpu(p).oper[1]^.reg,-taicpu(p).oper[0]^.val,0)
  92. else
  93. reference_reset_base(tmpref,taicpu(p).oper[1]^.reg,taicpu(p).oper[0]^.val,0);
  94. taicpu(p).opcode:=A_LEA;
  95. taicpu(p).loadref(0,tmpref);
  96. result:=true;
  97. end;
  98. end;
  99. { MOVEA #0,Ax to SUBA Ax,Ax, because it's shorter }
  100. A_MOVEA:
  101. if (taicpu(p).oper[0]^.typ = top_const) and
  102. (taicpu(p).oper[0]^.val = 0) then
  103. begin
  104. DebugMsg('Optimizer: MOVEA #0,Ax to SUBA Ax,Ax',p);
  105. taicpu(p).opcode:=A_SUBA;
  106. taicpu(p).opsize:=S_L; { otherwise it will be .W -> BOOM }
  107. taicpu(p).loadoper(0,taicpu(p).oper[1]^);
  108. result:=true;
  109. end;
  110. { CLR.L Dx on a 68000 is slower than MOVEQ #0,Dx }
  111. A_CLR:
  112. if (current_settings.cputype in [cpu_mc68000]) and
  113. (taicpu(p).oper[0]^.typ = top_reg) and
  114. (taicpu(p).opsize = S_L) and
  115. isintregister(taicpu(p).oper[0]^.reg) then
  116. begin
  117. //DebugMsg('Optimizer: CLR.L Dx to MOVEQ #0,Dx',p);
  118. taicpu(p).opcode:=A_MOVEQ;
  119. taicpu(p).loadoper(1,taicpu(p).oper[0]^);
  120. taicpu(p).loadconst(0,0);
  121. taicpu(p).ops:=2;
  122. result:=true;
  123. end;
  124. { CMP #0,<ea> equals to TST <ea>, just shorter and TST is more flexible anyway }
  125. A_CMP,A_CMPI:
  126. if (taicpu(p).oper[0]^.typ = top_const) and
  127. (taicpu(p).oper[0]^.val = 0) then
  128. begin
  129. DebugMsg('Optimizer: CMP #0 to TST',p);
  130. taicpu(p).opcode:=A_TST;
  131. taicpu(p).loadoper(0,taicpu(p).oper[1]^);
  132. taicpu(p).clearop(1);
  133. taicpu(p).ops:=1;
  134. result:=true;
  135. end;
  136. A_FCMP:
  137. if (taicpu(p).oper[0]^.typ = top_realconst) then
  138. begin
  139. if (taicpu(p).oper[0]^.val_real = 0.0) then
  140. begin
  141. DebugMsg('Optimizer: FCMP #0.0 to FTST',p);
  142. taicpu(p).opcode:=A_FTST;
  143. taicpu(p).opsize:=S_FX;
  144. taicpu(p).loadoper(0,taicpu(p).oper[1]^);
  145. taicpu(p).clearop(1);
  146. taicpu(p).ops:=1;
  147. result:=true;
  148. end
  149. else
  150. begin
  151. tmpsingle:=taicpu(p).oper[0]^.val_real;
  152. if (taicpu(p).opsize = S_FD) and
  153. ((taicpu(p).oper[0]^.val_real - tmpsingle) = 0.0) then
  154. begin
  155. DebugMsg('Optimizer: FCMP const to lesser precision',p);
  156. taicpu(p).opsize:=S_FS;
  157. result:=true;
  158. end;
  159. end;
  160. end;
  161. A_FMOVE,A_FMUL,A_FADD,A_FSUB,A_FDIV:
  162. if (taicpu(p).oper[0]^.typ = top_realconst) then
  163. begin
  164. tmpsingle:=taicpu(p).oper[0]^.val_real;
  165. if (taicpu(p).opsize = S_FD) and
  166. ((taicpu(p).oper[0]^.val_real - tmpsingle) = 0.0) then
  167. begin
  168. DebugMsg('Optimizer: FMOVE/FMUL/FADD/FSUB/FDIV const to lesser precision',p);
  169. taicpu(p).opsize:=S_FS;
  170. result:=true;
  171. end;
  172. end;
  173. end;
  174. end;
  175. end;
  176. end;
  177. begin
  178. casmoptimizer:=TCpuAsmOptimizer;
  179. end.