http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49039
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |ASSIGNED AssignedTo|unassigned at gcc dot |jakub at gcc dot gnu.org |gnu.org | --- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> 2011-05-18 16:46:09 UTC --- Ok, I think I see the bug. extract_range_from_binary_expr is called with MIN_EXPR, where vr0 is ~[-1UL, -1UL] and vr1 is ~[0, 0] and performs: /* For operations that make the resulting range directly proportional to the original ranges, apply the operation to the same end of each range. */ min = vrp_int_const_binop (code, vr0.min, vr1.min); max = vrp_int_const_binop (code, vr0.max, vr1.max); which for MIN_EXPR unsurprisingly gives min 0 max 0 and thus returns ~[0, 0] although it should have been VARYING in this case. For PLUS we already give up for VR_ANTI_RANGE earlier: if (code == PLUS_EXPR && vr0.type == VR_ANTI_RANGE) { set_value_range_to_varying (vr); return; } but we don't do so for MIN_EXPR/MAX_EXPR. For MAX_EXPR the same ranges will give similarly incorrect result: MAX_EXPR <~[-1UL, -1UL], ~[0, 0]> will yield ~[-1UL, -1UL] instead of correct VARYING. So, either we can just remove "code == PLUS_EXPR && " and give up with VR_ANTI_RANGE always, or if there is a way to do something better we could do so. I'll think about it some more. E.g. for MIN_EXPR/MAX_EXPR, if the anti ranges are the same we can certainly return that anti range instead of VARYING.