mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-09 16:49:00 +02:00
187 lines
5.0 KiB
ObjectPascal
187 lines
5.0 KiB
ObjectPascal
{
|
|
Copyright (c) 2015 by Jonas Maebe, member of the Free Pascal
|
|
Development Team
|
|
|
|
This unit implements the JVM 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 = class(TAsmOptimizer)
|
|
protected
|
|
function RemoveDoubleSwap(var p: tai): boolean;
|
|
function RemoveCommutativeSwap(var p: tai): boolean;
|
|
function RemoveLoadLoadSwap(var p: tai): boolean;
|
|
public
|
|
{ uses the same constructor as TAopObj }
|
|
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
|
procedure PeepHoleOptPass2;override;
|
|
function PostPeepHoleOptsCpu(var p: tai): boolean; override;
|
|
End;
|
|
|
|
Implementation
|
|
|
|
uses
|
|
aasmbase,aasmcpu,cgbase;
|
|
|
|
|
|
function TCpuAsmOptimizer.RemoveDoubleSwap(var p: tai): boolean;
|
|
var
|
|
next, next2: tai;
|
|
begin
|
|
result:=false;
|
|
{ remove two successive "swap" instructions }
|
|
if (taicpu(p).opcode=a_swap) and
|
|
GetNextInstruction(p,next) and
|
|
(next.typ=ait_instruction) and
|
|
(taicpu(next).opcode=a_swap) then
|
|
begin
|
|
{ can't be the instruction, must end in a return or so }
|
|
next2:=tai(next.next);
|
|
asml.remove(p);
|
|
asml.remove(next);
|
|
p.free;
|
|
next.free;
|
|
p:=next2;
|
|
result:=true;
|
|
end;
|
|
end;
|
|
|
|
|
|
{ returns whether p is an instruction that does not consume any stack slots,
|
|
and adds a new item on the stack that is one stack slot wide }
|
|
function OpCreatesSingleStackSlot(p: tai): boolean;
|
|
begin
|
|
result:=
|
|
(p.typ=ait_instruction) and
|
|
(taicpu(p).opcode in
|
|
[a_aload, a_aload_0, a_aload_1, a_aload_2, a_aload_3,
|
|
a_bipush,
|
|
a_fconst_0, a_fconst_1, a_fconst_2,
|
|
a_fload, a_fload_0, a_fload_1, a_fload_2, a_fload_3,
|
|
a_getstatic,
|
|
a_iconst_m1, a_iconst_0, a_iconst_1, a_iconst_2, a_iconst_3,
|
|
a_iconst_4, a_iconst_5,
|
|
a_iload, a_iload_0, a_iload_1, a_iload_2, a_iload_3,
|
|
a_new,
|
|
a_sipush]);
|
|
end;
|
|
|
|
|
|
function OpIsCommutativeSingleSlots(p: tai): boolean;
|
|
begin
|
|
result:=
|
|
(p.typ=ait_instruction) and
|
|
(taicpu(p).opcode in
|
|
[a_fadd, a_fmul,
|
|
a_iadd, a_iand, a_imul, a_ior, a_ixor,
|
|
a_pop2])
|
|
end;
|
|
|
|
|
|
function TCpuAsmOptimizer.RemoveCommutativeSwap(var p: tai): boolean;
|
|
var
|
|
next: tai;
|
|
begin
|
|
result:=false;
|
|
if (taicpu(p).opcode<>a_swap) then
|
|
exit;
|
|
{ if the next opcode is commutative operation, we can remove the swap }
|
|
if GetNextInstruction(p,next) and
|
|
OpIsCommutativeSingleSlots(next) then
|
|
begin
|
|
asml.remove(p);
|
|
p.free;
|
|
p:=next;
|
|
result:=true;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
|
|
var
|
|
next, next2: tai;
|
|
begin
|
|
result:=false;
|
|
case p.typ of
|
|
ait_instruction:
|
|
begin
|
|
if RemoveDoubleSwap(p) or
|
|
RemoveCommutativeSwap(p) then
|
|
exit(true)
|
|
end;
|
|
else
|
|
;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TCpuAsmOptimizer.PeepHoleOptPass2;
|
|
begin
|
|
end;
|
|
|
|
|
|
function TCpuAsmOptimizer.RemoveLoadLoadSwap(var p: tai): boolean;
|
|
var
|
|
next, prev1, prev2: tai;
|
|
begin
|
|
result:=false;
|
|
if (taicpu(p).opcode<>a_swap) then
|
|
exit;
|
|
{ if we can swap the previous two instructions that put the items on the
|
|
stack, we can remove the swap -- only do this in PostPeepholeOpts,
|
|
because this may make the temp alloc information invalid. Ideally, we
|
|
should move the tempallocs around too }
|
|
if GetLastInstruction(p,prev1) and
|
|
OpCreatesSingleStackSlot(prev1) and
|
|
GetLastInstruction(prev1,prev2) and
|
|
OpCreatesSingleStackSlot(prev2) then
|
|
begin
|
|
next:=tai(p.next);
|
|
asml.remove(prev2);
|
|
asml.InsertAfter(prev2,prev1);
|
|
asml.remove(p);
|
|
p.free;
|
|
p:=next;
|
|
result:=true;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TCpuAsmOptimizer.PostPeepHoleOptsCpu(var p: tai): boolean;
|
|
begin
|
|
result:=
|
|
(p.typ=ait_instruction) and
|
|
RemoveLoadLoadSwap(p);
|
|
end;
|
|
|
|
begin
|
|
casmoptimizer:=TCpuAsmOptimizer;
|
|
End.
|
|
|