https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78327
--- Comment #7 from Richard Biener <rguenth at gcc dot gnu.org> --- Well, the issue is that we don't always use the "nice" unsigned rep for anti-range tests but "simplify" the special case (unsigned char) n + 125 <= 127 to a cheaper signed comparison against zero via /* Non-equality compare simplifications from fold_binary */ (for cmp (lt gt le ge) /* Comparisons with the highest or lowest possible integer of the specified precision will have known values. */ (simplify (cmp (convert?@2 @0) INTEGER_CST@1) (if ((INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1))) && tree_nop_conversion_p (TREE_TYPE (@2), TREE_TYPE (@0))) ... (if (wi::eq_p (@1, signed_max) && TYPE_UNSIGNED (arg1_type) /* We will flip the signedness of the comparison operator associated with the mode of @1, so the sign bit is specified by this mode. Check that @1 is the signed max associated with this sign bit. */ && prec == GET_MODE_PRECISION (TYPE_MODE (arg1_type)) /* signed_type does not work on pointer types. */ && INTEGRAL_TYPE_P (arg1_type)) /* The following case also applies to X < signed_max+1 and X >= signed_max+1 because previous transformations. */ (if (cmp == LE_EXPR || cmp == GT_EXPR) (with { tree st = signed_type_for (arg1_type); } (if (cmp == LE_EXPR) (ge (convert:st @0) { build_zero_cst (st); }) (lt (convert:st @0) { build_zero_cst (st); })))))))))) so yes, we should add handling of (signed)X < / >= 0 to VRP. Note that early VRP doesn't handle any of these cases yet (it requires back-propagation to be implemented or of course the pattern matchings be generalized so they are usable from early VRP).