https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97505
--- Comment #1 from Aldy Hernandez <aldyh at gcc dot gnu.org> --- We are calculating ranges for the following: (gdb) dd stmt _18 = .UBSAN_CHECK_SUB (_58, _57); which gets turned into a MINUS_EXPR. Then we call extract_range_from_binary_expr on the MINUS_EXPR: /* Pretend the arithmetics is wrapping. If there is any overflow, we'll complain, but will actually do wrapping operation. */ flag_wrapv = 1; extract_range_from_binary_expr (vr, subcode, type, gimple_call_arg (stmt, 0), gimple_call_arg (stmt, 1)); flag_wrapv = saved_flag_wrapv; In extract_range_from_binary_expr, we calculate the range for _58 and _57 respectively as: (gdb) dd vr0 integer(kind=8) [-INF, _57 - 1] (gdb) dd vr1 integer(kind=8) [_58 + 1, +INF] Which extract_range_from_binary_expr can then use to reduce the MINUS_EXPR to ~[0,0]: /* If we didn't derive a range for MINUS_EXPR, and op1's range is ~[op0,op0] or vice-versa, then we can derive a non-null range. This happens often for pointer subtraction. */ if (vr->varying_p () && (code == MINUS_EXPR || code == POINTER_DIFF_EXPR) && TREE_CODE (op0) == SSA_NAME && ((vr0.kind () == VR_ANTI_RANGE && vr0.min () == op1 && vr0.min () == vr0.max ()) || (vr1.kind () == VR_ANTI_RANGE && vr1.min () == op0 && vr1.min () == vr1.max ()))) { vr->set_nonzero (expr_type); vr->equiv_clear (); } The ranger version is not handling these symbolics.