mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-22 11:49:23 +02:00
Bolder OptPass2Movx optimisations, including a simplification fix
This commit is contained in:
parent
da899df6b2
commit
f02b7508de
@ -7954,7 +7954,7 @@ unit aoptx86;
|
||||
|
||||
{ Data flow analysis }
|
||||
TestValMin, TestValMax: TCgInt;
|
||||
SmallerOverflow: Boolean;
|
||||
SmallerOverflow, BitwiseOnly, OrXorUsed: Boolean;
|
||||
|
||||
begin
|
||||
Result := False;
|
||||
@ -8000,6 +8000,8 @@ unit aoptx86;
|
||||
TrySmaller := S_NO;
|
||||
SmallerOverflow := False;
|
||||
RegChanged := False;
|
||||
BitwiseOnly := True;
|
||||
OrXorUsed := False;
|
||||
|
||||
hp1 := p;
|
||||
|
||||
@ -8118,9 +8120,7 @@ unit aoptx86;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ OR and XOR are not included because they can too easily fool
|
||||
the data flow analysis (they can cause non-linear behaviour) }
|
||||
A_ADD,A_SUB,A_AND,A_SHL,A_SHR:
|
||||
A_ADD,A_SUB,A_AND,A_OR,A_XOR,A_SHL,A_SHR:
|
||||
begin
|
||||
if
|
||||
(taicpu(hp1).oper[1]^.typ <> top_reg) or
|
||||
@ -8153,29 +8153,49 @@ unit aoptx86;
|
||||
) then
|
||||
Break;
|
||||
|
||||
{ Only process OR and XOR if there are only bitwise operations,
|
||||
since otherwise they can too easily fool the data flow
|
||||
analysis (they can cause non-linear behaviour) }
|
||||
|
||||
case taicpu(hp1).opcode of
|
||||
A_ADD:
|
||||
if (taicpu(hp1).oper[0]^.typ = top_reg) then
|
||||
begin
|
||||
TestValMin := TestValMin * 2;
|
||||
TestValMax := TestValMax * 2;
|
||||
end
|
||||
else
|
||||
begin
|
||||
TestValMin := TestValMin + taicpu(hp1).oper[0]^.val;
|
||||
TestValMax := TestValMax + taicpu(hp1).oper[0]^.val;
|
||||
end;
|
||||
begin
|
||||
if OrXorUsed then
|
||||
{ Too high a risk of non-linear behaviour that breaks DFA here }
|
||||
Break
|
||||
else
|
||||
BitwiseOnly := False;
|
||||
|
||||
if (taicpu(hp1).oper[0]^.typ = top_reg) then
|
||||
begin
|
||||
TestValMin := TestValMin * 2;
|
||||
TestValMax := TestValMax * 2;
|
||||
end
|
||||
else
|
||||
begin
|
||||
TestValMin := TestValMin + taicpu(hp1).oper[0]^.val;
|
||||
TestValMax := TestValMax + taicpu(hp1).oper[0]^.val;
|
||||
end;
|
||||
end;
|
||||
A_SUB:
|
||||
if (taicpu(hp1).oper[0]^.typ = top_reg) then
|
||||
begin
|
||||
TestValMin := 0;
|
||||
TestValMax := 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
TestValMin := TestValMin - taicpu(hp1).oper[0]^.val;
|
||||
TestValMax := TestValMax - taicpu(hp1).oper[0]^.val;
|
||||
end;
|
||||
begin
|
||||
if OrXorUsed then
|
||||
{ Too high a risk of non-linear behaviour that breaks DFA here }
|
||||
Break
|
||||
else
|
||||
BitwiseOnly := False;
|
||||
|
||||
if (taicpu(hp1).oper[0]^.typ = top_reg) then
|
||||
begin
|
||||
TestValMin := 0;
|
||||
TestValMax := 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
TestValMin := TestValMin - taicpu(hp1).oper[0]^.val;
|
||||
TestValMax := TestValMax - taicpu(hp1).oper[0]^.val;
|
||||
end;
|
||||
end;
|
||||
A_AND:
|
||||
if (taicpu(hp1).oper[0]^.typ = top_const) then
|
||||
begin
|
||||
@ -8211,6 +8231,26 @@ unit aoptx86;
|
||||
TestValMin := TestValMin and taicpu(hp1).oper[0]^.val;
|
||||
TestValMax := TestValMax and taicpu(hp1).oper[0]^.val;
|
||||
end;
|
||||
A_OR:
|
||||
begin
|
||||
if not BitwiseOnly then
|
||||
Break;
|
||||
|
||||
OrXorUsed := True;
|
||||
|
||||
TestValMin := TestValMin or taicpu(hp1).oper[0]^.val;
|
||||
TestValMax := TestValMax or taicpu(hp1).oper[0]^.val;
|
||||
end;
|
||||
A_XOR:
|
||||
begin
|
||||
if not BitwiseOnly then
|
||||
Break;
|
||||
|
||||
OrXorUsed := True;
|
||||
|
||||
TestValMin := TestValMin xor taicpu(hp1).oper[0]^.val;
|
||||
TestValMax := TestValMax xor taicpu(hp1).oper[0]^.val;
|
||||
end;
|
||||
A_SHL:
|
||||
begin
|
||||
TestValMin := TestValMin shl taicpu(hp1).oper[0]^.val;
|
||||
@ -8469,8 +8509,6 @@ unit aoptx86;
|
||||
hp2 := p;
|
||||
repeat
|
||||
|
||||
UpdateUsedRegs(TmpUsedRegs, tai(hp2.next));
|
||||
|
||||
{ Explicitly check for the excluded register (don't include the first
|
||||
instruction as it may be reading from here }
|
||||
if ((p <> hp2) and (RegInInstruction(taicpu(hp1).oper[1]^.reg, hp2))) or
|
||||
@ -8480,12 +8518,31 @@ unit aoptx86;
|
||||
Break;
|
||||
end;
|
||||
|
||||
UpdateUsedRegs(TmpUsedRegs, tai(hp2.next));
|
||||
|
||||
if not GetNextInstruction(hp2, hp2) then
|
||||
InternalError(2020112340);
|
||||
|
||||
until (hp2 = hp1);
|
||||
|
||||
if not RegInUse and not RegUsedAfterInstruction(ThisReg, hp1, TmpUsedRegs) then
|
||||
if not RegInUse and RegUsedAfterInstruction(ThisReg, hp1, TmpUsedRegs) then
|
||||
begin
|
||||
RegInUse := True;
|
||||
|
||||
{ We might still be able to get away with this }
|
||||
if GetNextInstructionUsingReg(hp1, hp2, ThisReg) and
|
||||
(hp2.typ = ait_instruction) and
|
||||
(
|
||||
{ Under -O1 and -O2, GetNextInstructionUsingReg may return an
|
||||
instruction that doesn't actually contain ThisReg }
|
||||
(cs_opt_level3 in current_settings.optimizerswitches) or
|
||||
RegInInstruction(ThisReg, hp2)
|
||||
) and
|
||||
RegLoadedWithNewValue(ThisReg, hp2) then
|
||||
RegInUse := False;
|
||||
end;
|
||||
|
||||
if not RegInUse then
|
||||
begin
|
||||
DebugMsg(SPeepholeOptimization + 'Simplified register usage so ' + debug_regname(taicpu(hp1).oper[1]^.reg) + ' = ' + debug_regname(taicpu(p).oper[1]^.reg), p);
|
||||
ThisReg := taicpu(hp1).oper[1]^.reg;
|
||||
|
Loading…
Reference in New Issue
Block a user