{ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal Development Team This unit implements the ARM64 optimizer object This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. **************************************************************************** } Unit aoptcpu; {$i fpcdefs.inc} { $define DEBUG_AOPTCPU} Interface uses globtype, globals, cutils, cgbase, cpubase, aasmtai, aasmcpu, aopt, aoptcpub, aoptarm; Type TCpuAsmOptimizer = class(TARMAsmOptimizer) { uses the same constructor as TAopObj } function PeepHoleOptPass1Cpu(var p: tai): boolean; override; function PeepHoleOptPass2Cpu(var p: tai): boolean; override; function PostPeepHoleOptsCpu(var p: tai): boolean; override; function RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;override; function InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;override; function LookForPostindexedPattern(var p : tai) : boolean; private function RemoveSuperfluousFMov(const p: tai; movp: tai; const optimizer: string): boolean; function OptPass1Shift(var p: tai): boolean; function OptPostCMP(var p: tai): boolean; function OptPass1Data(var p: tai): boolean; function OptPass1FData(var p: tai): Boolean; function OptPass1STP(var p: tai): boolean; function OptPass1Mov(var p: tai): boolean; function OptPass1FMov(var p: tai): Boolean; function OptPass2LDRSTR(var p: tai): boolean; End; Implementation uses aasmbase, aoptutils, cgutils, verbose; {$ifdef DEBUG_AOPTCPU} const SPeepholeOptimization: shortstring = 'Peephole Optimization: '; {$else DEBUG_AOPTCPU} { Empty strings help the optimizer to remove string concatenations that won't ever appear to the user on release builds. [Kit] } const SPeepholeOptimization = ''; {$endif DEBUG_AOPTCPU} function CanBeCond(p : tai) : boolean; begin result:=(p.typ=ait_instruction) and (taicpu(p).condition=C_None); end; function TCpuAsmOptimizer.RegLoadedWithNewValue(reg: tregister; hp: tai): boolean; var p: taicpu; begin Result := false; if not ((assigned(hp)) and (hp.typ = ait_instruction)) then exit; p := taicpu(hp); case p.opcode of { These operands do not write into a register at all } A_CMP, A_CMN, A_TST, A_B, A_BL, A_MSR, A_FCMP: exit; {Take care of post/preincremented store and loads, they will change their base register} A_STR, A_LDR: begin Result := false; { actually, this does not apply here because post-/preindexed does not mean that a register is loaded with a new value, it is only modified (taicpu(p).oper[1]^.typ=top_ref) and (taicpu(p).oper[1]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and (taicpu(p).oper[1]^.ref^.base = reg); } { STR does not load into it's first register } if p.opcode = A_STR then exit; end; else ; end; if Result then exit; case p.oper[0]^.typ of top_reg: Result := (p.oper[0]^.reg = reg); top_ref: Result := (taicpu(p).oper[0]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and (taicpu(p).oper[0]^.ref^.base = reg); else ; end; end; function TCpuAsmOptimizer.InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean; var p: taicpu; i: longint; begin instructionLoadsFromReg := false; if not (assigned(hp) and (hp.typ = ait_instruction)) then exit; p:=taicpu(hp); i:=1; { Start on oper[0]? } if taicpu(hp).spilling_get_operation_type(0) in [operand_read, operand_readwrite] then i:=0; while(i