@@ -3298,6 +3298,37 @@ extract_range_from_binary_expr (value_range *vr,
extract_range_from_binary_expr_1 (vr, code, expr_type, &n_vr0, &vr1);
}
+
+ /* EXACT_DIV_EXPR is typically used for pointer subtraction;
+ as a result a ~[0,0] may be better than what has already
+ been computed.
+
+ In particular if numerator has the range ~[0,0], then the
+ result range is going to be something like
+ [MININT/DIVISOR,MAXINT/DIVISOR], which is rarely useful.
+
+ So instead make the result range ~[0,0]. */
+ if (code == EXACT_DIV_EXPR
+ && TREE_CODE (op0) == SSA_NAME
+ && vr0.type == VR_ANTI_RANGE
+ && vr0.min == vr0.max
+ && integer_zerop (vr0.min))
+ set_value_range_to_nonnull (vr, TREE_TYPE (op0));
+
+ /* 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->type == VR_VARYING
+ && code == MINUS_EXPR
+ && TREE_CODE (op0) == SSA_NAME
+ && ((vr0.type == VR_ANTI_RANGE
+ && symbolic_range_based_on_p (&vr0, op1)
+ && vr0.min == vr0.max)
+ || (vr1.type == VR_ANTI_RANGE
+ && symbolic_range_based_on_p (&vr1, op0)
+ && vr1.min == vr1.max)))
+ set_value_range_to_nonnull (vr, TREE_TYPE (op0));
}
/* Extract range information from a unary operation CODE based on
@@ -8620,6 +8806,12 @@ intersect_ranges (enum value_range_type *vr0type,
else if (vrp_val_is_min (vr1min)
&& vrp_val_is_max (vr1max))
;
+ /* Choose the anti-range if it is ~[0,0], that range is special
+ enough to special case. */
+ else if (*vr0type == VR_ANTI_RANGE
+ && *vr0min == *vr0max
+ && integer_zerop (*vr0min))
+ ;
/* Else choose the range. */
else
{