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.