123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- {
- 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;
- Type
- TCpuAsmOptimizer = class(TAsmOptimizer)
- { uses the same constructor as TAopObj }
- function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
- procedure PeepHoleOptPass2;override;
- function GetNextInstructionUsingReg(Current : tai; out Next : tai; reg : TRegister) : Boolean;
- function LookForPostindexedPattern(p : taicpu) : boolean;
- procedure DebugMsg(const s : string; p : tai);
- End;
- Implementation
- uses
- aasmbase;
- {$ifdef DEBUG_AOPTCPU}
- procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);
- begin
- asml.insertbefore(tai_comment.Create(strpnew(s)), p);
- end;
- {$else DEBUG_AOPTCPU}
- procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);inline;
- begin
- end;
- {$endif DEBUG_AOPTCPU}
- function CanBeCond(p : tai) : boolean;
- begin
- result:=(p.typ=ait_instruction) and (taicpu(p).condition=C_None);
- end;
- function MatchInstruction(const instr: tai; const op: TAsmOps; const postfix: TOpPostfixes): boolean;
- begin
- result :=
- (instr.typ = ait_instruction) and
- ((op = []) or (taicpu(instr).opcode in op)) and
- ((postfix = []) or (taicpu(instr).oppostfix in postfix));
- end;
- function MatchInstruction(const instr: tai; const op: TAsmOp; const postfix: TOpPostfixes): boolean;
- begin
- result :=
- (instr.typ = ait_instruction) and
- (taicpu(instr).opcode = op) and
- ((postfix = []) or (taicpu(instr).oppostfix in postfix));
- end;
- function TCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai;
- Out Next: tai; reg: TRegister): Boolean;
- begin
- Next:=Current;
- repeat
- Result:=GetNextInstruction(Next,Next);
- until not (Result) or
- not(cs_opt_level3 in current_settings.optimizerswitches) or
- (Next.typ<>ait_instruction) or
- RegInInstruction(reg,Next) or
- is_calljmp(taicpu(Next).opcode);
- end;
- {
- optimize
- ldr/str regX,[reg1]
- ...
- add/sub reg1,reg1,regY/const
- into
- ldr/str regX,[reg1], regY/const
- }
- function TCpuAsmOptimizer.LookForPostindexedPattern(p: taicpu) : boolean;
- var
- hp1 : tai;
- begin
- Result:=false;
- if (p.oper[1]^.typ = top_ref) and
- (p.oper[1]^.ref^.addressmode=AM_OFFSET) and
- (p.oper[1]^.ref^.index=NR_NO) and
- (p.oper[1]^.ref^.offset=0) and
- GetNextInstructionUsingReg(p, hp1, p.oper[1]^.ref^.base) and
- { we cannot check NR_DEFAULTFLAGS for modification yet so don't allow a condition }
- MatchInstruction(hp1, [A_ADD, A_SUB], [PF_None]) and
- (taicpu(hp1).oper[0]^.reg=p.oper[1]^.ref^.base) and
- (taicpu(hp1).oper[1]^.reg=p.oper[1]^.ref^.base) and
- (
- { valid offset? }
- (taicpu(hp1).oper[2]^.typ=top_const) and
- (taicpu(hp1).oper[2]^.val>=-256) and
- (abs(taicpu(hp1).oper[2]^.val)<256)
- ) and
- { don't apply the optimization if the base register is loaded }
- (getsupreg(p.oper[0]^.reg)<>getsupreg(p.oper[1]^.ref^.base)) and
- not(RegModifiedBetween(taicpu(hp1).oper[0]^.reg,p,hp1)) and
- not(RegModifiedBetween(taicpu(hp1).oper[2]^.reg,p,hp1)) then
- begin
- DebugMsg('Peephole Str/LdrAdd/Sub2Str/Ldr Postindex done', p);
- p.oper[1]^.ref^.addressmode:=AM_POSTINDEXED;
- if taicpu(hp1).opcode=A_ADD then
- p.oper[1]^.ref^.offset:=taicpu(hp1).oper[2]^.val
- else
- p.oper[1]^.ref^.offset:=-taicpu(hp1).oper[2]^.val;
- asml.Remove(hp1);
- hp1.Free;
- Result:=true;
- end;
- end;
- function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
- begin
- result := false;
- if p.typ=ait_instruction then
- begin
- case taicpu(p).opcode of
- A_LDR:
- begin
- Result:=LookForPostindexedPattern(taicpu(p));
- end;
- A_STR:
- begin
- Result:=LookForPostindexedPattern(taicpu(p));
- end;
- end;
- end;
- end;
- procedure TCpuAsmOptimizer.PeepHoleOptPass2;
- begin
- end;
- begin
- casmoptimizer:=TCpuAsmOptimizer;
- End.
|