* SPARC, tmoddivnode improvements/fixes:

* don't bother reusing locations
  * don't optimize division into shift if overflow checking is enabled
  * if denominator is a constant and fits into 13 bit range, use it directly and save a register.

git-svn-id: trunk@26363 -
This commit is contained in:
sergei 2014-01-03 08:09:32 +00:00
parent cf6f408214
commit 0afd95e840

View File

@ -81,28 +81,18 @@ implementation
begin
secondpass(left);
secondpass(right);
location_copy(location,left.location);
location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
location.register:=cg.GetIntRegister(current_asmdata.CurrAsmList,OS_INT);
{ put numerator in register }
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
location_copy(location,left.location);
numerator := location.register;
if (nodetype = modn) then
resultreg := cg.GetIntRegister(current_asmdata.CurrAsmList,OS_INT)
else
begin
if (location.loc = LOC_CREGISTER) then
begin
location.loc := LOC_REGISTER;
location.register := cg.GetIntRegister(current_asmdata.CurrAsmList,OS_INT);
end;
resultreg := location.register;
end;
numerator := left.location.register;
resultreg := location.register;
if (nodetype = divn) and
(right.nodetype = ordconstn) and
ispowerof2(tordconstnode(right).value.svalue,power) then
ispowerof2(tordconstnode(right).value.svalue,power) and
(not (cs_check_overflow in current_settings.localswitches)) then
begin
if is_signed(left.resultdef) Then
begin
@ -120,9 +110,15 @@ implementation
else
begin
{ load divider in a register if necessary }
hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,
right.resultdef,right.resultdef,true);
divider := right.location.register;
divider:=NR_NO;
if (right.location.loc<>LOC_CONSTANT) or
(right.location.value<simm13lo) or
(right.location.value>simm13hi) then
begin
hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,
right.resultdef,right.resultdef,true);
divider:=right.location.register;
end;
{ needs overflow checking, (-maxlongint-1) div (-1) overflows! }
{ And on Sparc, the only way to catch a div-by-0 is by checking }
@ -144,7 +140,10 @@ implementation
op := divops[is_signed(right.resultdef),
cs_check_overflow in current_settings.localswitches];
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,numerator,divider,resultreg));
if (divider<>NR_NO) then
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,numerator,divider,resultreg))
else
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const_reg(op,numerator,right.location.value,resultreg));
if (nodetype = modn) then
begin
@ -154,7 +153,10 @@ implementation
current_asmdata.CurrAsmList.concat(ai);
current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_NOT,resultreg));
cg.a_label(current_asmdata.CurrAsmList,overflowlabel);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SMUL,resultreg,divider,resultreg));
if (divider<>NR_NO) then
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SMUL,resultreg,divider,resultreg))
else
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const_reg(A_SMUL,resultreg,right.location.value,resultreg));
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUB,numerator,resultreg,resultreg));
end;
end;