mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-11 11:29:29 +02:00
* fixed a serious bug in the CSE which (I think) only showed with
-dnewoptimizations when using multi-dimensional arrays with elements of a size different from 1, 2 or 4 (especially strings). * made the DFA/CSE more robust (much less dependent on specifics of the code generator)
This commit is contained in:
parent
55988e6f55
commit
e4ceb46242
@ -172,6 +172,7 @@ Begin {CheckSequence}
|
||||
{ be used anymore after the sequence, are still used nevertheless (when }
|
||||
{ range checking is on for instance, because this is not "normal" generated }
|
||||
{ code, but more or less manually inserted) }
|
||||
(*
|
||||
{$ifndef fpc}
|
||||
If TmpResult Then
|
||||
{$else fpc}
|
||||
@ -210,6 +211,7 @@ Begin {CheckSequence}
|
||||
Exclude(RegInfo.RegsLoadedForRef,RegCounter);
|
||||
End;
|
||||
End;
|
||||
*)
|
||||
{$ifndef fpc}
|
||||
CheckSequence := TmpResult;
|
||||
{$endif fpc}
|
||||
@ -543,69 +545,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function RegReadByInstruction(reg: TRegister; hp: pai): boolean;
|
||||
{ assumes hp doesn't modify registers implicitely (like div) }
|
||||
{ and that reg is a 32bit register }
|
||||
var p: paicpu;
|
||||
opCount: byte;
|
||||
begin
|
||||
RegReadByInstruction := false;
|
||||
p := paicpu(hp);
|
||||
if hp^.typ <> ait_instruction then
|
||||
exit;
|
||||
case p^.opcode of
|
||||
A_IMUL:
|
||||
case p^.ops of
|
||||
1: regReadByInstruction := (reg = R_EAX) or reginOp(reg,p^.oper[0]);
|
||||
2,3:
|
||||
regReadByInstruction := regInOp(reg,p^.oper[0]) or
|
||||
regInOp(reg,p^.oper[1]);
|
||||
end;
|
||||
{ A_IDIV,A_DIV,A_IMUL:
|
||||
begin
|
||||
regReadByInstruction :=
|
||||
regInOp(reg,p^.oper[0]) or
|
||||
(((p^.opcode = A_IDIV) or
|
||||
(p^.opcode = A_DIV)) and
|
||||
(reg = R_EAX));
|
||||
end;}
|
||||
else
|
||||
begin
|
||||
for opCount := 0 to 2 do
|
||||
if (p^.oper[opCount].typ = top_ref) and
|
||||
RegInRef(reg,p^.oper[opCount].ref^) then
|
||||
begin
|
||||
RegReadByInstruction := true;
|
||||
exit
|
||||
end;
|
||||
for opCount := 1 to MaxCh do
|
||||
case InsProp[p^.opcode].Ch[opCount] of
|
||||
Ch_RWOp1,Ch_ROp1{$ifdef arithopt},Ch_MOp1{$endif}:
|
||||
if (p^.oper[0].typ = top_reg) and
|
||||
(reg32(p^.oper[0].reg) = reg) then
|
||||
begin
|
||||
RegReadByInstruction := true;
|
||||
exit
|
||||
end;
|
||||
Ch_RWOp2,Ch_ROp2{$ifdef arithopt},Ch_MOp2{$endif}:
|
||||
if (p^.oper[1].typ = top_reg) and
|
||||
(reg32(p^.oper[1].reg) = reg) then
|
||||
begin
|
||||
RegReadByInstruction := true;
|
||||
exit
|
||||
end;
|
||||
Ch_RWOp3,Ch_ROp3{$ifdef arithopt},Ch_MOp3{$endif}:
|
||||
if (p^.oper[2].typ = top_reg) and
|
||||
(reg32(p^.oper[2].reg) = reg) then
|
||||
begin
|
||||
RegReadByInstruction := true;
|
||||
exit
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure DoReplaceReadReg(orgReg,newReg: tregister; p: paicpu);
|
||||
var opCount: byte;
|
||||
begin
|
||||
@ -653,7 +592,7 @@ function ReplaceReg(asmL: PaasmOutput; orgReg, newReg: TRegister; p: pai;
|
||||
{ false otherwise. If successful, the contents of newReg are set to c, }
|
||||
{ which should hold the contents of newReg before the current sequence }
|
||||
{ started }
|
||||
{ if the functino returns true, returnEndP holds the lat instruction }
|
||||
{ if the function returns true, returnEndP holds the last instruction }
|
||||
{ where newReg was replaced by orgReg }
|
||||
var endP, hp: Pai;
|
||||
removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead: Boolean;
|
||||
@ -878,7 +817,7 @@ Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai);
|
||||
{marks the instructions that can be removed by RemoveInstructs. They're not
|
||||
removed immediately because sometimes an instruction needs to be checked in
|
||||
two different sequences}
|
||||
Var Cnt, Cnt2: Longint;
|
||||
Var Cnt, Cnt2, Cnt3: Longint;
|
||||
p, hp1, hp2: Pai;
|
||||
hp3, hp4: pai;
|
||||
{$ifdef replacereg}
|
||||
@ -916,9 +855,14 @@ Begin
|
||||
Begin
|
||||
If (p = StartMod) And
|
||||
GetLastInstruction (p, hp1) And
|
||||
(hp1^.typ <> ait_marker)
|
||||
Then
|
||||
(hp1^.typ <> ait_marker) Then
|
||||
{so we don't try to check a sequence when p is the first instruction of the block}
|
||||
begin
|
||||
{$ifdef csdebug}
|
||||
hp5 := new(pai_asm_comment,init(strpnew(
|
||||
'cse checking '+att_reg2str[Reg32(Paicpu(p)^.oper[1].reg)])));
|
||||
insertLLItem(asml,p,p^.next,hp5);
|
||||
{$endif csdebug}
|
||||
If CheckSequence(p, Paicpu(p)^.oper[1].reg, Cnt, RegInfo) And
|
||||
(Cnt > 0) Then
|
||||
Begin
|
||||
@ -943,16 +887,31 @@ Begin
|
||||
While Cnt2 <= Cnt Do
|
||||
Begin
|
||||
If (hp1 = nil) And
|
||||
Not(RegInInstruction(Paicpu(hp2)^.oper[1].reg, p) Or
|
||||
RegInInstruction(Reg32(Paicpu(hp2)^.oper[1].reg), p)) And
|
||||
Not((p^.typ = ait_instruction) And
|
||||
(paicpu(p)^.OpCode = A_MOV) And
|
||||
(paicpu(p)^.Oper[0].typ = top_ref) And
|
||||
(PPaiProp(p^.OptInfo)^.Regs[Reg32(paicpu(p)^.Oper[1].reg)].NrOfMods
|
||||
<= (Cnt - Cnt2 + 1)))
|
||||
Then hp1 := p;
|
||||
Not(RegInInstruction(Paicpu(hp2)^.oper[1].reg, p)) And
|
||||
((p^.typ = ait_instruction) And
|
||||
((paicpu(p)^.OpCode = A_MOV) or
|
||||
(paicpu(p)^.opcode = A_MOVZX) or
|
||||
(paicpu(p)^.opcode = A_MOVSX)) And
|
||||
(paicpu(p)^.Oper[0].typ = top_ref)) Then
|
||||
if (PPaiProp(p^.OptInfo)^.Regs[Reg32(paicpu(p)^.Oper[1].reg)].NrOfMods
|
||||
<= (Cnt - Cnt2 + 1)) and
|
||||
(Reg32(paicpu(p)^.Oper[1].reg) in regInfo.regsLoadedForRef) then
|
||||
begin
|
||||
hp3 := p;
|
||||
for Cnt3 := PPaiProp(p^.OptInfo)^.Regs[Reg32(paicpu(p)^.Oper[1].reg)].NrOfMods
|
||||
downto 1 do
|
||||
begin
|
||||
{$ifndef noremove}
|
||||
PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
|
||||
if regInInstruction(paicpu(p)^.Oper[1].reg,hp3) then
|
||||
PPaiProp(hp3^.OptInfo)^.CanBeRemoved := True;
|
||||
{$endif noremove}
|
||||
getNextInstruction(hp3,hp3);
|
||||
end
|
||||
end
|
||||
else hp1 := p;
|
||||
{$ifndef noremove}
|
||||
if regInInstruction(Paicpu(hp2)^.oper[1].reg,p) then
|
||||
PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
|
||||
{$endif noremove}
|
||||
Inc(Cnt2);
|
||||
GetNextInstruction(p, p);
|
||||
@ -1072,7 +1031,8 @@ Begin
|
||||
End;
|
||||
hp3 := New(Pai_Marker,Init(NoPropInfoEnd));
|
||||
InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
|
||||
If hp1 <> nil Then p := hp1;
|
||||
If hp1 <> nil Then
|
||||
p := hp1;
|
||||
Continue;
|
||||
End
|
||||
Else
|
||||
@ -1085,14 +1045,14 @@ Begin
|
||||
Cnt2 := 1;
|
||||
While Cnt2 <= Cnt Do
|
||||
Begin
|
||||
If RegInInstruction(Paicpu(hp2)^.oper[1].reg, p) Or
|
||||
RegInInstruction(Reg32(Paicpu(hp2)^.oper[1].reg), p) Then
|
||||
If RegInInstruction(Paicpu(hp2)^.oper[1].reg, p) Then
|
||||
PPaiProp(p^.OptInfo)^.CanBeRemoved := False;
|
||||
Inc(Cnt2);
|
||||
GetNextInstruction(p, p);
|
||||
End;
|
||||
Continue;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
{$ifdef replacereg}
|
||||
@ -1216,7 +1176,14 @@ End.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.56 2000-03-25 19:05:47 jonas
|
||||
Revision 1.57 2000-04-10 12:45:57 jonas
|
||||
* fixed a serious bug in the CSE which (I think) only showed with
|
||||
-dnewoptimizations when using multi-dimensional arrays with
|
||||
elements of a size different from 1, 2 or 4 (especially strings).
|
||||
* made the DFA/CSE more robust (much less dependent on specifics of the
|
||||
code generator)
|
||||
|
||||
Revision 1.56 2000/03/25 19:05:47 jonas
|
||||
* fixed some things for -Or. Make cycle now works with -OG2p3r if
|
||||
you use -Aas. There still a bug in popt386.pas that causes a
|
||||
problem with the binary writer, but I haven't found it yet
|
||||
@ -1352,4 +1319,4 @@ End.
|
||||
Revision 1.24 1999/08/25 11:59:58 jonas
|
||||
* changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
|
||||
|
||||
}
|
||||
}
|
@ -64,11 +64,10 @@ Function RefsEquivalent(Const R1, R2: TReference; Var RegInfo: TRegInfo; OpAct:
|
||||
Function RefsEqual(Const R1, R2: TReference): Boolean;
|
||||
Function IsGP32Reg(Reg: TRegister): Boolean;
|
||||
Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
|
||||
Function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||
{$ifdef newOptimizations}
|
||||
Function RegInOp(Reg: TRegister; const o:toper): Boolean;
|
||||
{$endif newOptimizations}
|
||||
Function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||
function RegReadByInstruction(reg: TRegister; hp: pai): boolean;
|
||||
function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||
function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||
function RegInOp(Reg: TRegister; const o:toper): Boolean;
|
||||
|
||||
Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
|
||||
Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
|
||||
@ -771,52 +770,138 @@ Begin {checks whether Ref contains a reference to Reg}
|
||||
RegInRef := (Ref.Base = Reg) Or (Ref.Index = Reg)
|
||||
End;
|
||||
|
||||
Function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||
{checks if Reg is used by the instruction p1}
|
||||
Var Counter: Longint;
|
||||
TmpResult: Boolean;
|
||||
Begin
|
||||
TmpResult := False;
|
||||
If (Pai(p1)^.typ = ait_instruction) Then
|
||||
Begin
|
||||
Reg := Reg32(Reg);
|
||||
Counter := 0;
|
||||
Repeat
|
||||
Case Paicpu(p1)^.oper[Counter].typ Of
|
||||
Top_Reg: TmpResult := Reg = Reg32(Paicpu(p1)^.oper[Counter].reg);
|
||||
Top_Ref: TmpResult := RegInRef(Reg, Paicpu(p1)^.oper[Counter].ref^);
|
||||
End;
|
||||
Inc(Counter)
|
||||
Until (Counter = 3) or TmpResult;
|
||||
End;
|
||||
RegInInstruction := TmpResult
|
||||
End;
|
||||
function RegReadByInstruction(reg: TRegister; hp: pai): boolean;
|
||||
var p: paicpu;
|
||||
opCount: byte;
|
||||
begin
|
||||
RegReadByInstruction := false;
|
||||
reg := reg32(reg);
|
||||
p := paicpu(hp);
|
||||
if hp^.typ <> ait_instruction then
|
||||
exit;
|
||||
case p^.opcode of
|
||||
A_IMUL:
|
||||
case p^.ops of
|
||||
1: regReadByInstruction := (reg = R_EAX) or reginOp(reg,p^.oper[0]);
|
||||
2,3:
|
||||
regReadByInstruction := regInOp(reg,p^.oper[0]) or
|
||||
regInOp(reg,p^.oper[1]);
|
||||
end;
|
||||
A_IDIV,A_DIV,A_MUL:
|
||||
begin
|
||||
regReadByInstruction :=
|
||||
regInOp(reg,p^.oper[0]) or (reg = R_EAX);
|
||||
end;
|
||||
else
|
||||
begin
|
||||
for opCount := 0 to 2 do
|
||||
if (p^.oper[opCount].typ = top_ref) and
|
||||
RegInRef(reg,p^.oper[opCount].ref^) then
|
||||
begin
|
||||
RegReadByInstruction := true;
|
||||
exit
|
||||
end;
|
||||
for opCount := 1 to MaxCh do
|
||||
case InsProp[p^.opcode].Ch[opCount] of
|
||||
Ch_REAX..CH_REDI,CH_RWEAX..Ch_MEDI:
|
||||
if reg = TCh2Reg(InsProp[p^.opcode].Ch[opCount]) then
|
||||
begin
|
||||
RegReadByInstruction := true;
|
||||
exit
|
||||
end;
|
||||
Ch_RWOp1,Ch_ROp1{$ifdef arithopt},Ch_MOp1{$endif}:
|
||||
if (p^.oper[0].typ = top_reg) and
|
||||
(reg32(p^.oper[0].reg) = reg) then
|
||||
begin
|
||||
RegReadByInstruction := true;
|
||||
exit
|
||||
end;
|
||||
Ch_RWOp2,Ch_ROp2{$ifdef arithopt},Ch_MOp2{$endif}:
|
||||
if (p^.oper[1].typ = top_reg) and
|
||||
(reg32(p^.oper[1].reg) = reg) then
|
||||
begin
|
||||
RegReadByInstruction := true;
|
||||
exit
|
||||
end;
|
||||
Ch_RWOp3,Ch_ROp3{$ifdef arithopt},Ch_MOp3{$endif}:
|
||||
if (p^.oper[2].typ = top_reg) and
|
||||
(reg32(p^.oper[2].reg) = reg) then
|
||||
begin
|
||||
RegReadByInstruction := true;
|
||||
exit
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function regInInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||
{ Checks if Reg is used by the instruction p1 }
|
||||
{ Difference with "regReadBysinstruction() or regModifiedByInstruction()": }
|
||||
{ this one ignores CH_ALL opcodes, while regModifiedByInstruction doesn't }
|
||||
var p: paicpu;
|
||||
opCount: byte;
|
||||
begin
|
||||
reg := reg32(reg);
|
||||
regInInstruction := false;
|
||||
p := paicpu(p1);
|
||||
if p1^.typ <> ait_instruction then
|
||||
exit;
|
||||
case p^.opcode of
|
||||
A_IMUL:
|
||||
case p^.ops of
|
||||
1: regInInstruction := (reg = R_EAX) or reginOp(reg,p^.oper[0]);
|
||||
2,3:
|
||||
regInInstruction := regInOp(reg,p^.oper[0]) or
|
||||
regInOp(reg,p^.oper[1]) or regInOp(reg,p^.oper[2]);
|
||||
end;
|
||||
A_IDIV,A_DIV,A_MUL:
|
||||
regInInstruction :=
|
||||
regInOp(reg,p^.oper[0]) or
|
||||
(reg = R_EAX) or (reg = R_EDX)
|
||||
else
|
||||
begin
|
||||
for opCount := 1 to MaxCh do
|
||||
case InsProp[p^.opcode].Ch[opCount] of
|
||||
CH_REAX..CH_MEDI:
|
||||
if tch2reg(InsProp[p^.opcode].Ch[opCount]) = reg then
|
||||
begin
|
||||
regInInstruction := true;
|
||||
exit;
|
||||
end;
|
||||
Ch_ROp1..Ch_MOp1:
|
||||
if regInOp(reg,p^.oper[0]) then
|
||||
begin
|
||||
regInInstruction := true;
|
||||
exit
|
||||
end;
|
||||
Ch_ROp2..Ch_MOp2:
|
||||
if regInOp(reg,p^.oper[1]) then
|
||||
begin
|
||||
regInInstruction := true;
|
||||
exit
|
||||
end;
|
||||
Ch_ROp3..Ch_MOp3:
|
||||
if regInOp(reg,p^.oper[2]) then
|
||||
begin
|
||||
regInInstruction := true;
|
||||
exit
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{$ifdef newOptimizations}
|
||||
Function RegInOp(Reg: TRegister; const o:toper): Boolean;
|
||||
Begin
|
||||
RegInOp := False;
|
||||
reg := reg32(reg);
|
||||
Case o.typ Of
|
||||
top_reg: RegInOp := Reg = o.reg;
|
||||
top_reg: RegInOp := Reg = reg32(o.reg);
|
||||
top_ref: RegInOp := (Reg = o.ref^.Base) Or
|
||||
(Reg = o.ref^.Index);
|
||||
End;
|
||||
End;
|
||||
{$endif newOptimizations}
|
||||
(*
|
||||
Function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||
{returns true if Reg is modified by the instruction p1. P1 is assumed to be
|
||||
of the type ait_instruction}
|
||||
Var hp: Pai;
|
||||
Begin
|
||||
If GetLastInstruction(p1, hp)
|
||||
Then
|
||||
RegModifiedByInstruction :=
|
||||
PPAiProp(p1^.OptInfo)^.Regs[Reg].WState <>
|
||||
PPAiProp(hp^.OptInfo)^.Regs[Reg].WState
|
||||
Else RegModifiedByInstruction := True;
|
||||
End;
|
||||
*)
|
||||
|
||||
Function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||
Var InstrProp: TInsProp;
|
||||
@ -830,7 +915,7 @@ Begin
|
||||
A_IMUL:
|
||||
With paicpu(p1)^ Do
|
||||
TmpResult :=
|
||||
((ops = 1) and (reg = R_EAX)) or
|
||||
((ops = 1) and (reg in [R_EAX,R_EDX])) or
|
||||
((ops = 2) and (Reg32(oper[1].reg) = reg)) or
|
||||
((ops = 3) and (Reg32(oper[2].reg) = reg));
|
||||
A_DIV, A_IDIV, A_MUL:
|
||||
@ -1098,10 +1183,11 @@ Begin
|
||||
Else s := 0
|
||||
End;
|
||||
|
||||
Function RegInSequence(Reg: TRegister; Const Content: TContent): Boolean;
|
||||
{checks the whole sequence of Content (so StartMod and and the next NrOfMods
|
||||
Pai objects) to see whether Reg is used somewhere, without it being loaded
|
||||
with something else first}
|
||||
Function sequenceDependsonReg(Const Content: TContent; seqReg, Reg: TRegister): Boolean;
|
||||
{ Content is the sequence of instructions that describes the contents of }
|
||||
{ seqReg. Reg is being overwritten by the current instruction. If the }
|
||||
{ content of seqReg depends on reg (ie. because of a }
|
||||
{ "movl (seqreg,reg), seqReg" instruction), this function returns true }
|
||||
Var p: Pai;
|
||||
Counter: Byte;
|
||||
TmpResult: Boolean;
|
||||
@ -1117,35 +1203,30 @@ Begin
|
||||
If (p^.typ = ait_instruction) and
|
||||
((Paicpu(p)^.opcode = A_MOV) or
|
||||
(Paicpu(p)^.opcode = A_MOVZX) or
|
||||
(Paicpu(p)^.opcode = A_MOVSX))
|
||||
Then
|
||||
Begin
|
||||
If (Paicpu(p)^.oper[0].typ = top_ref) Then
|
||||
With Paicpu(p)^.oper[0].ref^ Do
|
||||
If (Base = procinfo^.FramePointer) And
|
||||
(Index = R_NO)
|
||||
Then
|
||||
Begin
|
||||
RegsChecked := RegsChecked + [Reg32(Paicpu(p)^.oper[1].reg)];
|
||||
If Reg = Reg32(Paicpu(p)^.oper[1].reg) Then
|
||||
Break;
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
If (Base = Reg) And
|
||||
Not(Base In RegsChecked)
|
||||
Then TmpResult := True;
|
||||
If Not(TmpResult) And
|
||||
(Index = Reg) And
|
||||
Not(Index In RegsChecked)
|
||||
Then TmpResult := True;
|
||||
End
|
||||
End
|
||||
Else TmpResult := RegInInstruction(Reg, p);
|
||||
(Paicpu(p)^.opcode = A_MOVSX) or
|
||||
(paicpu(p)^.opcode = A_LEA)) and
|
||||
(Paicpu(p)^.oper[0].typ = top_ref) Then
|
||||
With Paicpu(p)^.oper[0].ref^ Do
|
||||
If ((Base = procinfo^.FramePointer) or
|
||||
(assigned(symbol) and (base = R_NO))) And
|
||||
(Index = R_NO) Then
|
||||
Begin
|
||||
RegsChecked := RegsChecked + [Reg32(Paicpu(p)^.oper[1].reg)];
|
||||
If Reg = Reg32(Paicpu(p)^.oper[1].reg) Then
|
||||
Break;
|
||||
End
|
||||
Else
|
||||
tmpResult :=
|
||||
regReadByInstruction(reg,p) and
|
||||
regModifiedByInstruction(seqReg,p)
|
||||
Else
|
||||
tmpResult :=
|
||||
regReadByInstruction(reg,p) and
|
||||
regModifiedByInstruction(seqReg,p);
|
||||
Inc(Counter);
|
||||
GetNextInstruction(p,p)
|
||||
End;
|
||||
RegInSequence := TmpResult
|
||||
sequenceDependsonReg := TmpResult
|
||||
End;
|
||||
|
||||
Procedure DestroyReg(p1: PPaiProp; Reg: TRegister; doIncState:Boolean);
|
||||
@ -1173,20 +1254,19 @@ Begin
|
||||
WState := TmpWState;
|
||||
RState := TmpRState;
|
||||
End;
|
||||
For Counter := R_EAX to R_EDI Do
|
||||
With p1^.Regs[Counter] Do
|
||||
For counter := R_EAX to R_EDI Do
|
||||
With p1^.Regs[counter] Do
|
||||
If (Typ = Con_Ref) And
|
||||
RegInSequence(Reg, p1^.Regs[Counter])
|
||||
Then
|
||||
Begin
|
||||
if doIncState then
|
||||
IncState(WState);
|
||||
TmpWState := WState;
|
||||
TmpRState := RState;
|
||||
FillChar(p1^.Regs[Counter], SizeOf(TContent), 0);
|
||||
WState := TmpWState;
|
||||
RState := TmpRState;
|
||||
End;
|
||||
sequenceDependsOnReg(p1^.Regs[counter],counter,reg) Then
|
||||
Begin
|
||||
if doIncState then
|
||||
IncState(WState);
|
||||
TmpWState := WState;
|
||||
TmpRState := RState;
|
||||
FillChar(p1^.Regs[Counter], SizeOf(TContent), 0);
|
||||
WState := TmpWState;
|
||||
RState := TmpRState;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
|
||||
@ -1561,9 +1641,24 @@ Begin {initializes/desrtoys all registers}
|
||||
End;
|
||||
|
||||
Procedure DestroyOp(PaiObj: Pai; const o:Toper);
|
||||
{$ifdef statedebug}
|
||||
var hp: pai;
|
||||
{$endif statedebug}
|
||||
|
||||
Begin
|
||||
Case o.typ Of
|
||||
top_reg: DestroyReg(PPaiProp(PaiObj^.OptInfo), o.reg, true);
|
||||
top_reg:
|
||||
begin
|
||||
{$ifdef statedebug}
|
||||
hp := new(pai_asm_comment,init(strpnew('destroying '+att_reg2str[o.reg])));
|
||||
hp^.next := paiobj^.next;
|
||||
hp^.previous := paiobj;
|
||||
paiobj^.next := hp;
|
||||
if assigned(hp^.next) then
|
||||
hp^.next^.previous := hp;
|
||||
{$endif statedebug}
|
||||
DestroyReg(PPaiProp(PaiObj^.OptInfo), o.reg, true);
|
||||
end;
|
||||
top_ref:
|
||||
Begin
|
||||
ReadRef(PPaiProp(PaiObj^.OptInfo), o.ref);
|
||||
@ -1610,6 +1705,10 @@ Begin
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
{$ifdef statedebug}
|
||||
hp := new(pai_asm_comment,init(strpnew('destroying '+att_reg2str[reg])));
|
||||
insertllitem(asml,p,p^.next,hp);
|
||||
{$endif statedebug}
|
||||
DestroyReg(PPaiProp(p^.optinfo), Reg, true);
|
||||
{$ifdef StateDebug}
|
||||
hp := new(pai_asm_comment,init(strpnew(att_reg2str[reg]+': '+tostr(PPaiProp(p^.optinfo)^.Regs[reg].WState))));
|
||||
@ -1890,6 +1989,11 @@ Begin
|
||||
Case Paicpu(p)^.oper[1].typ Of
|
||||
Top_Reg:
|
||||
Begin
|
||||
{$ifdef statedebug}
|
||||
hp := new(pai_asm_comment,init(strpnew('destroying '+
|
||||
att_reg2str[Paicpu(p)^.oper[1].reg])));
|
||||
insertllitem(asml,p,p^.next,hp);
|
||||
{$endif statedebug}
|
||||
DestroyReg(CurProp, Paicpu(p)^.oper[1].reg, true);
|
||||
ReadReg(CurProp, Paicpu(p)^.oper[0].reg);
|
||||
{ CurProp^.Regs[Paicpu(p)^.oper[1].reg] :=
|
||||
@ -1908,7 +2012,6 @@ Begin
|
||||
Top_Ref:
|
||||
Begin {destination is always a register in this case}
|
||||
ReadRef(CurProp, Paicpu(p)^.oper[0].ref);
|
||||
ReadReg(CurProp, Paicpu(p)^.oper[1].reg);
|
||||
TmpReg := Reg32(Paicpu(p)^.oper[1].reg);
|
||||
If RegInRef(TmpReg, Paicpu(p)^.oper[0].ref^) And
|
||||
(CurProp^.Regs[TmpReg].Typ = Con_Ref)
|
||||
@ -1927,6 +2030,10 @@ Begin
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
{$ifdef statedebug}
|
||||
hp := new(pai_asm_comment,init(strpnew('destroying & initing '+att_reg2str[tmpreg])));
|
||||
insertllitem(asml,p,p^.next,hp);
|
||||
{$endif statedebug}
|
||||
DestroyReg(CurProp, TmpReg, true);
|
||||
If Not(RegInRef(TmpReg, Paicpu(p)^.oper[0].ref^)) Then
|
||||
With CurProp^.Regs[TmpReg] Do
|
||||
@ -1948,6 +2055,10 @@ Begin
|
||||
Top_Reg:
|
||||
Begin
|
||||
TmpReg := Reg32(Paicpu(p)^.oper[1].reg);
|
||||
{$ifdef statedebug}
|
||||
hp := new(pai_asm_comment,init(strpnew('destroying '+att_reg2str[tmpreg])));
|
||||
insertllitem(asml,p,p^.next,hp);
|
||||
{$endif statedebug}
|
||||
With CurProp^.Regs[TmpReg] Do
|
||||
Begin
|
||||
DestroyReg(CurProp, TmpReg, true);
|
||||
@ -1971,6 +2082,10 @@ Begin
|
||||
If (Paicpu(p)^.OpCode = A_IDIV) or
|
||||
(Paicpu(p)^.OpCode = A_DIV) Then
|
||||
ReadReg(CurProp,R_EDX);
|
||||
{$ifdef statedebug}
|
||||
hp := new(pai_asm_comment,init(strpnew('destroying eax and edx')));
|
||||
insertllitem(asml,p,p^.next,hp);
|
||||
{$endif statedebug}
|
||||
DestroyReg(CurProp, R_EAX, true);
|
||||
DestroyReg(CurProp, R_EDX, true)
|
||||
End;
|
||||
@ -1982,18 +2097,25 @@ Begin
|
||||
If (Paicpu(p)^.oper[1].typ = top_none) Then
|
||||
Begin
|
||||
ReadReg(CurProp,R_EAX);
|
||||
{$ifdef statedebug}
|
||||
hp := new(pai_asm_comment,init(strpnew('destroying eax and edx')));
|
||||
insertllitem(asml,p,p^.next,hp);
|
||||
{$endif statedebug}
|
||||
DestroyReg(CurProp, R_EAX, true);
|
||||
DestroyReg(CurProp, R_EDX, true)
|
||||
End
|
||||
Else
|
||||
{$ifdef arithopt}
|
||||
AddInstr2OpContents(Paicpu(p), Paicpu(p)^.oper[1])
|
||||
AddInstr2OpContents(
|
||||
{$ifdef statedebug}asml,{$endif}
|
||||
Paicpu(p), Paicpu(p)^.oper[1])
|
||||
{$else arithopt}
|
||||
DestroyOp(p, Paicpu(p)^.oper[1])
|
||||
{$endif arithopt}
|
||||
Else
|
||||
{$ifdef arithopt}
|
||||
AddInstr2OpContents(Paicpu(p), Paicpu(p)^.oper[2]);
|
||||
AddInstr2OpContents({$ifdef statedebug}asml,{$endif}
|
||||
Paicpu(p), Paicpu(p)^.oper[2]);
|
||||
{$else arithopt}
|
||||
DestroyOp(p, Paicpu(p)^.oper[2]);
|
||||
{$endif arithopt}
|
||||
@ -2003,8 +2125,17 @@ Begin
|
||||
begin
|
||||
readop(curprop,paicpu(p)^.oper[0]);
|
||||
if reginref(paicpu(p)^.oper[1].reg,paicpu(p)^.oper[0].ref^) then
|
||||
AddInstr2RegContents(paicpu(p), paicpu(p)^.oper[1].reg)
|
||||
else destroyreg(curprop,paicpu(p)^.oper[1].reg,true);
|
||||
AddInstr2RegContents({$ifdef statedebug}asml,{$endif}
|
||||
paicpu(p), paicpu(p)^.oper[1].reg)
|
||||
else
|
||||
begin
|
||||
{$ifdef statedebug}
|
||||
hp := new(pai_asm_comment,init(strpnew('destroying '+
|
||||
att_reg2str[paicpu(p)^.oper[1].reg])));
|
||||
insertllitem(asml,p,p^.next,hp);
|
||||
{$endif statedebug}
|
||||
destroyreg(curprop,paicpu(p)^.oper[1].reg,true);
|
||||
end;
|
||||
end;
|
||||
{$endif arithopt}
|
||||
Else
|
||||
@ -2019,13 +2150,17 @@ Begin
|
||||
Begin
|
||||
If (InstrProp.Ch[Cnt] >= Ch_RWEAX) Then
|
||||
ReadReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]));
|
||||
{$ifdef statedebug}
|
||||
hp := new(pai_asm_comment,init(strpnew('destroying '+
|
||||
att_reg2str[TCh2Reg(InstrProp.Ch[Cnt])])));
|
||||
insertllitem(asml,p,p^.next,hp);
|
||||
{$endif statedebug}
|
||||
DestroyReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]), true);
|
||||
End;
|
||||
{$ifdef arithopt}
|
||||
Ch_MEAX..Ch_MEDI:
|
||||
AddInstr2RegContents({$ifdef statedebug} asml, {$endif}
|
||||
Paicpu(p),
|
||||
TCh2Reg(InstrProp.Ch[Cnt]));
|
||||
AddInstr2RegContents({$ifdef statedebug} asml,{$endif}
|
||||
Paicpu(p),TCh2Reg(InstrProp.Ch[Cnt]));
|
||||
{$endif arithopt}
|
||||
Ch_CDirFlag: CurProp^.DirFlag := F_NotSet;
|
||||
Ch_SDirFlag: CurProp^.DirFlag := F_Set;
|
||||
@ -2075,6 +2210,11 @@ Begin
|
||||
Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU:
|
||||
Else
|
||||
Begin
|
||||
{$ifdef statedebug}
|
||||
hp := new(pai_asm_comment,init(strpnew(
|
||||
'destroying all regs for prev instruction')));
|
||||
insertllitem(asml,p, p^.next,hp);
|
||||
{$endif statedebug}
|
||||
DestroyAllRegs(CurProp);
|
||||
End;
|
||||
End;
|
||||
@ -2086,6 +2226,11 @@ Begin
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
{$ifdef statedebug}
|
||||
hp := new(pai_asm_comment,init(strpnew(
|
||||
'destroying all regs: unknown pai: '+tostr(ord(p^.typ)))));
|
||||
insertllitem(asml,p, p^.next,hp);
|
||||
{$endif statedebug}
|
||||
DestroyAllRegs(CurProp);
|
||||
End;
|
||||
End;
|
||||
@ -2190,7 +2335,14 @@ End.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.85 2000-03-25 18:58:00 jonas
|
||||
Revision 1.86 2000-04-10 12:45:56 jonas
|
||||
* fixed a serious bug in the CSE which (I think) only showed with
|
||||
-dnewoptimizations when using multi-dimensional arrays with
|
||||
elements of a size different from 1, 2 or 4 (especially strings).
|
||||
* made the DFA/CSE more robust (much less dependent on specifics of the
|
||||
code generator)
|
||||
|
||||
Revision 1.85 2000/03/25 18:58:00 jonas
|
||||
* moved AllocRegBetween() from csopt386 to this unit because it's now
|
||||
also used by popt386
|
||||
|
||||
@ -2278,4 +2430,4 @@ End.
|
||||
Revision 1.62 1999/10/07 16:07:35 jonas
|
||||
* small bugfix in ArrayRefsEq
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user