mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 22:49:23 +02:00
* factored out OptPass1Sub
+ make use of OptPass1Sub on x86_64 and i8086 as well git-svn-id: trunk@37572 -
This commit is contained in:
parent
ae92973196
commit
73fda1ccb6
@ -525,51 +525,6 @@ var
|
|||||||
GetFinalDestination := true;
|
GetFinalDestination := true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function DoSubAddOpt(var p: tai): Boolean;
|
|
||||||
begin
|
|
||||||
DoSubAddOpt := False;
|
|
||||||
if GetLastInstruction(p, hp1) and
|
|
||||||
(hp1.typ = ait_instruction) and
|
|
||||||
(taicpu(hp1).opsize = taicpu(p).opsize) then
|
|
||||||
case taicpu(hp1).opcode Of
|
|
||||||
A_DEC:
|
|
||||||
if (taicpu(hp1).oper[0]^.typ = top_reg) and
|
|
||||||
(taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
|
|
||||||
begin
|
|
||||||
taicpu(p).loadConst(0,taicpu(p).oper[0]^.val+1);
|
|
||||||
asml.remove(hp1);
|
|
||||||
hp1.free;
|
|
||||||
end;
|
|
||||||
A_SUB:
|
|
||||||
if (taicpu(hp1).oper[0]^.typ = top_const) and
|
|
||||||
(taicpu(hp1).oper[1]^.typ = top_reg) and
|
|
||||||
(taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
|
|
||||||
begin
|
|
||||||
taicpu(p).loadConst(0,taicpu(p).oper[0]^.val+taicpu(hp1).oper[0]^.val);
|
|
||||||
asml.remove(hp1);
|
|
||||||
hp1.free;
|
|
||||||
end;
|
|
||||||
A_ADD:
|
|
||||||
if (taicpu(hp1).oper[0]^.typ = top_const) and
|
|
||||||
(taicpu(hp1).oper[1]^.typ = top_reg) and
|
|
||||||
(taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
|
|
||||||
begin
|
|
||||||
taicpu(p).loadConst(0,taicpu(p).oper[0]^.val-taicpu(hp1).oper[0]^.val);
|
|
||||||
asml.remove(hp1);
|
|
||||||
hp1.free;
|
|
||||||
if (taicpu(p).oper[0]^.val = 0) then
|
|
||||||
begin
|
|
||||||
hp1 := tai(p.next);
|
|
||||||
asml.remove(p);
|
|
||||||
p.free;
|
|
||||||
if not GetLastInstruction(hp1, p) then
|
|
||||||
p := hp1;
|
|
||||||
DoSubAddOpt := True;
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
p := BlockStart;
|
p := BlockStart;
|
||||||
ClearUsedRegs;
|
ClearUsedRegs;
|
||||||
@ -1116,50 +1071,8 @@ begin
|
|||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
A_SUB:
|
A_SUB:
|
||||||
{ * change "subl $2, %esp; pushw x" to "pushl x"}
|
if OptPass1Sub(p) then
|
||||||
{ * change "sub/add const1, reg" or "dec reg" followed by
|
continue;
|
||||||
"sub const2, reg" to one "sub ..., reg" }
|
|
||||||
begin
|
|
||||||
if (taicpu(p).oper[0]^.typ = top_const) and
|
|
||||||
(taicpu(p).oper[1]^.typ = top_reg) then
|
|
||||||
if (taicpu(p).oper[0]^.val = 2) and
|
|
||||||
(taicpu(p).oper[1]^.reg = NR_ESP) and
|
|
||||||
{ Don't do the sub/push optimization if the sub }
|
|
||||||
{ comes from setting up the stack frame (JM) }
|
|
||||||
(not getLastInstruction(p,hp1) or
|
|
||||||
(hp1.typ <> ait_instruction) or
|
|
||||||
(taicpu(hp1).opcode <> A_MOV) or
|
|
||||||
(taicpu(hp1).oper[0]^.typ <> top_reg) or
|
|
||||||
(taicpu(hp1).oper[0]^.reg <> NR_ESP) or
|
|
||||||
(taicpu(hp1).oper[1]^.typ <> top_reg) or
|
|
||||||
(taicpu(hp1).oper[1]^.reg <> NR_EBP)) then
|
|
||||||
begin
|
|
||||||
hp1 := tai(p.next);
|
|
||||||
while Assigned(hp1) and
|
|
||||||
(tai(hp1).typ in [ait_instruction]+SkipInstr) and
|
|
||||||
not RegReadByInstruction(NR_ESP,hp1) and
|
|
||||||
not RegModifiedByInstruction(NR_ESP,hp1) do
|
|
||||||
hp1 := tai(hp1.next);
|
|
||||||
if Assigned(hp1) and
|
|
||||||
(tai(hp1).typ = ait_instruction) and
|
|
||||||
(taicpu(hp1).opcode = A_PUSH) and
|
|
||||||
(taicpu(hp1).opsize = S_W) then
|
|
||||||
begin
|
|
||||||
taicpu(hp1).changeopsize(S_L);
|
|
||||||
if taicpu(hp1).oper[0]^.typ=top_reg then
|
|
||||||
setsubreg(taicpu(hp1).oper[0]^.reg,R_SUBWHOLE);
|
|
||||||
hp1 := tai(p.next);
|
|
||||||
asml.remove(p);
|
|
||||||
p.free;
|
|
||||||
p := hp1;
|
|
||||||
continue
|
|
||||||
end;
|
|
||||||
if DoSubAddOpt(p) then
|
|
||||||
continue;
|
|
||||||
end
|
|
||||||
else if DoSubAddOpt(p) then
|
|
||||||
continue
|
|
||||||
end;
|
|
||||||
A_VMOVAPS,
|
A_VMOVAPS,
|
||||||
A_VMOVAPD:
|
A_VMOVAPD:
|
||||||
if OptPass1VMOVAP(p) then
|
if OptPass1VMOVAP(p) then
|
||||||
|
@ -109,7 +109,9 @@ unit aoptcpu;
|
|||||||
result:=true;
|
result:=true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end
|
A_SUB:
|
||||||
|
result:=OptPass1Sub(p);
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -55,6 +55,8 @@ unit aoptx86;
|
|||||||
class function isFoldableArithOp(hp1 : taicpu; reg : tregister) : boolean;
|
class function isFoldableArithOp(hp1 : taicpu; reg : tregister) : boolean;
|
||||||
procedure RemoveLastDeallocForFuncRes(p : tai);
|
procedure RemoveLastDeallocForFuncRes(p : tai);
|
||||||
|
|
||||||
|
function DoSubAddOpt(var p : tai) : Boolean;
|
||||||
|
|
||||||
function PrePeepholeOptSxx(var p : tai) : boolean;
|
function PrePeepholeOptSxx(var p : tai) : boolean;
|
||||||
|
|
||||||
function OptPass1AND(var p : tai) : boolean;
|
function OptPass1AND(var p : tai) : boolean;
|
||||||
@ -66,6 +68,7 @@ unit aoptx86;
|
|||||||
function OptPass1MOVXX(var p : tai) : boolean;
|
function OptPass1MOVXX(var p : tai) : boolean;
|
||||||
function OptPass1OP(const p : tai) : boolean;
|
function OptPass1OP(const p : tai) : boolean;
|
||||||
function OptPass1LEA(var p : tai) : boolean;
|
function OptPass1LEA(var p : tai) : boolean;
|
||||||
|
function OptPass1Sub(var p : tai) : boolean;
|
||||||
|
|
||||||
function OptPass2MOV(var p : tai) : boolean;
|
function OptPass2MOV(var p : tai) : boolean;
|
||||||
function OptPass2Imul(var p : tai) : boolean;
|
function OptPass2Imul(var p : tai) : boolean;
|
||||||
@ -1875,6 +1878,99 @@ unit aoptx86;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TX86AsmOptimizer.DoSubAddOpt(var p: tai): Boolean;
|
||||||
|
var
|
||||||
|
hp1 : tai;
|
||||||
|
begin
|
||||||
|
DoSubAddOpt := False;
|
||||||
|
if GetLastInstruction(p, hp1) and
|
||||||
|
(hp1.typ = ait_instruction) and
|
||||||
|
(taicpu(hp1).opsize = taicpu(p).opsize) then
|
||||||
|
case taicpu(hp1).opcode Of
|
||||||
|
A_DEC:
|
||||||
|
if (taicpu(hp1).oper[0]^.typ = top_reg) and
|
||||||
|
MatchOperand(taicpu(hp1).oper[1]^,taicpu(p).oper[1]^) then
|
||||||
|
begin
|
||||||
|
taicpu(p).loadConst(0,taicpu(p).oper[0]^.val+1);
|
||||||
|
asml.remove(hp1);
|
||||||
|
hp1.free;
|
||||||
|
end;
|
||||||
|
A_SUB:
|
||||||
|
if MatchOpType(taicpu(hp1),top_const,top_reg) and
|
||||||
|
MatchOperand(taicpu(hp1).oper[1]^,taicpu(p).oper[1]^) then
|
||||||
|
begin
|
||||||
|
taicpu(p).loadConst(0,taicpu(p).oper[0]^.val+taicpu(hp1).oper[0]^.val);
|
||||||
|
asml.remove(hp1);
|
||||||
|
hp1.free;
|
||||||
|
end;
|
||||||
|
A_ADD:
|
||||||
|
if MatchOpType(taicpu(hp1),top_const,top_reg) and
|
||||||
|
MatchOperand(taicpu(hp1).oper[1]^,taicpu(p).oper[1]^) then
|
||||||
|
begin
|
||||||
|
taicpu(p).loadConst(0,taicpu(p).oper[0]^.val-taicpu(hp1).oper[0]^.val);
|
||||||
|
asml.remove(hp1);
|
||||||
|
hp1.free;
|
||||||
|
if (taicpu(p).oper[0]^.val = 0) then
|
||||||
|
begin
|
||||||
|
hp1 := tai(p.next);
|
||||||
|
asml.remove(p);
|
||||||
|
p.free;
|
||||||
|
if not GetLastInstruction(hp1, p) then
|
||||||
|
p := hp1;
|
||||||
|
DoSubAddOpt := True;
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TX86AsmOptimizer.OptPass1Sub(var p : tai) : boolean;
|
||||||
|
var
|
||||||
|
hp1 : tai;
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
{ * change "subl $2, %esp; pushw x" to "pushl x"}
|
||||||
|
{ * change "sub/add const1, reg" or "dec reg" followed by
|
||||||
|
"sub const2, reg" to one "sub ..., reg" }
|
||||||
|
if MatchOpType(taicpu(p),top_const,top_reg) then
|
||||||
|
begin
|
||||||
|
{$ifdef i386}
|
||||||
|
if (taicpu(p).oper[0]^.val = 2) and
|
||||||
|
(taicpu(p).oper[1]^.reg = NR_ESP) and
|
||||||
|
{ Don't do the sub/push optimization if the sub }
|
||||||
|
{ comes from setting up the stack frame (JM) }
|
||||||
|
(not(GetLastInstruction(p,hp1)) or
|
||||||
|
not(MatchInstruction(hp1,A_MOV,[S_L]) and
|
||||||
|
MatchOperand(taicpu(hp1).oper[0]^,NR_ESP) and
|
||||||
|
MatchOperand(taicpu(hp1).oper[0]^,NR_EBP))) then
|
||||||
|
begin
|
||||||
|
hp1 := tai(p.next);
|
||||||
|
while Assigned(hp1) and
|
||||||
|
(tai(hp1).typ in [ait_instruction]+SkipInstr) and
|
||||||
|
not RegReadByInstruction(NR_ESP,hp1) and
|
||||||
|
not RegModifiedByInstruction(NR_ESP,hp1) do
|
||||||
|
hp1 := tai(hp1.next);
|
||||||
|
if Assigned(hp1) and
|
||||||
|
MatchInstruction(hp1,A_PUSH,[S_W]) then
|
||||||
|
begin
|
||||||
|
taicpu(hp1).changeopsize(S_L);
|
||||||
|
if taicpu(hp1).oper[0]^.typ=top_reg then
|
||||||
|
setsubreg(taicpu(hp1).oper[0]^.reg,R_SUBWHOLE);
|
||||||
|
hp1 := tai(p.next);
|
||||||
|
asml.remove(p);
|
||||||
|
p.free;
|
||||||
|
p := hp1;
|
||||||
|
Result:=true;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{$endif i386}
|
||||||
|
if DoSubAddOpt(p) then
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TX86AsmOptimizer.OptPass2MOV(var p : tai) : boolean;
|
function TX86AsmOptimizer.OptPass2MOV(var p : tai) : boolean;
|
||||||
var
|
var
|
||||||
TmpUsedRegs : TAllUsedRegs;
|
TmpUsedRegs : TAllUsedRegs;
|
||||||
|
@ -106,6 +106,8 @@ uses
|
|||||||
result:=OptPass1MOVXX(p);
|
result:=OptPass1MOVXX(p);
|
||||||
A_LEA:
|
A_LEA:
|
||||||
result:=OptPass1LEA(p);
|
result:=OptPass1LEA(p);
|
||||||
|
A_SUB:
|
||||||
|
result:=OptPass1Sub(p);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user