mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-01 21:26:03 +02:00
+ extra checks in RegsEquivalent so some more optimizations can be done (which
where disabled by the second fix from revision 1.22)
This commit is contained in:
parent
10d267e9fc
commit
09f430de39
@ -88,7 +88,6 @@ Begin {CheckSequence}
|
||||
RegInfo.OldRegsEncountered := RegInfo.NewRegsEncountered;
|
||||
RegInfo.New2OldReg[ProcInfo.FramePointer] := ProcInfo.FramePointer;
|
||||
RegInfo.New2OldReg[R_ESP] := R_ESP;
|
||||
RegInfo.Old2NewReg := RegInfo.New2OldReg;
|
||||
Found := 0;
|
||||
hp2 := PPaiProp(PrevNonRemovablePai^.fileinfo.line)^.Regs[RegCounter].StartMod;
|
||||
If (PrevNonRemovablePai <> PPaiProp(PrevNonRemovablePai^.fileinfo.line)^.Regs[RegCounter].StartMod)
|
||||
@ -554,7 +553,11 @@ End.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.16 1998-12-02 16:23:31 jonas
|
||||
Revision 1.17 1998-12-17 16:37:39 jonas
|
||||
+ extra checks in RegsEquivalent so some more optimizations can be done (which
|
||||
where disabled by the second fix from revision 1.22)
|
||||
|
||||
Revision 1.16 1998/12/02 16:23:31 jonas
|
||||
* changed "if longintvar in set" to case or "if () or () .." statements
|
||||
* tree.pas: changed inlinenumber (and associated constructor/vars) to a byte
|
||||
|
||||
|
@ -42,15 +42,18 @@ Type
|
||||
TRegInfo = Record
|
||||
NewRegsEncountered, OldRegsEncountered: TRegSet;
|
||||
RegsLoadedForRef: TRegSet;
|
||||
Old2NewReg, New2OldReg: TRegArray;
|
||||
New2OldReg: TRegArray;
|
||||
End;
|
||||
|
||||
{possible actions on an operand: read, write or modify (= read & write)}
|
||||
TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
|
||||
|
||||
{*********************** Procedures and Functions ************************}
|
||||
|
||||
Procedure InsertLLItem(AsmL: PAasmOutput; prev, foll, new_one: PLinkedList_Item);
|
||||
|
||||
Function Reg32(Reg: TRegister): TRegister;
|
||||
Function RefsEquivalent(Const R1, R2: TReference; Var RegInfo: TRegInfo): Boolean;
|
||||
Function RefsEquivalent(Const R1, R2: TReference; Var RegInfo: TRegInfo; OpAct: TOpAction): Boolean;
|
||||
Function RefsEqual(Const R1, R2: TReference): Boolean;
|
||||
Function IsGP32Reg(Reg: TRegister): Boolean;
|
||||
Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
|
||||
@ -61,7 +64,7 @@ Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
|
||||
Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
|
||||
|
||||
Procedure UpdateUsedRegs(Var UsedRegs: TRegSet; p: Pai);
|
||||
Function RegsEquivalent(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo): Boolean;
|
||||
Function RegsEquivalent(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo; OpAct: TopAction): Boolean;
|
||||
Function InstructionsEquivalent(p1, p2: Pai; Var RegInfo: TRegInfo): Boolean;
|
||||
Function OpsEqual(typ: Longint; op1, op2: Pointer): Boolean;
|
||||
|
||||
@ -830,21 +833,18 @@ Begin
|
||||
NewRegsEncountered := NewRegsEncountered + [NewReg];
|
||||
OldRegsEncountered := OldRegsEncountered + [OldReg];
|
||||
New2OldReg[NewReg] := OldReg;
|
||||
Old2NewReg[OldReg] := NewReg;
|
||||
Case OldReg Of
|
||||
R_EAX..R_EDI:
|
||||
Begin
|
||||
NewRegsEncountered := NewRegsEncountered + [Reg32toReg16(NewReg)];
|
||||
OldRegsEncountered := OldRegsEncountered + [Reg32toReg16(OldReg)];
|
||||
New2OldReg[Reg32toReg16(NewReg)] := Reg32toReg16(OldReg);
|
||||
Old2NewReg[Reg32toReg16(OldReg)] := Reg32toReg16(NewReg);
|
||||
If (NewReg in [R_EAX..R_EBX]) And
|
||||
(OldReg in [R_EAX..R_EBX]) Then
|
||||
Begin
|
||||
NewRegsEncountered := NewRegsEncountered + [Reg32toReg8(NewReg)];
|
||||
OldRegsEncountered := OldRegsEncountered + [Reg32toReg8(OldReg)];
|
||||
New2OldReg[Reg32toReg8(NewReg)] := Reg32toReg8(OldReg);
|
||||
Old2NewReg[Reg32toReg8(OldReg)] := Reg32toReg8(NewReg);
|
||||
End;
|
||||
End;
|
||||
R_AX..R_DI:
|
||||
@ -852,14 +852,12 @@ Begin
|
||||
NewRegsEncountered := NewRegsEncountered + [Reg16toReg32(NewReg)];
|
||||
OldRegsEncountered := OldRegsEncountered + [Reg16toReg32(OldReg)];
|
||||
New2OldReg[Reg16toReg32(NewReg)] := Reg16toReg32(OldReg);
|
||||
Old2NewReg[Reg16toReg32(OldReg)] := Reg16toReg32(NewReg);
|
||||
If (NewReg in [R_AX..R_BX]) And
|
||||
(OldReg in [R_AX..R_BX]) Then
|
||||
Begin
|
||||
NewRegsEncountered := NewRegsEncountered + [Reg16toReg8(NewReg)];
|
||||
OldRegsEncountered := OldRegsEncountered + [Reg16toReg8(OldReg)];
|
||||
New2OldReg[Reg16toReg8(NewReg)] := Reg16toReg8(OldReg);
|
||||
Old2NewReg[Reg16toReg8(OldReg)] := Reg16toReg8(NewReg);
|
||||
End;
|
||||
End;
|
||||
R_AL..R_BL:
|
||||
@ -869,7 +867,6 @@ Begin
|
||||
OldRegsEncountered := OldRegsEncountered + [Reg8toReg32(OldReg)]
|
||||
+ [Reg8toReg16(OldReg)];
|
||||
New2OldReg[Reg8toReg32(NewReg)] := Reg8toReg32(OldReg);
|
||||
Old2NewReg[Reg8toReg16(OldReg)] := Reg8toReg16(NewReg);
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
@ -892,7 +889,7 @@ Begin
|
||||
End;
|
||||
|
||||
|
||||
Function RegsEquivalent(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo): Boolean;
|
||||
Function RegsEquivalent(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo; OPAct: TOpAction): Boolean;
|
||||
Begin
|
||||
If Not((OldReg = R_NO) Or (NewReg = R_NO)) Then
|
||||
If RegsSameSize(OldReg, NewReg) Then
|
||||
@ -902,27 +899,44 @@ Begin
|
||||
processed. This happens if it has been compared with a register that doesn't
|
||||
have an 8 bit component (such as EDI). In that case the 8 bit component is
|
||||
still set to R_NO and the comparison in the Else-part will fail}
|
||||
If Not((Reg32(NewReg) in NewRegsEncountered) Or
|
||||
(Reg32(OldReg) in OldRegsEncountered)) Then
|
||||
Begin
|
||||
AddReg2RegInfo(OldReg, NewReg, RegInfo);
|
||||
RegsEquivalent := True
|
||||
End
|
||||
Else RegsEquivalent :=
|
||||
(Reg32(NewReg) in NewRegsEncountered) And
|
||||
(Reg32(OldReg) in OldRegsEncountered) And
|
||||
(OldReg = New2OldReg[NewReg])
|
||||
If (Reg32(OldReg) in OldRegsEncountered) Then
|
||||
If (Reg32(NewReg) in NewRegsEncountered) Then
|
||||
RegsEquivalent := (OldReg = New2OldReg[NewReg])
|
||||
|
||||
{ If we haven't encountered the new register yet, but we have encountered the
|
||||
old one already, the new one can only be correct if it's being written to
|
||||
(and consequently the old one is also being written to), otherwise
|
||||
|
||||
movl -8(%ebp), %eax and movl -8(%ebp), %eax
|
||||
movl (%eax), %eax movl (%edx), %edx
|
||||
|
||||
are considered equivalent}
|
||||
|
||||
Else
|
||||
If (OpAct = OpAct_Write) Then
|
||||
Begin
|
||||
AddReg2RegInfo(OldReg, NewReg, RegInfo);
|
||||
RegsEquivalent := True
|
||||
End
|
||||
Else Regsequivalent := False
|
||||
Else
|
||||
If Not(Reg32(NewReg) in NewRegsEncountered) Then
|
||||
Begin
|
||||
AddReg2RegInfo(OldReg, NewReg, RegInfo);
|
||||
RegsEquivalent := True
|
||||
End
|
||||
Else RegsEquivalent := False
|
||||
Else RegsEquivalent := False
|
||||
Else RegsEquivalent := OldReg = NewReg
|
||||
End;
|
||||
|
||||
Function RefsEquivalent(Const R1, R2: TReference; var RegInfo: TRegInfo): Boolean;
|
||||
Function RefsEquivalent(Const R1, R2: TReference; var RegInfo: TRegInfo; OpAct: TOpAction): Boolean;
|
||||
Begin
|
||||
If R1.IsIntValue
|
||||
Then RefsEquivalent := R2.IsIntValue and (R1.Offset = R2.Offset)
|
||||
Else If (R1.Offset = R2.Offset) And
|
||||
RegsEquivalent(R1.Base, R2.Base, RegInfo) And
|
||||
RegsEquivalent(R1.Index, R2.Index, RegInfo) And
|
||||
RegsEquivalent(R1.Base, R2.Base, RegInfo, OpAct) And
|
||||
RegsEquivalent(R1.Index, R2.Index, RegInfo, OpAct) And
|
||||
(R1.Segment = R2.Segment) And (R1.ScaleFactor = R2.ScaleFactor)
|
||||
Then
|
||||
Begin
|
||||
@ -1266,12 +1280,12 @@ Begin
|
||||
End;
|
||||
End;}
|
||||
|
||||
Function OpsEquivalent(typ: Longint; OldOp, NewOp: Pointer; Var RegInfo: TRegInfo): Boolean;
|
||||
Function OpsEquivalent(typ: Longint; OldOp, NewOp: Pointer; Var RegInfo: TRegInfo; OpAct: TopAction): Boolean;
|
||||
Begin {checks whether the two ops are equivalent}
|
||||
Case typ Of
|
||||
Top_Reg: OpsEquivalent := RegsEquivalent(TRegister(OldOp), TRegister(NewOp), RegInfo);
|
||||
Top_Reg: OpsEquivalent :=RegsEquivalent(TRegister(OldOp), TRegister(NewOp), RegInfo, OpAct);
|
||||
Top_Const: OpsEquivalent := OldOp = NewOp;
|
||||
Top_Ref: OpsEquivalent := RefsEquivalent(TReference(OldOp^), TReference(NewOp^), RegInfo);
|
||||
Top_Ref: OpsEquivalent := RefsEquivalent(TReference(OldOp^), TReference(NewOp^), RegInfo, OpAct);
|
||||
Top_None: OpsEquivalent := True
|
||||
Else OpsEquivalent := False
|
||||
End;
|
||||
@ -1328,7 +1342,7 @@ Begin {checks whether two Pai386 instructions are equal}
|
||||
{the registers from op2 have to be equivalent, but not necessarily equal}
|
||||
InstructionsEquivalent :=
|
||||
RegsEquivalent(TRegister(Pai386(p1)^.op2), TRegister(Pai386(p2)^.op2),
|
||||
RegInfo);
|
||||
RegInfo, OpAct_Write);
|
||||
End
|
||||
{the registers are loaded with values from different memory locations. If
|
||||
this was allowed, the instructions "mov -4(esi),eax" and "mov -4(ebp),eax"
|
||||
@ -1343,57 +1357,50 @@ Begin {checks whether two Pai386 instructions are equal}
|
||||
Reg32(TRegister(Pai386(p2)^.op2)),R_NO,R_ESP])
|
||||
{it won't do any harm if the register is already in RegsLoadedForRef}
|
||||
Then
|
||||
{$ifdef csdebug}
|
||||
Begin
|
||||
{$endif csdebug}
|
||||
RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef + [Base];
|
||||
{$ifdef csdebug}
|
||||
Writeln(att_reg2str[base], ' added');
|
||||
end;
|
||||
{$endif csdebug}
|
||||
end;
|
||||
If Not(Index in [ProcInfo.FramePointer,
|
||||
Reg32(TRegister(Pai386(p2)^.op2)),R_NO,R_ESP])
|
||||
Then
|
||||
{$ifdef csdebug}
|
||||
Begin
|
||||
{$endif csdebug}
|
||||
RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef + [Index];
|
||||
{$ifdef csdebug}
|
||||
Writeln(att_reg2str[index], ' added');
|
||||
end;
|
||||
{$endif csdebug}
|
||||
end;
|
||||
|
||||
End;
|
||||
If Not(Reg32(TRegister(Pai386(p2)^.op2)) In [ProcInfo.FramePointer,
|
||||
R_NO,R_ESP])
|
||||
Then
|
||||
{$ifdef csdebug}
|
||||
Begin
|
||||
{$endif csdebug}
|
||||
|
||||
RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef -
|
||||
[Reg32(TRegister(Pai386(p2)^.op2))];
|
||||
{$ifdef csdebug}
|
||||
Writeln(att_reg2str[Reg32(TRegister(Pai386(p2)^.op2))], ' removed');
|
||||
end;
|
||||
{$endif csdebug}
|
||||
InstructionsEquivalent :=
|
||||
OpsEquivalent(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1, RegInfo) And
|
||||
OpsEquivalent(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2, RegInfo)
|
||||
end;
|
||||
InstructionsEquivalent :=
|
||||
OpsEquivalent(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1, RegInfo, OpAct_Read) And
|
||||
OpsEquivalent(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2, RegInfo, OpAct_Write)
|
||||
End
|
||||
Else
|
||||
{an instruction <> mov, movzx, movsx}
|
||||
If (Pai386(p1)^.op3t = top_none) Then
|
||||
InstructionsEquivalent :=
|
||||
OpsEquivalent(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1, RegInfo) And
|
||||
OpsEquivalent(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2, RegInfo)
|
||||
OpsEquivalent(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1, RegInfo, OpAct_Unknown) And
|
||||
OpsEquivalent(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2, RegInfo, OpAct_Unknown)
|
||||
Else
|
||||
InstructionsEquivalent :=
|
||||
OpsEquivalent(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1, RegInfo) And
|
||||
OpsEquivalent(Pai386(p1)^.op1t, Pai386(p1)^.op1, Pai386(p2)^.op1, RegInfo, OpAct_Unknown) And
|
||||
OpsEquivalent(Pai386(p1)^.op2t, Pointer(Longint(TwoWords(Pai386(p1)^.op2).Word1)),
|
||||
Pointer(Longint(TwoWords(Pai386(p2)^.op2).Word1)), RegInfo) And
|
||||
Pointer(Longint(TwoWords(Pai386(p2)^.op2).Word1)), RegInfo, OpAct_Unknown) And
|
||||
OpsEquivalent(Pai386(p1)^.op3t, Pointer(Longint(TwoWords(Pai386(p1)^.op2).Word2)),
|
||||
Pointer(Longint(TwoWords(Pai386(p2)^.op2).Word2)), RegInfo)
|
||||
Pointer(Longint(TwoWords(Pai386(p2)^.op2).Word2)), RegInfo, OpAct_Unknown)
|
||||
{the instructions haven't even got the same structure, so they're certainly
|
||||
not equivalent}
|
||||
Else InstructionsEquivalent := False;
|
||||
@ -2084,7 +2091,11 @@ End.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.32 1998-12-15 19:33:58 jonas
|
||||
Revision 1.33 1998-12-17 16:37:38 jonas
|
||||
+ extra checks in RegsEquivalent so some more optimizations can be done (which
|
||||
where disabled by the second fix from revision 1.22)
|
||||
|
||||
Revision 1.32 1998/12/15 19:33:58 jonas
|
||||
* uncommented OpsEqual & added to interface because popt386 uses it now
|
||||
|
||||
Revision 1.31 1998/12/11 00:03:13 peter
|
||||
|
Loading…
Reference in New Issue
Block a user