mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-10 02:28:22 +02:00
* 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:
parent
4ac3953c34
commit
3c2dab9878
6
.gitattributes
vendored
6
.gitattributes
vendored
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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
113
compiler/i386/aoptcpub.pas
Normal 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.
|
36
compiler/i386/aoptcpud.pas
Normal file
36
compiler/i386/aoptcpud.pas
Normal 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
@ -133,11 +133,7 @@ implementation
|
||||
,cpuinfo
|
||||
{$endif arm}
|
||||
{$ifndef NOOPT}
|
||||
{$ifdef i386}
|
||||
,aopt386
|
||||
{$else i386}
|
||||
,aopt
|
||||
{$endif i386}
|
||||
,aopt
|
||||
{$endif}
|
||||
;
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user