From 05d38053f77e80d5159f7d6188f669a4acd5852d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A1roly=20Balogh?= Date: Mon, 2 Feb 2015 08:52:19 +0000 Subject: [PATCH] m68k: optimize a few more trivial cases git-svn-id: trunk@29606 - --- compiler/m68k/aoptcpu.pas | 92 ++++++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 16 deletions(-) diff --git a/compiler/m68k/aoptcpu.pas b/compiler/m68k/aoptcpu.pas index 693c461065..2012575318 100644 --- a/compiler/m68k/aoptcpu.pas +++ b/compiler/m68k/aoptcpu.pas @@ -25,6 +25,8 @@ unit aoptcpu; {$i fpcdefs.inc} +{$define DEBUG_AOPTCPU} + Interface uses @@ -33,16 +35,31 @@ unit aoptcpu; Type TCpuAsmOptimizer = class(TAsmOptimizer) function PeepHoleOptPass1Cpu(var p: tai): boolean; override; + + { outputs a debug message into the assembler file } + procedure DebugMsg(const s: string; p: tai); End; Implementation uses - cutils, aasmcpu; + cutils, aasmcpu, cgutils; + +{$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 TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean; var next: tai; + tmpref: treference; begin result:=false; case p.typ of @@ -50,21 +67,64 @@ unit aoptcpu; begin //asml.insertbefore(tai_comment.Create(strpnew('pass1 called for instr')), p); - { LEA (Ax),Ax is a NOP if src and dest reg is equal, so remove it. } - if getnextinstruction(p,next) and (taicpu(p).opcode = A_LEA) and - (not assigned(taicpu(p).oper[0]^.ref^.symbol)) and - (((taicpu(p).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) and - (taicpu(p).oper[0]^.ref^.index = NR_NO)) or - ((taicpu(p).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg) and - (taicpu(p).oper[0]^.ref^.base = NR_NO))) and - (taicpu(p).oper[0]^.ref^.offset = 0) then - begin - //asml.insertbefore(tai_comment.Create(strpnew('LEA (Ax),Ax removed')), p); - asml.remove(p); - p.free; - p:=next; - result:=true; - end; + case taicpu(p).opcode of + { LEA (Ax),Ax is a NOP if src and dest reg is equal, so remove it. } + A_LEA: + if GetNextInstruction(p,next) and not assigned(taicpu(p).oper[0]^.ref^.symbol) and + (((taicpu(p).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) and + (taicpu(p).oper[0]^.ref^.index = NR_NO)) or + ((taicpu(p).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg) and + (taicpu(p).oper[0]^.ref^.base = NR_NO))) and + (taicpu(p).oper[0]^.ref^.offset = 0) then + begin + DebugMsg('Optimizer: LEA 0(Ax),Ax removed',p); + asml.remove(p); + p.free; + p:=next; + result:=true; + end; + { Address register sub/add can be replaced with ADDQ/SUBQ or LEA if the value is in the + SmallInt range, which is shorter to encode and faster to execute on most 68k } + A_SUB,A_SUBA,A_ADD,A_ADDA: + if (taicpu(p).oper[1]^.typ = top_reg) and isaddressregister(taicpu(p).oper[1]^.reg) and + (taicpu(p).oper[0]^.typ = top_const) then + begin + if isvalueforaddqsubq(taicpu(p).oper[0]^.val) then + begin + DebugMsg('Optimizer: SUB/ADD #val,Ax to SUBQ/ADDQ',p); + taicpu(p).opsize:=S_L; // this is safe, because we're targetting an address reg + if taicpu(p).opcode in [A_ADD,A_ADDA] then + taicpu(p).opcode:=A_ADDQ + else + taicpu(p).opcode:=A_SUBQ; + result:=true; + end + else + if isvalue16bit(abs(taicpu(p).oper[0]^.val)) then + begin + DebugMsg('Optimizer: SUB/ADD #val,Ax to LEA val(Ax),Ax',p); + if taicpu(p).opcode in [A_SUB,A_SUBA] then + reference_reset_base(tmpref,taicpu(p).oper[1]^.reg,-taicpu(p).oper[0]^.val,0) + else + reference_reset_base(tmpref,taicpu(p).oper[1]^.reg,taicpu(p).oper[0]^.val,0); + taicpu(p).opcode:=A_LEA; + taicpu(p).loadref(0,tmpref); + result:=true; + end; + end; + { CMP #0, equals to TST , just shorter and TST is more flexible anyway } + A_CMP: + if (taicpu(p).oper[0]^.typ = top_const) and + (taicpu(p).oper[0]^.val = 0) then + begin + DebugMsg('Optimizer: CMP #0 to TST',p); + taicpu(p).opcode:=A_TST; + taicpu(p).loadoper(0,taicpu(p).oper[1]^); + taicpu(p).clearop(1); + taicpu(p).ops:=1; + result:=true; + end; + end; end; end; end;