aoptcpu.pas 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. {
  2. Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
  3. Development Team
  4. This unit implements the ARM64 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 aoptcpu;
  19. {$i fpcdefs.inc}
  20. { $define DEBUG_AOPTCPU}
  21. Interface
  22. uses
  23. globtype, globals,
  24. cutils,
  25. cgbase, cpubase, aasmtai, aasmcpu, aopt, aoptcpub;
  26. Type
  27. TCpuAsmOptimizer = class(TAsmOptimizer)
  28. { uses the same constructor as TAopObj }
  29. function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
  30. procedure PeepHoleOptPass2;override;
  31. function GetNextInstructionUsingReg(Current : tai; out Next : tai; reg : TRegister) : Boolean;
  32. function LookForPostindexedPattern(p : taicpu) : boolean;
  33. procedure DebugMsg(const s : string; p : tai);
  34. End;
  35. Implementation
  36. uses
  37. aasmbase;
  38. {$ifdef DEBUG_AOPTCPU}
  39. procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);
  40. begin
  41. asml.insertbefore(tai_comment.Create(strpnew(s)), p);
  42. end;
  43. {$else DEBUG_AOPTCPU}
  44. procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);inline;
  45. begin
  46. end;
  47. {$endif DEBUG_AOPTCPU}
  48. function CanBeCond(p : tai) : boolean;
  49. begin
  50. result:=(p.typ=ait_instruction) and (taicpu(p).condition=C_None);
  51. end;
  52. function MatchInstruction(const instr: tai; const op: TAsmOps; const postfix: TOpPostfixes): boolean;
  53. begin
  54. result :=
  55. (instr.typ = ait_instruction) and
  56. ((op = []) or (taicpu(instr).opcode in op)) and
  57. ((postfix = []) or (taicpu(instr).oppostfix in postfix));
  58. end;
  59. function MatchInstruction(const instr: tai; const op: TAsmOp; const postfix: TOpPostfixes): boolean;
  60. begin
  61. result :=
  62. (instr.typ = ait_instruction) and
  63. (taicpu(instr).opcode = op) and
  64. ((postfix = []) or (taicpu(instr).oppostfix in postfix));
  65. end;
  66. function TCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai;
  67. Out Next: tai; reg: TRegister): Boolean;
  68. begin
  69. Next:=Current;
  70. repeat
  71. Result:=GetNextInstruction(Next,Next);
  72. until not (Result) or
  73. not(cs_opt_level3 in current_settings.optimizerswitches) or
  74. (Next.typ<>ait_instruction) or
  75. RegInInstruction(reg,Next) or
  76. is_calljmp(taicpu(Next).opcode);
  77. end;
  78. {
  79. optimize
  80. ldr/str regX,[reg1]
  81. ...
  82. add/sub reg1,reg1,regY/const
  83. into
  84. ldr/str regX,[reg1], regY/const
  85. }
  86. function TCpuAsmOptimizer.LookForPostindexedPattern(p: taicpu) : boolean;
  87. var
  88. hp1 : tai;
  89. begin
  90. Result:=false;
  91. if (p.oper[1]^.typ = top_ref) and
  92. (p.oper[1]^.ref^.addressmode=AM_OFFSET) and
  93. (p.oper[1]^.ref^.index=NR_NO) and
  94. (p.oper[1]^.ref^.offset=0) and
  95. GetNextInstructionUsingReg(p, hp1, p.oper[1]^.ref^.base) and
  96. { we cannot check NR_DEFAULTFLAGS for modification yet so don't allow a condition }
  97. MatchInstruction(hp1, [A_ADD, A_SUB], [PF_None]) and
  98. (taicpu(hp1).oper[0]^.reg=p.oper[1]^.ref^.base) and
  99. (taicpu(hp1).oper[1]^.reg=p.oper[1]^.ref^.base) and
  100. (
  101. { valid offset? }
  102. (taicpu(hp1).oper[2]^.typ=top_const) and
  103. (taicpu(hp1).oper[2]^.val>=-256) and
  104. (abs(taicpu(hp1).oper[2]^.val)<256)
  105. ) and
  106. { don't apply the optimization if the base register is loaded }
  107. (getsupreg(p.oper[0]^.reg)<>getsupreg(p.oper[1]^.ref^.base)) and
  108. not(RegModifiedBetween(taicpu(hp1).oper[0]^.reg,p,hp1)) and
  109. not(RegModifiedBetween(taicpu(hp1).oper[2]^.reg,p,hp1)) then
  110. begin
  111. DebugMsg('Peephole Str/LdrAdd/Sub2Str/Ldr Postindex done', p);
  112. p.oper[1]^.ref^.addressmode:=AM_POSTINDEXED;
  113. if taicpu(hp1).opcode=A_ADD then
  114. p.oper[1]^.ref^.offset:=taicpu(hp1).oper[2]^.val
  115. else
  116. p.oper[1]^.ref^.offset:=-taicpu(hp1).oper[2]^.val;
  117. asml.Remove(hp1);
  118. hp1.Free;
  119. Result:=true;
  120. end;
  121. end;
  122. function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
  123. begin
  124. result := false;
  125. if p.typ=ait_instruction then
  126. begin
  127. case taicpu(p).opcode of
  128. A_LDR:
  129. begin
  130. Result:=LookForPostindexedPattern(taicpu(p));
  131. end;
  132. A_STR:
  133. begin
  134. Result:=LookForPostindexedPattern(taicpu(p));
  135. end;
  136. end;
  137. end;
  138. end;
  139. procedure TCpuAsmOptimizer.PeepHoleOptPass2;
  140. begin
  141. end;
  142. begin
  143. casmoptimizer:=TCpuAsmOptimizer;
  144. End.