https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107668

--- Comment #10 from Aldy Hernandez <aldyh at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #8)
> While the patch passed bootstrap/regtest, I'm afraid it is not correct.
> 
> What we have is lhs = op1 * 0.0; with range of lhs [-0.0, 0.0] and range of
> op2 [0.0, 0.0] and we call fop_mult.op1_range to determine range of op1.
> Now, if it would be HONOR_NANS, the division lhs / op2 aka [-0.0, 0.0] /
> [0.0, 0.0] would compute NAN and float_binary_op_range_finish would take the:
>   // If we get a known NAN from reverse op, it means either that
>   // the other operand was known NAN (in that case we know nothing),
>   // or the reverse operation introduced a known NAN.
>   // Say for lhs = op1 * op2 if lhs is [-0, +0] and op2 is too,
>   // 0 / 0 is known NAN.  Just punt in that case.
>   // Or if lhs is a known NAN, we also don't know anything.
>   if (r.known_isnan () || lhs.known_isnan ())
>     {
>       r.set_varying (type);
>       return true;
>     }
> path.  VARYING is the range we want in this case btw, because anything times
> 0.0
> is 0.0 or -0.0 (well, if INF/NANs are honored, we could make it [-MAX, MAX],
> or
> if honoring signed zeros and lhs range would be just [0.0, 0.0] or [-0.0,
> -0.0]
> or op2 one of these it could be even [-MAX, -0.0] or [0.0, MAX].
> But because NANs aren't honored and INFs neither, we get from [-0.0, 0.0] /
> [0.0, 0.0] division UNDEFINED range (NAN with NAN removed).
> So, a safe fix would be to handle r.undefined_p () the same as r.known_isnan
> () or lhs.known_isnan () and if we want to eventually improve the
> op[12]_range
> calls for individual ops for some special cases, we can.
> 
> Aldy, thoughts on this?

OMG, head hurts on this one.

Yeah, op1 could have been anything so varying seems like the right thing to do.

I was curious if we were doing something in operator_div::op1_range for
integers, but we haven't even thought that far :).

OK for trunk btw.

Reply via email to