Better Code generation for SAR/ROR/ROL inline nodes

The old code forced dst and src to be the same, which is highly x86
specific and creates bad register utilization on other architectures
like arm.

The new version will use more imaginary registers, allowing the register
allocator to do a better job.

I've merged second_sar and second_rox into a single procedure
second_rox_sar because they were very similar.

git-svn-id: trunk@21809 -
This commit is contained in:
masta 2012-07-06 21:33:28 +00:00
parent 9825fbf554
commit bba75a079c

View File

@ -54,8 +54,7 @@ interface
procedure second_round_real; virtual; procedure second_round_real; virtual;
procedure second_trunc_real; virtual; procedure second_trunc_real; virtual;
procedure second_abs_long; virtual; procedure second_abs_long; virtual;
procedure second_rox; virtual; procedure second_rox_sar; virtual;
procedure second_sar; virtual;
procedure second_bsfbsr; virtual; procedure second_bsfbsr; virtual;
procedure second_new; virtual; procedure second_new; virtual;
procedure second_setlength; virtual; abstract; procedure second_setlength; virtual; abstract;
@ -168,11 +167,10 @@ implementation
in_rol_x, in_rol_x,
in_rol_x_y, in_rol_x_y,
in_ror_x, in_ror_x,
in_ror_x_y: in_ror_x_y,
second_rox;
in_sar_x, in_sar_x,
in_sar_x_y: in_sar_x_y:
second_sar; second_rox_sar;
in_bsf_x, in_bsf_x,
in_bsr_x: in_bsr_x:
second_BsfBsr; second_BsfBsr;
@ -721,10 +719,9 @@ implementation
end; end;
procedure tcginlinenode.second_rox; procedure tcginlinenode.second_rox_sar;
var var
op : topcg; op : topcg;
{hcountreg : tregister;}
op1,op2 : tnode; op1,op2 : tnode;
begin begin
{ one or two parameters? } { one or two parameters? }
@ -733,13 +730,15 @@ implementation
begin begin
op1:=tcallparanode(tcallparanode(left).right).left; op1:=tcallparanode(tcallparanode(left).right).left;
op2:=tcallparanode(left).left; op2:=tcallparanode(left).left;
secondpass(op2);
end end
else else
op1:=left; begin
op1:=left;
op2:=nil;
end;
secondpass(op1); secondpass(op1);
{ load left operator in a register }
location_copy(location,op1.location);
case inlinenumber of case inlinenumber of
in_ror_x, in_ror_x,
in_ror_x_y: in_ror_x_y:
@ -747,66 +746,35 @@ implementation
in_rol_x, in_rol_x,
in_rol_x_y: in_rol_x_y:
op:=OP_ROL; op:=OP_ROL;
in_sar_x,
in_sar_x_y:
op:=OP_SAR;
end; end;
hlcg.location_force_reg(current_asmdata.CurrAsmList,location,op1.resultdef,resultdef,false);
if (left.nodetype=callparan) and hlcg.location_force_reg(current_asmdata.CurrAsmList,op1.location,op1.resultdef,resultdef,true);
assigned(tcallparanode(left).right) then
location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
if assigned(op2) then
begin begin
secondpass(op2);
{ rotating by a constant directly coded: } { rotating by a constant directly coded: }
if op2.nodetype=ordconstn then if op2.nodetype=ordconstn then
cg.a_op_const_reg(current_asmdata.CurrAsmList,op,location.size, hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,resultdef,
tordconstnode(op2).value.uvalue and (resultdef.size*8-1),location.register) tordconstnode(op2).value.uvalue and (resultdef.size*8-1),
op1.location.register, location.register)
else else
begin begin
hlcg.location_force_reg(current_asmdata.CurrAsmList,op2.location,op2.resultdef,resultdef,false); hlcg.location_force_reg(current_asmdata.CurrAsmList,op2.location,
{ do modulo 2 operation } op2.resultdef,resultdef,true);
cg.a_op_reg_reg(current_asmdata.CurrAsmList,op,location.size,op2.location.register,location.register); hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,resultdef,
op2.location.register,op1.location.register,
location.register);
end; end;
end end
else else
cg.a_op_const_reg(current_asmdata.CurrAsmList,op,location.size,1,location.register); hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,resultdef,1,
end; op1.location.register,location.register);
procedure tcginlinenode.second_sar;
var
{hcountreg : tregister;}
op1,op2 : tnode;
begin
if (left.nodetype=callparan) and
assigned(tcallparanode(left).right) then
begin
op1:=tcallparanode(tcallparanode(left).right).left;
op2:=tcallparanode(left).left;
end
else
begin
op1:=left;
op2:=nil;
end;
secondpass(op1);
{ load left operator in a register }
location_copy(location,op1.location);
hlcg.location_force_reg(current_asmdata.CurrAsmList,location,op1.resultdef,resultdef,false);
if not(assigned(op2)) then
hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,resultdef,1,location.register)
else
begin
secondpass(op2);
{ shifting by a constant directly coded: }
if op2.nodetype=ordconstn then
hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,resultdef,
tordconstnode(op2).value.uvalue and (resultdef.size*8-1),location.register)
else
begin
hlcg.location_force_reg(current_asmdata.CurrAsmList,op2.location,op2.resultdef,resultdef,false);
hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_SAR,resultdef,op2.location.register,location.register);
end;
end;
end; end;