https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97725
--- Comment #3 from Andrew Macleod <amacleod at redhat dot com> --- Created attachment 49512 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49512&action=edit Use a multirange value in value_query::value_of_* This was triggered by a new call into range_of_stmt to reevaluate _3 = e_15 != 0; we already knew it was [1,1], and had folded some stuff away. however, e_15 had been further refined so _3 was out of date. mostly harmless, except e_15 now has a range of long int [-1, -1][4294967294, 4294967295] obviously that will still evaluate to [1,1]... except it didn't :-P it came back VARYING. != checks if the intersection of the 2 operands is empty... which it should be, but the code reuses the result range passed in as the temporary.. and that turns out of be a value_range. so when we copy [-1, -1][4294967294, 4294967295] into the value_range, it cant be fully represented, and we end up with long int [-1, 4294967295] and can no longer tell it is not equal to [0,0]. doh. First, the range-ops code for not_equal and equal should be adjusted to not use the range passed in as a temporary.. the consumer may well know this is a boolean and only pass in an int_range<1> on purpose. second, the true root is that the 3 value_of_* routines actually pass in a value_range rather than a multirange... Original thinking was we are looking for a single value result. But there are other range_ops routines that build into the value passed, like multiply and others, so its better to simple pass in an int_range_max or something similar could happen elsewhere. testing the attached patch