--- /dev/null
+--- gcc/gcc/tree-vrp.c 2005-07-14 15:54:28.000000000 -0700
++++ gcc/gcc/tree-vrp.c.new 2005-07-16 17:25:25.000000000 -0700
+@@ -1267,6 +1267,7 @@ extract_range_from_unary_expr (value_ran
+ {
+ enum tree_code code = TREE_CODE (expr);
+ tree min, max, op0;
++ enum value_range_type vr_type;
+ int cmp;
+ value_range_t vr0 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
+
+@@ -1295,8 +1296,10 @@ extract_range_from_unary_expr (value_ran
+ else
+ set_value_range_to_varying (&vr0);
+
++ vr_type = vr0.type;
++
+ /* If VR0 is UNDEFINED, so is the result. */
+- if (vr0.type == VR_UNDEFINED)
++ if (vr_type == VR_UNDEFINED)
+ {
+ set_value_range_to_undefined (vr);
+ return;
+@@ -1306,7 +1309,7 @@ extract_range_from_unary_expr (value_ran
+ operand is neither a pointer nor an integral type, set the
+ resulting range to VARYING. TODO, in some cases we may be able
+ to derive anti-ranges (like non-zero values). */
+- if (vr0.type == VR_VARYING
++ if (vr_type == VR_VARYING
+ || (!INTEGRAL_TYPE_P (TREE_TYPE (op0))
+ && !POINTER_TYPE_P (TREE_TYPE (op0)))
+ || symbolic_range_p (&vr0))
+@@ -1342,7 +1345,7 @@ extract_range_from_unary_expr (value_ran
+ or equal to the new max, then we can safely use the newly
+ computed range for EXPR. This allows us to compute
+ accurate ranges through many casts. */
+- if (vr0.type == VR_RANGE)
++ if (vr_type == VR_RANGE)
+ {
+ tree new_min, new_max;
+
+@@ -1392,17 +1395,29 @@ extract_range_from_unary_expr (value_ran
+ return;
+ }
+
+- /* NEGATE_EXPR flips the range around. */
+- min = (vr0.max == TYPE_MAX_VALUE (TREE_TYPE (expr)))
+- ? TYPE_MIN_VALUE (TREE_TYPE (expr))
+- : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
++ if (flag_wrapv && vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)))
++ {
++ tree one = build_int_cst (TREE_TYPE (expr), 1);
+
+- max = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)))
+- ? TYPE_MAX_VALUE (TREE_TYPE (expr))
+- : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
++ type = VR_ANTI_RANGE;
++ max = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
++ max = int_const_binop (MINUS_EXPR, max, one, 0);
++ min = int_const_binop (PLUS_EXPR, min, one, 0);
++ }
++ else
++ {
++ /* NEGATE_EXPR flips the range around. */
++ min = (vr0.max == TYPE_MAX_VALUE (TREE_TYPE (expr)))
++ ? TYPE_MIN_VALUE (TREE_TYPE (expr))
++ : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
++
++ max = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)))
++ ? TYPE_MAX_VALUE (TREE_TYPE (expr))
++ : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
++ }
+ }
+ else if (code == ABS_EXPR
+- && !TYPE_UNSIGNED (TREE_TYPE (expr)))
++ && !(flag_wrapv || TYPE_UNSIGNED (TREE_TYPE (expr))))
+ {
+ /* ABS_EXPR may flip the range around, if the original range
+ included negative values. */
+@@ -1436,7 +1451,7 @@ extract_range_from_unary_expr (value_ran
+ set_value_range_to_varying (vr);
+ }
+ else
+- set_value_range (vr, vr0.type, min, max, NULL);
++ set_value_range (vr, vr_type, min, max, NULL);
+ }
+
+