diff --git a/compiler/i386/csopt386.pas b/compiler/i386/csopt386.pas index 2e7339731d..f8f1a7bd43 100644 --- a/compiler/i386/csopt386.pas +++ b/compiler/i386/csopt386.pas @@ -258,7 +258,7 @@ var getlastinstruction(p,hp) then stillValid := stillValid and not(supreg in ptaiprop(hp.optinfo)^.usedregs); - passedFlagsModifyingInstr := + passedFlagsModifyingInstr := passedFlagsModifyingInstr or instrWritesFlags(currentPrev); end; @@ -274,9 +274,9 @@ var for regCounter := loopstart to RS_EDI do with ptaiprop(p.optinfo)^.regs[regCounter] do if ((startmod <> - ptaiprop(currentPrev.optinfo)^.regs[regCounter].startmod) or + ptaiprop(currentPrev.optinfo)^.regs[regCounter].startmod) or (nrofMods <> - ptaiprop(currentPrev.optinfo)^.regs[regCounter].nrofMods)) and + ptaiprop(currentPrev.optinfo)^.regs[regCounter].nrofMods)) and (ptaiprop(p.optinfo)^.regs[regCounter].typ in [con_ref,con_noRemoveRef]) then begin findChangedRegister := regCounter; @@ -305,7 +305,8 @@ var end; getPrevSequence := RS_INVALID; - passedFlagsModifyingInstr := instrWritesFlags(currentPrev); + passedFlagsModifyingInstr := passedFlagsModifyingInstr or + instrWritesFlags(currentPrev); if not getLastInstruction(currentPrev,hp) then exit; @@ -402,7 +403,7 @@ var hp2, hp3{, EndMod},highPrev, orgPrev: tai; {Cnt,} OldNrofMods: Longint; startRegInfo, OrgRegInfo, HighRegInfo: toptreginfo; - regModified: array[RS_EAX..RS_ESP] of boolean; + regModified, lastregloadremoved: array[RS_EAX..RS_ESP] of boolean; HighFound, OrgRegFound: longint; regcounter, regCounter2, tmpreg, base, index: tsuperregister; OrgRegResult: Boolean; @@ -434,6 +435,7 @@ begin {CheckSequence} while (regcounter <> RS_INVALID) do begin fillchar(regModified,sizeof(regModified),0); + fillchar(lastregloadremoved,sizeof(lastregloadremoved),0); reginfo := startRegInfo; Found := 0; hp2 := ptaiprop(prev.optinfo)^.Regs[regcounter].StartMod; @@ -454,8 +456,8 @@ begin {CheckSequence} if checkingprevsequences then begin prevreginfo := reginfo; - end - else if (hp3.typ = ait_instruction) and + end; + if (hp3.typ = ait_instruction) and ((taicpu(hp3).opcode = A_MOV) or (taicpu(hp3).opcode = A_MOVZX) or (taicpu(hp3).opcode = A_LEA) or @@ -464,6 +466,7 @@ begin {CheckSequence} not(regInOp(getsupreg(taicpu(hp3).oper[1]^.reg),taicpu(hp3).oper[0]^)) then begin tmpreg := getsupreg(taicpu(hp3).oper[1]^.reg); + lastregloadremoved[tmpreg] := ptaiprop(hp2.optinfo)^.canberemoved; reginfo.lastReload[tmpreg] := hp3; case taicpu(hp3).oper[0]^.typ of top_ref: @@ -481,13 +484,22 @@ begin {CheckSequence} with ptaiprop(hp3.optinfo)^.regs[tmpreg] do if nrofMods > (oldNrofMods - found) then oldNrofMods := found + nrofMods; + { next is safe because instructions are equivalent } + with ptaiprop(hp2.optinfo)^.regs[getsupreg(taicpu(hp2).oper[1]^.reg)] do + if nrofMods > (oldNrofMods - found) then + oldNrofMods := found + nrofMods; end; end; top_reg: if regModified[getsupreg(taicpu(hp3).oper[0]^.reg)] then - with ptaiprop(hp3.optinfo)^.regs[tmpreg] do - if nrofMods > (oldNrofMods - found) then - oldNrofMods := found + nrofMods; + begin + with ptaiprop(hp3.optinfo)^.regs[tmpreg] do + if nrofMods > (oldNrofMods - found) then + oldNrofMods := found + nrofMods; + with ptaiprop(hp2.optinfo)^.regs[getsupreg(taicpu(hp2).oper[1]^.reg)] do + if nrofMods > (oldNrofMods - found) then + oldNrofMods := found + nrofMods; + end; end; end; for regCounter2 := RS_EAX to RS_EDI do @@ -505,8 +517,9 @@ begin {CheckSequence} for regCounter2 := RS_EAX to RS_EDI do if (reginfo.new2OldReg[regCounter2] <> RS_INVALID) and (regCounter2 in ptaiprop(hp3.optinfo)^.usedRegs) and - not regLoadedWithNewValue(regCounter2,false,hp3) then - include(reginfo.regsStillUsedAfterSeq,regCounter2); + not regLoadedWithNewValue(regCounter2,false,hp3) and + lastregloadremoved[regcounter2] then + found := 0; if checkingPrevSequences then begin @@ -836,7 +849,7 @@ var l: longint; {$endif replaceregdebug} dummyregs: tregset; - tmpState: byte; + tmpState, newrstate: byte; prevcontenttyp: byte; memconflict: boolean; invalsmemwrite: boolean; @@ -852,19 +865,31 @@ begin hp.previous.next := hp; {$endif replaceregdebug} { ptaiprop(p.optinfo)^.Regs[reg] := c;} + newrstate := c.rstate; + incstate(newrstate,$7f); while (p <> endP) do begin + if not(ptaiprop(p.optinfo)^.canberemoved) and + regreadbyinstruction(supreg,p) then + incstate(newrstate,1); ptaiprop(p.optinfo)^.Regs[supreg] := c; + ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate; getNextInstruction(p,p); end; tmpState := ptaiprop(p.optinfo)^.Regs[supreg].wState; + if (newrstate = ptaiprop(p.optinfo)^.Regs[supreg].rState) then + internalerror(2004101012); dummyregs := [supreg]; repeat + newrstate := ptaiprop(p.optinfo)^.Regs[supreg].rState; prevcontenttyp := ptaiprop(p.optinfo)^.Regs[supreg].typ; // is this a write to memory that destroys the contents we are restoring? memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,dummyregs,true,invalsmemwrite); if not memconflict and not invalsmemwrite then - ptaiprop(p.optinfo)^.Regs[supreg] := c; + begin + ptaiprop(p.optinfo)^.Regs[supreg] := c; + ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate; + end; until invalsmemwrite or memconflict or not getNextInstruction(p,p) or @@ -873,10 +898,13 @@ begin ((prevcontenttyp <> con_invalid) and (ptaiprop(p.optinfo)^.Regs[supreg].typ = con_invalid)); if assigned(p) and - ((p.typ = ait_label) or - memconflict or - invalsmemwrite) then - clearRegContentsFrom(supreg,p,p); + (p.typ <> ait_marker) then + if ((p.typ = ait_label) or + memconflict or + invalsmemwrite) then + clearRegContentsFrom(supreg,p,p) + else if (ptaiprop(p.optinfo)^.Regs[supreg].rstate = newrstate) then + incstate(ptaiprop(p.optinfo)^.Regs[supreg].rstate,20); {$ifdef replaceregdebug} if assigned(p) then begin @@ -1186,24 +1214,13 @@ begin end; -function ReplaceReg(asml: TAAsmOutput; orgsupreg, newsupreg: tsuperregister; p, - seqstart: tai; const c: TContent; orgRegCanBeModified: Boolean; - var returnEndP: tai): Boolean; -{ Tries to replace orgsupreg with newsupreg in all instructions coming after p } -{ until orgsupreg gets loaded with a new value. Returns true if successful, } -{ false otherwise. if successful, the contents of newsupreg are set to c, } -{ which should hold the contents of newsupreg before the current sequence } -{ started } -{ if the function returns true, returnEndP holds the last instruction } -{ where newsupreg was replaced by orgsupreg } +function canreplacereg(orgsupreg, newsupreg: tsuperregister; p: tai; + orgRegCanBeModified: boolean; var resnewregmodified, resorgregread, resremovelast: boolean; var returnendp: tai): boolean; var endP, hp: tai; - removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead, - stateChanged, readStateChanged: Boolean; - - + removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead: boolean; begin - ReplaceReg := false; + canreplacereg := false; tmpResult := true; sequenceEnd := false; newRegModified := false; @@ -1281,7 +1298,7 @@ begin not RegModifiedByInstruction(orgsupreg,endP); end; end; - sequenceEnd := sequenceEnd and + canreplacereg := sequenceEnd and (removeLast or (orgRegCanBeModified or not(newRegModified))) and (not(assigned(endp)) or @@ -1291,7 +1308,35 @@ begin not(newRegModified and (orgsupreg in ptaiprop(endp.optinfo)^.usedRegs) and not(RegLoadedWithNewValue(orgsupreg,true,taicpu(endP)))))); - if SequenceEnd then + if canreplacereg then + begin + resnewregmodified := newregmodified; + resorgregread := orgregread; + resremovelast := removelast; + returnendp := endp; + end; +end; + + + +function ReplaceReg(asml: TAAsmOutput; orgsupreg, newsupreg: tsuperregister; p, + seqstart: tai; const c: TContent; orgRegCanBeModified: Boolean; + var returnEndP: tai): Boolean; +{ Tries to replace orgsupreg with newsupreg in all instructions coming after p } +{ until orgsupreg gets loaded with a new value. Returns true if successful, } +{ false otherwise. if successful, the contents of newsupreg are set to c, } +{ which should hold the contents of newsupreg before the current sequence } +{ started } +{ if the function returns true, returnEndP holds the last instruction } +{ where newsupreg was replaced by orgsupreg } +var + endP, hp: tai; + removeLast, sequenceEnd, newRegModified, orgRegRead, + stateChanged, readStateChanged: Boolean; + +begin + replacereg := false; + if canreplacereg(orgsupreg,newsupreg,p,orgregcanbemodified,newregmodified, orgregread, removelast,endp) then begin {$ifdef replaceregdebug} hp := tai_comment.Create(strpnew( @@ -1424,7 +1469,7 @@ procedure removePrevNotUsedLoad(p: tai; supreg: tsuperregister; check: boolean); { (e.g. when you have a "mov 8(%ebp),%eax", you can be sure the previous } { value of %eax isn't used anymore later on) } var - hp1: tai; + hp1, next, beforestartmod: tai; begin if getLastInstruction(p,hp1) then with ptaiprop(hp1.optinfo)^.regs[supreg] do @@ -1435,7 +1480,17 @@ begin (not(regInInstruction(supreg,p)) and (not(supreg in ptaiprop(hp1.optinfo)^.usedRegs) or findRegDealloc(supreg,p)))) then - ptaiprop(startMod.optinfo)^.canBeRemoved := true; + begin + ptaiprop(startMod.optinfo)^.canBeRemoved := true; + getnextinstruction(p,next); + { give the register that was modified by this instruction again } + { the contents it had before this instruction } + if getlastinstruction(startmod,beforestartmod) then + RestoreRegContentsTo(supreg,ptaiprop(beforestartmod.optinfo)^.regs[supreg], + startmod,p) + else + ClearRegContentsFrom(supreg,startmod,hp1); + end; end; @@ -2122,7 +2177,18 @@ end. { $Log$ - Revision 1.69 2004-10-31 21:45:03 peter + Revision 1.70 2004-12-18 15:16:10 jonas + * fixed tracking of usage of flags register + * fixed destroying of "memwrite"'s + * fixed checking of entire sequences in all cases (previously this was + only guaranteed if the new sequence was longer than the old one, and + not if vice versa) + * fixed wrong removal of sequences if a register load was already + completely removed in the previous sequence (because in that case, + that register has to be removed and renamed in the new sequence as + well before removing the new sequence) + + Revision 1.69 2004/10/31 21:45:03 peter * generic tlocation * move tlocation to cgutils diff --git a/compiler/i386/daopt386.pas b/compiler/i386/daopt386.pas index 9f6b0b27b3..6d8e4b29cc 100644 --- a/compiler/i386/daopt386.pas +++ b/compiler/i386/daopt386.pas @@ -70,7 +70,6 @@ type toptreginfo = Record NewRegsEncountered, OldRegsEncountered: TRegSet; RegsLoadedForRef: TRegSet; - regsStillUsedAfterSeq: TRegSet; lastReload: array[RS_EAX..RS_ESP] of tai; New2OldReg: TRegArray; end; @@ -2574,7 +2573,8 @@ begin { DestroyReg(curprop, RS_EAX, true);} AddInstr2RegContents({$ifdef statedebug}list,{$endif} taicpu(p), RS_EAX); - DestroyReg(curprop, RS_EDX, true) + DestroyReg(curprop, RS_EDX, true); + LastFlagsChangeProp := curprop; end; A_IMUL: begin @@ -2601,6 +2601,7 @@ begin else AddInstr2OpContents({$ifdef statedebug}list,{$endif} taicpu(p), taicpu(p).oper[2]^); + LastFlagsChangeProp := curprop; end; A_LEA: begin @@ -2791,7 +2792,18 @@ end. { $Log$ - Revision 1.76 2004-12-18 14:07:35 jonas + Revision 1.77 2004-12-18 15:16:10 jonas + * fixed tracking of usage of flags register + * fixed destroying of "memwrite"'s + * fixed checking of entire sequences in all cases (previously this was + only guaranteed if the new sequence was longer than the old one, and + not if vice versa) + * fixed wrong removal of sequences if a register load was already + completely removed in the previous sequence (because in that case, + that register has to be removed and renamed in the new sequence as + well before removing the new sequence) + + Revision 1.76 2004/12/18 14:07:35 jonas * fixed compilation with -dcsdebug -dallocregdebug Revision 1.75 2004/12/12 10:50:34 florian