diff --git a/.gitattributes b/.gitattributes index bcd4d60c30..03a8e3b093 100644 --- a/.gitattributes +++ b/.gitattributes @@ -804,6 +804,7 @@ compiler/x86/aasmcpu.pas svneol=native#text/plain compiler/x86/agx86att.pas svneol=native#text/plain compiler/x86/agx86int.pas svneol=native#text/plain compiler/x86/agx86nsm.pas svneol=native#text/plain +compiler/x86/aoptx86.pas svneol=native#text/pascal compiler/x86/cga.pas svneol=native#text/plain compiler/x86/cgx86.pas svneol=native#text/plain compiler/x86/cpubase.pas svneol=native#text/plain diff --git a/compiler/i386/daopt386.pas b/compiler/i386/daopt386.pas index cd9f1e9104..01d4b9631e 100644 --- a/compiler/i386/daopt386.pas +++ b/compiler/i386/daopt386.pas @@ -171,8 +171,6 @@ type procedure InsertLLItem(AsmL: TAsmList; prev, foll, new_one: TLinkedListItem); - -function RefsEqual(const R1, R2: TReference): Boolean; function isgp32reg(supreg: tsuperregister): Boolean; function reginref(supreg: tsuperregister; const ref: treference): boolean; function RegReadByInstruction(supreg: tsuperregister; hp: tai): boolean; @@ -270,7 +268,8 @@ Uses {$endif} {$endif} {$endif} - globals, systems, verbose, symconst, cgobj,procinfo; + globals, systems, verbose, symconst, cgobj, procinfo, + aoptx86; Type TRefCompare = function(const r1, r2: treference; size1, size2: tcgsize): boolean; @@ -679,17 +678,6 @@ begin end; -function refsequal(const r1, r2: treference): boolean; -begin - refsequal := - (r1.offset = r2.offset) and - (r1.segment = r2.segment) and (r1.base = r2.base) and - (r1.index = r2.index) and (r1.scalefactor = r2.scalefactor) and - (r1.symbol=r2.symbol) and (r1.refaddr = r2.refaddr) and - (r1.relsymbol = r2.relsymbol); -end; - - {$push} {$q-} diff --git a/compiler/i386/popt386.pas b/compiler/i386/popt386.pas index 6086a61906..f982276834 100644 --- a/compiler/i386/popt386.pas +++ b/compiler/i386/popt386.pas @@ -44,7 +44,8 @@ uses cobjects, {$endif finaldestdebug} cpuinfo,cpubase,cgutils,daopt386, - cgx86; + cgx86, + aoptx86; function isFoldableArithOp(hp1: taicpu; reg: tregister): boolean; @@ -122,7 +123,7 @@ begin (taicpu(hp1).opcode = A_FILD))) and (taicpu(hp1).oper[0]^.typ = top_ref) and (taicpu(hp1).opsize = taicpu(p).opsize) and - refsEqual(taicpu(p).oper[0]^.ref^, taicpu(hp1).oper[0]^.ref^) then + RefsEqual(taicpu(p).oper[0]^.ref^, taicpu(hp1).oper[0]^.ref^) then begin { replacing fstp f;fld f by fst f is only valid for extended because of rounding } if (taicpu(p).opsize=S_FX) and diff --git a/compiler/x86/aoptx86.pas b/compiler/x86/aoptx86.pas new file mode 100644 index 0000000000..00d238d43a --- /dev/null +++ b/compiler/x86/aoptx86.pas @@ -0,0 +1,150 @@ +{ + Copyright (c) 1998-2002 by Florian Klaempfl and Jonas Maebe + + This unit contains the peephole optimizer. + + 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 aoptx86; + +{$i fpcdefs.inc} + +{ $define DEBUG_AOPTCPU} + + interface + + uses + globtype, + cpubase, + aasmtai, + cgbase,cgutils; + + 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,op3: TAsmOp; const opsize: topsizes): boolean; + + function MatchOperand(const oper: TOper; const reg: TRegister): boolean; inline; + function MatchOperand(const oper: TOper; const a: tcgint): boolean; inline; + + function RefsEqual(const r1, r2: treference): boolean; + + function MatchReference(const ref : treference;base,index : TRegister) : Boolean; + + function MatchOpType(const instr : tai;ot0,ot1 : toptype) : Boolean; + + implementation + + uses + verbose, + aasmcpu; + + function MatchInstruction(const instr: tai; const op: TAsmOp; const opsize: topsizes): boolean; + begin + result := + (instr.typ = ait_instruction) and + (taicpu(instr).opcode = op) and + ((opsize = []) or (taicpu(instr).opsize in opsize)); + end; + + + function MatchInstruction(const instr: tai; const op1,op2: TAsmOp; const opsize: topsizes): boolean; + begin + result := + (instr.typ = ait_instruction) and + ((taicpu(instr).opcode = op1) or + (taicpu(instr).opcode = op2) + ) and + ((opsize = []) or (taicpu(instr).opsize in opsize)); + end; + + + function MatchInstruction(const instr: tai; const op1,op2,op3: TAsmOp; const opsize: topsizes): boolean; + begin + result := + (instr.typ = ait_instruction) and + ((taicpu(instr).opcode = op1) or + (taicpu(instr).opcode = op2) or + (taicpu(instr).opcode = op3) + ) and + ((opsize = []) or (taicpu(instr).opsize in opsize)); + end; + + + function MatchOperand(const oper: TOper; const reg: TRegister): boolean; inline; + begin + result := (oper.typ = top_reg) and (oper.reg = reg); + end; + + + function MatchOperand(const oper: TOper; const a: tcgint): boolean; inline; + begin + result := (oper.typ = top_const) and (oper.val = a); + end; + + + function MatchOperand(const oper1: TOper; const oper2: TOper): boolean; inline; + begin + result := oper1.typ = oper2.typ; + + if result then + case oper1.typ of + top_const: + Result:=oper1.val = oper2.val; + top_reg: + Result:=oper1.reg = oper2.reg; + top_ref: + Result:=RefsEqual(oper1.ref^, oper2.ref^); + else + internalerror(2013102801); + end + end; + + + function RefsEqual(const r1, r2: treference): boolean; + begin + RefsEqual := + (r1.offset = r2.offset) and + (r1.segment = r2.segment) and (r1.base = r2.base) and + (r1.index = r2.index) and (r1.scalefactor = r2.scalefactor) and + (r1.symbol=r2.symbol) and (r1.refaddr = r2.refaddr) and + (r1.relsymbol = r2.relsymbol); + end; + + + function MatchReference(const ref : treference;base,index : TRegister) : Boolean; + begin + Result:=(ref.offset=0) and + (ref.scalefactor in [0,1]) and + (ref.segment=NR_NO) and + (ref.symbol=nil) and + (ref.relsymbol=nil) and + ((base=NR_INVALID) or + (ref.base=base)) and + ((index=NR_INVALID) or + (ref.index=index)); + end; + + + function MatchOpType(const instr : tai;ot0,ot1 : toptype) : Boolean; + begin + Result:=(taicpu(instr).ops=2) and + (taicpu(instr).oper[0]^.typ=ot0) and + (taicpu(instr).oper[1]^.typ=ot1); + end; + +end. + diff --git a/compiler/x86_64/aoptcpu.pas b/compiler/x86_64/aoptcpu.pas index b6df4eedf2..3f5acf937f 100644 --- a/compiler/x86_64/aoptcpu.pas +++ b/compiler/x86_64/aoptcpu.pas @@ -43,6 +43,7 @@ uses cgbase, cgutils, aoptobj, aasmbase, aasmdata, aasmcpu, + aoptx86, itcpugas; function isFoldableArithOp(hp1: taicpu; reg: tregister): boolean; @@ -64,93 +65,6 @@ begin end; -function MatchInstruction(const instr: tai; const op: TAsmOp; const opsize: topsizes): boolean; - begin - result := - (instr.typ = ait_instruction) and - (taicpu(instr).opcode = op) and - ((opsize = []) or (taicpu(instr).opsize in opsize)); - end; - - -function MatchInstruction(const instr: tai; const op1,op2: TAsmOp; const opsize: topsizes): boolean; - begin - result := - (instr.typ = ait_instruction) and - ((taicpu(instr).opcode = op1) or - (taicpu(instr).opcode = op2) - ) and - ((opsize = []) or (taicpu(instr).opsize in opsize)); - end; - - -function MatchInstruction(const instr: tai; const op1,op2,op3: TAsmOp; const opsize: topsizes): boolean; - begin - result := - (instr.typ = ait_instruction) and - ((taicpu(instr).opcode = op1) or - (taicpu(instr).opcode = op2) or - (taicpu(instr).opcode = op3) - ) and - ((opsize = []) or (taicpu(instr).opsize in opsize)); - end; - - -function MatchOperand(const oper: TOper; const reg: TRegister): boolean; inline; - begin - result := (oper.typ = top_reg) and (oper.reg = reg); - end; - - -function MatchOperand(const oper: TOper; const a: tcgint): boolean; inline; - begin - result := (oper.typ = top_const) and (oper.val = a); - end; - -function refsequal(const r1, r2: treference): boolean; - begin - refsequal := - (r1.offset = r2.offset) and - (r1.segment = r2.segment) and (r1.base = r2.base) and - (r1.index = r2.index) and (r1.scalefactor = r2.scalefactor) and - (r1.symbol=r2.symbol) and (r1.refaddr = r2.refaddr) and - (r1.relsymbol = r2.relsymbol); - end; - - -function MatchOperand(const oper1: TOper; const oper2: TOper): boolean; inline; - begin - result := oper1.typ = oper2.typ; - - if result then - case oper1.typ of - top_const: - Result:=oper1.val = oper2.val; - top_reg: - Result:=oper1.reg = oper2.reg; - top_ref: - Result:=RefsEqual(oper1.ref^, oper2.ref^); - else - internalerror(2013102801); - end - end; - - -function MatchReference(const ref : treference;base,index : TRegister) : Boolean; - begin - Result:=(ref.offset=0) and - (ref.scalefactor in [0,1]) and - (ref.segment=NR_NO) and - (ref.symbol=nil) and - (ref.relsymbol=nil) and - ((base=NR_INVALID) or - (ref.base=base)) and - ((index=NR_INVALID) or - (ref.index=index)); - end; - - - function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean; var hp1, hp2: tai;