mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-15 15:19:25 +02:00
* modified patch of Paul W to replace leave by mov/pop, resolves #26455
git-svn-id: trunk@29633 -
This commit is contained in:
parent
1bc72d437c
commit
35a04ad095
@ -343,7 +343,7 @@ unit cgcpu;
|
||||
begin
|
||||
if (not paramanager.use_fixed_stack) then
|
||||
internal_restore_regs(list,not (pi_has_stack_allocs in current_procinfo.flags));
|
||||
list.concat(Taicpu.op_none(A_LEAVE,S_NO));
|
||||
generate_leave(list);
|
||||
end;
|
||||
list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
|
||||
end;
|
||||
|
@ -79,6 +79,35 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
function IsExitCode(p : tai) : boolean;
|
||||
var
|
||||
hp2,hp3 : tai;
|
||||
begin
|
||||
result:=(p.typ=ait_instruction) and
|
||||
((taicpu(p).opcode = A_RET) or
|
||||
((taicpu(p).opcode=A_LEAVE) and
|
||||
GetNextInstruction(p,hp2) and
|
||||
(hp2.typ=ait_instruction) and
|
||||
(taicpu(hp2).opcode=A_RET)
|
||||
) or
|
||||
((taicpu(p).opcode=A_MOV) and
|
||||
(taicpu(p).oper[0]^.typ=top_reg) and
|
||||
(taicpu(p).oper[0]^.reg=NR_EBP) and
|
||||
(taicpu(p).oper[1]^.typ=top_reg) and
|
||||
(taicpu(p).oper[1]^.reg=NR_ESP) and
|
||||
GetNextInstruction(p,hp2) and
|
||||
(hp2.typ=ait_instruction) and
|
||||
(taicpu(hp2).opcode=A_POP) and
|
||||
(taicpu(hp2).oper[0]^.typ=top_reg) and
|
||||
(taicpu(hp2).oper[0]^.reg=NR_EBP) and
|
||||
GetNextInstruction(hp2,hp3) and
|
||||
(hp3.typ=ait_instruction) and
|
||||
(taicpu(hp3).opcode=A_RET)
|
||||
)
|
||||
);
|
||||
end;
|
||||
|
||||
|
||||
function doFpuLoadStoreOpt(asmL: TAsmList; var p: tai): boolean;
|
||||
{ returns true if a "continue" should be done after this optimization }
|
||||
var hp1, hp2: tai;
|
||||
@ -99,8 +128,7 @@ begin
|
||||
if (taicpu(p).opsize=S_FX) and
|
||||
getNextInstruction(hp1, hp2) and
|
||||
(hp2.typ = ait_instruction) and
|
||||
((taicpu(hp2).opcode = A_LEAVE) or
|
||||
(taicpu(hp2).opcode = A_RET)) and
|
||||
IsExitCode(hp2) and
|
||||
(taicpu(p).oper[0]^.ref^.base = current_procinfo.FramePointer) and
|
||||
not(assigned(current_procinfo.procdef.funcretsym) and
|
||||
(taicpu(p).oper[0]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
|
||||
@ -517,7 +545,6 @@ function MatchReference(const ref : treference;base,index : TRegister) : Boolean
|
||||
(ref.index=index));
|
||||
end;
|
||||
|
||||
|
||||
{ First pass of peephole optimizations }
|
||||
procedure PeepHoleOptPass1(Asml: TAsmList; BlockStart, BlockEnd: tai);
|
||||
|
||||
@ -1214,8 +1241,7 @@ begin
|
||||
result)}
|
||||
if GetNextInstruction(p, hp1) and
|
||||
(tai(hp1).typ = ait_instruction) then
|
||||
if ((taicpu(hp1).opcode = A_LEAVE) or
|
||||
(taicpu(hp1).opcode = A_RET)) and
|
||||
if IsExitCode(hp1) and
|
||||
(taicpu(p).oper[1]^.typ = top_ref) and
|
||||
(taicpu(p).oper[1]^.ref^.base = current_procinfo.FramePointer) and
|
||||
not(assigned(current_procinfo.procdef.funcretsym) and
|
||||
@ -1873,9 +1899,7 @@ begin
|
||||
if (taicpu(p).oper[0]^.typ = top_ref) and
|
||||
GetNextInstruction(p, hp1) and
|
||||
GetNextInstruction(hp1, hp2) and
|
||||
(hp2.typ = ait_instruction) and
|
||||
((taicpu(hp2).opcode = A_LEAVE) or
|
||||
(taicpu(hp2).opcode = A_RET)) and
|
||||
IsExitCode(hp2) and
|
||||
(taicpu(p).oper[0]^.ref^.base = current_procinfo.FramePointer) and
|
||||
(taicpu(p).oper[0]^.ref^.index = NR_NO) and
|
||||
not(assigned(current_procinfo.procdef.funcretsym) and
|
||||
|
@ -1781,15 +1781,7 @@ unit cgcpu;
|
||||
cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);
|
||||
end
|
||||
else
|
||||
begin
|
||||
if current_settings.cputype < cpu_186 then
|
||||
begin
|
||||
list.concat(Taicpu.op_reg_reg(A_MOV, S_W, NR_BP, NR_SP));
|
||||
list.concat(Taicpu.op_reg(A_POP, S_W, NR_BP));
|
||||
end
|
||||
else
|
||||
list.concat(Taicpu.op_none(A_LEAVE,S_NO));
|
||||
end;
|
||||
generate_leave(list);
|
||||
list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
|
||||
end;
|
||||
|
||||
|
@ -128,6 +128,8 @@ unit cgx86;
|
||||
procedure g_external_wrapper(list: TAsmList; procdef: tprocdef; const externalname: string); override;
|
||||
|
||||
procedure make_simple_ref(list:TAsmList;var ref: treference);
|
||||
|
||||
procedure generate_leave(list : TAsmList);
|
||||
protected
|
||||
procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
|
||||
procedure check_register_size(size:tcgsize;reg:tregister);
|
||||
@ -175,6 +177,9 @@ unit cgx86;
|
||||
|
||||
function UseIncDec: boolean;
|
||||
|
||||
{ returns true, if the compiler should use leave instead of mov/pop }
|
||||
function UseLeave: boolean;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
@ -203,6 +208,18 @@ unit cgx86;
|
||||
end;
|
||||
|
||||
|
||||
function UseLeave: boolean;
|
||||
begin
|
||||
{$if defined(x86_64)}
|
||||
{ Modern processors should be happy with mov;pop, maybe except older AMDs }
|
||||
Result:=cs_opt_size in current_settings.optimizerswitches;
|
||||
{$elseif defined(i386)}
|
||||
Result:=(cs_opt_size in current_settings.optimizerswitches) or (current_settings.optimizecputype<cpu_Pentium2);
|
||||
{$elseif defined(i8086)}
|
||||
Result:=current_settings.cputype>=cpu_186;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
const
|
||||
TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_MOV,A_ADD,A_AND,A_DIV,
|
||||
A_IDIV,A_IMUL,A_MUL,A_NEG,A_NOT,A_OR,
|
||||
@ -2999,6 +3016,26 @@ unit cgx86;
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgx86.generate_leave(list: TAsmList);
|
||||
begin
|
||||
if UseLeave then
|
||||
list.concat(taicpu.op_none(A_LEAVE,S_NO))
|
||||
else
|
||||
begin
|
||||
{$if defined(x86_64)}
|
||||
list.Concat(taicpu.op_reg_reg(A_MOV,S_Q,NR_RBP,NR_RSP));
|
||||
list.Concat(taicpu.op_reg(A_POP,S_Q,NR_RBP));
|
||||
{$elseif defined(i386)}
|
||||
list.Concat(taicpu.op_reg_reg(A_MOV,S_L,NR_EBP,NR_ESP));
|
||||
list.Concat(taicpu.op_reg(A_POP,S_L,NR_EBP));
|
||||
{$elseif defined(i8086)}
|
||||
list.Concat(taicpu.op_reg_reg(A_MOV,S_W,NR_BP,NR_SP));
|
||||
list.Concat(taicpu.op_reg(A_POP,S_W,NR_BP));
|
||||
{$endif}
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ produces if necessary overflowcode }
|
||||
procedure tcgx86.g_overflowcheck(list: TAsmList; const l:tlocation;def:tdef);
|
||||
var
|
||||
@ -3025,6 +3062,7 @@ unit cgx86;
|
||||
a_label(list,hl);
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgx86.g_external_wrapper(list: TAsmList; procdef: tprocdef; const externalname: string);
|
||||
var
|
||||
ref : treference;
|
||||
|
@ -398,7 +398,7 @@ unit cgcpu;
|
||||
list.concat(Taicpu.op_reg(A_POP,tcgsize2opsize[OS_ADDR],current_procinfo.framepointer));
|
||||
end
|
||||
else
|
||||
list.concat(Taicpu.op_none(A_LEAVE,S_NO));
|
||||
generate_leave(list);
|
||||
list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user