* modified patch of Paul W to replace leave by mov/pop, resolves #26455

git-svn-id: trunk@29633 -
This commit is contained in:
florian 2015-02-05 20:51:12 +00:00
parent 1bc72d437c
commit 35a04ad095
5 changed files with 73 additions and 19 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;