mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-13 12:49:20 +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 }
|
{ be used anymore after the sequence, are still used nevertheless (when }
|
||||||
{ range checking is on for instance, because this is not "normal" generated }
|
{ range checking is on for instance, because this is not "normal" generated }
|
||||||
{ code, but more or less manually inserted) }
|
{ code, but more or less manually inserted) }
|
||||||
|
(*
|
||||||
{$ifndef fpc}
|
{$ifndef fpc}
|
||||||
If TmpResult Then
|
If TmpResult Then
|
||||||
{$else fpc}
|
{$else fpc}
|
||||||
@ -210,6 +211,7 @@ Begin {CheckSequence}
|
|||||||
Exclude(RegInfo.RegsLoadedForRef,RegCounter);
|
Exclude(RegInfo.RegsLoadedForRef,RegCounter);
|
||||||
End;
|
End;
|
||||||
End;
|
End;
|
||||||
|
*)
|
||||||
{$ifndef fpc}
|
{$ifndef fpc}
|
||||||
CheckSequence := TmpResult;
|
CheckSequence := TmpResult;
|
||||||
{$endif fpc}
|
{$endif fpc}
|
||||||
@ -543,69 +545,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
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);
|
procedure DoReplaceReadReg(orgReg,newReg: tregister; p: paicpu);
|
||||||
var opCount: byte;
|
var opCount: byte;
|
||||||
begin
|
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, }
|
{ false otherwise. If successful, the contents of newReg are set to c, }
|
||||||
{ which should hold the contents of newReg before the current sequence }
|
{ which should hold the contents of newReg before the current sequence }
|
||||||
{ started }
|
{ 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 }
|
{ where newReg was replaced by orgReg }
|
||||||
var endP, hp: Pai;
|
var endP, hp: Pai;
|
||||||
removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead: Boolean;
|
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
|
{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
|
||||||
two different sequences}
|
two different sequences}
|
||||||
Var Cnt, Cnt2: Longint;
|
Var Cnt, Cnt2, Cnt3: Longint;
|
||||||
p, hp1, hp2: Pai;
|
p, hp1, hp2: Pai;
|
||||||
hp3, hp4: pai;
|
hp3, hp4: pai;
|
||||||
{$ifdef replacereg}
|
{$ifdef replacereg}
|
||||||
@ -916,9 +855,14 @@ Begin
|
|||||||
Begin
|
Begin
|
||||||
If (p = StartMod) And
|
If (p = StartMod) And
|
||||||
GetLastInstruction (p, hp1) And
|
GetLastInstruction (p, hp1) And
|
||||||
(hp1^.typ <> ait_marker)
|
(hp1^.typ <> ait_marker) Then
|
||||||
Then
|
|
||||||
{so we don't try to check a sequence when p is the first instruction of the block}
|
{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
|
If CheckSequence(p, Paicpu(p)^.oper[1].reg, Cnt, RegInfo) And
|
||||||
(Cnt > 0) Then
|
(Cnt > 0) Then
|
||||||
Begin
|
Begin
|
||||||
@ -943,16 +887,31 @@ Begin
|
|||||||
While Cnt2 <= Cnt Do
|
While Cnt2 <= Cnt Do
|
||||||
Begin
|
Begin
|
||||||
If (hp1 = nil) And
|
If (hp1 = nil) And
|
||||||
Not(RegInInstruction(Paicpu(hp2)^.oper[1].reg, p) Or
|
Not(RegInInstruction(Paicpu(hp2)^.oper[1].reg, p)) And
|
||||||
RegInInstruction(Reg32(Paicpu(hp2)^.oper[1].reg), p)) And
|
((p^.typ = ait_instruction) And
|
||||||
Not((p^.typ = ait_instruction) And
|
((paicpu(p)^.OpCode = A_MOV) or
|
||||||
(paicpu(p)^.OpCode = A_MOV) And
|
(paicpu(p)^.opcode = A_MOVZX) or
|
||||||
(paicpu(p)^.Oper[0].typ = top_ref) And
|
(paicpu(p)^.opcode = A_MOVSX)) And
|
||||||
(PPaiProp(p^.OptInfo)^.Regs[Reg32(paicpu(p)^.Oper[1].reg)].NrOfMods
|
(paicpu(p)^.Oper[0].typ = top_ref)) Then
|
||||||
<= (Cnt - Cnt2 + 1)))
|
if (PPaiProp(p^.OptInfo)^.Regs[Reg32(paicpu(p)^.Oper[1].reg)].NrOfMods
|
||||||
Then hp1 := p;
|
<= (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}
|
{$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}
|
{$endif noremove}
|
||||||
Inc(Cnt2);
|
Inc(Cnt2);
|
||||||
GetNextInstruction(p, p);
|
GetNextInstruction(p, p);
|
||||||
@ -1072,7 +1031,8 @@ Begin
|
|||||||
End;
|
End;
|
||||||
hp3 := New(Pai_Marker,Init(NoPropInfoEnd));
|
hp3 := New(Pai_Marker,Init(NoPropInfoEnd));
|
||||||
InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
|
InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
|
||||||
If hp1 <> nil Then p := hp1;
|
If hp1 <> nil Then
|
||||||
|
p := hp1;
|
||||||
Continue;
|
Continue;
|
||||||
End
|
End
|
||||||
Else
|
Else
|
||||||
@ -1085,14 +1045,14 @@ Begin
|
|||||||
Cnt2 := 1;
|
Cnt2 := 1;
|
||||||
While Cnt2 <= Cnt Do
|
While Cnt2 <= Cnt Do
|
||||||
Begin
|
Begin
|
||||||
If RegInInstruction(Paicpu(hp2)^.oper[1].reg, p) Or
|
If RegInInstruction(Paicpu(hp2)^.oper[1].reg, p) Then
|
||||||
RegInInstruction(Reg32(Paicpu(hp2)^.oper[1].reg), p) Then
|
|
||||||
PPaiProp(p^.OptInfo)^.CanBeRemoved := False;
|
PPaiProp(p^.OptInfo)^.CanBeRemoved := False;
|
||||||
Inc(Cnt2);
|
Inc(Cnt2);
|
||||||
GetNextInstruction(p, p);
|
GetNextInstruction(p, p);
|
||||||
End;
|
End;
|
||||||
Continue;
|
Continue;
|
||||||
End;
|
End;
|
||||||
|
End;
|
||||||
End;
|
End;
|
||||||
End;
|
End;
|
||||||
{$ifdef replacereg}
|
{$ifdef replacereg}
|
||||||
@ -1216,7 +1176,14 @@ End.
|
|||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$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
|
* 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
|
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
|
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
|
Revision 1.24 1999/08/25 11:59:58 jonas
|
||||||
* changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
|
* 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 RefsEqual(Const R1, R2: TReference): Boolean;
|
||||||
Function IsGP32Reg(Reg: TRegister): Boolean;
|
Function IsGP32Reg(Reg: TRegister): Boolean;
|
||||||
Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
|
Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
|
||||||
Function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
|
function RegReadByInstruction(reg: TRegister; hp: pai): boolean;
|
||||||
{$ifdef newOptimizations}
|
function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||||
Function RegInOp(Reg: TRegister; const o:toper): Boolean;
|
function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||||
{$endif newOptimizations}
|
function RegInOp(Reg: TRegister; const o:toper): Boolean;
|
||||||
Function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
|
|
||||||
|
|
||||||
Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
|
Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
|
||||||
Function GetLastInstruction(Current: Pai; Var Last: 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)
|
RegInRef := (Ref.Base = Reg) Or (Ref.Index = Reg)
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
|
function RegReadByInstruction(reg: TRegister; hp: pai): boolean;
|
||||||
{checks if Reg is used by the instruction p1}
|
var p: paicpu;
|
||||||
Var Counter: Longint;
|
opCount: byte;
|
||||||
TmpResult: Boolean;
|
begin
|
||||||
Begin
|
RegReadByInstruction := false;
|
||||||
TmpResult := False;
|
reg := reg32(reg);
|
||||||
If (Pai(p1)^.typ = ait_instruction) Then
|
p := paicpu(hp);
|
||||||
Begin
|
if hp^.typ <> ait_instruction then
|
||||||
Reg := Reg32(Reg);
|
exit;
|
||||||
Counter := 0;
|
case p^.opcode of
|
||||||
Repeat
|
A_IMUL:
|
||||||
Case Paicpu(p1)^.oper[Counter].typ Of
|
case p^.ops of
|
||||||
Top_Reg: TmpResult := Reg = Reg32(Paicpu(p1)^.oper[Counter].reg);
|
1: regReadByInstruction := (reg = R_EAX) or reginOp(reg,p^.oper[0]);
|
||||||
Top_Ref: TmpResult := RegInRef(Reg, Paicpu(p1)^.oper[Counter].ref^);
|
2,3:
|
||||||
End;
|
regReadByInstruction := regInOp(reg,p^.oper[0]) or
|
||||||
Inc(Counter)
|
regInOp(reg,p^.oper[1]);
|
||||||
Until (Counter = 3) or TmpResult;
|
end;
|
||||||
End;
|
A_IDIV,A_DIV,A_MUL:
|
||||||
RegInInstruction := TmpResult
|
begin
|
||||||
End;
|
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;
|
Function RegInOp(Reg: TRegister; const o:toper): Boolean;
|
||||||
Begin
|
Begin
|
||||||
RegInOp := False;
|
RegInOp := False;
|
||||||
|
reg := reg32(reg);
|
||||||
Case o.typ Of
|
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
|
top_ref: RegInOp := (Reg = o.ref^.Base) Or
|
||||||
(Reg = o.ref^.Index);
|
(Reg = o.ref^.Index);
|
||||||
End;
|
End;
|
||||||
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;
|
Function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||||
Var InstrProp: TInsProp;
|
Var InstrProp: TInsProp;
|
||||||
@ -830,7 +915,7 @@ Begin
|
|||||||
A_IMUL:
|
A_IMUL:
|
||||||
With paicpu(p1)^ Do
|
With paicpu(p1)^ Do
|
||||||
TmpResult :=
|
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 = 2) and (Reg32(oper[1].reg) = reg)) or
|
||||||
((ops = 3) and (Reg32(oper[2].reg) = reg));
|
((ops = 3) and (Reg32(oper[2].reg) = reg));
|
||||||
A_DIV, A_IDIV, A_MUL:
|
A_DIV, A_IDIV, A_MUL:
|
||||||
@ -1098,10 +1183,11 @@ Begin
|
|||||||
Else s := 0
|
Else s := 0
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Function RegInSequence(Reg: TRegister; Const Content: TContent): Boolean;
|
Function sequenceDependsonReg(Const Content: TContent; seqReg, Reg: TRegister): Boolean;
|
||||||
{checks the whole sequence of Content (so StartMod and and the next NrOfMods
|
{ Content is the sequence of instructions that describes the contents of }
|
||||||
Pai objects) to see whether Reg is used somewhere, without it being loaded
|
{ seqReg. Reg is being overwritten by the current instruction. If the }
|
||||||
with something else first}
|
{ content of seqReg depends on reg (ie. because of a }
|
||||||
|
{ "movl (seqreg,reg), seqReg" instruction), this function returns true }
|
||||||
Var p: Pai;
|
Var p: Pai;
|
||||||
Counter: Byte;
|
Counter: Byte;
|
||||||
TmpResult: Boolean;
|
TmpResult: Boolean;
|
||||||
@ -1117,35 +1203,30 @@ Begin
|
|||||||
If (p^.typ = ait_instruction) and
|
If (p^.typ = ait_instruction) and
|
||||||
((Paicpu(p)^.opcode = A_MOV) or
|
((Paicpu(p)^.opcode = A_MOV) or
|
||||||
(Paicpu(p)^.opcode = A_MOVZX) or
|
(Paicpu(p)^.opcode = A_MOVZX) or
|
||||||
(Paicpu(p)^.opcode = A_MOVSX))
|
(Paicpu(p)^.opcode = A_MOVSX) or
|
||||||
Then
|
(paicpu(p)^.opcode = A_LEA)) and
|
||||||
Begin
|
(Paicpu(p)^.oper[0].typ = top_ref) Then
|
||||||
If (Paicpu(p)^.oper[0].typ = top_ref) Then
|
With Paicpu(p)^.oper[0].ref^ Do
|
||||||
With Paicpu(p)^.oper[0].ref^ Do
|
If ((Base = procinfo^.FramePointer) or
|
||||||
If (Base = procinfo^.FramePointer) And
|
(assigned(symbol) and (base = R_NO))) And
|
||||||
(Index = R_NO)
|
(Index = R_NO) Then
|
||||||
Then
|
Begin
|
||||||
Begin
|
RegsChecked := RegsChecked + [Reg32(Paicpu(p)^.oper[1].reg)];
|
||||||
RegsChecked := RegsChecked + [Reg32(Paicpu(p)^.oper[1].reg)];
|
If Reg = Reg32(Paicpu(p)^.oper[1].reg) Then
|
||||||
If Reg = Reg32(Paicpu(p)^.oper[1].reg) Then
|
Break;
|
||||||
Break;
|
End
|
||||||
End
|
Else
|
||||||
Else
|
tmpResult :=
|
||||||
Begin
|
regReadByInstruction(reg,p) and
|
||||||
If (Base = Reg) And
|
regModifiedByInstruction(seqReg,p)
|
||||||
Not(Base In RegsChecked)
|
Else
|
||||||
Then TmpResult := True;
|
tmpResult :=
|
||||||
If Not(TmpResult) And
|
regReadByInstruction(reg,p) and
|
||||||
(Index = Reg) And
|
regModifiedByInstruction(seqReg,p);
|
||||||
Not(Index In RegsChecked)
|
|
||||||
Then TmpResult := True;
|
|
||||||
End
|
|
||||||
End
|
|
||||||
Else TmpResult := RegInInstruction(Reg, p);
|
|
||||||
Inc(Counter);
|
Inc(Counter);
|
||||||
GetNextInstruction(p,p)
|
GetNextInstruction(p,p)
|
||||||
End;
|
End;
|
||||||
RegInSequence := TmpResult
|
sequenceDependsonReg := TmpResult
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Procedure DestroyReg(p1: PPaiProp; Reg: TRegister; doIncState:Boolean);
|
Procedure DestroyReg(p1: PPaiProp; Reg: TRegister; doIncState:Boolean);
|
||||||
@ -1173,20 +1254,19 @@ Begin
|
|||||||
WState := TmpWState;
|
WState := TmpWState;
|
||||||
RState := TmpRState;
|
RState := TmpRState;
|
||||||
End;
|
End;
|
||||||
For Counter := R_EAX to R_EDI Do
|
For counter := R_EAX to R_EDI Do
|
||||||
With p1^.Regs[Counter] Do
|
With p1^.Regs[counter] Do
|
||||||
If (Typ = Con_Ref) And
|
If (Typ = Con_Ref) And
|
||||||
RegInSequence(Reg, p1^.Regs[Counter])
|
sequenceDependsOnReg(p1^.Regs[counter],counter,reg) Then
|
||||||
Then
|
Begin
|
||||||
Begin
|
if doIncState then
|
||||||
if doIncState then
|
IncState(WState);
|
||||||
IncState(WState);
|
TmpWState := WState;
|
||||||
TmpWState := WState;
|
TmpRState := RState;
|
||||||
TmpRState := RState;
|
FillChar(p1^.Regs[Counter], SizeOf(TContent), 0);
|
||||||
FillChar(p1^.Regs[Counter], SizeOf(TContent), 0);
|
WState := TmpWState;
|
||||||
WState := TmpWState;
|
RState := TmpRState;
|
||||||
RState := TmpRState;
|
End;
|
||||||
End;
|
|
||||||
End;
|
End;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
@ -1561,9 +1641,24 @@ Begin {initializes/desrtoys all registers}
|
|||||||
End;
|
End;
|
||||||
|
|
||||||
Procedure DestroyOp(PaiObj: Pai; const o:Toper);
|
Procedure DestroyOp(PaiObj: Pai; const o:Toper);
|
||||||
|
{$ifdef statedebug}
|
||||||
|
var hp: pai;
|
||||||
|
{$endif statedebug}
|
||||||
|
|
||||||
Begin
|
Begin
|
||||||
Case o.typ Of
|
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:
|
top_ref:
|
||||||
Begin
|
Begin
|
||||||
ReadRef(PPaiProp(PaiObj^.OptInfo), o.ref);
|
ReadRef(PPaiProp(PaiObj^.OptInfo), o.ref);
|
||||||
@ -1610,6 +1705,10 @@ Begin
|
|||||||
End
|
End
|
||||||
Else
|
Else
|
||||||
Begin
|
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);
|
DestroyReg(PPaiProp(p^.optinfo), Reg, true);
|
||||||
{$ifdef StateDebug}
|
{$ifdef StateDebug}
|
||||||
hp := new(pai_asm_comment,init(strpnew(att_reg2str[reg]+': '+tostr(PPaiProp(p^.optinfo)^.Regs[reg].WState))));
|
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
|
Case Paicpu(p)^.oper[1].typ Of
|
||||||
Top_Reg:
|
Top_Reg:
|
||||||
Begin
|
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);
|
DestroyReg(CurProp, Paicpu(p)^.oper[1].reg, true);
|
||||||
ReadReg(CurProp, Paicpu(p)^.oper[0].reg);
|
ReadReg(CurProp, Paicpu(p)^.oper[0].reg);
|
||||||
{ CurProp^.Regs[Paicpu(p)^.oper[1].reg] :=
|
{ CurProp^.Regs[Paicpu(p)^.oper[1].reg] :=
|
||||||
@ -1908,7 +2012,6 @@ Begin
|
|||||||
Top_Ref:
|
Top_Ref:
|
||||||
Begin {destination is always a register in this case}
|
Begin {destination is always a register in this case}
|
||||||
ReadRef(CurProp, Paicpu(p)^.oper[0].ref);
|
ReadRef(CurProp, Paicpu(p)^.oper[0].ref);
|
||||||
ReadReg(CurProp, Paicpu(p)^.oper[1].reg);
|
|
||||||
TmpReg := Reg32(Paicpu(p)^.oper[1].reg);
|
TmpReg := Reg32(Paicpu(p)^.oper[1].reg);
|
||||||
If RegInRef(TmpReg, Paicpu(p)^.oper[0].ref^) And
|
If RegInRef(TmpReg, Paicpu(p)^.oper[0].ref^) And
|
||||||
(CurProp^.Regs[TmpReg].Typ = Con_Ref)
|
(CurProp^.Regs[TmpReg].Typ = Con_Ref)
|
||||||
@ -1927,6 +2030,10 @@ Begin
|
|||||||
End
|
End
|
||||||
Else
|
Else
|
||||||
Begin
|
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);
|
DestroyReg(CurProp, TmpReg, true);
|
||||||
If Not(RegInRef(TmpReg, Paicpu(p)^.oper[0].ref^)) Then
|
If Not(RegInRef(TmpReg, Paicpu(p)^.oper[0].ref^)) Then
|
||||||
With CurProp^.Regs[TmpReg] Do
|
With CurProp^.Regs[TmpReg] Do
|
||||||
@ -1948,6 +2055,10 @@ Begin
|
|||||||
Top_Reg:
|
Top_Reg:
|
||||||
Begin
|
Begin
|
||||||
TmpReg := Reg32(Paicpu(p)^.oper[1].reg);
|
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
|
With CurProp^.Regs[TmpReg] Do
|
||||||
Begin
|
Begin
|
||||||
DestroyReg(CurProp, TmpReg, true);
|
DestroyReg(CurProp, TmpReg, true);
|
||||||
@ -1971,6 +2082,10 @@ Begin
|
|||||||
If (Paicpu(p)^.OpCode = A_IDIV) or
|
If (Paicpu(p)^.OpCode = A_IDIV) or
|
||||||
(Paicpu(p)^.OpCode = A_DIV) Then
|
(Paicpu(p)^.OpCode = A_DIV) Then
|
||||||
ReadReg(CurProp,R_EDX);
|
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_EAX, true);
|
||||||
DestroyReg(CurProp, R_EDX, true)
|
DestroyReg(CurProp, R_EDX, true)
|
||||||
End;
|
End;
|
||||||
@ -1982,18 +2097,25 @@ Begin
|
|||||||
If (Paicpu(p)^.oper[1].typ = top_none) Then
|
If (Paicpu(p)^.oper[1].typ = top_none) Then
|
||||||
Begin
|
Begin
|
||||||
ReadReg(CurProp,R_EAX);
|
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_EAX, true);
|
||||||
DestroyReg(CurProp, R_EDX, true)
|
DestroyReg(CurProp, R_EDX, true)
|
||||||
End
|
End
|
||||||
Else
|
Else
|
||||||
{$ifdef arithopt}
|
{$ifdef arithopt}
|
||||||
AddInstr2OpContents(Paicpu(p), Paicpu(p)^.oper[1])
|
AddInstr2OpContents(
|
||||||
|
{$ifdef statedebug}asml,{$endif}
|
||||||
|
Paicpu(p), Paicpu(p)^.oper[1])
|
||||||
{$else arithopt}
|
{$else arithopt}
|
||||||
DestroyOp(p, Paicpu(p)^.oper[1])
|
DestroyOp(p, Paicpu(p)^.oper[1])
|
||||||
{$endif arithopt}
|
{$endif arithopt}
|
||||||
Else
|
Else
|
||||||
{$ifdef arithopt}
|
{$ifdef arithopt}
|
||||||
AddInstr2OpContents(Paicpu(p), Paicpu(p)^.oper[2]);
|
AddInstr2OpContents({$ifdef statedebug}asml,{$endif}
|
||||||
|
Paicpu(p), Paicpu(p)^.oper[2]);
|
||||||
{$else arithopt}
|
{$else arithopt}
|
||||||
DestroyOp(p, Paicpu(p)^.oper[2]);
|
DestroyOp(p, Paicpu(p)^.oper[2]);
|
||||||
{$endif arithopt}
|
{$endif arithopt}
|
||||||
@ -2003,8 +2125,17 @@ Begin
|
|||||||
begin
|
begin
|
||||||
readop(curprop,paicpu(p)^.oper[0]);
|
readop(curprop,paicpu(p)^.oper[0]);
|
||||||
if reginref(paicpu(p)^.oper[1].reg,paicpu(p)^.oper[0].ref^) then
|
if reginref(paicpu(p)^.oper[1].reg,paicpu(p)^.oper[0].ref^) then
|
||||||
AddInstr2RegContents(paicpu(p), paicpu(p)^.oper[1].reg)
|
AddInstr2RegContents({$ifdef statedebug}asml,{$endif}
|
||||||
else destroyreg(curprop,paicpu(p)^.oper[1].reg,true);
|
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;
|
end;
|
||||||
{$endif arithopt}
|
{$endif arithopt}
|
||||||
Else
|
Else
|
||||||
@ -2019,13 +2150,17 @@ Begin
|
|||||||
Begin
|
Begin
|
||||||
If (InstrProp.Ch[Cnt] >= Ch_RWEAX) Then
|
If (InstrProp.Ch[Cnt] >= Ch_RWEAX) Then
|
||||||
ReadReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]));
|
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);
|
DestroyReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]), true);
|
||||||
End;
|
End;
|
||||||
{$ifdef arithopt}
|
{$ifdef arithopt}
|
||||||
Ch_MEAX..Ch_MEDI:
|
Ch_MEAX..Ch_MEDI:
|
||||||
AddInstr2RegContents({$ifdef statedebug} asml, {$endif}
|
AddInstr2RegContents({$ifdef statedebug} asml,{$endif}
|
||||||
Paicpu(p),
|
Paicpu(p),TCh2Reg(InstrProp.Ch[Cnt]));
|
||||||
TCh2Reg(InstrProp.Ch[Cnt]));
|
|
||||||
{$endif arithopt}
|
{$endif arithopt}
|
||||||
Ch_CDirFlag: CurProp^.DirFlag := F_NotSet;
|
Ch_CDirFlag: CurProp^.DirFlag := F_NotSet;
|
||||||
Ch_SDirFlag: CurProp^.DirFlag := F_Set;
|
Ch_SDirFlag: CurProp^.DirFlag := F_Set;
|
||||||
@ -2075,6 +2210,11 @@ Begin
|
|||||||
Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU:
|
Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU:
|
||||||
Else
|
Else
|
||||||
Begin
|
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);
|
DestroyAllRegs(CurProp);
|
||||||
End;
|
End;
|
||||||
End;
|
End;
|
||||||
@ -2086,6 +2226,11 @@ Begin
|
|||||||
End
|
End
|
||||||
Else
|
Else
|
||||||
Begin
|
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);
|
DestroyAllRegs(CurProp);
|
||||||
End;
|
End;
|
||||||
End;
|
End;
|
||||||
@ -2190,7 +2335,14 @@ End.
|
|||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$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
|
* moved AllocRegBetween() from csopt386 to this unit because it's now
|
||||||
also used by popt386
|
also used by popt386
|
||||||
|
|
||||||
@ -2278,4 +2430,4 @@ End.
|
|||||||
Revision 1.62 1999/10/07 16:07:35 jonas
|
Revision 1.62 1999/10/07 16:07:35 jonas
|
||||||
* small bugfix in ArrayRefsEq
|
* small bugfix in ArrayRefsEq
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user