* i386 peephole assembler uses largely the common peephole optimizer infrastructure, the resulting code is besides a few improvements the same

git-svn-id: trunk@33542 -
This commit is contained in:
florian 2016-04-21 20:14:01 +00:00
parent 4ac3953c34
commit 3c2dab9878
11 changed files with 732 additions and 3172 deletions

6
.gitattributes vendored
View File

@ -188,7 +188,9 @@ compiler/hlcgobj.pas svneol=native#text/plain
compiler/html/i386/readme.txt svneol=native#text/plain
compiler/html/powerpc/readme.txt svneol=native#text/plain
compiler/htypechk.pas svneol=native#text/plain
compiler/i386/aopt386.pas svneol=native#text/plain
compiler/i386/aoptcpu.pas svneol=native#text/plain
compiler/i386/aoptcpub.pas svneol=native#text/plain
compiler/i386/aoptcpud.pas svneol=native#text/plain
compiler/i386/cgcpu.pas svneol=native#text/plain
compiler/i386/cpubase.inc svneol=native#text/plain
compiler/i386/cpuelf.pas svneol=native#text/plain
@ -197,7 +199,6 @@ compiler/i386/cpunode.pas svneol=native#text/plain
compiler/i386/cpupara.pas svneol=native#text/plain
compiler/i386/cpupi.pas svneol=native#text/plain
compiler/i386/cputarg.pas svneol=native#text/plain
compiler/i386/daopt386.pas svneol=native#text/plain
compiler/i386/hlcgcpu.pas svneol=native#text/plain
compiler/i386/i386att.inc svneol=native#text/plain
compiler/i386/i386atts.inc svneol=native#text/plain
@ -214,7 +215,6 @@ compiler/i386/n386ld.pas svneol=native#text/plain
compiler/i386/n386mat.pas svneol=native#text/plain
compiler/i386/n386mem.pas svneol=native#text/plain
compiler/i386/n386set.pas svneol=native#text/plain
compiler/i386/popt386.pas svneol=native#text/plain
compiler/i386/r386ari.inc svneol=native#text/plain
compiler/i386/r386att.inc svneol=native#text/plain
compiler/i386/r386con.inc svneol=native#text/plain

View File

@ -40,7 +40,7 @@ Unit aopt;
Constructor create(_AsmL: TAsmList); virtual; reintroduce;
{ call the necessary optimizer procedures }
Procedure Optimize;
Procedure Optimize;virtual;
Destructor destroy;override;
private
@ -50,6 +50,7 @@ Unit aopt;
Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
Procedure BuildLabelTableAndFixRegAlloc;
procedure clear;
protected
procedure pass_1;
End;
TAsmOptimizerClass = class of TAsmOptimizer;

View File

@ -339,10 +339,10 @@ Unit AoptObj;
procedure RemoveDelaySlot(hp1: tai);
{ peephole optimizer }
procedure PrePeepHoleOpts;
procedure PeepHoleOptPass1;
procedure PrePeepHoleOpts; virtual;
procedure PeepHoleOptPass1; virtual;
procedure PeepHoleOptPass2; virtual;
procedure PostPeepHoleOpts;
procedure PostPeepHoleOpts; virtual;
{ processor dependent methods }
// if it returns true, perform a "continue"

View File

@ -1,118 +0,0 @@
{
Copyright (c) 1998-2002 by Jonas Maebe
This unit calls the optimization procedures to optimize the assembler
code for i386+
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 aopt386;
{$i fpcdefs.inc}
Interface
Uses
aasmbase,aasmtai,aasmdata,aasmcpu;
Procedure Optimize(AsmL: TAsmList);
Implementation
Uses
globtype,
globals,
DAOpt386,POpt386;
Procedure Optimize(AsmL: TAsmList);
Var
BlockStart, BlockEnd, HP: Tai;
pass: longint;
slowopt, changed, lastLoop: boolean;
Begin
slowopt := (cs_opt_level3 in current_settings.optimizerswitches);
pass := 0;
changed := false;
dfa := TDFAObj.create(asml);
repeat
lastLoop :=
not(slowopt) or
(not changed and (pass > 2)) or
{ prevent endless loops }
(pass = 4);
changed := false;
{ Setup labeltable, always necessary }
blockstart := tai(asml.first);
blockend := dfa.pass_1(blockstart);
{ Blockend now either contains an ait_marker with Kind = mark_AsmBlockStart, }
{ or nil }
While Assigned(BlockStart) Do
Begin
if (cs_opt_peephole in current_settings.optimizerswitches) then
begin
if (pass = 0) then
PrePeepHoleOpts(AsmL, BlockStart, BlockEnd);
{ Peephole optimizations }
PeepHoleOptPass1(AsmL, BlockStart, BlockEnd);
{ Only perform them twice in the first pass }
if pass = 0 then
PeepHoleOptPass1(AsmL, BlockStart, BlockEnd);
end;
{ More peephole optimizations }
if (cs_opt_peephole in current_settings.optimizerswitches) then
begin
PeepHoleOptPass2(AsmL, BlockStart, BlockEnd);
if lastLoop then
PostPeepHoleOpts(AsmL, BlockStart, BlockEnd);
end;
{ Free memory }
dfa.clear;
{ Continue where we left off, BlockEnd is either the start of an }
{ assembler block or nil }
BlockStart := BlockEnd;
While Assigned(BlockStart) And
(BlockStart.typ = ait_Marker) And
(Tai_Marker(BlockStart).Kind = mark_AsmBlockStart) Do
Begin
{ We stopped at an assembler block, so skip it }
Repeat
BlockStart := Tai(BlockStart.Next);
Until (BlockStart.Typ = Ait_Marker) And
(Tai_Marker(Blockstart).Kind = mark_AsmBlockEnd);
{ Blockstart now contains a Tai_marker(mark_AsmBlockEnd) }
If GetNextInstruction(BlockStart, HP) And
((HP.typ <> ait_Marker) Or
(Tai_Marker(HP).Kind <> mark_AsmBlockStart)) Then
{ There is no assembler block anymore after the current one, so }
{ optimize the next block of "normal" instructions }
BlockEnd := dfa.pass_1(blockstart)
{ Otherwise, skip the next assembler block }
else
blockStart := hp;
End;
End;
inc(pass);
until lastLoop;
dfa.free;
End;
End.

File diff suppressed because it is too large Load Diff

113
compiler/i386/aoptcpub.pas Normal file
View File

@ -0,0 +1,113 @@
{
Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
Development Team
This unit contains several types and constants necessary for the
optimizer to work on the sparc architecture
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 aoptcpub; { Assembler OPTimizer CPU specific Base }
{$i fpcdefs.inc}
{ enable the following define if memory references can have a scaled index }
{ define RefsHaveScale}
{ enable the following define if memory references can have a segment }
{ override }
{ define RefsHaveSegment}
Interface
Uses
cpubase,aasmcpu,AOptBase;
Type
{ type of a normal instruction }
TInstr = Taicpu;
PInstr = ^TInstr;
{ ************************************************************************* }
{ **************************** TCondRegs ********************************** }
{ ************************************************************************* }
{ Info about the conditional registers }
TCondRegs = Object
Constructor Init;
Destructor Done;
End;
{ ************************************************************************* }
{ **************************** TAoptBaseCpu ******************************* }
{ ************************************************************************* }
TAoptBaseCpu = class(TAoptBase)
End;
{ ************************************************************************* }
{ ******************************* Constants ******************************* }
{ ************************************************************************* }
Const
{ the maximum number of things (registers, memory, ...) a single instruction }
{ changes }
MaxCh = 3;
{ the maximum number of operands an instruction has }
MaxOps = 3;
{Oper index of operand that contains the source (reference) with a load }
{instruction }
LoadSrc = 0;
{Oper index of operand that contains the destination (register) with a load }
{instruction }
LoadDst = 1;
{Oper index of operand that contains the source (register) with a store }
{instruction }
StoreSrc = 0;
{Oper index of operand that contains the destination (reference) with a load }
{instruction }
StoreDst = 1;
aopt_uncondjmp = A_JMP;
aopt_condjmp = A_Jcc;
Implementation
{ ************************************************************************* }
{ **************************** TCondRegs ********************************** }
{ ************************************************************************* }
Constructor TCondRegs.init;
Begin
End;
Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
Begin
End;
End.

View File

@ -0,0 +1,36 @@
{
Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
Development Team
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 aoptcpud;
{$i fpcdefs.inc}
interface
uses
aoptda;
type
TAOptDFACpu = class(TAOptDFA)
end;
implementation
end.

File diff suppressed because it is too large Load Diff

View File

@ -133,11 +133,7 @@ implementation
,cpuinfo
{$endif arm}
{$ifndef NOOPT}
{$ifdef i386}
,aopt386
{$else i386}
,aopt
{$endif i386}
,aopt
{$endif}
;

View File

@ -31,7 +31,13 @@ unit aoptx86;
globtype,
cpubase,
aasmtai,
cgbase,cgutils;
cgbase,cgutils,
aopt;
type
TX86AsmOptimizer = class(TAsmOptimizer)
function RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean; override;
end;
function MatchInstruction(const instr: tai; const op: TAsmOp; const opsize: topsizes): boolean;
function MatchInstruction(const instr: tai; const op1,op2: TAsmOp; const opsize: topsizes): boolean;
@ -147,5 +153,40 @@ unit aoptx86;
(taicpu(instr).oper[1]^.typ=ot1);
end;
function TX86AsmOptimizer.RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;
var
p: taicpu;
begin
if not assigned(hp) or
(hp.typ <> ait_instruction) then
begin
Result := false;
exit;
end;
p := taicpu(hp);
Result :=
(((p.opcode = A_MOV) or
(p.opcode = A_MOVZX) or
(p.opcode = A_MOVSX) or
(p.opcode = A_LEA) or
(p.opcode = A_VMOVSS) or
(p.opcode = A_VMOVSD) or
(p.opcode = A_VMOVQ) or
(p.opcode = A_MOVSS) or
(p.opcode = A_MOVSD) or
(p.opcode = A_MOVQ)) and
(p.oper[1]^.typ = top_reg) and
(getsupreg(p.oper[1]^.reg) = getsupreg(reg)) and
((p.oper[0]^.typ = top_const) or
((p.oper[0]^.typ = top_reg) and
(getsupreg(p.oper[0]^.reg) <> getsupreg(reg))) or
((p.oper[0]^.typ = top_ref) and
not RegInRef(reg,p.oper[0]^.ref^)))) or
((p.opcode = A_POP) and
(getsupreg(p.oper[0]^.reg) = getsupreg(reg)));
end;
end.

View File

@ -27,12 +27,11 @@ unit aoptcpu;
interface
uses cgbase, cpubase, aasmtai, aopt, aoptcpub;
uses cgbase, cpubase, aasmtai, aopt, aoptx86, aoptcpub;
type
TCpuAsmOptimizer = class(TAsmOptimizer)
TCpuAsmOptimizer = class(TX86AsmOptimizer)
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
function RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean; override;
end;
implementation
@ -44,7 +43,6 @@ uses
cgutils,
aoptobj,
aasmbase, aasmdata, aasmcpu,
aoptx86,
itcpugas;
function isFoldableArithOp(hp1: taicpu; reg: tregister): boolean;
@ -66,40 +64,6 @@ begin
end;
function TCpuAsmOptimizer.RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;
var
p: taicpu;
begin
if not assigned(hp) or
(hp.typ <> ait_instruction) then
begin
Result := false;
exit;
end;
p := taicpu(hp);
Result :=
(((p.opcode = A_MOV) or
(p.opcode = A_MOVZX) or
(p.opcode = A_MOVSX) or
(p.opcode = A_LEA) or
(p.opcode = A_VMOVSS) or
(p.opcode = A_VMOVSD) or
(p.opcode = A_VMOVQ) or
(p.opcode = A_MOVSS) or
(p.opcode = A_MOVSD) or
(p.opcode = A_MOVQ)) and
(p.oper[1]^.typ = top_reg) and
(getsupreg(p.oper[1]^.reg) = getsupreg(reg)) and
((p.oper[0]^.typ = top_const) or
((p.oper[0]^.typ = top_reg) and
(getsupreg(p.oper[0]^.reg) <> getsupreg(reg))) or
((p.oper[0]^.typ = top_ref) and
not RegInRef(reg,p.oper[0]^.ref^)))) or
((p.opcode = A_POP) and
(getsupreg(p.oper[0]^.reg) = getsupreg(reg)));
end;
function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
var
hp1, hp2: tai;