diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ae35c9f1be95b95b97c212fa596a6cdd255244b4..e8c85944ef69eab5fc7fc8e325b73a147b77a03a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2005-08-15  Sebastian Pop  <pop@cri.ensmp.fr>
+
+	PR 23386
+	* tree-data-ref.c (estimate_niter_from_size_of_data): When
+	step is negative compute the estimation from init downwards to zero.
+	
 2005-08-14  James A. Morrison  <phython@gcc.gnu.org>
 
 	* fold-const (fold_binary): Call fold_build2 instead of fold (build.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23386.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23386.c
new file mode 100644
index 0000000000000000000000000000000000000000..d322f995b97970d5c7cc86b13a36ff5e89155197
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23386.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int f[100];
+int g[100];
+unsigned char
+f1 (int a, int b)
+{
+  __SIZE_TYPE__ ix;
+  if (a)
+    return 1;
+  for (ix = 4; ix--;)
+      if (f[ix] != g[ix])
+	  return 0;
+  return 1;
+}
+
+int main(void)
+{
+  if (!f1 (0, 2))
+    __builtin_abort();
+  return 0;
+}
+
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index 24856eda9563b9381d9ad45804241b76a620e138..1848128551ad2955742d23b8ff452ca8ccd952b0 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -751,7 +751,7 @@ estimate_niter_from_size_of_data (struct loop *loop,
 				  tree access_fn, 
 				  tree stmt)
 {
-  tree estimation;
+  tree estimation = NULL_TREE;
   tree array_size, data_size, element_size;
   tree init, step;
 
@@ -773,11 +773,28 @@ estimate_niter_from_size_of_data (struct loop *loop,
       && TREE_CODE (init) == INTEGER_CST
       && TREE_CODE (step) == INTEGER_CST)
     {
-      estimation = fold_build2 (CEIL_DIV_EXPR, integer_type_node,
-				fold_build2 (MINUS_EXPR, integer_type_node,
-					     data_size, init), step);
-
-      record_estimate (loop, estimation, boolean_true_node, stmt);
+      tree i_plus_s = fold_build2 (PLUS_EXPR, integer_type_node, init, step);
+      tree sign = fold_build2 (GT_EXPR, boolean_type_node, i_plus_s, init);
+
+      if (sign == boolean_true_node)
+	estimation = fold_build2 (CEIL_DIV_EXPR, integer_type_node,
+				  fold_build2 (MINUS_EXPR, integer_type_node,
+					       data_size, init), step);
+
+      /* When the step is negative, as in PR23386: (init = 3, step =
+	 0ffffffff, data_size = 100), we have to compute the
+	 estimation as ceil_div (init, 0 - step) + 1.  */
+      else if (sign == boolean_false_node)
+	estimation = 
+	  fold_build2 (PLUS_EXPR, integer_type_node,
+		       fold_build2 (CEIL_DIV_EXPR, integer_type_node,
+				    init,
+				    fold_build2 (MINUS_EXPR, unsigned_type_node,
+						 integer_zero_node, step)),
+		       integer_one_node);
+
+      if (estimation)
+	record_estimate (loop, estimation, boolean_true_node, stmt);
     }
 }