From e02d95ed13c98d36dce9c38bda3ed1d161c851ee Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sat, 27 Oct 2001 10:20:43 +0000 Subject: [PATCH] + replace mem accesses to locations to which a reg was stored recently with that reg --- compiler/i386/csopt386.pas | 158 ++++++++++++++++++++++++------------- compiler/i386/daopt386.pas | 102 +++++++++++++++++------- 2 files changed, 177 insertions(+), 83 deletions(-) diff --git a/compiler/i386/csopt386.pas b/compiler/i386/csopt386.pas index d6a644fe81..31b2484d74 100644 --- a/compiler/i386/csopt386.pas +++ b/compiler/i386/csopt386.pas @@ -70,6 +70,7 @@ var tmpRef: treference; regCounter: tregister; opCount: byte; + dummy: boolean; begin modifiesConflictingMemLocation := false; if p1.typ <> ait_instruction then @@ -81,7 +82,7 @@ begin for regCounter := R_EAX to R_EDI do begin if writeToMemDestroysContents(reg32(p.oper[0].reg),p.oper[1].ref^, - regCounter,c[regCounter]) then + regCounter,c[regCounter],dummy) then begin exclude(regsStillValid,regCounter); modifiesConflictingMemLocation := not(reg in regsStillValid); @@ -170,7 +171,7 @@ begin tmpRef.base := R_EDI; tmpRef.index := R_EDI; for regCounter := R_EAX to R_EDI do - if writeToMemDestroysContents(R_NO,tmpRef,regCounter,c[regCounter]) then + if writeToMemDestroysContents(R_NO,tmpRef,regCounter,c[regCounter],dummy) then begin exclude(regsStillValid,regCounter); modifiesConflictingMemLocation := not(reg in regsStillValid); @@ -720,6 +721,16 @@ begin {$endif replaceregdebug} end; +procedure clearmemwrites(p: tai; reg: tregister); +var + beginmemwrite: tai; +begin + beginmemwrite := pTaiprop(p.optinfo)^.regs[reg].memwrite; + repeat + pTaiprop(p.optinfo)^.regs[reg].memwrite := nil; + until not getnextinstruction(p,p) or + (pTaiprop(p.optinfo)^.regs[reg].memwrite <> beginmemwrite); +end; Procedure ClearRegContentsFrom(reg: TRegister; p, endP: Tai); { first clears the contents of reg from p till endP. Then the contents are } @@ -729,6 +740,7 @@ var hp: Tai; l: longint; {$endif replaceregdebug} + regcounter: tregister; oldStartmod: Tai; begin {$ifdef replaceregdebug} @@ -744,12 +756,25 @@ begin PTaiProp(p.optInfo)^.Regs[reg].typ := con_unknown; While (p <> endP) Do Begin - PTaiProp(p.optInfo)^.Regs[reg].typ := con_unknown; + for regcounter := R_EAX to R_EDI do + if (regcounter <> reg) and + assigned(pTaiprop(p.optinfo)^.regs[reg].memwrite) and + reginref(regcounter,pTaiprop(p.optinfo)^.regs[reg].memwrite.oper[1].ref^) then + clearmemwrites(p,regcounter); + with PTaiProp(p.optInfo)^.Regs[reg] do + begin + typ := con_unknown; + memwrite := nil; + end; getNextInstruction(p,p); end; oldStartmod := PTaiProp(p.optInfo)^.Regs[reg].startmod; repeat - PTaiProp(p.optInfo)^.Regs[reg].typ := con_unknown; + with PTaiProp(p.optInfo)^.Regs[reg] do + begin + typ := con_unknown; + memwrite := nil; + end; until not getNextInstruction(p,p) or (PTaiProp(p.optInfo)^.Regs[reg].startmod <> oldStartmod); {$ifdef replaceregdebug} @@ -1311,45 +1336,57 @@ begin (p.opcode = A_IDIV)); end; -function memtoreg(const t: Taicpu; const ref: treference): tregister; +function memtoreg(const t: Taicpu; const ref: treference; var startp: tai): tregister; var hp: tai; p: pTaiprop; regcounter: tregister; + optimizable: boolean; begin - if not getlastinstruction(t,hp) then + if not getlastinstruction(t,hp) or + not issimplememloc(ref) then begin memtoreg := R_NO; exit; end; p := pTaiprop(hp.optinfo); - if isSimpleMemLoc(ref) then + optimizable := false; + for regcounter := R_EAX to R_EDI do begin - for regcounter := R_EAX to R_EDI do - if (p^.regs[regcounter].typ in [CON_REF,CON_NOREMOVEREF]) and - (p^.regs[regcounter].nrofmods = 1) and - ((Taicpu(p^.regs[regcounter].startmod).opcode = A_MOV) or - (Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVZX) or - (Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVSX)) and - (taicpu(p^.regs[regcounter].startmod).oper[0].typ = top_ref) and - refsequal(ref,taicpu(p^.regs[regcounter].startmod).oper[0].ref^) then - begin - if ((t.opsize <> S_B) or - (regcounter <> R_EDI)) and - sizescompatible(Taicpu(p^.regs[regcounter].startmod).opsize,t.opsize) then - begin - case t.opsize of - S_B,S_BW,S_BL: - memtoreg := reg32toreg8(regcounter); - S_W,S_WL: - memtoreg := reg32toreg16(regcounter); - S_L: - memtoreg := regcounter; - end; - exit; + if (assigned(p^.regs[regcounter].memwrite) and + refsequal(ref,p^.regs[regcounter].memwrite.oper[1].ref^)) then + begin + optimizable := true; + hp := p^.regs[regcounter].memwrite; + end + else if ((p^.regs[regcounter].typ in [CON_REF,CON_NOREMOVEREF]) and + (p^.regs[regcounter].nrofmods = 1) and + ((Taicpu(p^.regs[regcounter].startmod).opcode = A_MOV) or + (Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVZX) or + (Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVSX)) and + (taicpu(p^.regs[regcounter].startmod).oper[0].typ = top_ref) and + refsequal(ref,taicpu(p^.regs[regcounter].startmod).oper[0].ref^)) then + begin + optimizable := true; + hp := p^.regs[regcounter].startmod; + end; + if optimizable then + if ((t.opsize <> S_B) or + (regcounter <> R_EDI)) and + sizescompatible(Taicpu(hp).opsize,t.opsize) then + begin + case t.opsize of + S_B,S_BW,S_BL: + memtoreg := reg32toreg8(regcounter); + S_W,S_WL: + memtoreg := reg32toreg16(regcounter); + S_L: + memtoreg := regcounter; end; - end; - end; + startp := hp; + exit; + end; + end; memtoreg := R_NO; end; @@ -1643,14 +1680,20 @@ Begin begin regcounter := memtoreg(taicpu(p), - Taicpu(p).oper[0].ref^); + Taicpu(p).oper[0].ref^,hp5); if regcounter <> R_NO then - begin - Taicpu(p).loadreg(0,regcounter); - allocregbetween(asml,reg32(regcounter), - pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod, - p); - end; + if (taicpu(p).opcode = A_MOV) and + (taicpu(p).oper[1].typ = top_reg) and + (taicpu(p).oper[1].reg = regcounter) then + pTaiProp(p.optinfo)^.canberemoved := true + else + begin + Taicpu(p).loadreg(0,regcounter); + regcounter := reg32(regcounter); + allocregbetween(asml,regcounter,hp5,p); + incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1); + updatestate(regcounter,p); + end; end; end; { at first, only try optimizations of large blocks, because doing } @@ -1715,13 +1758,14 @@ Begin begin regcounter := memtoreg(taicpu(p), - Taicpu(p).oper[0].ref^); + Taicpu(p).oper[0].ref^,hp5); if regcounter <> R_NO then begin Taicpu(p).loadreg(0,regcounter); - allocregbetween(asml,reg32(regcounter), - pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod, - p); + regcounter := reg32(regcounter); + allocregbetween(asml,regcounter,hp5,p); + incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1); + updatestate(regcounter,p); end; end; Ch_MOp1: @@ -1730,7 +1774,7 @@ Begin begin regcounter := memtoreg(taicpu(p), - Taicpu(p).oper[0].ref^); + Taicpu(p).oper[0].ref^,hp5); if (regcounter <> R_NO) (* and (not getNextInstruction(p,hp1) or (RegLoadedWithNewValue(reg32(regcounter),false,hp1) or @@ -1744,11 +1788,13 @@ Begin new(pTaiprop(hp1.optinfo)); pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^; insertllitem(asml,p,p.next,hp1); + incstate(pTaiProp(hp1.optinfo)^.regs[reg32(regcounter)].rstate,1); + updatestate(reg32(regcounter),hp1); hp1 := Tai_Marker.Create(NoPropInfoStart); insertllitem(asml,p,p.next,hp1); Taicpu(p).loadreg(0,regcounter); - allocregbetween(asml,reg32(regcounter), - pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod, + regcounter := reg32(regcounter); + allocregbetween(asml,regcounter,hp5, tai(p.next.next)); end; end; @@ -1759,13 +1805,14 @@ Begin begin regcounter := memtoreg(taicpu(p), - Taicpu(p).oper[1].ref^); + Taicpu(p).oper[1].ref^,hp5); if regcounter <> R_NO then begin Taicpu(p).loadreg(1,regcounter); - allocregbetween(asml,reg32(regcounter), - pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod, - p); + regcounter := reg32(regcounter); + allocregbetween(asml,regcounter,hp5,p); + incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1); + updatestate(regcounter,p); end; end; Ch_MOp2: @@ -1780,7 +1827,7 @@ Begin begin regcounter := memtoreg(taicpu(p), - Taicpu(p).oper[1].ref^); + Taicpu(p).oper[1].ref^,hp5); if (regcounter <> R_NO) (* and (not getNextInstruction(p,hp1) or (RegLoadedWithNewValue(reg32(regcounter),false,hp1) or @@ -1794,11 +1841,13 @@ Begin new(pTaiprop(hp1.optinfo)); pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^; insertllitem(asml,p,p.next,hp1); + incstate(pTaiProp(hp1.optinfo)^.regs[reg32(regcounter)].rstate,1); + updatestate(reg32(regcounter),hp1); hp1 := Tai_Marker.Create(NoPropInfoStart); insertllitem(asml,p,p.next,hp1); Taicpu(p).loadreg(1,regcounter); - allocregbetween(asml,reg32(regcounter), - pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod, + regcounter := reg32(regcounter); + allocregbetween(asml,regcounter,hp5, tai(p.next.next)); end; end; @@ -1904,7 +1953,10 @@ End. { $Log$ - Revision 1.20 2001-10-14 11:50:21 jonas + Revision 1.21 2001-10-27 10:20:43 jonas + + replace mem accesses to locations to which a reg was stored recently with that reg + + Revision 1.20 2001/10/14 11:50:21 jonas + also replace mem references in modify operands with regs Revision 1.19 2001/10/12 13:58:05 jonas diff --git a/compiler/i386/daopt386.pas b/compiler/i386/daopt386.pas index 340767b903..c611a329e8 100644 --- a/compiler/i386/daopt386.pas +++ b/compiler/i386/daopt386.pas @@ -73,6 +73,7 @@ type {start and end of block instructions that defines the content of this register.} StartMod: Tai; + MemWrite: Taicpu; {how many instructions starting with StarMod does the block consist of} NrOfMods: Byte; {the type of the content of the register: unknown, memory, constant} @@ -170,7 +171,7 @@ function instrWritesFlags(p: Tai): boolean; function instrReadsFlags(p: Tai): boolean; function writeToMemDestroysContents(regWritten: tregister; const ref: treference; - reg: tregister; const c: tcontent): boolean; + reg: tregister; const c: tcontent; var invalsmemwrite: boolean): boolean; function writeToRegDestroysContents(destReg: tregister; reg: tregister; const c: tcontent): boolean; function writeDestroysContents(const op: toper; reg: tregister; @@ -1328,12 +1329,17 @@ begin for counter := R_EAX to R_EDI Do if counter <> reg then with p1^.regs[counter] Do - if (typ in [con_ref,con_noRemoveRef]) and - sequenceDependsOnReg(p1^.Regs[counter],counter,reg) then - if typ in [con_ref,con_invalid] then - typ := con_invalid - { con_invalid and con_noRemoveRef = con_unknown } - else typ := con_unknown; + begin + if (typ in [con_ref,con_noRemoveRef]) and + sequenceDependsOnReg(p1^.Regs[counter],counter,reg) then + if typ in [con_ref,con_invalid] then + typ := con_invalid + { con_invalid and con_noRemoveRef = con_unknown } + else typ := con_unknown; + if assigned(memwrite) and + regInRef(counter,memwrite.oper[1].ref^) then + memwrite := nil; + end; end; Procedure DestroyReg(p1: PTaiProp; Reg: TRegister; doIncState:Boolean); @@ -1364,6 +1370,7 @@ Begin typ := con_invalid { con_invalid and con_noRemoveRef = con_unknown } else typ := con_unknown; + memwrite := nil; end; invalidateDependingRegs(p1,reg); end; @@ -1737,17 +1744,12 @@ begin end; function writeToMemDestroysContents(regWritten: tregister; const ref: treference; - reg: tregister; const c: tcontent): boolean; + reg: tregister; const c: tcontent; var invalsmemwrite: boolean): boolean; { returns whether the contents c of reg are invalid after regWritten is } { is written to ref } var refsEq: trefCompare; begin - if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then - begin - writeToMemDestroysContents := false; - exit; - end; reg := reg32(reg); regWritten := reg32(regWritten); if isSimpleRef(ref) then @@ -1760,6 +1762,16 @@ begin else { local/global variable or parameter which is not an array } refsEq := {$ifdef fpc}@{$endif}refsEqual; + invalsmemwrite := + assigned(c.memwrite) and + ((not(cs_uncertainOpts in aktglobalswitches) and + containsPointerRef(c.memwrite)) or + refsEq(c.memwrite.oper[1].ref^,ref)); + if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then + begin + writeToMemDestroysContents := false; + exit; + end; { write something to a parameter, a local or global variable, so } { * with uncertain optimizations on: } @@ -1785,7 +1797,7 @@ begin ) ) ) - ) + ); end else { write something to a pointer location, so } @@ -1794,15 +1806,26 @@ begin { a parameter, except if DestroyRefs is called because of a "movsl" } { * with uncertain optimzations off: } { - destroy every register which contains a memory location } - with c do - writeToMemDestroysContents := - (typ in [con_ref,con_noRemoveRef]) and + begin + invalsmemwrite := + assigned(c.memwrite) and (not(cs_UncertainOpts in aktglobalswitches) or - { for movsl } - ((ref.base = R_EDI) and (ref.index = R_EDI)) or - { don't destroy if reg contains a parameter, local or global variable } - containsPointerLoad(c) - ) + containsPointerRef(c.memwrite)); + if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then + begin + writeToMemDestroysContents := false; + exit; + end; + with c do + writeToMemDestroysContents := + (typ in [con_ref,con_noRemoveRef]) and + (not(cs_UncertainOpts in aktglobalswitches) or + { for movsl } + ((ref.base = R_EDI) and (ref.index = R_EDI)) or + { don't destroy if reg contains a parameter, local or global variable } + containsPointerLoad(c) + ); + end; end; function writeToRegDestroysContents(destReg: tregister; reg: tregister; @@ -1819,6 +1842,8 @@ function writeDestroysContents(const op: toper; reg: tregister; const c: tcontent): boolean; { returns whether the contents c of reg are invalid after regWritten is } { is written to op } +var + dummy: boolean; begin reg := reg32(reg); case op.typ of @@ -1827,7 +1852,7 @@ begin writeToRegDestroysContents(op.reg,reg,c); top_ref: writeDestroysContents := - writeToMemDestroysContents(R_NO,op.ref^,reg,c); + writeToMemDestroysContents(R_NO,op.ref^,reg,c,dummy); else writeDestroysContents := false; end; @@ -1839,11 +1864,16 @@ procedure destroyRefs(p: Tai; const ref: treference; regWritten: tregister); { is called because of a "mov?? %reg, (mem)" instruction) } var counter: TRegister; + destroymemwrite: boolean; begin for counter := R_EAX to R_EDI Do - if writeToMemDestroysContents(regWritten,ref,counter, - pTaiProp(p.optInfo)^.regs[counter]) then - destroyReg(pTaiProp(p.optInfo), counter, false) + begin + if writeToMemDestroysContents(regWritten,ref,counter, + pTaiProp(p.optInfo)^.regs[counter],destroymemwrite) then + destroyReg(pTaiProp(p.optInfo), counter, false) + else if destroymemwrite then + pTaiProp(p.optinfo)^.regs[counter].MemWrite := nil; + end; End; Procedure DestroyAllRegs(p: PTaiProp); @@ -1853,6 +1883,7 @@ Begin {initializes/desrtoys all registers} Begin ReadReg(p, Counter); DestroyReg(p, Counter, true); + p^.regs[counter].MemWrite := nil; End; p^.DirFlag := F_Unknown; End; @@ -1914,6 +1945,7 @@ Begin PTaiProp(Tai(StartMod).OptInfo)^.Regs[Reg].NrOfMods := NrOfMods; NrOfInstrSinceLastMod[Reg] := 0; invalidateDependingRegs(p.optinfo,reg); + pTaiprop(p.optinfo)^.regs[reg].memwrite := nil; {$ifdef StateDebug} hp := Tai_asm_comment.Create(strpnew(att_reg2str[reg]+': '+tostr(PTaiProp(p.optinfo)^.Regs[reg].WState) + ' -- ' + tostr(PTaiProp(p.optinfo)^.Regs[reg].nrofmods)))); @@ -2237,6 +2269,7 @@ Begin { that depended on the previous value of } { this register } invalidateDependingRegs(curprop,tmpreg); + curprop^.regs[tmpreg].memwrite := nil; end; end else @@ -2260,11 +2293,17 @@ Begin {$endif StateDebug} End; Top_Ref: - { can only be if oper[0] = top_reg } Begin - ReadReg(CurProp, Taicpu(p).oper[0].reg); ReadRef(CurProp, Taicpu(p).oper[1].ref); - DestroyRefs(p, Taicpu(p).oper[1].ref^, Taicpu(p).oper[0].reg); + if taicpu(p).oper[0].typ = top_reg then + begin + ReadReg(CurProp, Taicpu(p).oper[0].reg); + DestroyRefs(p, Taicpu(p).oper[1].ref^, Taicpu(p).oper[0].reg); + pTaiProp(p.optinfo)^.regs[reg32(Taicpu(p).oper[0].reg)].memwrite := + Taicpu(p); + end + else + DestroyRefs(p, Taicpu(p).oper[1].ref^, R_NO); End; End; top_symbol,Top_Const: @@ -2552,7 +2591,10 @@ End. { $Log$ - Revision 1.22 2001-10-12 13:58:05 jonas + Revision 1.23 2001-10-27 10:20:43 jonas + + replace mem accesses to locations to which a reg was stored recently with that reg + + Revision 1.22 2001/10/12 13:58:05 jonas + memory references are now replaced by register reads in "regular" instructions (e.g. "addl ref1,%eax" will be replaced by "addl %ebx,%eax" if %ebx contains ref1). Previously only complete load sequences were