View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0036353 | FPC | Compiler | public | 2019-11-25 00:50 | 2019-11-26 23:10 |
Reporter | J. Gareth Moreton | Assigned To | Florian | ||
Priority | low | Severity | minor | Reproducibility | N/A |
Status | resolved | Resolution | fixed | ||
Platform | Cross-platform | OS | Microsoft Windows | OS Version | 10 Professional |
Product Version | 3.3.1 | Product Build | r43582 | ||
Target Version | Fixed in Version | 3.3.1 | |||
Summary | 0036353: [Refactor] Peephole Semantics | ||||
Description | This patch, mentioned briefly in the core mailing list, seeks to improve maintainability, safety and efficiency in the peephole optimizer by slightly modifying some function headers based on their intended purpose. See "Additional Information" for a complete list. Code generatd by the compiler should be completely identical. | ||||
Steps To Reproduce | Apply patch and confirm correct compilation on all platforms. | ||||
Additional Information | - Non-virtual methods and class methods that don't need to access any fields from the current object are now static methods, thus removing the hidden "Self" parameter and reducing overhead. This includes a large number of frequently-used functions such as SkipEntryExitMarker and SuperRegistersEqual. - GetNextInstruction, GetLastInstruction, SkipEntryExitMarker and SkipLabels have had their 'var' parameter changed to an 'out' parameter because they shouldn't depend on its input value. This will cause the compiler to throw warnings if you start using the value without initialising it first, and may open up optimisation opportunities in the future (e.g. storing written values in a temporary register and only writing it to the actual variable when the routine exits). | ||||
Tags | compiler, optimizations, patch, refactor | ||||
Fixed in Revision | 43595 | ||||
FPCOldBugId | |||||
FPCTarget | - | ||||
Attached Files |
|
|
peephole_semantics.patch (13,766 bytes)
Index: compiler/aoptbase.pas =================================================================== --- compiler/aoptbase.pas (revision 43561) +++ compiler/aoptbase.pas (working copy) @@ -49,9 +49,9 @@ { returns true if register Reg is used by instruction p1 } Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;virtual; { returns true if register Reg occurs in operand op } - Function RegInOp(Reg: TRegister; const op: toper): Boolean; + class function RegInOp(Reg: TRegister; const op: toper): Boolean; static; { returns true if register Reg is used in the reference Ref } - Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean; + class function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean; static; function RegModifiedByInstruction(Reg: TRegister; p1: tai): boolean;virtual; @@ -61,13 +61,13 @@ { gets the next tai object after current that contains info relevant } { to the optimizer in p1. If there is none, it returns false and } { sets p1 to nil } - class Function GetNextInstruction(Current: tai; Var Next: tai): Boolean; - { gets the previous tai object after current that contains info } - { relevant to the optimizer in last. If there is none, it retuns } - { false and sets last to nil } - Function GetLastInstruction(Current: tai; Var Last: tai): Boolean; + class function GetNextInstruction(Current: tai; out Next: tai): Boolean; static; + { gets the previous tai object after current that contains info } + { relevant to the optimizer in last. If there is none, it returns } + { false and sets last to nil } + class function GetLastInstruction(Current: tai; out Last: tai): Boolean; static; - function SkipEntryExitMarker(current: tai; var next: tai): boolean; + class function SkipEntryExitMarker(current: tai; out next: tai): boolean; static; { processor dependent methods } @@ -104,10 +104,10 @@ { compares reg1 and reg2 having the same type and being the same super registers so the register size is neglected } - function SuperRegistersEqual(reg1,reg2 : TRegister) : Boolean;{$ifdef USEINLINE}inline;{$endif} + class function SuperRegistersEqual(reg1,reg2 : TRegister) : Boolean; static; {$ifdef USEINLINE}inline;{$endif} end; - function labelCanBeSkipped(p: tai_label): boolean; + function labelCanBeSkipped(p: tai_label): boolean; {$ifdef USEINLINE}inline;{$endif} implementation @@ -140,7 +140,7 @@ End; - Function TAOptBase.RegInOp(Reg: TRegister; const op: toper): Boolean; + class function TAOptBase.RegInOp(Reg: TRegister; const op: toper): Boolean; Begin Case op.typ Of Top_Reg: RegInOp := SuperRegistersEqual(Reg,op.reg); @@ -154,7 +154,7 @@ End; - Function TAOptBase.RegInRef(Reg: TRegister; Const Ref: TReference): Boolean; + class function TAOptBase.RegInRef(Reg: TRegister; Const Ref: TReference): Boolean; Begin RegInRef := SuperRegistersEqual(Ref.Base,Reg) {$ifdef cpurefshaveindexreg} @@ -176,13 +176,13 @@ End; - function labelCanBeSkipped(p: tai_label): boolean; inline; + function labelCanBeSkipped(p: tai_label): boolean; {$ifdef USEINLINE}inline;{$endif} begin labelCanBeSkipped := not(p.labsym.is_used) or (p.labsym.labeltype<>alt_jump); end; - class Function TAOptBase.GetNextInstruction(Current: tai; Var Next: tai): Boolean; + class function TAOptBase.GetNextInstruction(Current: tai; out Next: tai): Boolean; Begin Repeat Current := tai(Current.Next); @@ -221,7 +221,7 @@ End; End; - Function TAOptBase.GetLastInstruction(Current: tai; Var Last: tai): Boolean; + class function TAOptBase.GetLastInstruction(Current: tai; out Last: tai): Boolean; Begin Repeat Current := Tai(Current.previous); @@ -263,7 +263,7 @@ End; - function TAOptBase.SkipEntryExitMarker(current: tai; var next: tai): boolean; + class function TAOptBase.SkipEntryExitMarker(current: tai; out next: tai): boolean; begin result:=true; if current.typ<>ait_marker then @@ -316,7 +316,7 @@ end; - function TAOptBase.SuperRegistersEqual(reg1,reg2 : TRegister) : Boolean;{$ifdef USEINLINE}inline;{$endif} + class function TAOptBase.SuperRegistersEqual(reg1,reg2 : TRegister) : Boolean;{$ifdef USEINLINE}inline;{$endif} Begin { Do an optimized version of Index: compiler/aoptobj.pas =================================================================== --- compiler/aoptobj.pas (revision 43561) +++ compiler/aoptobj.pas (working copy) @@ -201,13 +201,13 @@ { returns whether the reference Ref is used somewhere in the loading } { sequence Content } - Function RefInSequence(Const Ref: TReference; Content: TContent; - RefsEq: TRefCompare): Boolean; + class function RefInSequence(Const Ref: TReference; Content: TContent; + RefsEq: TRefCompare): Boolean; static; { returns whether the instruction P reads from and/or writes } { to Reg } - Function RefInInstruction(Const Ref: TReference; p: Tai; - RefsEq: TRefCompare): Boolean; + class function RefInInstruction(Const Ref: TReference; p: Tai; + RefsEq: TRefCompare): Boolean; static; { returns whether two references with at least one pointing to an array } { may point to the same memory location } @@ -272,7 +272,7 @@ Procedure CreateUsedRegs(var regs: TAllUsedRegs); Procedure ClearUsedRegs; Procedure UpdateUsedRegs(p : Tai); - class procedure UpdateUsedRegs(var Regs: TAllUsedRegs; p: Tai); + class procedure UpdateUsedRegs(var Regs: TAllUsedRegs; p: Tai); static; { If UpdateUsedRegsAndOptimize has read ahead, the result is one before the next valid entry (so "p.Next" returns what's expected). If no @@ -282,16 +282,16 @@ Function CopyUsedRegs(var dest : TAllUsedRegs) : boolean; procedure RestoreUsedRegs(const Regs : TAllUsedRegs); procedure TransferUsedRegs(var dest: TAllUsedRegs); - class Procedure ReleaseUsedRegs(const regs : TAllUsedRegs); - class Function RegInUsedRegs(reg : TRegister;regs : TAllUsedRegs) : boolean; - class Procedure IncludeRegInUsedRegs(reg : TRegister;var regs : TAllUsedRegs); - class Procedure ExcludeRegFromUsedRegs(reg: TRegister;var regs : TAllUsedRegs); + class procedure ReleaseUsedRegs(const regs : TAllUsedRegs); static; + class function RegInUsedRegs(reg : TRegister;regs : TAllUsedRegs) : boolean; static; + class procedure IncludeRegInUsedRegs(reg : TRegister;var regs : TAllUsedRegs); static; + class procedure ExcludeRegFromUsedRegs(reg: TRegister;var regs : TAllUsedRegs); static; - Function GetAllocationString(const regs : TAllUsedRegs) : string; + class function GetAllocationString(const regs : TAllUsedRegs) : string; static; { returns true if the label L is found between hp and the next } { instruction } - Function FindLabel(L: TasmLabel; Var hp: Tai): Boolean; + class function FindLabel(L: TasmLabel; Var hp: Tai): Boolean; static; { inserts new_one between prev and foll in AsmL } Procedure InsertLLItem(prev, foll, new_one: TLinkedListItem); @@ -299,10 +299,10 @@ { If P is a Tai object releveant to the optimizer, P is returned If it is not relevant tot he optimizer, the first object after P that is relevant is returned } - Function SkipHead(P: Tai): Tai; + class function SkipHead(P: Tai): Tai; static; { returns true if the operands o1 and o2 are completely equal } - Function OpsEqual(const o1,o2:toper): Boolean; + class function OpsEqual(const o1,o2:toper): Boolean; static; { Returns the next ait_alloc object with ratype ra_alloc for Reg is found in the block @@ -310,7 +310,7 @@ instruction. If none is found, it returns nil } - Function FindRegAlloc(Reg: TRegister; StartPai: Tai): tai_regalloc; + class function FindRegAlloc(Reg: TRegister; StartPai: Tai): tai_regalloc; static; { Returns the last ait_alloc object with ratype ra_alloc for Reg is found in the block @@ -318,7 +318,7 @@ instruction. If none is found, it returns nil } - Function FindRegAllocBackward(Reg : TRegister; StartPai : Tai) : tai_regalloc; + class function FindRegAllocBackward(Reg : TRegister; StartPai : Tai) : tai_regalloc; static; { Returns the next ait_alloc object with ratype ra_dealloc @@ -325,7 +325,7 @@ for Reg which is found in the block of Tai's starting with StartPai and ending with the next "real" instruction. If none is found, it returns nil } - Function FindRegDeAlloc(Reg: TRegister; StartPai: Tai): tai_regalloc; + class function FindRegDeAlloc(Reg: TRegister; StartPai: Tai): tai_regalloc; static; { allocates register reg between (and including) instructions p1 and p2 the type of p1 and p2 must not be in SkipInstr } @@ -890,7 +890,7 @@ Else s := 0 End; - Function TPaiProp.RefInInstruction(Const Ref: TReference; p: Tai; + class Function TPaiProp.RefInInstruction(Const Ref: TReference; p: Tai; RefsEq: TRefCompare): Boolean; Var Count: AWord; TmpResult: Boolean; @@ -908,7 +908,7 @@ RefInInstruction := TmpResult; End; - Function TPaiProp.RefInSequence(Const Ref: TReference; Content: TContent; + class function TPaiProp.RefInSequence(Const Ref: TReference; Content: TContent; RefsEq: TRefCompare): Boolean; Var p: Tai; Counter: Byte; @@ -1161,7 +1161,7 @@ end; - function TAOptObj.GetAllocationString(const regs: TAllUsedRegs): string; + class function TAOptObj.GetAllocationString(const regs: TAllUsedRegs): string; var i : TRegisterType; j : TSuperRegister; @@ -1173,7 +1173,7 @@ end; - Function TAOptObj.FindLabel(L: TasmLabel; Var hp: Tai): Boolean; + class function TAOptObj.FindLabel(L: TasmLabel; Var hp: Tai): Boolean; Var TempP: Tai; Begin TempP := hp; @@ -1213,7 +1213,7 @@ End; - Function TAOptObj.SkipHead(P: Tai): Tai; + class function TAOptObj.SkipHead(P: Tai): Tai; Var OldP: Tai; Begin Repeat @@ -1239,7 +1239,7 @@ SkipHead := P; End; - Function TAOptObj.OpsEqual(const o1,o2:toper): Boolean; + class function TAOptObj.OpsEqual(const o1,o2:toper): Boolean; Begin if o1.typ=o2.typ then Case o1.typ Of @@ -1261,7 +1261,7 @@ End; - Function TAOptObj.FindRegAlloc(Reg: TRegister; StartPai: Tai): tai_regalloc; + class function TAOptObj.FindRegAlloc(Reg: TRegister; StartPai: Tai): tai_regalloc; Begin Result:=nil; Repeat @@ -1291,7 +1291,7 @@ End; - Function TAOptObj.FindRegAllocBackward(Reg: TRegister; StartPai: Tai): tai_regalloc; + class function TAOptObj.FindRegAllocBackward(Reg: TRegister; StartPai: Tai): tai_regalloc; Begin Result:=nil; Repeat @@ -1317,7 +1317,7 @@ End; - function TAOptObj.FindRegDeAlloc(Reg: TRegister; StartPai: Tai): tai_regalloc; + class function TAOptObj.FindRegDeAlloc(Reg: TRegister; StartPai: Tai): tai_regalloc; Begin Result:=nil; Repeat Index: compiler/aoptutils.pas =================================================================== --- compiler/aoptutils.pas (revision 43561) +++ compiler/aoptutils.pas (working copy) @@ -36,7 +36,7 @@ {$endif max_operands>2} { skips all labels and returns the next "real" instruction } - function SkipLabels(hp: tai; var hp2: tai): boolean; + function SkipLabels(hp: tai; out hp2: tai): boolean; { sets hp2 to hp and returns True if hp is not nil } function SetAndTest(const hp: tai; out hp2: tai): Boolean; @@ -68,7 +68,7 @@ { skips all labels and returns the next "real" instruction } - function SkipLabels(hp: tai; var hp2: tai): boolean; + function SkipLabels(hp: tai; out hp2: tai): boolean; begin while assigned(hp.next) and (tai(hp.next).typ in SkipInstr + [ait_label,ait_align]) Do Index: compiler/x86/aoptx86.pas =================================================================== --- compiler/x86/aoptx86.pas (revision 43561) +++ compiler/x86/aoptx86.pas (working copy) @@ -52,8 +52,8 @@ procedure DebugMsg(const s : string; p : tai);inline; - class function IsExitCode(p : tai) : boolean; - class function isFoldableArithOp(hp1 : taicpu; reg : tregister) : boolean; + class function IsExitCode(p : tai) : boolean; static; + class function isFoldableArithOp(hp1 : taicpu; reg : tregister) : boolean; static; procedure RemoveLastDeallocForFuncRes(p : tai); function DoSubAddOpt(var p : tai) : Boolean; |
|
Thanks, applied. |
Date Modified | Username | Field | Change |
---|---|---|---|
2019-11-25 00:50 | J. Gareth Moreton | New Issue | |
2019-11-25 00:50 | J. Gareth Moreton | File Added: peephole_semantics.patch | |
2019-11-25 00:51 | J. Gareth Moreton | Priority | normal => low |
2019-11-25 00:51 | J. Gareth Moreton | FPCTarget | => - |
2019-11-25 00:52 | J. Gareth Moreton | Description Updated | View Revisions |
2019-11-25 00:53 | J. Gareth Moreton | Description Updated | View Revisions |
2019-11-25 01:05 | J. Gareth Moreton | Tag Attached: patch | |
2019-11-25 01:05 | J. Gareth Moreton | Tag Attached: compiler | |
2019-11-25 01:05 | J. Gareth Moreton | Tag Attached: optimizations | |
2019-11-25 01:05 | J. Gareth Moreton | Tag Attached: refactor | |
2019-11-26 23:10 | Florian | Assigned To | => Florian |
2019-11-26 23:10 | Florian | Status | new => resolved |
2019-11-26 23:10 | Florian | Resolution | open => fixed |
2019-11-26 23:10 | Florian | Fixed in Version | => 3.3.1 |
2019-11-26 23:10 | Florian | Fixed in Revision | => 43595 |
2019-11-26 23:10 | Florian | Note Added: 0119519 |