* search much further back for CSE sequences (non-conflicting stores are

now passed)
  * remove more unnecessary loads of registers (especially the self pointer)
This commit is contained in:
Jonas Maebe 2000-09-29 23:14:45 +00:00
parent ec5edf7be2
commit 9e77e31a28

View File

@ -58,61 +58,100 @@ Begin
End; End;
} }
function modifiesMemLocation(p1: pai): boolean; function modifiesConflictingMemLocation(p1: pai; reg: tregister; c: tregContent;
var p: paicpu; var regsStillValid: tregset): boolean;
opCount: byte; var
p: paicpu;
tmpRef: treference;
regCounter: tregister;
opCount: byte;
begin begin
modifiesMemLocation := false; modifiesConflictingMemLocation := false;
if p1^.typ <> ait_instruction then if p1^.typ <> ait_instruction then
exit; exit;
p := paicpu(p1); p := paicpu(p1);
for opCount := 1 to MaxCh do case p^.opcode of
case InsProp[p^.opcode].Ch[opCount] of A_MOV,A_MOVSX,A_MOVZX:
Ch_MOp1,CH_WOp1,CH_RWOp1: if p^.oper[1].typ = top_ref then
if (p^.oper[0].typ = top_ref) or for regCounter := R_EAX to R_EDI do
((p^.oper[0].typ = top_reg) and
not(reg32(p^.oper[0].reg) in (usableregs+[R_EDI]))) then
begin begin
modifiesMemLocation := true; if writeToMemDestroysContents(reg32(p^.oper[0].reg),p^.oper[1].ref^,
exit regCounter,c[regCounter]) then
end; begin
Ch_MOp2,CH_WOp2,CH_RWOp2: exclude(regsStillValid,regCounter);
if (p^.oper[1].typ = top_ref) or modifiesConflictingMemLocation := not(reg in regsStillValid);
((p^.oper[1].typ = top_reg) and end;
not(reg32(p^.oper[1].reg) in (usableregs+[R_EDI]))) then end
{ else
for regCounter := R_EAX to R_EDI do
begin begin
modifiesMemLocation := true; if writeDestroysContents(p^.oper[1],regCounter,c[regCounter]) then
exit begin
end; exclude(regsStillValid,regCounter);
Ch_MOp3,CH_WOp3,CH_RWOp3: modifiesConflictingMemLocation := not(reg in regsStillValid);
if (p^.oper[2].typ = top_ref) or end
((p^.oper[2].typ = top_reg) and end};
not(reg32(p^.oper[2].reg) in (usableregs+[R_EDI]))) then A_IMUL,A_DIV, A_IDIV, A_MUL:; { they never write to memory }
begin else
modifiesMemLocation := true; for opCount := 1 to MaxCh do
exit case InsProp[p^.opcode].Ch[opCount] of
end; Ch_MOp1,CH_WOp1,CH_RWOp1:
Ch_WMemEDI: if paicpu(p)^.oper[0].typ = top_ref then
begin for regCounter := R_EAX to R_EDI do
modifiesMemLocation := true; if writeDestroysContents(p^.oper[0],regCounter,c[regCounter]) then
exit; begin
exclude(regsStillValid,regCounter);
modifiesConflictingMemLocation := not(reg in regsStillValid);
end;
Ch_MOp2,CH_WOp2,CH_RWOp2:
if paicpu(p)^.oper[1].typ = top_ref then
for regCounter := R_EAX to R_EDI do
if writeDestroysContents(p^.oper[1],regCounter,c[regCounter]) then
begin
exclude(regsStillValid,regCounter);
modifiesConflictingMemLocation := not(reg in regsStillValid);
end;
Ch_MOp3,CH_WOp3,CH_RWOp3:
if paicpu(p)^.oper[2].typ = top_ref then
for regCounter := R_EAX to R_EDI do
if writeDestroysContents(p^.oper[2],regCounter,c[regCounter]) then
begin
exclude(regsStillValid,regCounter);
modifiesConflictingMemLocation := not(reg in regsStillValid);
end;
Ch_WMemEDI:
begin
fillchar(tmpref,sizeof(tmpref),0);
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
begin
exclude(regsStillValid,regCounter);
modifiesConflictingMemLocation := not(reg in regsStillValid);
end;
end;
end; end;
end; end;
end; end;
function getPrevSequence(reg: tregister; current: pai; var prev: pai; var passedJump: boolean): function getPrevSequence(p: pai; reg: tregister; currentPrev: pai; var newPrev: pai;
tregister; var passedJump: boolean; var regsNotRead, regsStillValid: tregset): tregister;
const
current_reg: tregister = R_NO;
function stillValid(p: pai): boolean; function stillValid(p: pai): boolean;
begin begin
stillValid := stillValid :=
(p^.typ = ait_instruction) and (p^.typ = ait_instruction) and
(paicpu(p)^.opcode <> a_jmp) and (paicpu(p)^.opcode <> a_jmp) and
(ppaiprop(p^.optinfo)^.regs[reg].state = (ppaiprop(p^.optinfo)^.regs[reg].wstate =
ppaiprop(current^.optinfo)^.regs[reg].state) and ppaiprop(currentPrev^.optinfo)^.regs[reg].wstate) and
{ in case destroyreg is called with doIncState = false } { in case destroyreg is called with doIncState = false }
(ppaiprop(p^.optinfo)^.regs[reg].typ = (ppaiprop(p^.optinfo)^.regs[reg].typ =
ppaiprop(current^.optinfo)^.regs[reg].typ); ppaiprop(currentPrev^.optinfo)^.regs[reg].typ) and
(reg in (regsNotRead * regsStillValid));
passedJump := passedJump :=
(p^.typ = ait_instruction) and (p^.typ = ait_instruction) and
(paicpu(p)^.is_jmp); (paicpu(p)^.is_jmp);
@ -122,54 +161,86 @@ function getPrevSequence(reg: tregister; current: pai; var prev: pai; var passed
var var
regCounter: tregister; regCounter: tregister;
begin begin
for regCounter := R_EAX to R_EDI do for regCounter := succ(current_reg) to R_EDI do
with ppaiprop(p^.optinfo)^.regs[regCounter] do with ppaiprop(p^.optinfo)^.regs[regCounter] do
if ((startmod <> if ((startmod <>
ppaiprop(current^.optinfo)^.regs[regCounter].startmod) or ppaiprop(currentPrev^.optinfo)^.regs[regCounter].startmod) or
(nrOfMods <> (nrOfMods <>
ppaiprop(current^.optinfo)^.regs[regCounter].nrOfMods)) and ppaiprop(currentPrev^.optinfo)^.regs[regCounter].nrOfMods)) and
(not ppaiprop(p^.optinfo)^.canBeRemoved) and
(ppaiprop(p^.optinfo)^.regs[regCounter].typ in (ppaiprop(p^.optinfo)^.regs[regCounter].typ in
[con_ref,con_noRemoveRef]) then [con_ref,con_noRemoveRef]) then
begin begin
findChangedRegister := regCounter; findChangedRegister := regCounter;
current_reg := regCounter;
exit; exit;
end; end;
current_reg := R_NO;
findChangedRegister := R_NO; findChangedRegister := R_NO;
end; end;
var var
hp, prevFound: pai; hp, prevFound: pai;
tmpResult: tregister; tmpResult, regCounter: tregister;
begin begin
getPrevSequence := R_NO; if not(current_reg in [R_NO,R_EDI]) then
{ no memory writes (could be refined further) }
passedJump := passedJump or
((current^.typ = ait_instruction) and
(paicpu(current)^.is_jmp));
if modifiesMemLocation(current) or
(passedJump and not(reg in (usableregs+[R_EDI]))) or
not getLastInstruction(current,hp) then
exit;
tmpResult := R_NO;
while (tmpResult = R_NO) and
stillValid(hp) do
begin 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
(paicpu(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
not(modifiesConflictingMemLocation(prevFound,reg,
ppaiprop(p^.optinfo)^.regs,regsStillValid)) do
begin
{ only update the regsread for the instructions we already passed }
if not(ppaiprop(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 } { in case getPreviousInstruction fails and sets hp to nil in the }
{ next iteration } { next iteration }
prevFound := hp; prevFound := hp;
tmpResult := findChangedRegister(hp); if not(ppaiprop(hp^.optinfo)^.canBeRemoved) then
if modifiesMemLocation(hp) or tmpResult := findChangedRegister(hp);
{ do not load the self pointer or a regvar before a (conditional) } 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 } { jump with a new value, since if the jump is taken, the old value }
{ is (probably) still necessary } { is (probably) still necessary }
(passedJump and not(reg in (usableregs+[R_EDI]))) or (passedJump and not(reg in (usableregs+[R_EDI]))) or
not getLastInstruction(hp,hp) then not getLastInstruction(hp,hp) then
break; break;
end; end;
getPrevSequence := tmpResult; getPrevSequence := tmpResult;
if tmpResult <> R_NO then if tmpResult <> R_NO then
prev := prevFound; newPrev := prevFound;
end;
function isSimpleMemLoc(const ref: treference): boolean;
begin
isSimpleMemLoc :=
(ref.index = R_NO) and
(not(ref.base in (usableregs+[R_EDI])) or
(assigned(ref.symbol) and
(ref.base = R_NO) and
(ref.index = R_NO)));
end; end;
@ -181,26 +252,25 @@ end;
Function CheckSequence(p: Pai; var prev: pai; Reg: TRegister; Var Found: Longint; Function CheckSequence(p: Pai; var prev: pai; Reg: TRegister; Var Found: Longint;
Var RegInfo: TRegInfo): Boolean; Var RegInfo: TRegInfo): Boolean;
const
checkingPrevSequences: boolean = false;
var
regsNotRead, regsStillValid: tregset;
function getNextRegToTest(var orgP: pai; currentReg: tregister): tregister; function getNextRegToTest(var prev: pai; currentReg: tregister): tregister;
const const
checkingPrevSequences: boolean = false;
passedJump: boolean = false; passedJump: boolean = false;
begin begin
if currentReg = R_NO then
checkingPrevSequences := false;
if not checkingPrevSequences then if not checkingPrevSequences then
begin begin
Repeat Repeat
Inc(currentReg); Inc(currentReg);
Until (currentReg > R_EDI) or Until (currentReg > R_EDI) or
(ppaiprop(orgP^.optInfo)^.regs[currentReg].typ (ppaiprop(prev^.optInfo)^.regs[currentReg].typ
in [con_ref,con_noRemoveRef]); in [con_ref,con_noRemoveRef]);
if currentReg > R_EDI then if currentReg > R_EDI then
begin begin
if not modifiesMemLocation(orgP) and if isSimpleMemLoc(paicpu(p)^.oper[0].ref^) then
(ppaiprop(orgP^.optinfo)^.regs[reg].rstate =
ppaiprop(p^.optinfo)^.regs[reg].rstate) then
begin begin
checkingPrevSequences := true; checkingPrevSequences := true;
passedJump := false; passedJump := false;
@ -211,7 +281,8 @@ Function CheckSequence(p: Pai; var prev: pai; Reg: TRegister; Var Found: Longint
else getNextRegToTest := currentReg; else getNextRegToTest := currentReg;
end; end;
if checkingPrevSequences then if checkingPrevSequences then
getNextRegToTest := getPrevSequence(reg,orgP,orgP, passedJump); getNextRegToTest :=
getPrevSequence(p,reg,prev,prev,passedJump,regsNotRead,RegsStillValid);
end; end;
Var hp2, hp3{, EndMod},highPrev, orgPrev: Pai; Var hp2, hp3{, EndMod},highPrev, orgPrev: Pai;
@ -238,6 +309,9 @@ Begin {CheckSequence}
oldRegsEncountered := newRegsEncountered; oldRegsEncountered := newRegsEncountered;
end; end;
checkingPrevSequences := false;
regsNotRead := [R_EAX,R_EBX,R_ECX,R_EDX,R_ESP,R_EBP,R_EDI,R_ESI];
regsStillValid := regsNotRead;
GetLastInstruction(p, prev); GetLastInstruction(p, prev);
regCounter := getNextRegToTest(prev,R_NO); regCounter := getNextRegToTest(prev,R_NO);
While (RegCounter <> R_NO) Do While (RegCounter <> R_NO) Do
@ -268,11 +342,23 @@ Begin {CheckSequence}
GetNextInstruction(hp3, hp3); GetNextInstruction(hp3, hp3);
Inc(Found) Inc(Found)
End; End;
for regCounter2 := R_EAX to R_EDX do
for regCounter2 := R_EAX to R_EDI do
if (regInfo.new2OldReg[regCounter2] <> R_NO) and if (regInfo.new2OldReg[regCounter2] <> R_NO) and
(regCounter2 in PPaiProp(hp3^.optInfo)^.usedRegs) and (regCounter2 in PPaiProp(hp3^.optInfo)^.usedRegs) and
not regLoadedWithNewValue(regCounter2,false,hp3) then not regLoadedWithNewValue(regCounter2,false,hp3) then
include(regInfo.regsStillUsedAfterSeq,regCounter2); 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
found := 0;
break;
end;
If (Found <> OldNrOfMods) or If (Found <> OldNrOfMods) or
{ the following is to avoid problems with rangecheck code (see testcse2) } { the following is to avoid problems with rangecheck code (see testcse2) }
(assigned(hp3) and (assigned(hp3) and
@ -1144,6 +1230,7 @@ begin
ppaiprop(startMod^.optInfo)^.canBeRemoved := true; ppaiprop(startMod^.optInfo)^.canBeRemoved := true;
end; end;
Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai); Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai);
{marks the instructions that can be removed by RemoveInstructs. They're not {marks the instructions that can be removed by RemoveInstructs. They're not
removed immediately because sometimes an instruction needs to be checked in removed immediately because sometimes an instruction needs to be checked in
@ -1407,7 +1494,11 @@ Begin
allocRegBetween(asmL,paicpu(p)^.oper[0].reg, allocRegBetween(asmL,paicpu(p)^.oper[0].reg,
PPaiProp(p^.optInfo)^.regs[paicpu(p)^.oper[0].reg].startMod, PPaiProp(p^.optInfo)^.regs[paicpu(p)^.oper[0].reg].startMod,
hp1); hp1);
end; end
else
if reg32(paicpu(p)^.oper[0].reg) <> reg32(paicpu(p)^.oper[1].reg) then
removePrevNotUsedLoad(p,reg32(paicpu(p)^.oper[1].reg),false);
end end
end; end;
top_symbol,Top_Const: top_symbol,Top_Const:
@ -1424,7 +1515,10 @@ Begin
begin begin
PPaiProp(p^.OptInfo)^.CanBeRemoved := True; PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
allocRegBetween(asmL,regCounter,startMod,p); allocRegBetween(asmL,regCounter,startMod,p);
end; end
else
removePrevNotUsedLoad(p,reg32(paicpu(p)^.oper[1].reg),false);
End; End;
Top_Ref: Top_Ref:
if (paicpu(p)^.oper[0].typ = top_const) and if (paicpu(p)^.oper[0].typ = top_const) and
@ -1438,6 +1532,7 @@ Begin
End; End;
End; End;
End; End;
End; End;
A_STD: If GetLastInstruction(p, hp1) And A_STD: If GetLastInstruction(p, hp1) And
(PPaiProp(hp1^.OptInfo)^.DirFlag = F_Set) Then (PPaiProp(hp1^.OptInfo)^.DirFlag = F_Set) Then
@ -1495,7 +1590,12 @@ End.
{ {
$Log$ $Log$
Revision 1.12 2000-09-26 11:49:41 jonas Revision 1.13 2000-09-29 23:14:45 jonas
* search much further back for CSE sequences (non-conflicting stores are
now passed)
* remove more unnecessary loads of registers (especially the self pointer)
Revision 1.12 2000/09/26 11:49:41 jonas
* writes to register variables and to the self pointer now also count as * writes to register variables and to the self pointer now also count as
memore writes memore writes