* 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/i386/readme.txt svneol=native#text/plain
compiler/html/powerpc/readme.txt svneol=native#text/plain compiler/html/powerpc/readme.txt svneol=native#text/plain
compiler/htypechk.pas 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/cgcpu.pas svneol=native#text/plain
compiler/i386/cpubase.inc svneol=native#text/plain compiler/i386/cpubase.inc svneol=native#text/plain
compiler/i386/cpuelf.pas 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/cpupara.pas svneol=native#text/plain
compiler/i386/cpupi.pas svneol=native#text/plain compiler/i386/cpupi.pas svneol=native#text/plain
compiler/i386/cputarg.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/hlcgcpu.pas svneol=native#text/plain
compiler/i386/i386att.inc svneol=native#text/plain compiler/i386/i386att.inc svneol=native#text/plain
compiler/i386/i386atts.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/n386mat.pas svneol=native#text/plain
compiler/i386/n386mem.pas svneol=native#text/plain compiler/i386/n386mem.pas svneol=native#text/plain
compiler/i386/n386set.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/r386ari.inc svneol=native#text/plain
compiler/i386/r386att.inc svneol=native#text/plain compiler/i386/r386att.inc svneol=native#text/plain
compiler/i386/r386con.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; Constructor create(_AsmL: TAsmList); virtual; reintroduce;
{ call the necessary optimizer procedures } { call the necessary optimizer procedures }
Procedure Optimize; Procedure Optimize;virtual;
Destructor destroy;override; Destructor destroy;override;
private private
@ -50,6 +50,7 @@ Unit aopt;
Also fixes some RegDeallocs like "# %eax released; push (%eax)" } Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
Procedure BuildLabelTableAndFixRegAlloc; Procedure BuildLabelTableAndFixRegAlloc;
procedure clear; procedure clear;
protected
procedure pass_1; procedure pass_1;
End; End;
TAsmOptimizerClass = class of TAsmOptimizer; TAsmOptimizerClass = class of TAsmOptimizer;

View File

@ -339,10 +339,10 @@ Unit AoptObj;
procedure RemoveDelaySlot(hp1: tai); procedure RemoveDelaySlot(hp1: tai);
{ peephole optimizer } { peephole optimizer }
procedure PrePeepHoleOpts; procedure PrePeepHoleOpts; virtual;
procedure PeepHoleOptPass1; procedure PeepHoleOptPass1; virtual;
procedure PeepHoleOptPass2; virtual; procedure PeepHoleOptPass2; virtual;
procedure PostPeepHoleOpts; procedure PostPeepHoleOpts; virtual;
{ processor dependent methods } { processor dependent methods }
// if it returns true, perform a "continue" // 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 ,cpuinfo
{$endif arm} {$endif arm}
{$ifndef NOOPT} {$ifndef NOOPT}
{$ifdef i386} ,aopt
,aopt386
{$else i386}
,aopt
{$endif i386}
{$endif} {$endif}
; ;

View File

@ -31,7 +31,13 @@ unit aoptx86;
globtype, globtype,
cpubase, cpubase,
aasmtai, 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 op: TAsmOp; const opsize: topsizes): boolean;
function MatchInstruction(const instr: tai; const op1,op2: 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); (taicpu(instr).oper[1]^.typ=ot1);
end; 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. end.

View File

@ -27,12 +27,11 @@ unit aoptcpu;
interface interface
uses cgbase, cpubase, aasmtai, aopt, aoptcpub; uses cgbase, cpubase, aasmtai, aopt, aoptx86, aoptcpub;
type type
TCpuAsmOptimizer = class(TAsmOptimizer) TCpuAsmOptimizer = class(TX86AsmOptimizer)
function PeepHoleOptPass1Cpu(var p: tai): boolean; override; function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
function RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean; override;
end; end;
implementation implementation
@ -44,7 +43,6 @@ uses
cgutils, cgutils,
aoptobj, aoptobj,
aasmbase, aasmdata, aasmcpu, aasmbase, aasmdata, aasmcpu,
aoptx86,
itcpugas; itcpugas;
function isFoldableArithOp(hp1: taicpu; reg: tregister): boolean; function isFoldableArithOp(hp1: taicpu; reg: tregister): boolean;
@ -66,40 +64,6 @@ begin
end; 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; function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
var var
hp1, hp2: tai; hp1, hp2: tai;