mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-22 13:13:25 +02:00
+ all code generator generated "mov reg1,reg2" instructions are now
attempted to be removed using the replacereg code (-dnewoptimizations) * small fixes to -dreplacereg code
This commit is contained in:
parent
b15a98cfa4
commit
02381105d6
@ -189,12 +189,11 @@ Begin {CheckSequence}
|
||||
{ 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
|
||||
If GetNextInstruction(hp2, hp2) and
|
||||
(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
|
||||
@ -430,24 +429,6 @@ begin
|
||||
end
|
||||
end;
|
||||
|
||||
function regLoadedWithNewValue(reg: tregister; hp: pai): boolean;
|
||||
{ assumes reg is a 32bit register }
|
||||
var p: paicpu;
|
||||
begin
|
||||
p := paicpu(hp);
|
||||
regLoadedWithNewValue :=
|
||||
assigned(hp) and
|
||||
((hp^.typ = ait_instruction) and
|
||||
(((p^.opcode = A_MOV) or
|
||||
(p^.opcode = A_MOVZX) or
|
||||
(p^.opcode = A_MOVSX) or
|
||||
(p^.opcode = A_LEA)) and
|
||||
(p^.oper[1].typ = top_reg) and
|
||||
(Reg32(p^.oper[1].reg) = reg)) or
|
||||
((p^.opcode = A_POP) and
|
||||
(Reg32(p^.oper[0].reg) = reg)));
|
||||
end;
|
||||
|
||||
Procedure RestoreRegContentsTo(reg: TRegister; const c: TContent; p, endP: pai);
|
||||
var
|
||||
{$ifdef replaceregdebug}
|
||||
@ -526,19 +507,20 @@ end;
|
||||
function NoHardCodedRegs(p: paicpu): boolean;
|
||||
var chCount: byte;
|
||||
begin
|
||||
if (p^.opcode = A_IMUL) then
|
||||
noHardCodedRegs := p^.ops <> 1
|
||||
else
|
||||
begin
|
||||
NoHardCodedRegs := true;
|
||||
with InsProp[p^.opcode] do
|
||||
for chCount := 1 to MaxCh do
|
||||
if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
|
||||
begin
|
||||
NoHardCodedRegs := false;
|
||||
break
|
||||
end;
|
||||
end;
|
||||
case p^.opcode of
|
||||
A_IMUL: noHardCodedRegs := p^.ops <> 1;
|
||||
else
|
||||
begin
|
||||
NoHardCodedRegs := true;
|
||||
with InsProp[p^.opcode] do
|
||||
for chCount := 1 to MaxCh do
|
||||
if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
|
||||
begin
|
||||
NoHardCodedRegs := false;
|
||||
break
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure ChangeReg(var Reg: TRegister; orgReg, newReg: TRegister);
|
||||
@ -575,7 +557,8 @@ function RegSizesOK(oldReg,newReg: TRegister; p: paicpu): boolean;
|
||||
var opCount: byte;
|
||||
begin
|
||||
RegSizesOK := true;
|
||||
if not(IsGP32reg(oldReg) and IsGP32Reg(newReg)) then
|
||||
{ if only one of them is a general purpose register ... }
|
||||
if (IsGP32reg(oldReg) xor IsGP32Reg(newReg)) then
|
||||
begin
|
||||
for opCount := 0 to 2 do
|
||||
if (p^.oper[opCount].typ = top_reg) and
|
||||
@ -690,7 +673,7 @@ begin
|
||||
end;
|
||||
|
||||
function ReplaceReg(orgReg, newReg: TRegister; p: pai;
|
||||
const c: TContent): Boolean;
|
||||
const c: TContent; orgRegCanBeModified: Boolean): Boolean;
|
||||
{ Tries to replace orgreg with newreg in all instructions coming after p }
|
||||
{ until orgreg gets loaded with a new value. Returns true if successful, }
|
||||
{ false otherwise. If successful, the contents of newReg are set to c, }
|
||||
@ -709,23 +692,42 @@ begin
|
||||
begin
|
||||
tmpResult :=
|
||||
getNextInstruction(endP,endP);
|
||||
if tmpresult and not assigned(endP^.optInfo) then
|
||||
begin
|
||||
hp := new(pai_asm_comment,init(strpnew('next no optinfo')));
|
||||
hp^.next := endp;
|
||||
hp^.previous := endp^.previous;
|
||||
endp^.previous := hp;
|
||||
if assigned(hp^.previous) then
|
||||
hp^.previous^.next := hp;
|
||||
exit;
|
||||
end;
|
||||
If tmpResult and
|
||||
{ don't take into account instructions that will be removed }
|
||||
Not (PPaiProp(endP^.optInfo)^.canBeRemoved) then
|
||||
begin
|
||||
sequenceEnd :=
|
||||
noHardCodedRegs(paicpu(endP)) and
|
||||
(RegLoadedWithNewValue(newReg,paicpu(endP)) or
|
||||
(GetNextInstruction(endp,hp) and
|
||||
FindRegDealloc(newReg,hp)));
|
||||
RegLoadedWithNewValue(newReg,true,paicpu(endP)) or
|
||||
(GetNextInstruction(endp,hp) and
|
||||
FindRegDealloc(newReg,hp));
|
||||
newRegModified :=
|
||||
newRegModified or
|
||||
(not(sequenceEnd) and
|
||||
RegModifiedByInstruction(newReg,endP));
|
||||
orgRegRead := newRegModified and RegReadByInstruction(orgReg,endP);
|
||||
sequenceEnd := SequenceEnd and not(newRegModified and orgRegRead);
|
||||
sequenceEnd := SequenceEnd and
|
||||
{ since newReg will be replaced by orgReg, we can't allow that newReg }
|
||||
{ gets modified if orgReg is still read afterwards (since after }
|
||||
{ replacing, this would mean that orgReg first gets modified and then }
|
||||
{ gets read in the assumption it still contains the unmodified value) }
|
||||
not(newRegModified and orgRegRead) and
|
||||
{ since newReg will be replaced by orgReg, we can't allow that newReg }
|
||||
{ gets modified if orgRegCanBeModified = false }
|
||||
(orgRegCanBeModified or not(newRegModified));
|
||||
tmpResult :=
|
||||
not(newRegModified and orgRegRead) and
|
||||
(orgRegCanBeModified or not(newRegModified)) and
|
||||
(endP^.typ = ait_instruction) and
|
||||
not(paicpu(endP)^.is_jmp) and
|
||||
NoHardCodedRegs(paicpu(endP)) and
|
||||
@ -734,9 +736,10 @@ begin
|
||||
end;
|
||||
end;
|
||||
sequenceEnd := sequenceEnd and
|
||||
RegSizesOk(orgReg,newReg,paicpu(endP)) and
|
||||
not(newRegModified and
|
||||
(orgReg in PPaiProp(endP^.optInfo)^.usedRegs) and
|
||||
not(RegLoadedWithNewValue(orgReg,paicpu(endP))));
|
||||
not(RegLoadedWithNewValue(orgReg,true,paicpu(endP))));
|
||||
|
||||
if SequenceEnd then
|
||||
begin
|
||||
@ -777,11 +780,11 @@ begin
|
||||
{ isn't used anymore }
|
||||
{ In case b, the newreg was completely replaced by oldreg, so it's contents }
|
||||
{ are unchanged compared the start of this sequence, so restore them }
|
||||
If RegLoadedWithNewValue(newReg,endP) then
|
||||
If RegLoadedWithNewValue(newReg,true,endP) then
|
||||
GetLastInstruction(endP,hp)
|
||||
else hp := endP;
|
||||
if (p <> endp) or
|
||||
not RegLoadedWithNewValue(newReg,endP) then
|
||||
not RegLoadedWithNewValue(newReg,true,endP) then
|
||||
RestoreRegContentsTo(newReg, c ,p, hp);
|
||||
{ In both case a and b, it is possible that the new register was modified }
|
||||
{ (e.g. an add/sub), so if it was replaced by oldreg in that instruction, }
|
||||
@ -956,7 +959,7 @@ Begin
|
||||
getLastInstruction(p,hp3);
|
||||
If not ReplaceReg(RegInfo.New2OldReg[RegCounter],
|
||||
regCounter,hp3,
|
||||
PPaiProp(hp4^.optInfo)^.Regs[regCounter]) then
|
||||
PPaiProp(hp4^.optInfo)^.Regs[regCounter],true) then
|
||||
begin
|
||||
{$endif replacereg}
|
||||
hp3 := New(Paicpu,Op_Reg_Reg(A_MOV, S_L,
|
||||
@ -1064,6 +1067,21 @@ Begin
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
{$ifdef replacereg}
|
||||
top_Reg:
|
||||
{ try to replace the new reg with the old reg }
|
||||
if (paicpu(p)^.opcode = A_MOV) and
|
||||
getLastInstruction(p,hp4) then
|
||||
begin
|
||||
Case paicpu(p)^.oper[1].typ of
|
||||
top_Reg:
|
||||
if ReplaceReg(paicpu(p)^.oper[0].reg,
|
||||
paicpu(p)^.oper[1].reg,p,
|
||||
PPaiProp(hp4^.optInfo)^.Regs[regCounter],false) then
|
||||
PPaiProp(p^.optInfo)^.canBeRemoved := true;
|
||||
end
|
||||
end;
|
||||
{$endif replacereg}
|
||||
Top_Const:
|
||||
Begin
|
||||
Case Paicpu(p)^.oper[1].typ Of
|
||||
@ -1149,7 +1167,13 @@ End.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.39 2000-01-13 13:07:05 jonas
|
||||
Revision 1.40 2000-01-22 16:10:06 jonas
|
||||
+ all code generator generated "mov reg1,reg2" instructions are now
|
||||
attempted to be removed using the replacereg code
|
||||
(-dnewoptimizations)
|
||||
* small fixes to -dreplacereg code
|
||||
|
||||
Revision 1.39 2000/01/13 13:07:05 jonas
|
||||
* released -dalignreg
|
||||
* some small fixes to -dnewOptimizations helper procedures
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user