* 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
This commit is contained in:
Jonas Maebe 2001-08-29 14:07:43 +00:00
parent 2990981dbc
commit 003549eba1
3 changed files with 221 additions and 128 deletions

View File

@ -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

View File

@ -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

View File

@ -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