diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 977f32a79ede64258fa02a6bf31cc0b5b69da8ac..fd3d122112a03b9f69829280340b305a5f1e15ee 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2006-06-04  Richard Guenther  <rguenther@suse.de>
+
+	PR tree-optimization/27039
+	* fold-const.c (fold_comparison): Handle pointer comparison
+	again for all comparison codes.  Compare offsets in signed
+	size type.
+	(fold_binary): Move code from here.
+
 2006-06-03  Roger Sayle  <roger@eyesopen.com>
 
 	PR target/26223
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 7930bb454d4ed5a611b52b354e9aba446ace3fad..3c8575e60e32252dc1d949a10e26146b82223ec7 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -7764,6 +7764,41 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
 	return fold_build2 (code, type, variable, lhs);
     }
 
+  /* If this is a comparison of two exprs that look like an ARRAY_REF of the
+     same object, then we can fold this to a comparison of the two offsets in
+     signed size type.  This is possible because pointer arithmetic is
+     restricted to retain within an object and overflow on pointer differences
+     is undefined as of 6.5.6/8 and /9 with respect to the signed ptrdiff_t.  */
+  if (POINTER_TYPE_P (TREE_TYPE (arg0))
+      && !flag_wrapv && !flag_trapv)
+    {
+      tree base0, offset0, base1, offset1;
+
+      if (extract_array_ref (arg0, &base0, &offset0)
+	  && extract_array_ref (arg1, &base1, &offset1)
+	  && operand_equal_p (base0, base1, 0))
+        {
+	  tree signed_size_type_node;
+	  signed_size_type_node = signed_type_for (size_type_node);
+
+	  /* By converting to signed size type we cover middle-end pointer
+	     arithmetic which operates on unsigned pointer types of size
+	     type size and ARRAY_REF offsets which are properly sign or
+	     zero extended from their type in case it is narrower than
+	     size type.  */
+	  if (offset0 == NULL_TREE)
+	    offset0 = build_int_cst (signed_size_type_node, 0);
+	  else
+	    offset0 = fold_convert (signed_size_type_node, offset0);
+	  if (offset1 == NULL_TREE)
+	    offset1 = build_int_cst (signed_size_type_node, 0);
+	  else
+	    offset1 = fold_convert (signed_size_type_node, offset1);
+
+	  return fold_build2 (code, type, offset0, offset1);
+	}
+    }
+
   if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
     {
       tree targ0 = strip_float_extensions (arg0);
@@ -10539,34 +10574,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 			      tem, build_int_cst (TREE_TYPE (tem), 0));
 	}
 
-      /* If this is a comparison of two exprs that look like an
-	 ARRAY_REF of the same object, then we can fold this to a
-	 comparison of the two offsets.  This is only safe for
-	 EQ_EXPR and NE_EXPR because of overflow issues.  */
-      {
-	tree base0, offset0, base1, offset1;
-
-	if (extract_array_ref (arg0, &base0, &offset0)
-	    && extract_array_ref (arg1, &base1, &offset1)
-	    && operand_equal_p (base0, base1, 0))
-          {
-	    /* Handle no offsets on both sides specially.  */
-	    if (offset0 == NULL_TREE && offset1 == NULL_TREE)
-	      return fold_build2 (code, type, integer_zero_node,
-				  integer_zero_node);
-
-	    if (!offset0 || !offset1
-		|| TREE_TYPE (offset0) == TREE_TYPE (offset1))
-	      {
-	        if (offset0 == NULL_TREE)
-		  offset0 = build_int_cst (TREE_TYPE (offset1), 0);
-		if (offset1 == NULL_TREE)
-	          offset1 = build_int_cst (TREE_TYPE (offset0), 0);
-		return fold_build2 (code, type, offset0, offset1);
-	      }
-	  }
-      }
-
       if (integer_zerop (arg1)
 	  && tree_expr_nonzero_p (arg0))
         {
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1553c98c6bfb28109f8af78bd056068eaeeb4d23..21fa2734273435cba91411d999a3c485a91fa45c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-06-04  Richard Guenther  <rguenther@suse.de>
+
+	PR tree-optimization/27039
+	* gcc.dg/tree-ssa/loop-17.c: New testcase.
+
 2006-06-03  Roger Sayle  <roger@eyesopen.com>
 
 	PR target/26223
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c
new file mode 100644
index 0000000000000000000000000000000000000000..26e49862091972e8215c584dbf951986687402d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-sccp-details" } */
+
+/* To determine the number of iterations in this loop we need to fold
+   p_4 + 4B > p_4 + 8B to false.  This transformation has caused
+   troubles in the past due to overflow issues.  */
+
+int foo (int *p)
+{
+  int i = 0, *x;
+
+  for (x = p; x < p + 2; x++)
+    i++;
+
+  return i;
+}
+
+/* { dg-final { scan-tree-dump "set_nb_iterations_in_loop = 2" "sccp" } } */
+/* { dg-final { cleanup-tree-dump "sccp" } } */