123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- {
- Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
- Development Team
- This unit implements the ARM 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}
- Interface
- uses cpubase, aasmtai, aopt, aoptcpub;
- Type
- { TCpuAsmOptimizer }
- TCpuAsmOptimizer = class(TAsmOptimizer)
- { uses the same constructor as TAopObj }
- function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
- End;
- Implementation
- uses
- verbose,
- aasmbase,aasmcpu,
- cgbase;
- { TCpuAsmOptimizer }
- function Test_Set(const RegSet,t: tcpuregisterset): boolean;
- begin
- result := ((RegSet*t) = []) or ((RegSet*t) = t);
- end;
- function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
- var
- v: LongInt;
- hp1: tai;
- begin
- result := false;
- case p.typ of
- ait_instruction:
- begin
- { Collapse ADD r0,r0,r1 -> ADD r0,r1 }
- if (taicpu(p).opcode in [A_ADD,A_SUB,A_AND,A_EOR,A_OR,A_MUL]) and
- (taicpu(p).ops = 3) and
- (taicpu(p).oper[0]^.typ = top_reg) and
- (taicpu(p).oper[1]^.typ = top_reg) and
- (taicpu(p).oper[2]^.typ = top_reg) and
- (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
- begin
- hp1:=taicpu.op_reg_reg(taicpu(p).opcode,taicpu(p).oper[0]^.reg,taicpu(p).oper[2]^.reg);
- AsmL.InsertBefore(hp1,p);
- //InsertLLItem(p.Previous,p.Next,hp1);
- AsmL.Remove(p);
- p.Free;
- p:=hp1;
- result:=true;
- end
- { Collapse ADD r0,r1,r0 -> ADD r0,r1
- SUB needs RSUB }
- else if (taicpu(p).opcode in [A_ADD,A_AND,A_EOR,A_OR,A_MUL]) and
- (taicpu(p).ops = 3) and
- (taicpu(p).oper[0]^.typ = top_reg) and
- (taicpu(p).oper[1]^.typ = top_reg) and
- (taicpu(p).oper[2]^.typ = top_reg) and
- (taicpu(p).oper[0]^.reg = taicpu(p).oper[2]^.reg) then
- begin
- hp1:=taicpu.op_reg_reg(taicpu(p).opcode,taicpu(p).oper[0]^.reg,taicpu(p).oper[1]^.reg);
- AsmL.InsertBefore(hp1,p);
- //InsertLLItem(p.Previous,p.Next,hp1);
- AsmL.Remove(p);
- p.Free;
- p:=hp1;
- result:=true;
- end
- else
- case taicpu(p).opcode of
- { Collapse instructions into a compact format }
- A_SUB:
- begin
- { SUB r0,r0,imm8 -> SUB r0,imm8 }
- if (taicpu(p).ops=3) and
- (taicpu(p).oper[0]^.typ = top_reg) and
- (taicpu(p).oper[1]^.typ = top_reg) and
- (taicpu(p).oper[2]^.typ = top_const) and
- (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) and
- in_signed_bits(taicpu(p).oper[2]^.val, 8) then
- begin
- hp1:=taicpu.op_reg_const(taicpu(p).opcode,taicpu(p).oper[0]^.reg,taicpu(p).oper[2]^.val);
- AsmL.InsertBefore(hp1,p);
- //InsertLLItem(p.Previous,p.Next,hp1);
- AsmL.Remove(p);
- p.Free;
- p:=hp1;
- result:=true;
- end
- { SUB r0,r1,r0 -> RSUB r0,r1 }
- else if (taicpu(p).ops=3) and
- (taicpu(p).oper[0]^.typ = top_reg) and
- (taicpu(p).oper[1]^.typ = top_reg) and
- (taicpu(p).oper[2]^.typ = top_reg) and
- (taicpu(p).oper[0]^.reg = taicpu(p).oper[2]^.reg) then
- begin
- hp1:=taicpu.op_reg_reg(A_RSUB,taicpu(p).oper[0]^.reg,taicpu(p).oper[1]^.reg);
- AsmL.InsertBefore(hp1,p);
- //InsertLLItem(p.Previous,p.Next,hp1);
- AsmL.Remove(p);
- p.Free;
- p:=hp1;
- result:=true;
- end;
- end;
- A_LSL,
- A_LSR,
- A_ASR:
- begin
- { LSL r0,r0,imm8 -> LSL r0,imm8 }
- if (taicpu(p).ops=3) and
- (taicpu(p).oper[0]^.typ = top_reg) and
- (taicpu(p).oper[1]^.typ = top_reg) and
- (taicpu(p).oper[2]^.typ = top_const) and
- (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
- begin
- hp1:=taicpu.op_reg_const(taicpu(p).opcode,taicpu(p).oper[0]^.reg,taicpu(p).oper[2]^.val);
- AsmL.InsertBefore(hp1,p);
- //InsertLLItem(p.Previous,p.Next,hp1);
- AsmL.Remove(p);
- p.Free;
- p:=hp1;
- result:=true;
- end
- end;
- A_STM:
- begin
- { Try to compress STM --sp, LIST down to PUSHM LIST }
- if (taicpu(p).oper[0]^.ref^.base = NR_STACK_POINTER_REG) and
- (taicpu(p).oper[0]^.ref^.addressmode = AM_PREINDEXED) and
- (taicpu(p).oper[1]^.regset^ <> []) then
- begin
- if test_set(taicpu(p).oper[1]^.regset^, [0..3]) and
- test_set(taicpu(p).oper[1]^.regset^, [4..7]) and
- test_set(taicpu(p).oper[1]^.regset^, [8..9]) and
- test_set(taicpu(p).oper[1]^.regset^, [10]) and
- test_set(taicpu(p).oper[1]^.regset^, [11]) and
- test_set(taicpu(p).oper[1]^.regset^, [12]) and
- test_set(taicpu(p).oper[1]^.regset^, [14]) and
- test_set(taicpu(p).oper[1]^.regset^, [15]) and
- ((taicpu(p).oper[1]^.regset^ * [13]) = []) then
- begin
- hp1:=taicpu.op_regset(A_PUSHM,taicpu(p).oper[1]^.regtyp,taicpu(p).oper[1]^.subreg,taicpu(p).oper[1]^.regset^);
- AsmL.InsertBefore(hp1,p);
- //InsertLLItem(p.Previous,p.Next,hp1);
- AsmL.Remove(p);
- p.Free;
- p:=hp1;
- result:=true;
- exit;
- end;
- end;
- end;
- A_LDM:
- begin
- { Try to compress LDM sp++, LIST down to POPM LIST }
- if (taicpu(p).oper[0]^.ref^.base = NR_STACK_POINTER_REG) and
- ((taicpu(p).oper[0]^.ref^.addressmode = AM_POSTINDEXED) or
- (RS_STACK_POINTER_REG in taicpu(p).oper[1]^.regset^)) and
- (taicpu(p).oper[1]^.regset^ <> []) then
- begin
- if test_set(taicpu(p).oper[1]^.regset^, [0..3]) and
- test_set(taicpu(p).oper[1]^.regset^, [4..7]) and
- test_set(taicpu(p).oper[1]^.regset^, [8..9]) and
- test_set(taicpu(p).oper[1]^.regset^, [10]) and
- test_set(taicpu(p).oper[1]^.regset^, [11]) and
- test_set(taicpu(p).oper[1]^.regset^, [12]) and
- test_set(taicpu(p).oper[1]^.regset^, [14]) and
- test_set(taicpu(p).oper[1]^.regset^, [15]) and
- ((taicpu(p).oper[1]^.regset^ * [13]) = []) then
- begin
- hp1:=taicpu.op_regset(A_POPM,taicpu(p).oper[1]^.regtyp,taicpu(p).oper[1]^.subreg,taicpu(p).oper[1]^.regset^);
- AsmL.InsertBefore(hp1,p);
- //InsertLLItem(p.Previous,p.Next,hp1);
- AsmL.Remove(p);
- p.Free;
- p:=hp1;
- result:=true;
- exit;
- end;
- end;
- end;
- end;
- end;
- end;
- end;
- begin
- casmoptimizer:=TCpuAsmOptimizer;
- End.
|