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