diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ce53bb296270dda410bd56461e98a66ab2fbd7a1..79f68e9ca44d000a2f73eebcfd63f052350930bb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2006-06-09  Richard Guenther  <rguenther@suse.de>
+
+	PR tree-optimization/26998
+	* tree-vrp.c (extract_range_from_unary_expr): For NEGATE_EXPR
+	of signed types, only TYPE_MIN_VALUE is special, but for both,
+	minimum and maximum value.  Likewise VR_ANTI_RANGE is special
+	in this case, as is -fwrapv.
+
 2006-06-08  Mike Stump  <mrs@apple.com>
 
 	PR target/26427
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 267c08c28fa12eb435aa8906e450a38148730ef9..f187c313572c255f967e9f65d873e011c1a9b4f5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2006-06-09  Richard Guenther  <rguenther@suse.de>
+
+	PR tree-optimization/26998
+	* gcc.dg/torture/pr26998.c: New testcase.
+	* gcc.dg/tree-ssa/vrp29.c: New testcase.
+
 2006-06-08  Mike Stump  <mrs@apple.com>
 
 	* gcc.dg/pr27095.c: Account for stubs.
diff --git a/gcc/testsuite/gcc.dg/torture/pr26998.c b/gcc/testsuite/gcc.dg/torture/pr26998.c
new file mode 100644
index 0000000000000000000000000000000000000000..d50c344734e0ca3f2807ae44e28fd793c53d7691
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr26998.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+int decCompareOp (int result)
+{
+    if (result != (int)0x80000000)
+    {
+        result = -result;
+        return (result > 0);
+    }
+    return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp29.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp29.c
new file mode 100644
index 0000000000000000000000000000000000000000..bace4ffcadfe38bd708ddcb500154ce8b3646ee8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp29.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort(void);
+
+void decCompareOp (int result)
+{
+  if (result != (int)0x80000000)
+    {
+      result = -result;
+      if (result != (int)0x80000001)
+        abort ();
+    }
+}
+
+int main()
+{
+  decCompareOp (0x7fffffff);
+  return 0;
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 3ac01fb70f36f55eb2057c3a964bba444e17321c..9eac7e9b67deb8b2b03d6e86b5bfd7372bee56ab 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -1795,14 +1795,21 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
   if (code == NEGATE_EXPR
       && !TYPE_UNSIGNED (TREE_TYPE (expr)))
     {
-      /* NEGATE_EXPR flips the range around.  */
-      min = (vr0.max == TYPE_MAX_VALUE (TREE_TYPE (expr)) && !flag_wrapv)
-	     ? 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)) && !flag_wrapv)
-	     ? TYPE_MAX_VALUE (TREE_TYPE (expr))
-	     : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
+      /* NEGATE_EXPR flips the range around.  We need to treat
+	 TYPE_MIN_VALUE specially dependent on wrapping, range type
+	 and if it was used as minimum or maximum value:  
+	  -~[MIN, MIN] == ~[MIN, MIN]
+	  -[MIN, 0] == [0, MAX]  for -fno-wrapv
+	  -[MIN, 0] == [0, MIN]  for -fwrapv (will be set to varying later)  */
+      min = vr0.max == TYPE_MIN_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))
+	    ? (vr0.type == VR_ANTI_RANGE || flag_wrapv
+	       ? 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 == NEGATE_EXPR