mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-15 13:09:07 +02:00
* fixed small efficiency which caused some missed optimizations (saves 1
assembler instruction on the whole compiler/RTL source tree! :)
This commit is contained in:
parent
0950b2201a
commit
47b0fcf922
@ -61,12 +61,13 @@ Function CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint; Var RegInfo:
|
|||||||
is returned}
|
is returned}
|
||||||
Var hp2, hp3{, EndMod}: Pai;
|
Var hp2, hp3{, EndMod}: Pai;
|
||||||
PrevNonRemovablePai: Pai;
|
PrevNonRemovablePai: Pai;
|
||||||
|
Cnt, OldNrOfMods: Longint;
|
||||||
OrgRegInfo, HighRegInfo: TRegInfo;
|
OrgRegInfo, HighRegInfo: TRegInfo;
|
||||||
HighFound, OrgRegFound: Byte;
|
HighFound, OrgRegFound: Byte;
|
||||||
RegCounter: TRegister;
|
RegCounter: TRegister;
|
||||||
OrgRegResult: Boolean;
|
OrgRegResult: Boolean;
|
||||||
TmpResult: Boolean;
|
TmpResult: Boolean;
|
||||||
OldNrOfMods: Byte;
|
TmpState: Byte;
|
||||||
Begin {CheckSequence}
|
Begin {CheckSequence}
|
||||||
Reg := Reg32(Reg);
|
Reg := Reg32(Reg);
|
||||||
TmpResult := False;
|
TmpResult := False;
|
||||||
@ -100,91 +101,21 @@ Begin {CheckSequence}
|
|||||||
GetNextInstruction(hp3, hp3);
|
GetNextInstruction(hp3, hp3);
|
||||||
Inc(Found)
|
Inc(Found)
|
||||||
End;
|
End;
|
||||||
If (Found <> OldNrOfMods)
|
If (Found <> OldNrOfMods) Then
|
||||||
Then
|
Begin
|
||||||
Begin
|
TmpResult := False;
|
||||||
(* If ((Found+1) = OldNrOfMods) And
|
If (found > 0) then
|
||||||
Assigned(hp2) And
|
{this is correct because we only need to turn off the CanBeRemoved flag
|
||||||
(Pai(hp2)^.typ = ait_instruction) And
|
when an instruction has already been processed by CheckSequence
|
||||||
((Paicpu(hp2)^.opcode = A_MOV) or
|
(otherwise CanBeRemoved can't be true and thus can't have to be turned off).
|
||||||
(Paicpu(p1)^.opcode = A_MOVZX)) And
|
If it has already been processed by CheckSequence and flagged to be
|
||||||
(Paicpu(hp2)^.oper[0].typ = top_ref) And
|
removed, it means that it has been checked against a previous sequence
|
||||||
(Paicpu(hp2)^.optype[1] = top_reg) And
|
and that it was equal (otherwise CheckSequence would have returned false
|
||||||
Assigned(hp3) And
|
and the instruction wouldn't have been removed). If this "If found > 0"
|
||||||
(Pai(hp3)^.typ = ait_instruction) And
|
check is left out, incorrect optimizations are performed.}
|
||||||
((Paicpu(hp3)^.opcode = A_MOV) or
|
Found := PPaiProp(Pai(p)^.OptInfo)^.Regs[Reg].NrOfMods
|
||||||
(Paicpu(hp3)^.opcode = A_MOVZX)) And
|
End
|
||||||
(Paicpu(hp3)^.oper[0].typ = top_ref) And
|
Else TmpResult := True;
|
||||||
(Paicpu(hp3)^.optype[1] = top_reg) And
|
|
||||||
(Paicpu(hp2)^.opcode <> Paicpu(hp3)^.opcode) And
|
|
||||||
RefsEquivalent(TReference(Paicpu(hp2)^.oper[1]^),TReference(Paicpu(hp3)^.oper[1]^), RegInfo)
|
|
||||||
Then
|
|
||||||
|
|
||||||
{hack to be able to optimize
|
|
||||||
mov (mem), reg
|
|
||||||
mov (reg), reg
|
|
||||||
mov (reg), reg [*]
|
|
||||||
test reg, reg and the oposite (where the marked instructions are
|
|
||||||
jne l1 switched)
|
|
||||||
mov (mem), reg
|
|
||||||
mov (reg), reg
|
|
||||||
movzx (reg), reg [*]}
|
|
||||||
|
|
||||||
If (Paicpu(hp2)^.opcode = A_MOV)
|
|
||||||
Then
|
|
||||||
Begin
|
|
||||||
If (Paicpu(hp2)^.opsize = S_B) And
|
|
||||||
RegsEquivalent(Reg8toReg32(TRegister(Paicpu(hp2)^.oper[1])),
|
|
||||||
TRegister(Paicpu(hp3)^.oper[1]), RegInfo)
|
|
||||||
Then
|
|
||||||
Begin
|
|
||||||
Paicpu(hp2)^.opcode := A_MOVZX;
|
|
||||||
Paicpu(hp2)^.opsize := S_BL;
|
|
||||||
Paicpu(hp2)^.loadoper(1,Paicpu(hp3)^.oper[1]);
|
|
||||||
Inc(Found);
|
|
||||||
TmpResult := True;
|
|
||||||
End
|
|
||||||
Else
|
|
||||||
Begin
|
|
||||||
TmpResult := False;
|
|
||||||
If (Found > 0) Then
|
|
||||||
Found := PPaiProp(Pai(p)^.OptInfo)^.Regs[Reg].NrOfMods
|
|
||||||
End
|
|
||||||
End
|
|
||||||
Else
|
|
||||||
Begin
|
|
||||||
If (Paicpu(hp3)^.opsize = S_B) And
|
|
||||||
RegsEquivalent(TRegister(Paicpu(hp2)^.oper[1]),
|
|
||||||
Reg8toReg32(TRegister(Paicpu(hp3)^.oper[1])),
|
|
||||||
RegInfo)
|
|
||||||
Then
|
|
||||||
Begin
|
|
||||||
TmpResult := True;
|
|
||||||
Inc(Found)
|
|
||||||
End
|
|
||||||
Else
|
|
||||||
Begin
|
|
||||||
TmpResult := False;
|
|
||||||
If (Found > 0) Then
|
|
||||||
Found := PPaiProp(Pai(p)^.OptInfo)^.Regs[Reg].NrOfMods
|
|
||||||
End
|
|
||||||
End
|
|
||||||
Else *)
|
|
||||||
Begin
|
|
||||||
TmpResult := False;
|
|
||||||
If (found > 0) then
|
|
||||||
{this is correct because we only need to turn off the CanBeRemoved flag
|
|
||||||
when an instruction has already been processed by CheckSequence
|
|
||||||
(otherwise CanBeRemoved can't be true and thus can't have to be turned off).
|
|
||||||
If it has already been processed by CheckSequence and flagged to be
|
|
||||||
removed, it means that it has been checked against a previous sequence
|
|
||||||
and that it was equal (otherwise CheckSequence would have returned false
|
|
||||||
and the instruction wouldn't have been removed). If this "If found > 0"
|
|
||||||
check is left out, incorrect optimizations are performed.}
|
|
||||||
Found := PPaiProp(Pai(p)^.OptInfo)^.Regs[Reg].NrOfMods
|
|
||||||
End
|
|
||||||
End
|
|
||||||
Else TmpResult := True;
|
|
||||||
If TmpResult And
|
If TmpResult And
|
||||||
(Found > HighFound)
|
(Found > HighFound)
|
||||||
Then
|
Then
|
||||||
@ -211,16 +142,70 @@ Begin {CheckSequence}
|
|||||||
(HighFound > OrgRegFound))
|
(HighFound > OrgRegFound))
|
||||||
Then
|
Then
|
||||||
Begin
|
Begin
|
||||||
|
{$ifndef fpc}
|
||||||
|
TmpResult := True;
|
||||||
|
{$else fpc}
|
||||||
CheckSequence := True;
|
CheckSequence := True;
|
||||||
|
{$endif fpc}
|
||||||
RegInfo := HighRegInfo;
|
RegInfo := HighRegInfo;
|
||||||
Found := HighFound
|
Found := HighFound
|
||||||
End
|
End
|
||||||
Else
|
Else
|
||||||
Begin
|
Begin
|
||||||
|
{$ifndef fpc}
|
||||||
|
TmpResult := OrgRegResult;
|
||||||
|
{$else fpc}
|
||||||
CheckSequence := OrgRegResult;
|
CheckSequence := OrgRegResult;
|
||||||
|
{$endif fpc}
|
||||||
Found := OrgRegFound;
|
Found := OrgRegFound;
|
||||||
RegInfo := OrgRegInfo;
|
RegInfo := OrgRegInfo;
|
||||||
End;
|
End;
|
||||||
|
{ sometimes, registers in RegsLoadedForRef (which normally aren't/shouldn't }
|
||||||
|
{ 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}
|
||||||
|
If CheckSequence And (Found > 0) Then
|
||||||
|
{$endif fpc}
|
||||||
|
For RegCounter := R_EAX to R_EDI Do
|
||||||
|
If (RegCounter in RegInfo.RegsLoadedForRef) And
|
||||||
|
(RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
|
||||||
|
Begin
|
||||||
|
OldNrOfMods := PPaiProp(PrevNonRemovablePai^.OptInfo)^.
|
||||||
|
Regs[RegInfo.New2OldReg[RegCounter]].NrOfMods;
|
||||||
|
hp2 := p;
|
||||||
|
For Cnt := 1 to Pred(OldNrOfMods) Do
|
||||||
|
GetNextInstruction(hp2, hp2);
|
||||||
|
{ hp2 now containts the last instruction of the sequence }
|
||||||
|
{ get the writestate at this point of the register in TmpState }
|
||||||
|
TmpState := PPaiProp(hp2^.OptInfo)^.Regs[RegCounter].WState;
|
||||||
|
{ hp3 := first instruction after the sequence }
|
||||||
|
GetNextInstruction(hp2, hp2);
|
||||||
|
{ now, even though reg is in RegsLoadedForRef, sometimes it's still used }
|
||||||
|
{ afterwards. It is not if either it is not in usedregs anymore after the }
|
||||||
|
{ sequence, or if it is loaded with a new value right after the sequence }
|
||||||
|
If (TmpState = PPaiProp(hp2^.OptInfo)^.Regs[RegCounter].WState) And
|
||||||
|
(RegCounter in PPaiProp(hp2^.OptInfo)^.UsedRegs) Then
|
||||||
|
{ it is still used, so remove it from RegsLoadedForRef }
|
||||||
|
Begin
|
||||||
|
{$ifdef regrefdebug}
|
||||||
|
hp3 := new(pai_asm_comment,init(strpnew(att_reg2str[regcounter]+
|
||||||
|
' removed from regsloadedforref')));
|
||||||
|
hp3^.fileinfo := hp2^.fileinfo;
|
||||||
|
hp3^.next := hp2^.next;
|
||||||
|
hp3^.previous := hp2;
|
||||||
|
hp2^.next := hp3;
|
||||||
|
If assigned(hp3^.next) then
|
||||||
|
Pai(hp3^.next)^.previous := hp3;
|
||||||
|
{$endif regrefdebug}
|
||||||
|
Exclude(RegInfo.RegsLoadedForRef,RegCounter);
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
{$ifndef fpc}
|
||||||
|
CheckSequence := TmpResult;
|
||||||
|
{$endif fpc}
|
||||||
End; {CheckSequence}
|
End; {CheckSequence}
|
||||||
|
|
||||||
Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai);
|
Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai);
|
||||||
@ -252,11 +237,6 @@ Begin
|
|||||||
A_MOV, A_MOVZX, A_MOVSX:
|
A_MOV, A_MOVZX, A_MOVSX:
|
||||||
Begin
|
Begin
|
||||||
Case Paicpu(p)^.oper[0].typ Of
|
Case Paicpu(p)^.oper[0].typ Of
|
||||||
{ Top_Reg:
|
|
||||||
Case Paicpu(p)^.optype[1] Of
|
|
||||||
Top_Reg:;
|
|
||||||
Top_Ref:;
|
|
||||||
End;}
|
|
||||||
Top_Ref:
|
Top_Ref:
|
||||||
Begin {destination is always a register in this case}
|
Begin {destination is always a register in this case}
|
||||||
With PPaiProp(p^.OptInfo)^.Regs[Reg32(Paicpu(p)^.oper[1].reg)] Do
|
With PPaiProp(p^.OptInfo)^.Regs[Reg32(Paicpu(p)^.oper[1].reg)] Do
|
||||||
@ -267,201 +247,167 @@ Begin
|
|||||||
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}
|
||||||
If CheckSequence(p, Paicpu(p)^.oper[1].reg, Cnt, RegInfo) And
|
If CheckSequence(p, Paicpu(p)^.oper[1].reg, Cnt, RegInfo) And
|
||||||
(Cnt > 0)
|
(Cnt > 0) Then
|
||||||
Then
|
Begin
|
||||||
Begin
|
hp1 := nil;
|
||||||
hp1 := nil;
|
{ although it's perfectly ok to remove an instruction which doesn't contain }
|
||||||
{although it's perfectly ok to remove an instruction which doesn't contain
|
{ the register that we've just checked (CheckSequence takes care of that), }
|
||||||
the register that we've just checked (CheckSequence takes care of that),
|
{ the sequence containing this other register should also be completely }
|
||||||
the sequence containing this other register should also be completely
|
{ checked and removed, otherwise we may get situations like this: }
|
||||||
checked and removed, otherwise we may get situations like this:
|
{ }
|
||||||
|
{ movl 12(%ebp), %edx movl 12(%ebp), %edx }
|
||||||
|
{ movl 16(%ebp), %eax movl 16(%ebp), %eax }
|
||||||
|
{ movl 8(%edx), %edx movl 8(%edx), %edx }
|
||||||
|
{ movl (%eax), eax movl (%eax), eax }
|
||||||
|
{ cmpl %eax, %edx cmpl %eax, %edx }
|
||||||
|
{ jnz l123 getting converted to jnz l123 }
|
||||||
|
{ movl 12(%ebp), %edx movl 4(%eax), eax }
|
||||||
|
{ movl 16(%ebp), %eax }
|
||||||
|
{ movl 8(%edx), %edx }
|
||||||
|
{ movl 4(%eax), eax }
|
||||||
|
hp2 := p;
|
||||||
|
Cnt2 := 1;
|
||||||
|
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;
|
||||||
|
{$ifndef noremove}
|
||||||
|
PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
|
||||||
|
{$endif noremove}
|
||||||
|
Inc(Cnt2);
|
||||||
|
GetNextInstruction(p, p);
|
||||||
|
End;
|
||||||
|
hp3 := New(Pai_Marker,Init(NoPropInfoStart));
|
||||||
|
InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
|
||||||
|
{hp4 is used to get the contents of the registers before the sequence}
|
||||||
|
GetLastInstruction(hp2, hp4);
|
||||||
|
{ If some registers were different in the old and the new sequence, move }
|
||||||
|
{ the contents of those old registers to the new ones }
|
||||||
|
{$IfDef CSDebug}
|
||||||
|
For RegCounter := R_EAX To R_EDI Do
|
||||||
|
If (RegCounter in RegInfo.RegsLoadedForRef) Then
|
||||||
|
Begin
|
||||||
|
hp5 := new(pai_asm_comment,init(strpnew('New: '+att_reg2str[RegCounter]+', Old: '+
|
||||||
|
att_reg2str[RegInfo.New2OldReg[RegCounter]])));
|
||||||
|
InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp5);
|
||||||
|
End;
|
||||||
|
{$EndIf CSDebug}
|
||||||
|
For RegCounter := R_EAX To R_EDI Do
|
||||||
|
Begin
|
||||||
|
If (RegInfo.New2OldReg[RegCounter] <> R_NO) Then
|
||||||
|
If Not(RegCounter In RegInfo.RegsLoadedForRef) And
|
||||||
|
{old reg new reg}
|
||||||
|
(RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
|
||||||
|
|
||||||
movl 12(%ebp), %edx movl 12(%ebp), %edx
|
Begin
|
||||||
movl 16(%ebp), %eax movl 16(%ebp), %eax
|
hp3 := New(Paicpu,Op_Reg_Reg(A_MOV, S_L,
|
||||||
movl 8(%edx), %edx movl 8(%edx), %edx
|
{old reg new reg}
|
||||||
movl (%eax), eax movl (%eax), eax
|
RegInfo.New2OldReg[RegCounter], RegCounter));
|
||||||
cmpl %eax, %edx cmpl %eax, %edx
|
hp3^.fileinfo := hp2^.fileinfo;
|
||||||
jnz l123 getting converted to jnz l123
|
InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp3);
|
||||||
movl 12(%ebp), %edx movl 4(%eax), eax
|
End
|
||||||
movl 16(%ebp), %eax
|
Else
|
||||||
movl 8(%edx), %edx
|
{ imagine the following code: }
|
||||||
movl 4(%eax), eax}
|
{ normal wrong optimized }
|
||||||
|
{ movl 8(%ebp), %eax movl 8(%ebp), %eax }
|
||||||
|
{ movl (%eax), %eax movl (%eax), %eax }
|
||||||
|
{ cmpl 8(%ebp), %eax cmpl 8(%ebp), %eax }
|
||||||
|
{ jne l1 jne l1 }
|
||||||
|
{ movl 8(%ebp), %eax }
|
||||||
|
{ movl (%eax), %edi movl %eax, %edi }
|
||||||
|
{ movl %edi, -4(%ebp) movl %edi, -4(%ebp) }
|
||||||
|
{ movl 8(%ebp), %eax }
|
||||||
|
{ pushl 70(%eax) pushl 70(%eax) }
|
||||||
|
{ }
|
||||||
|
{ The error is that at the moment that the last instruction is executed, }
|
||||||
|
{ %eax doesn't contain 8(%ebp) anymore. Solution: the contents of }
|
||||||
|
{ registers that are completely removed from a sequence (= registers in }
|
||||||
|
{ RegLoadedForRef, have to be changed to their contents from before the }
|
||||||
|
{ sequence. }
|
||||||
|
Begin
|
||||||
|
|
||||||
|
{load Cnt2 with the total number of instructions of this sequence}
|
||||||
|
Cnt2 := PPaiProp(hp4^.OptInfo)^.
|
||||||
|
Regs[RegInfo.New2OldReg[RegCounter]].NrOfMods;
|
||||||
|
|
||||||
|
hp3 := hp2;
|
||||||
|
For Cnt := 1 to Pred(Cnt2) Do
|
||||||
|
GetNextInstruction(hp3, hp3);
|
||||||
|
TmpState := PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState;
|
||||||
|
GetNextInstruction(hp3, hp3);
|
||||||
|
{$ifdef csdebug}
|
||||||
|
Writeln('Cnt2: ',Cnt2);
|
||||||
|
hp5 := new(pai_asm_comment,init(strpnew('starting here...')));
|
||||||
|
InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp5);
|
||||||
|
{$endif csdebug}
|
||||||
|
hp3 := hp2;
|
||||||
|
{first change the contents of the register inside the sequence}
|
||||||
|
For Cnt := 1 to Cnt2 Do
|
||||||
|
Begin
|
||||||
|
{save the WState of the last pai object of the sequence for later use}
|
||||||
|
TmpState := PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState;
|
||||||
|
{$ifdef csdebug}
|
||||||
|
hp5 := new(pai_asm_comment,init(strpnew('WState for '+att_reg2str[Regcounter]+': '
|
||||||
|
+tostr(tmpstate))));
|
||||||
|
InsertLLItem(AsmL, hp3, pai(hp3^.next), hp5);
|
||||||
|
{$endif csdebug}
|
||||||
|
PPaiProp(hp3^.OptInfo)^.Regs[RegCounter] :=
|
||||||
|
PPaiProp(hp4^.OptInfo)^.Regs[RegCounter];
|
||||||
|
GetNextInstruction(hp3, hp3);
|
||||||
|
End;
|
||||||
|
{here, hp3 = p = Pai object right after the sequence, TmpState = WState of
|
||||||
|
RegCounter at the last Pai object of the sequence}
|
||||||
|
GetLastInstruction(hp3, hp3);
|
||||||
|
While GetNextInstruction(hp3, hp3) And
|
||||||
|
(PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState
|
||||||
|
= TmpState) Do
|
||||||
|
{$ifdef csdebug}
|
||||||
|
begin
|
||||||
|
hp5 := new(pai_asm_comment,init(strpnew('WState for '+att_reg2str[Regcounter]+': '+
|
||||||
|
tostr(PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState))));
|
||||||
|
InsertLLItem(AsmL, hp3, pai(hp3^.next), hp5);
|
||||||
|
{$endif csdebug}
|
||||||
|
PPaiProp(hp3^.OptInfo)^.Regs[RegCounter] :=
|
||||||
|
PPaiProp(hp4^.OptInfo)^.Regs[RegCounter];
|
||||||
|
{$ifdef csdebug}
|
||||||
|
end;
|
||||||
|
{$endif csdebug}
|
||||||
|
{$ifdef csdebug}
|
||||||
|
hp5 := new(pai_asm_comment,init(strpnew('stopping here...')));
|
||||||
|
InsertLLItem(AsmL, hp3, pai(hp3^.next), hp5);
|
||||||
|
{$endif csdebug}
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
hp3 := New(Pai_Marker,Init(NoPropInfoEnd));
|
||||||
|
InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
|
||||||
|
If hp1 <> nil Then p := hp1;
|
||||||
|
Continue;
|
||||||
|
End
|
||||||
|
Else
|
||||||
|
If (Cnt > 0) And
|
||||||
|
(PPaiProp(p^.OptInfo)^.
|
||||||
|
Regs[Reg32(Paicpu(p)^.oper[1].reg)].Typ = Con_Ref) And
|
||||||
|
(PPaiProp(p^.OptInfo)^.CanBeRemoved) Then
|
||||||
|
Begin
|
||||||
hp2 := p;
|
hp2 := p;
|
||||||
Cnt2 := 1;
|
Cnt2 := 1;
|
||||||
While Cnt2 <= Cnt Do
|
While Cnt2 <= Cnt Do
|
||||||
Begin
|
Begin
|
||||||
If (hp1 = nil) And
|
If RegInInstruction(Paicpu(hp2)^.oper[1].reg, p) Or
|
||||||
Not(RegInInstruction(Paicpu(hp2)^.oper[1].reg, p) Or
|
RegInInstruction(Reg32(Paicpu(hp2)^.oper[1].reg), p) Then
|
||||||
RegInInstruction(Reg32(Paicpu(hp2)^.oper[1].reg), p)) And
|
PPaiProp(p^.OptInfo)^.CanBeRemoved := False;
|
||||||
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;
|
|
||||||
{$ifndef noremove}
|
|
||||||
PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
|
|
||||||
{$endif noremove}
|
|
||||||
Inc(Cnt2);
|
Inc(Cnt2);
|
||||||
GetNextInstruction(p, p);
|
GetNextInstruction(p, p);
|
||||||
End;
|
End;
|
||||||
hp3 := New(Pai_Marker,Init(NoPropInfoStart));
|
|
||||||
InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
|
|
||||||
{imagine the following code:
|
|
||||||
normal wrong optimized
|
|
||||||
movl 8(%ebp), %eax movl 8(%ebp), %eax
|
|
||||||
movl (%eax), %eax movl (%eax), %eax
|
|
||||||
cmpl 8(%ebp), %eax cmpl 8(%ebp), %eax
|
|
||||||
jne l1 jne l1
|
|
||||||
movl 8(%ebp), %eax
|
|
||||||
movl (%eax), %edi movl %eax, %edi
|
|
||||||
movl %edi, -4(%ebp) movl %edi, -4(%ebp)
|
|
||||||
movl 8(%ebp), %eax
|
|
||||||
pushl 70(%eax) pushl 70(%eax)
|
|
||||||
|
|
||||||
The error is that at the moment that the last instruction is executed,
|
|
||||||
%eax doesn't contain 8(%ebp) anymore. Solution: the contents of registers
|
|
||||||
that are completely removed from a sequence, have to be changed to their
|
|
||||||
contents from before the sequence.}
|
|
||||||
|
|
||||||
{hp4 is used to get the contents of the registers before the sequence}
|
|
||||||
GetLastInstruction(hp2, hp4);
|
|
||||||
{If some registers were different in the old and the new sequence, move
|
|
||||||
the contents of those old registers to the new ones}
|
|
||||||
{$IfDef CSDebug}
|
|
||||||
For RegCounter := R_EAX To R_EDI Do
|
|
||||||
If (RegCounter in RegInfo.RegsLoadedForRef) Then
|
|
||||||
Begin
|
|
||||||
hp5 := new(pai_asm_comment,init(strpnew('New: '+att_reg2str[RegCounter]+', Old: '+
|
|
||||||
att_reg2str[RegInfo.New2OldReg[RegCounter]])));
|
|
||||||
InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp5);
|
|
||||||
End;
|
|
||||||
{$EndIf CSDebug}
|
|
||||||
For RegCounter := R_EAX To R_EDI Do
|
|
||||||
Begin
|
|
||||||
If (RegInfo.New2OldReg[RegCounter] <> R_NO) Then
|
|
||||||
If Not(RegCounter In RegInfo.RegsLoadedForRef) And
|
|
||||||
{old reg new reg}
|
|
||||||
(RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
|
|
||||||
|
|
||||||
Begin
|
|
||||||
hp3 := New(Paicpu,Op_Reg_Reg(A_MOV, S_L,
|
|
||||||
{old reg new reg}
|
|
||||||
RegInfo.New2OldReg[RegCounter], RegCounter));
|
|
||||||
hp3^.fileinfo := hp2^.fileinfo;
|
|
||||||
InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp3);
|
|
||||||
End
|
|
||||||
Else
|
|
||||||
If (RegCounter In RegInfo.RegsLoadedForRef) Then
|
|
||||||
{change the contents of this register to the its contents before the
|
|
||||||
sequence (for all instructions in and after the sequence, until the register
|
|
||||||
is reloaded)}
|
|
||||||
Begin
|
|
||||||
{load Cnt2 with the total number of instructions of this sequence}
|
|
||||||
Cnt2 := PPaiProp(hp4^.OptInfo)^.
|
|
||||||
Regs[RegInfo.New2OldReg[RegCounter]].NrOfMods;
|
|
||||||
{sometimes, a register can not be removed from a sequence, because it's
|
|
||||||
still used afterwards:
|
|
||||||
|
|
||||||
movl -8(%ebp), %eax movl -8(%ebp), %eax
|
|
||||||
movl 70(%eax), %eax movl 70(%eax), %eax
|
|
||||||
cmpl 74(%eax), %eax cmpl 74(%eax), %eax
|
|
||||||
jne l1 can't be changed to jne l1
|
|
||||||
movl -8(%ebp), %eax
|
|
||||||
movl 70(%eax), %edi movl %eax, %edi
|
|
||||||
boundl R_282, %edi boundl R_282, %edi
|
|
||||||
pushl 70(%eax) pushl 70(%eax)
|
|
||||||
|
|
||||||
because eax now contains the wrong value when 70(%eax) is pushed}
|
|
||||||
|
|
||||||
hp3 := hp2;
|
|
||||||
For Cnt := 1 to Pred(Cnt2) Do
|
|
||||||
GetNextInstruction(hp3, hp3);
|
|
||||||
TmpState := PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState;
|
|
||||||
GetNextInstruction(hp3, hp3);
|
|
||||||
If (TmpState <> PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState) Or
|
|
||||||
Not(RegCounter in PPaiProp(hp3^.OptInfo)^.UsedRegs) Then
|
|
||||||
Begin
|
|
||||||
{$ifdef csdebug}
|
|
||||||
Writeln('Cnt2: ',Cnt2);
|
|
||||||
hp5 := new(pai_asm_comment,init(strpnew('starting here...')));
|
|
||||||
InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp5);
|
|
||||||
{$endif csdebug}
|
|
||||||
hp3 := hp2;
|
|
||||||
{first change the contents of the register inside the sequence}
|
|
||||||
For Cnt := 1 to Cnt2 Do
|
|
||||||
Begin
|
|
||||||
{save the WState of the last pai object of the sequence for later use}
|
|
||||||
TmpState := PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState;
|
|
||||||
{$ifdef csdebug}
|
|
||||||
hp5 := new(pai_asm_comment,init(strpnew('WState for '+att_reg2str[Regcounter]+': '
|
|
||||||
+tostr(tmpstate))));
|
|
||||||
InsertLLItem(AsmL, hp3, pai(hp3^.next), hp5);
|
|
||||||
{$endif csdebug}
|
|
||||||
PPaiProp(hp3^.OptInfo)^.Regs[RegCounter] :=
|
|
||||||
PPaiProp(hp4^.OptInfo)^.Regs[RegCounter];
|
|
||||||
GetNextInstruction(hp3, hp3);
|
|
||||||
End;
|
|
||||||
{here, hp3 = p = Pai object right after the sequence, TmpState = WState of
|
|
||||||
RegCounter at the last Pai object of the sequence}
|
|
||||||
GetLastInstruction(hp3, hp3);
|
|
||||||
While GetNextInstruction(hp3, hp3) And
|
|
||||||
(PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState
|
|
||||||
= TmpState) Do
|
|
||||||
{$ifdef csdebug}
|
|
||||||
begin
|
|
||||||
hp5 := new(pai_asm_comment,init(strpnew('WState for '+att_reg2str[Regcounter]+': '+
|
|
||||||
tostr(PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState))));
|
|
||||||
InsertLLItem(AsmL, hp3, pai(hp3^.next), hp5);
|
|
||||||
{$endif csdebug}
|
|
||||||
PPaiProp(hp3^.OptInfo)^.Regs[RegCounter] :=
|
|
||||||
PPaiProp(hp4^.OptInfo)^.Regs[RegCounter];
|
|
||||||
{$ifdef csdebug}
|
|
||||||
end;
|
|
||||||
{$endif csdebug}
|
|
||||||
End
|
|
||||||
Else
|
|
||||||
Begin
|
|
||||||
{$ifdef csdebug}
|
|
||||||
Writeln('Got there for ',att_Reg2Str[RegCounter]);
|
|
||||||
{$endif csdebug}
|
|
||||||
hp3 := hp2;
|
|
||||||
For Cnt := 1 to Cnt2 Do
|
|
||||||
Begin
|
|
||||||
If RegModifiedByInstruction(RegCounter, hp3)
|
|
||||||
Then PPaiProp(hp3^.OptInfo)^.CanBeRemoved := False;
|
|
||||||
GetNextInstruction(hp3, hp3);
|
|
||||||
End;
|
|
||||||
End;
|
|
||||||
{$ifdef csdebug}
|
|
||||||
hp5 := new(pai_asm_comment,init(strpnew('stopping here...')));
|
|
||||||
InsertLLItem(AsmL, hp3, pai(hp3^.next), hp5);
|
|
||||||
{$endif csdebug}
|
|
||||||
End;
|
|
||||||
End;
|
|
||||||
hp3 := New(Pai_Marker,Init(NoPropInfoEnd));
|
|
||||||
InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
|
|
||||||
If hp1 <> nil Then p := hp1;
|
|
||||||
Continue;
|
Continue;
|
||||||
End
|
End;
|
||||||
Else
|
|
||||||
If (Cnt > 0) And
|
|
||||||
(PPaiProp(p^.OptInfo)^.
|
|
||||||
Regs[Reg32(Paicpu(p)^.oper[1].reg)].Typ = Con_Ref) And
|
|
||||||
(PPaiProp(p^.OptInfo)^.CanBeRemoved) Then
|
|
||||||
Begin
|
|
||||||
hp2 := p;
|
|
||||||
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
|
|
||||||
PPaiProp(p^.OptInfo)^.CanBeRemoved := False;
|
|
||||||
Inc(Cnt2);
|
|
||||||
GetNextInstruction(p, p);
|
|
||||||
End;
|
|
||||||
Continue;
|
|
||||||
End;
|
|
||||||
End;
|
End;
|
||||||
End;
|
End;
|
||||||
Top_Const:
|
Top_Const:
|
||||||
@ -553,7 +499,11 @@ End.
|
|||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.25 1999-09-27 23:44:50 peter
|
Revision 1.26 1999-09-30 14:43:13 jonas
|
||||||
|
* fixed small efficiency which caused some missed optimizations (saves 1
|
||||||
|
assembler instruction on the whole compiler/RTL source tree! :)
|
||||||
|
|
||||||
|
Revision 1.25 1999/09/27 23:44:50 peter
|
||||||
* procinfo is now a pointer
|
* procinfo is now a pointer
|
||||||
* support for result setting in sub procedure
|
* support for result setting in sub procedure
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user