From fccf4109e03a4da0037ad83fdd4cf2407453b67e Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sun, 20 Sep 1998 17:12:35 +0000 Subject: [PATCH] * small fix for uncertain optimizations & more cleaning up --- compiler/csopt386.pas | 106 ++++--------------- compiler/daopt386.pas | 230 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 206 insertions(+), 130 deletions(-) diff --git a/compiler/csopt386.pas b/compiler/csopt386.pas index 0cfd61622c..10b5976ff0 100644 --- a/compiler/csopt386.pas +++ b/compiler/csopt386.pas @@ -44,108 +44,30 @@ Function CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint): Boolean; Found holds the number of instructions between StartMod and EndMod and false is returned} Var hp2, hp3, EndMod: Pai; - TmpResult: Boolean; - RegsNotYetChecked: Set Of TRegister; Counter: Byte; - - Function NoChangedRegInRef(oldp, newp: Pai): Boolean; - Var TmpP: Pai; - {checks if the first operator of newp is a reference and in that case checks - whether that reference includes regs that have been changed since oldp. This - to avoid wrong optimizations like - - movl 8(%epb), %eax movl 8(%epb), %eax - movl 12(%epb), %edx movl 12(%epb), %edx - movl (%eax,%edx,1), %edi movl (%eax,%edx,1), %edi - pushl %edi being converted to pushl %edi - movl 8(%epb), %eax movl 16(%ebp), %edx - movl 16(%epb), %edx pushl %edi - movl (%eax,%edx,1), %edi - pushl %edi - - because first is checked whether %eax isn't changed (it isn't) and - consequently all instructions containg %eax are removed} - Begin - TmpResult := True; - If (Pai(NewP)^.typ = ait_instruction) Then - Case Pai386(NewP)^.op1t Of - Top_Reg: - If (Reg32(TRegister(Pai386(NewP)^.op1)) in RegsNotYetChecked) Then - Begin - RegsNotYetChecked := RegsNotYetChecked - [Reg32(TRegister(Pai386(NewP)^.op1))]; - TmpP := NewP; - While GetLastInstruction(TmpP, TmpP) And - PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do; - TmpResult := Assigned(TmpP) And - RegsSameContent(oldp, TmpP, Reg32(TRegister(Pai386(Newp)^.op1))) - End; - Top_Ref: - With TReference(Pai386(NewP)^.op1^) Do - Begin - If (Base in RegsNotYetChecked) And - (Base <> R_NO) Then - Begin - RegsNotYetChecked := RegsNotYetChecked - [Base]; - TmpP := NewP; - While GetLastInstruction(TmpP, TmpP) And - PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do; - TmpResult := Assigned(TmpP) And - RegsSameContent(oldp, TmpP, Base) - End; - If TmpResult And - (Index <> R_NO) And - (Index in RegsNotYetChecked) Then - Begin - RegsNotYetChecked := RegsNotYetChecked - [Index]; - TmpP := NewP; - While GetLastInstruction(TmpP, TmpP) And - PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do; - TmpResult := Assigned(TmpP) And - RegsSameContent(oldp, TmpP, Index); - End; - End; - End; - NoChangedRegInRef := TmpResult; - End; - Begin {CheckSequence} Reg := Reg32(Reg); Found := 0; - GetLastInstruction(p, hp3); + hp3 := p; + While GetLastInstruction(hp3, hp3) And + PPAiProp(hp3^.fileinfo.line)^.CanBeRemoved Do; hp2 := PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].StartMod; - EndMod := PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].StartMod; + EndMod := hp2; If (PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].NrOfMods = 1) Then Counter := 1 Else For Counter := 2 to PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].NrOfMods Do GetNextInstruction(EndMod, EndMod); hp3 := p; - RegsNotYetChecked := [R_EAX..R_EDI]; While (Found <> Counter) And - InstructionsEqual(hp2, hp3) And - NoChangedRegInRef(EndMod, hp3) Do + InstructionsEqual(hp2, hp3) Do Begin - If (hp2^.typ = ait_instruction) And - (Pai386(hp2)^._operator in [a_mov, a_movsx, a_movzx]) And - (Pai386(hp2)^.op2t = top_reg) - Then RegsNotYetChecked := RegsNotYetChecked - - [Reg32(TRegister(Pai386(hp2)^.op2))]; GetNextInstruction(hp2, hp2); GetNextInstruction(hp3, hp3); Inc(Found) End; If (Found <> Counter) Then -{hack to be able to optimize - mov (mem), reg - mov (reg), reg - mov (reg), reg [*] - test reg, reg and the oposite (where the marked instructions are - jne l1 switched) - mov (mem), reg - mov (reg), reg - movzx (reg), reg [*]} - Begin If ((Found+1) = Counter) And Assigned(hp2) And @@ -159,9 +81,19 @@ Begin {CheckSequence} (Pai386(hp3)^.op1t = top_ref) And (Pai386(hp3)^.op2t = top_reg) And (Pai386(hp2)^._operator <> Pai386(hp3)^._operator) And - RefsEqual(TReference(Pai386(hp2)^.op1^),TReference(Pai386(hp3)^.op1^)) And - NoChangedRegInRef(EndMod, hp3) + RefsEqual(TReference(Pai386(hp2)^.op1^),TReference(Pai386(hp3)^.op1^)) Then + +{hack to be able to optimize + mov (mem), reg + mov (reg), reg + mov (reg), reg [*] + test reg, reg and the oposite (where the marked instructions are + jne l1 switched) + mov (mem), reg + mov (reg), reg + movzx (reg), reg [*]} + If (Pai386(hp2)^._operator = A_MOV) Then Begin @@ -392,8 +324,8 @@ End. { $Log$ - Revision 1.6 1998-09-17 21:54:21 jonas - * big error (with little consequences) corrected in NoChangedRegInRef + Revision 1.7 1998-09-20 17:12:35 jonas + * small fix for uncertain optimizations & more cleaning up Revision 1.5 1998/09/16 17:59:59 jonas * optimizer now completely dependant on GetNext/GetLast instruction, works again with -dRegAlloc diff --git a/compiler/daopt386.pas b/compiler/daopt386.pas index cda1e387cb..34f69d40df 100644 --- a/compiler/daopt386.pas +++ b/compiler/daopt386.pas @@ -59,7 +59,6 @@ Procedure ShutDownDFA; Function FindLabel(L: PLabel; Var hp: Pai): Boolean; {Procedure FindLoHiLabels(AsmL: PAasmOutput; Var LoLab, HiLab, LabDif: Longint);} - {******************************* Constants *******************************} Const @@ -71,9 +70,7 @@ Const {$ifdef GDB} ,ait_stabs, ait_stabn, ait_stab_function_name {$endif GDB} -{$ifdef regalloc} ,ait_regalloc, ait_regdealloc -{$endif regalloc} ]; {the maximum number of things (registers, memory, ...) a single instruction @@ -90,6 +87,14 @@ Const Type + TRegArray = Array[R_EAX..R_EDI] of TRegister; + TRegSet = Set of TRegister; + TRegInfo = Record + RegsEncountered: TRegSet; + SubstRegs: TRegArray; + End; + + {What an instruction can change} TChange = (C_None, C_REAX, C_RECX, C_REDX, C_REBX, C_RESP, C_REBP, C_RESI, C_REDI, @@ -190,7 +195,10 @@ Var Implementation -Uses globals, systems, strings, verbose, hcodegen; +Uses globals, systems, strings, verbose, hcodegen, + {$ifdef i386} + cgi386; + {$endif i386} Const AsmInstr: Array[tasmop] Of TAsmInstrucProp = ( {MOV} (Ch: (C_Op2, C_None, C_None)), @@ -588,7 +596,7 @@ Procedure FindLoHiLabels(AsmL: PAasmOutput; Var LowLabel, HighLabel, LabelDif: L {Walks through the paasmlist to find the lowest and highest label number; Since 0.9.3: also removes unused labels} Var LabelFound: Boolean; - P{, hp1}: Pai; + P, hp1: Pai; Begin LabelFound := False; LowLabel := MaxLongint; @@ -714,6 +722,35 @@ End; {********************* Compare parts of Pai objects *********************} +Function RegsEquivalent(Reg1, Reg2: TRegister; Var RegInfo: TRegInfo): Boolean; +Begin + With RegInfo Do + If Not(Reg1 in RegsEncountered) Then + Begin + RegsEncountered := RegsEncountered + [Reg1]; + SubstRegs[Reg1] := Reg2; + RegsEquivalent := True + End + Else RegsEquivalent := Reg1 = SubstRegs[Reg2]; +End; + +Function RefsEquivalent(Const R1, R2: TReference; var RegInfo: TRegInfo): Boolean; +Begin + If R1.IsIntValue + Then RefsEquivalent := R2.IsIntValue and (R1.Offset = R2.Offset) + Else If (R1.Offset = R2.Offset) And + RegsEquivalent(R1.Base, R2.Base, RegInfo) And + RegsEquivalent(R1.Index, R2.Index, RegInfo) And + (R1.Segment = R2.Segment) And (R1.ScaleFactor = R2.ScaleFactor) + Then + Begin + If Assigned(R1.Symbol) + Then RefsEquivalent := Assigned(R2.Symbol) And (R1.Symbol^=R2.Symbol^) + Else RefsEquivalent := Not(Assigned(R2.Symbol)); + End + Else RefsEquivalent := False; +End; + Function RefsEqual(Const R1, R2: TReference): Boolean; Begin If R1.IsIntValue @@ -738,6 +775,14 @@ Begin Else IsGP32reg := False End; +Function SubstRegInRef(Reg: TRegister; Const Ref: TReference; var RegInfo: TRegInfo): Boolean; +Begin + Reg := Reg32(Reg); + With RegInfo Do + SubstRegInRef := RegsEquivalent(Reg, SubstRegs[Ref.Base], RegInfo) And + RegsEquivalent(Reg, SubstRegs[Ref.Base], RegInfo); +End; + Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean; Begin {checks whether Ref contains a reference to Reg} Reg := Reg32(Reg); @@ -863,21 +908,77 @@ Begin Else s := 0 End; +Function RegInSequence(Reg: TRegister; Const Content: TContent): Boolean; +{checks the whole sequence of Content (so StartMod and and the next NrOfMods + Pai objects) to see whether Reg is used somewhere, without it being loaded + with something else first} +Var p: Pai; + Counter: Byte; + TmpResult: Boolean; + RegsChecked: TRegSet; +Begin + RegsChecked := []; + p := Content.StartMod; + TmpResult := False; + Counter := 1; + While Not(TmpResult) And + (Counter <= Content.NrOfMods) Do + Begin + If (p^.typ = ait_instruction) and + (Pai386(p)^._operator in [A_MOV, A_MOVZX, A_MOVSX]) + Then + If (Pai386(p)^.op1t = top_ref) + Then + With TReference(Pai386(p)^.op1^) Do + If (Base = ProcInfo.FramePointer) And + (Index = R_NO) + Then RegsChecked := RegsChecked + [Reg32(TRegister(Pai386(p)^.op2))] + Else + Begin + If (Base = Reg) And + Not(Base In RegsChecked) + Then TmpResult := True; + If Not(TmpResult) And + (Index = Reg) And + Not(Index In RegsChecked) + Then TmpResult := True; + End; + Inc(Counter); + GetNextInstruction(p,p) + End; + RegInSequence := TmpResult +End; + Procedure DestroyReg(p1: PPaiProp; Reg: TRegister); -{Destroys the contents of the register Reg in the PPaiProp of P} +{Destroys the contents of the register Reg in the PPaiProp p1, as well as the + contents of registers are loaded with a memory location based on Reg} Var TmpState: Longint; + Counter: TRegister; Begin Reg := Reg32(Reg); NrOfInstrSinceLastMod[Reg] := 0; If (Reg >= R_EAX) And (Reg <= R_EDI) Then - With p1^.Regs[Reg] Do - Begin - IncState(State); - TmpState := State; - FillChar(p1^.Regs[Reg], SizeOf(TContent), 0); - State := TmpState; - End; + Begin + With p1^.Regs[Reg] Do + Begin + IncState(State); + TmpState := State; + FillChar(p1^.Regs[Reg], SizeOf(TContent), 0); + State := TmpState; + End; + For Counter := R_EAX to R_EDI Do + With p1^.Regs[Counter] Do + If (Typ = Con_Ref) And + RegInSequence(Reg, p1^.Regs[Counter]) + Then + Begin + IncState(State); + TmpState := State; + FillChar(p1^.Regs[Counter], SizeOf(TContent), 0); + State := TmpState; + End; + End; End; Function OpsEqual(typ: Longint; op1, op2: Pointer): Boolean; @@ -903,13 +1004,6 @@ Function InstructionsEqual(p1, p2: Pai): Boolean; Begin {checks whether two Pai386 instructions are equal} InstructionsEqual := Assigned(p1) And Assigned(p2) And -{ $ifdef regalloc - ((((Pai(p1)^.typ = ait_regalloc) And - (Pai(p2)^.typ = ait_regalloc)) Or - ((Pai(p1)^.typ = ait_regdealloc) And - (Pai(p2)^.typ = ait_regdealloc))) And - (PaiRegAlloc(p1)^.reg = PaiRegAlloc(p2)^.reg)) Or - endif regalloc} ((Pai(p1)^.typ = ait_instruction) And (Pai(p1)^.typ = ait_instruction) And (Pai386(p1)^._operator = Pai386(p2)^._operator) And @@ -919,6 +1013,43 @@ Begin {checks whether two Pai386 instructions are equal} OpsEqual(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2)) End; +Function RefInInstruction(Const Ref: TReference; p: Pai): Boolean; +{checks whehter Ref is used in P} +Var TmpResult: Boolean; +Begin + TmpResult := False; + If (p^.typ = ait_instruction) Then + Begin + If (Pai386(p)^.op1t = Top_Ref) + Then TmpResult := RefsEqual(Ref, TReference(Pai386(p)^.op1^)); + If Not(TmpResult) And + (Pai386(p)^.op2t = Top_Ref) + Then TmpResult := RefsEqual(Ref, TReference(Pai386(p)^.op2^)); + End; + RefInInstruction := TmpResult; +End; + +Function RefInSequence(Const Ref: TReference; Content: TContent): Boolean; +{checks the whole sequence of Content (so StartMod and and the next NrOfMods + Pai objects) to see whether Ref is used somewhere} +Var p: Pai; + Counter: Byte; + TmpResult: Boolean; +Begin + p := Content.StartMod; + TmpResult := False; + Counter := 1; + While Not(TmpResult) And + (Counter <= Content.NrOfMods) Do + Begin + If (p^.typ = ait_instruction) And + RefInInstruction(Ref, p) + Then TmpResult := True; + Inc(Counter); + GetNextInstruction(p,p) + End; + RefInSequence := TmpResult +End; Procedure DestroyRefs(p: pai; Const Ref: TReference; WhichReg: TRegister); {destroys all registers which possibly contain a reference to Ref, WhichReg @@ -933,21 +1064,29 @@ Begin Then {write something to a parameter, a local or global variable, so * with uncertzain optimizations on: - - destroy the contents of registers <> WhichReg whose StartMod is of - the form "mov?? (Ref), %reg". WhichReg is destroyed if it's StartMod - is of that form and NrOfMods > 1 (so if it is a pointer based on Ref) - * with uncertzain optimizations off: + - destroy the contents of registers whose contents have somewhere a + "mov?? (Ref), %reg". WhichReg (this is the register whose contents + are being written to memory) is not destroyed if it's StartMod is + of that form and NrOfMods = 1 (so if it holds ref, but is not a + pointer based on Ref) + * with uncertain optimizations off: - also destroy registers that contain any pointer} For Counter := R_EAX to R_EDI Do With PPaiProp(p^.fileinfo.line)^.Regs[Counter] Do Begin If (typ = Con_Ref) And + (Not(cs_UncertainOpts in aktglobalswitches) And + (NrOfMods <> 1) + ) Or + (RefInSequence(Ref,PPaiProp(p^.fileinfo.line)^.Regs[Counter]) And + ((Counter <> WhichReg) Or + ((NrOfMods = 1) And {StarMod is always of the type ait_instruction} - (Pai386(StartMod)^.op1t = top_ref) And - ((RefsEqual(TReference(Pai386(StartMod)^.op1^), Ref) And - ((Counter <> WhichReg) Or (NrOfMods <> 1))) Or - (Not(cs_UncertainOpts in aktglobalswitches) And - (NrOfMods <> 1))) + (Pai386(StartMod)^.op1t = top_ref) And + RefsEqual(TReference(Pai386(StartMod)^.op1^), Ref) + ) + ) + ) Then DestroyReg(PPaiProp(p^.fileinfo.line), Counter) End Else @@ -999,7 +1138,11 @@ Begin BuildLabelTable(AsmL, LTable, LoLab, LabDif); End; -Function DoDFAPass2(First: Pai): Pai; +Function DoDFAPass2( +{$Ifdef StateDebug} +AsmL: PAasmOutput; +{$endif statedebug} +First: Pai): Pai; {Analyzes the Data Flow of an assembler list. Starts creating the reg contents for the instructions starting with p. Returns the last pai which has been processed} @@ -1037,7 +1180,7 @@ Begin Begin GetLastInstruction(p, hp); CurProp^.Regs := PPaiProp(hp^.fileinfo.line)^.Regs; - CurProp^.DirFlag := PPaiProp(hp^.fileinfo.line)^.DirFlag + CurProp^.DirFlag := PPaiProp(hp^.fileinfo.line)^.DirFlag; End {$ifdef JumpAnal} End @@ -1237,9 +1380,7 @@ Begin {$ifdef GDB} ait_stabs, ait_stabn, ait_stab_function_name:; {$endif GDB} -{$ifdef regalloc} ait_regalloc, ait_regdealloc:; -{$endif regalloc} ait_instruction: Begin InstrProp := AsmInstr[Pai386(p)^._operator]; @@ -1263,17 +1404,17 @@ Begin Top_Ref: Begin {destination is always a register in this case} TmpReg := Reg32(TRegister(Pai386(p)^.op2)); - If (RegInRef(TmpReg, TReference(Pai386(p)^.op1^))) +{$ifdef StateDebug} + hp := new(pai_asm_comment,init(strpnew(att_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].State)))); + InsertLLItem(AsmL, p, p^.next, hp); +{$endif SteDebug} + If RegInRef(TmpReg, TReference(Pai386(p)^.op1^)) And + (CurProp^.Regs[TmpReg].Typ = Con_Ref) Then Begin With CurProp^.Regs[TmpReg] Do Begin IncState(State); - If (typ <> Con_Ref) Then - Begin - typ := Con_Ref; - StartMod := p; - End; {also store how many instructions are part of the sequence in the first instructions PPaiProp, so it can be easily accessed from within CheckSequence} @@ -1455,7 +1596,11 @@ End; Function DFAPass2(AsmL: PAasmOutPut): Pai; Begin If InitDFAPass2(AsmL) - Then DFAPass2 := DoDFAPass2(Pai(AsmL^.First)) + Then DFAPass2 := DoDFAPass2( +{$ifdef statedebug} + asml, +{$endif statedbug} + Pai(AsmL^.First)) Else DFAPass2 := Nil; End; @@ -1469,9 +1614,8 @@ End. { $Log$ - Revision 1.13 1998-09-17 09:42:36 peter - + pass_2 for cg386 - * Message() -> CGMessage() for pass_1/pass_2 + Revision 1.14 1998-09-20 17:12:36 jonas + * small fix for uncertain optimizations & more cleaning up Revision 1.12 1998/09/16 18:00:01 jonas * optimizer now completely dependant on GetNext/GetLast instruction, works again with -dRegAlloc