Commit c95c47f3 by Paul Eggert

(expand_float): When converting an unsigned type U to a smaller or equal-sized…

(expand_float): When converting an unsigned type U to a smaller or equal-sized floating type F where there's no hardware support for unsigned-to-float conversion...

(expand_float): When converting an unsigned type U
to a smaller or equal-sized floating type F where there's no
hardware support for unsigned-to-float conversion, use a temporary
floating type larger than F if possible, since this avoids
rounding problems that are worst when U is just greater than
the maximum signed integer of the same size.

From-SVN: r3778
parent 0cdd3ddd
......@@ -3572,11 +3572,27 @@ expand_float (to, from, unsignedp)
if (flag_force_mem)
from = force_not_mem (from);
/* Look for a usable floating mode FMODE wider than the source and at
least as wide as the target. Using FMODE will avoid rounding woes
with unsigned values greater than the signed maximum value. */
for (fmode = GET_MODE (to); fmode != VOIDmode;
fmode = GET_MODE_WIDER_MODE (fmode))
if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
&& can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
break;
if (fmode == VOIDmode)
{
/* There is no such mode. Pretend the target is wide enough.
This may cause rounding problems, unfortunately. */
fmode = GET_MODE (to);
}
/* If we are about to do some arithmetic to correct for an
unsigned operand, do it in a pseudo-register. */
if (GET_CODE (to) != REG || REGNO (to) <= LAST_VIRTUAL_REGISTER)
target = gen_reg_rtx (GET_MODE (to));
if (GET_MODE (to) != fmode
|| GET_CODE (to) != REG || REGNO (to) <= LAST_VIRTUAL_REGISTER)
target = gen_reg_rtx (fmode);
/* Convert as signed integer to floating. */
expand_float (target, from, 0);
......@@ -3591,8 +3607,8 @@ expand_float (to, from, unsignedp)
Rather than setting up a dconst_dot_5, let's hope SCO
fixes the bug. */
offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
temp = expand_binop (GET_MODE (to), add_optab, target,
immed_real_const_1 (offset, GET_MODE (to)),
temp = expand_binop (fmode, add_optab, target,
immed_real_const_1 (offset, fmode),
target, 0, OPTAB_LIB_WIDEN);
if (temp != target)
emit_move_insn (target, temp);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment