diff --git a/compiler/i386/csopt386.pas b/compiler/i386/csopt386.pas index 2a7a3a0def..e2ccfefdae 100644 --- a/compiler/i386/csopt386.pas +++ b/compiler/i386/csopt386.pas @@ -180,104 +180,6 @@ begin end; end; -function getPrevSequence(p: Tai; reg: tregister; currentPrev: Tai; var newPrev: Tai; - var passedJump: boolean; var regsNotRead, regsStillValid: tregset): tregister; - -const - current_reg: tregister = R_NO; - - function stillValid(p: Tai): boolean; - begin - stillValid := - (p.typ = ait_instruction) and - (Taicpu(p).opcode <> a_jmp) and - (pTaiprop(p.optinfo)^.regs[reg].wstate = - pTaiprop(currentPrev.optinfo)^.regs[reg].wstate) and - { in case destroyreg is called with doIncState = false } - (pTaiprop(p.optinfo)^.regs[reg].typ = - pTaiprop(currentPrev.optinfo)^.regs[reg].typ) and - (reg in (regsNotRead * regsStillValid)); - passedJump := - (p.typ = ait_instruction) and - (Taicpu(p).is_jmp); - end; - - function findChangedRegister(p: Tai): tregister; - var - regCounter: tregister; - begin - for regCounter := succ(current_reg) to R_EDI do - with pTaiprop(p.optinfo)^.regs[regCounter] do - if ((startmod <> - pTaiprop(currentPrev.optinfo)^.regs[regCounter].startmod) or - (nrOfMods <> - pTaiprop(currentPrev.optinfo)^.regs[regCounter].nrOfMods)) and - (pTaiprop(p.optinfo)^.regs[regCounter].typ in - [con_ref,con_noRemoveRef]) then - begin - findChangedRegister := regCounter; - current_reg := regCounter; - exit; - end; - current_reg := R_NO; - findChangedRegister := R_NO; - end; - -var - hp, prevFound: Tai; - tmpResult, regCounter: tregister; -begin - if not(current_reg in [R_NO,R_EDI]) then - begin - tmpResult := findChangedRegister(currentPrev); - if tmpResult <> R_NO then - begin - getPrevSequence := tmpResult; - exit; - end; - end; - - getPrevSequence := R_NO; - passedJump := passedJump or - ((currentPrev.typ = ait_instruction) and - (Taicpu(currentPrev).is_jmp)); - - if (passedJump and not(reg in (usableregs+[R_EDI]))) or - not getLastInstruction(currentPrev,hp) then - exit; - - prevFound := currentPrev; - tmpResult := R_NO; - - while (tmpResult = R_NO) and - stillValid(hp) and - (pTaiprop(prevFound.optinfo)^.canBeRemoved or - not(modifiesConflictingMemLocation(prevFound,reg, - pTaiprop(p.optinfo)^.regs,regsStillValid))) do - begin - { only update the regsread for the instructions we already passed } - if not(pTaiprop(prevFound.optinfo)^.canBeRemoved) then - for regCounter := R_EAX to R_EDI do - if regReadByInstruction(regCounter,prevFound) then - exclude(regsNotRead,regCounter); - - { in case getPreviousInstruction fails and sets hp to nil in the } - { next iteration } - prevFound := hp; - if not(pTaiprop(hp.optinfo)^.canBeRemoved) then - tmpResult := findChangedRegister(hp); - if { do not load the self pointer or a regvar before a (conditional) } - { jump with a new value, since if the jump is taken, the old value } - { is (probably) still necessary } - (passedJump and not(reg in (usableregs+[R_EDI]))) or - not getLastInstruction(hp,hp) then - break; - end; - getPrevSequence := tmpResult; - if tmpResult <> R_NO then - newPrev := prevFound; -end; - function isSimpleMemLoc(const ref: treference): boolean; begin @@ -297,14 +199,114 @@ end; Function CheckSequence(p: Tai; var prev: Tai; Reg: TRegister; Var Found: Longint; Var RegInfo: TRegInfo; findPrevSeqs: boolean): Boolean; -const - checkingPrevSequences: boolean = false; var - regsNotRead, regsStillValid: tregset; + regsNotRead, regsStillValid : tregset; + checkingPrevSequences, + passedFlagsModifyingInstr, + passedJump : boolean; + + function getPrevSequence(p: Tai; reg: tregister; currentPrev: Tai; var newPrev: Tai): tregister; + + const + current_reg: tregister = R_NO; + + function stillValid(p: Tai): boolean; + begin + stillValid := + (p.typ = ait_instruction) and + (Taicpu(p).opcode <> a_jmp) and + (pTaiprop(p.optinfo)^.regs[reg].wstate = + pTaiprop(currentPrev.optinfo)^.regs[reg].wstate) and + { in case destroyreg is called with doIncState = false } + (pTaiprop(p.optinfo)^.regs[reg].typ = + pTaiprop(currentPrev.optinfo)^.regs[reg].typ) and + (reg in (regsNotRead * regsStillValid)); + passedJump := + (p.typ = ait_instruction) and + (Taicpu(p).is_jmp); + passedFlagsModifyingInstr := + instrWritesFlags(currentPrev); + end; + + function findChangedRegister(p: Tai): tregister; + var + regCounter: tregister; + begin + for regCounter := succ(current_reg) to R_EDI do + with pTaiprop(p.optinfo)^.regs[regCounter] do + if ((startmod <> + pTaiprop(currentPrev.optinfo)^.regs[regCounter].startmod) or + (nrOfMods <> + pTaiprop(currentPrev.optinfo)^.regs[regCounter].nrOfMods)) and + (pTaiprop(p.optinfo)^.regs[regCounter].typ in + [con_ref,con_noRemoveRef]) then + begin + findChangedRegister := regCounter; + current_reg := regCounter; + exit; + end; + current_reg := R_NO; + findChangedRegister := R_NO; + end; + + var + hp, prevFound: Tai; + tmpResult, regCounter: tregister; + begin + if not(current_reg in [R_NO,R_EDI]) then + begin + tmpResult := findChangedRegister(currentPrev); + if tmpResult <> R_NO then + begin + getPrevSequence := tmpResult; + exit; + end; + end; + + getPrevSequence := R_NO; + passedJump := passedJump or + ((currentPrev.typ = ait_instruction) and + (Taicpu(currentPrev).is_jmp)); + passedFlagsModifyingInstr := instrWritesFlags(currentPrev); + + if (passedJump and not(reg in (usableregs+[R_EDI]))) or + not getLastInstruction(currentPrev,hp) then + exit; + + prevFound := currentPrev; + tmpResult := R_NO; + + while (tmpResult = R_NO) and + stillValid(hp) and + (pTaiprop(prevFound.optinfo)^.canBeRemoved or + not(modifiesConflictingMemLocation(prevFound,reg, + pTaiprop(p.optinfo)^.regs,regsStillValid))) do + begin + { only update the regsread for the instructions we already passed } + if not(pTaiprop(prevFound.optinfo)^.canBeRemoved) then + for regCounter := R_EAX to R_EDI do + if regReadByInstruction(regCounter,prevFound) then + exclude(regsNotRead,regCounter); + + { in case getPreviousInstruction fails and sets hp to nil in the } + { next iteration } + prevFound := hp; + if not(pTaiprop(hp.optinfo)^.canBeRemoved) then + tmpResult := findChangedRegister(hp); + if { do not load the self pointer or a regvar before a (conditional) } + { jump with a new value, since if the jump is taken, the old value } + { is (probably) still necessary } + (passedJump and not(reg in (usableregs+[R_EDI]))) or + not getLastInstruction(hp,hp) then + break; + end; + getPrevSequence := tmpResult; + if tmpResult <> R_NO then + newPrev := prevFound; + end; + function getNextRegToTest(var prev: Tai; currentReg: tregister): tregister; - const - passedJump: boolean = false; begin if not checkingPrevSequences then begin @@ -329,7 +331,7 @@ var if checkingPrevSequences then if findPrevSeqs then getNextRegToTest := - getPrevSequence(p,reg,prev,prev,passedJump,regsNotRead,RegsStillValid) + getPrevSequence(p,reg,prev,prev) else getNextRegToTest := R_NO; end; @@ -341,8 +343,7 @@ Var hp2, hp3{, EndMod},highPrev, orgPrev: Tai; HighFound, OrgRegFound: Byte; RegCounter, regCounter2, tmpreg, base, index: TRegister; OrgRegResult: Boolean; - TmpResult: Boolean; - {TmpState: Byte;} + TmpResult, flagResultsNeeded: Boolean; Begin {CheckSequence} Reg := Reg32(Reg); TmpResult := False; @@ -360,6 +361,8 @@ Begin {CheckSequence} end; checkingPrevSequences := false; + passedFlagsModifyingInstr := false; + flagResultsNeeded := false; regsNotRead := [R_EAX,R_EBX,R_ECX,R_EDX,R_ESP,R_EBP,R_EDI,R_ESI]; regsStillValid := regsNotRead; GetLastInstruction(p, prev); @@ -417,6 +420,10 @@ Begin {CheckSequence} for regCounter2 := R_EAX to R_EDI do regModified[regCounter2] := regModified[regCounter2] or regModifiedByInstruction(regCounter2,hp3); + if flagResultsNeeded then + flagResultsNeeded := not instrReadsFlags(hp3); + if not flagResultsNeeded then + flagResultsNeeded := pTaiprop(hp3.optinfo)^.FlagsUsed; GetNextInstruction(hp2, hp2); GetNextInstruction(hp3, hp3); Inc(Found); @@ -429,15 +436,18 @@ Begin {CheckSequence} include(regInfo.regsStillUsedAfterSeq,regCounter2); if checkingPrevSequences then - for regCounter2 := R_EAX to R_EDI do - if not(regInfo.new2OldReg[regCounter2] in [R_NO,regCounter2]) and - (not(regCounter2 in (regsNotRead * regsStillValid)) or - not(regInfo.new2OldReg[regCounter2] in regsStillValid)) then - begin + begin + for regCounter2 := R_EAX to R_EDI do + if not(regInfo.new2OldReg[regCounter2] in [R_NO,regCounter2]) and + (not(regCounter2 in (regsNotRead * regsStillValid)) or + not(regInfo.new2OldReg[regCounter2] in regsStillValid)) then + begin + found := 0; + break; + end; + if passedFlagsModifyingInstr and flagResultsNeeded then found := 0; - break; - end; - + end; If (Found <> OldNrOfMods) or { the following is to avoid problems with rangecheck code (see testcse2) } (assigned(hp3) and @@ -1375,6 +1385,7 @@ Begin Cnt2 := 1; While Cnt2 <= Cnt Do Begin +(* If not(regInInstruction(Taicpu(hp2).oper[1].reg, p)) and not(pTaiprop(p.optinfo)^.canBeRemoved) then begin @@ -1409,8 +1420,9 @@ Begin PTaiProp(p.OptInfo)^.CanBeRemoved := True {$endif noremove} end +*) {$ifndef noremove} - else +(* else *) PTaiProp(p.OptInfo)^.CanBeRemoved := True {$endif noremove} ; Inc(Cnt2); @@ -1718,7 +1730,13 @@ End. { $Log$ - Revision 1.16 2001-08-26 13:36:55 florian + Revision 1.17 2001-08-29 14:07:43 jonas + * the optimizer now keeps track of flags register usage. This fixes some + optimizer bugs with int64 calculations (because of the carry flag usage) + * fixed another bug which caused wrong optimizations with complex + array expressions + + Revision 1.16 2001/08/26 13:36:55 florian * some cg reorganisation * some PPC updates diff --git a/compiler/i386/daopt386.pas b/compiler/i386/daopt386.pas index 624ba1452a..04cc64313e 100644 --- a/compiler/i386/daopt386.pas +++ b/compiler/i386/daopt386.pas @@ -130,6 +130,8 @@ type {$endif tempOpts} { can this instruction be removed? } CanBeRemoved: Boolean; + { are the resultflags set by this instruction used? } + FlagsUsed: Boolean; End; PTaiProp = ^TTaiProp; @@ -164,6 +166,8 @@ function RegReadByInstruction(reg: TRegister; hp: Tai): boolean; function RegModifiedByInstruction(Reg: TRegister; p1: Tai): Boolean; function RegInInstruction(Reg: TRegister; p1: Tai): Boolean; function RegInOp(Reg: TRegister; const o:toper): Boolean; +function instrWritesFlags(p: Tai): boolean; +function instrReadsFlags(p: Tai): boolean; function writeToMemDestroysContents(regWritten: tregister; const ref: treference; reg: tregister; const c: tcontent): boolean; @@ -952,6 +956,46 @@ Begin RegModifiedByInstruction := TmpResult End; + +function instrWritesFlags(p: Tai): boolean; +var + l: longint; +begin + instrWritesFlags := true; + case p.typ of + ait_instruction: + begin + for l := 1 to MaxCh do + if InsProp[Taicpu(p).opcode].Ch[l] in [Ch_WFlags,Ch_RWFlags,Ch_All] then + exit; + end; + ait_label: + exit; + else + instrWritesFlags := false; + end; +end; + +function instrReadsFlags(p: Tai): boolean; +var + l: longint; +begin + instrReadsFlags := true; + case p.typ of + ait_instruction: + begin + for l := 1 to MaxCh do + if InsProp[Taicpu(p).opcode].Ch[l] in [Ch_RFlags,Ch_RWFlags,Ch_All] then + exit; + end; + ait_label: + exit; + else + instrReadsFlags := false; + end; +end; + + {********************* GetNext and GetLastInstruction *********************} Function GetNextInstruction(Current: Tai; Var Next: Tai): Boolean; { skips ait_regalloc, ait_regdealloc and ait_stab* objects and puts the } @@ -1877,11 +1921,11 @@ BlockStart, BlockEnd: Tai); contents for the instructions starting with p. Returns the last Tai which has been processed} Var - CurProp: PTaiProp; + CurProp, LastFlagsChangeProp: PTaiProp; Cnt, InstrCnt : Longint; InstrProp: TInsProp; UsedRegs: TRegSet; - p, hp : Tai; + prev, p, hp : Tai; TmpRef: TReference; TmpReg: TRegister; {$ifdef AnalyzeLoops} @@ -1889,6 +1933,8 @@ Var {$endif AnalyzeLoops} Begin p := BlockStart; + LastFlagsChangeProp := nil; + prev := nil; UsedRegs := []; UpdateUsedregs(UsedRegs, p); SkipHead(P); @@ -1898,16 +1944,16 @@ Begin While (P <> BlockEnd) Do Begin CurProp := @TaiPropBlock^[InstrCnt]; - If (p <> BlockStart) + If assigned(prev) Then Begin {$ifdef JumpAnal} If (p.Typ <> ait_label) Then {$endif JumpAnal} Begin - GetLastInstruction(p, hp); - CurProp^.regs := PTaiProp(hp.OptInfo)^.Regs; - CurProp^.DirFlag := PTaiProp(hp.OptInfo)^.DirFlag; + CurProp^.regs := PTaiProp(prev.OptInfo)^.Regs; + CurProp^.DirFlag := PTaiProp(prev.OptInfo)^.DirFlag; + CurProp^.FlagsUsed := false; End End Else @@ -2332,7 +2378,18 @@ Begin tmpRef.index := R_EDI; DestroyRefs(p, TmpRef, R_NO) End; - Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU: + Ch_RFlags: + if assigned(LastFlagsChangeProp) then + LastFlagsChangeProp^.FlagsUsed := true; + Ch_WFlags: + LastFlagsChangeProp := CurProp; + Ch_RWFlags: + begin + if assigned(LastFlagsChangeProp) then + LastFlagsChangeProp^.FlagsUsed := true; + LastFlagsChangeProp := CurProp; + end; + Ch_FPU:; Else Begin {$ifdef statedebug} @@ -2341,6 +2398,7 @@ Begin insertllitem(asml,p, p.next,hp); {$endif statedebug} DestroyAllRegs(CurProp); + LastFlagsChangeProp := CurProp; End; End; Inc(Cnt); @@ -2360,6 +2418,7 @@ Begin End; End; Inc(InstrCnt); + prev := p; GetNextInstruction(p, p); End; End; @@ -2413,6 +2472,7 @@ Begin Begin InitDFAPass2 := True; GetMem(TaiPropBlock, NrOfTaiObjs*SizeOf(TTaiProp)); + fillchar(TaiPropBlock^,NrOfTaiObjs*SizeOf(TTaiProp),0); p := BlockStart; SkipHead(p); For Count := 1 To NrOfTaiObjs Do @@ -2452,7 +2512,13 @@ End. { $Log$ - Revision 1.19 2001-08-26 13:36:55 florian + Revision 1.20 2001-08-29 14:07:43 jonas + * the optimizer now keeps track of flags register usage. This fixes some + optimizer bugs with int64 calculations (because of the carry flag usage) + * fixed another bug which caused wrong optimizations with complex + array expressions + + Revision 1.19 2001/08/26 13:36:55 florian * some cg reorganisation * some PPC updates diff --git a/compiler/i386/rropt386.pas b/compiler/i386/rropt386.pas index d0f9959b08..4c10076d3b 100644 --- a/compiler/i386/rropt386.pas +++ b/compiler/i386/rropt386.pas @@ -51,7 +51,8 @@ begin canBeFirstSwitch := (p.ops >= 2) and (reg32(p.oper[p.ops-1].reg) = reg) and - (p.oper[0].typ <> top_ref); + (p.oper[0].typ <> top_ref) and + (not pTaiprop(p.optinfo)^.FlagsUsed); A_INC,A_DEC,A_SUB,A_ADD: canBeFirstSwitch := (p.oper[1].typ = top_reg) and @@ -59,14 +60,16 @@ begin (reg32(p.oper[1].reg) = reg) and (p.oper[0].typ <> top_ref) and ((p.opcode <> A_SUB) or - (p.oper[0].typ = top_const)); + (p.oper[0].typ = top_const)) and + (not pTaiprop(p.optinfo)^.FlagsUsed); A_SHL: canBeFirstSwitch := (p.opsize = S_L) and (p.oper[1].typ = top_reg) and (p.oper[1].reg = reg) and (p.oper[0].typ = top_const) and - (p.oper[0].val in [1,2,3]); + (p.oper[0].val in [1,2,3]) and + (not pTaiprop(p.optinfo)^.FlagsUsed); end; end; @@ -335,7 +338,13 @@ End. { $Log$ - Revision 1.6 2001-01-06 23:35:06 jonas + Revision 1.7 2001-08-29 14:07:43 jonas + * the optimizer now keeps track of flags register usage. This fixes some + optimizer bugs with int64 calculations (because of the carry flag usage) + * fixed another bug which caused wrong optimizations with complex + array expressions + + Revision 1.6 2001/01/06 23:35:06 jonas * fixed webbug 1323 Revision 1.5 2000/12/25 00:07:34 peter