diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index a312507d01fa28e578dcb684c6dd04589c7b2751..c6bed7875ffa5546de11df53e0fdff7a2a4fe3fe 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,14 @@
+2006-04-01  Roger Sayle  <roger@eyesopen.com>
+
+	* dependency.c (gfc_dep_compare_expr): Strip parentheses and unary
+	plus operators when comparing expressions.  Handle comparisons of
+	the form "X+C vs. X", "X vs. X+C", "X-C vs. X" and "X vs. X-C" where
+	C is an integer constant.  Handle comparisons of the form "P+Q vs.
+	R+S" and "P-Q vs. R-S".  Handle comparisons of integral extensions
+	specially (increasing functions) so extend(A) > extend(B), when A>B.
+	(gfc_check_element_vs_element): Move test later, so that we ignore
+	the fact that "A < B" or "A > B" when A or B contains a forall index.
+
 2006-03-31  Asher Langton  <langton2@llnl.gov>
 
 	PR fortran/25358
diff --git a/gcc/fortran/dependency.c b/gcc/fortran/dependency.c
index ca370b64bf60ff13c402291557cbfe1c0d86b7ff..c3762bdc4d8b8de0094d4f6a4b403fc82ec5fa3a 100644
--- a/gcc/fortran/dependency.c
+++ b/gcc/fortran/dependency.c
@@ -72,8 +72,112 @@ gfc_expr_is_one (gfc_expr * expr, int def)
 int
 gfc_dep_compare_expr (gfc_expr * e1, gfc_expr * e2)
 {
+  gfc_actual_arglist *args1;
+  gfc_actual_arglist *args2;
   int i;
 
+  if (e1->expr_type == EXPR_OP
+      && (e1->value.op.operator == INTRINSIC_UPLUS
+          || e1->value.op.operator == INTRINSIC_PARENTHESES))
+    return gfc_dep_compare_expr (e1->value.op.op1, e2);
+  if (e2->expr_type == EXPR_OP
+      && (e2->value.op.operator == INTRINSIC_UPLUS
+          || e2->value.op.operator == INTRINSIC_PARENTHESES))
+    return gfc_dep_compare_expr (e1, e2->value.op.op1);
+
+  if (e1->expr_type == EXPR_OP
+      && e1->value.op.operator == INTRINSIC_PLUS)
+    {
+      /* Compare X+C vs. X.  */
+      if (e1->value.op.op2->expr_type == EXPR_CONSTANT
+	  && e1->value.op.op2->ts.type == BT_INTEGER
+	  && gfc_dep_compare_expr (e1->value.op.op1, e2) == 0)
+	return mpz_sgn (e1->value.op.op2->value.integer);
+
+      /* Compare P+Q vs. R+S.  */
+      if (e2->expr_type == EXPR_OP
+	  && e2->value.op.operator == INTRINSIC_PLUS)
+	{
+	  int l, r;
+
+	  l = gfc_dep_compare_expr (e1->value.op.op1, e2->value.op.op1);
+	  r = gfc_dep_compare_expr (e1->value.op.op2, e2->value.op.op2);
+	  if (l == 0 && r == 0)
+	    return 0;
+	  if (l == 0 && r != -2)
+	    return r;
+	  if (l != -2 && r == 0)
+	    return l;
+	  if (l == 1 && r == 1)
+	    return 1;
+	  if (l == -1 && r == -1)
+	    return -1;
+
+	  l = gfc_dep_compare_expr (e1->value.op.op1, e2->value.op.op2);
+	  r = gfc_dep_compare_expr (e1->value.op.op2, e2->value.op.op1);
+	  if (l == 0 && r == 0)
+	    return 0;
+	  if (l == 0 && r != -2)
+	    return r;
+	  if (l != -2 && r == 0)
+	    return l;
+	  if (l == 1 && r == 1)
+	    return 1;
+	  if (l == -1 && r == -1)
+	    return -1;
+	}
+    }
+
+  /* Compare X vs. X+C.  */
+  if (e2->expr_type == EXPR_OP
+      && e2->value.op.operator == INTRINSIC_PLUS)
+    {
+      if (e2->value.op.op2->expr_type == EXPR_CONSTANT
+	  && e2->value.op.op2->ts.type == BT_INTEGER
+	  && gfc_dep_compare_expr (e1, e2->value.op.op1) == 0)
+	return -mpz_sgn (e2->value.op.op2->value.integer);
+    }
+
+  /* Compare X-C vs. X.  */
+  if (e1->expr_type == EXPR_OP
+      && e1->value.op.operator == INTRINSIC_MINUS)
+    {
+      if (e1->value.op.op2->expr_type == EXPR_CONSTANT
+	  && e1->value.op.op2->ts.type == BT_INTEGER
+	  && gfc_dep_compare_expr (e1->value.op.op1, e2) == 0)
+	return -mpz_sgn (e1->value.op.op2->value.integer);
+
+      /* Compare P-Q vs. R-S.  */
+      if (e2->expr_type == EXPR_OP
+	  && e2->value.op.operator == INTRINSIC_MINUS)
+	{
+	  int l, r;
+
+	  l = gfc_dep_compare_expr (e1->value.op.op1, e2->value.op.op1);
+	  r = gfc_dep_compare_expr (e1->value.op.op2, e2->value.op.op2);
+	  if (l == 0 && r == 0)
+	    return 0;
+	  if (l != -2 && r == 0)
+	    return l;
+	  if (l == 0 && r != -2)
+	    return -r;
+	  if (l == 1 && r == -1)
+	    return 1;
+	  if (l == -1 && r == 1)
+	    return -1;
+	}
+    }
+
+  /* Compare X vs. X-C.  */
+  if (e2->expr_type == EXPR_OP
+      && e2->value.op.operator == INTRINSIC_MINUS)
+    {
+      if (e2->value.op.op2->expr_type == EXPR_CONSTANT
+	  && e2->value.op.op2->ts.type == BT_INTEGER
+	  && gfc_dep_compare_expr (e1, e2->value.op.op1) == 0)
+	return mpz_sgn (e2->value.op.op2->value.integer);
+    }
+
   if (e1->expr_type != e2->expr_type)
     return -2;
 
@@ -119,12 +223,29 @@ gfc_dep_compare_expr (gfc_expr * e1, gfc_expr * e2)
 	  || e1->value.function.isym != e2->value.function.isym)
 	return -2;
 
+      args1 = e1->value.function.actual;
+      args2 = e2->value.function.actual;
+
       /* We should list the "constant" intrinsic functions.  Those
 	 without side-effects that provide equal results given equal
 	 argument lists.  */
       switch (e1->value.function.isym->generic_id)
 	{
 	case GFC_ISYM_CONVERSION:
+	  /* Handle integer extensions specially, as __convert_i4_i8
+	     is not only "constant" but also "unary" and "increasing".  */
+	  if (args1 && !args1->next
+	      && args2 && !args2->next
+	      && e1->ts.type == BT_INTEGER
+	      && args1->expr->ts.type == BT_INTEGER
+	      && e1->ts.kind > args1->expr->ts.kind
+	      && e2->ts.type == e1->ts.type
+	      && e2->ts.kind == e1->ts.kind
+	      && args2->expr->ts.type == args1->expr->ts.type
+	      && args2->expr->ts.kind == args2->expr->ts.kind)
+	    return gfc_dep_compare_expr (args1->expr, args2->expr);
+	  break;
+
 	case GFC_ISYM_REAL:
 	case GFC_ISYM_LOGICAL:
 	case GFC_ISYM_DBLE:
@@ -135,18 +256,14 @@ gfc_dep_compare_expr (gfc_expr * e1, gfc_expr * e2)
 	}
 
       /* Compare the argument lists for equality.  */
-      {
-	gfc_actual_arglist *args1 = e1->value.function.actual;
-	gfc_actual_arglist *args2 = e2->value.function.actual;
-	while (args1 && args2)
-	  {
-	    if (gfc_dep_compare_expr (args1->expr, args2->expr) != 0)
-	      return -2;
-	    args1 = args1->next;
-	    args2 = args2->next;
-	  }
-	return (args1 || args2) ? -2 : 0;
-      }
+      while (args1 && args2)
+	{
+	  if (gfc_dep_compare_expr (args1->expr, args2->expr) != 0)
+	    return -2;
+	  args1 = args1->next;
+	  args2 = args2->next;
+	}
+      return (args1 || args2) ? -2 : 0;
       
     default:
       return -2;
@@ -904,8 +1021,6 @@ gfc_check_element_vs_element (gfc_ref * lref, gfc_ref * rref, int n)
   i = gfc_dep_compare_expr (r_start, l_start);
   if (i == 0)
     return GFC_DEP_EQUAL;
-  if (i != -2)
-    return GFC_DEP_NODEP;
 
   /* Treat two scalar variables as potentially equal.  This allows
      us to prove that a(i,:) and a(j,:) have no dependency.  See
@@ -920,6 +1035,8 @@ gfc_check_element_vs_element (gfc_ref * lref, gfc_ref * rref, int n)
       || contains_forall_index_p (l_start))
     return GFC_DEP_OVERLAP;
 
+  if (i != -2)
+    return GFC_DEP_NODEP;
   return GFC_DEP_EQUAL;
 }
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 80d1d7f6d84d3c6e4b9b254a311aec3ce950e0d0..6901373486866b79331675df2edcf3f1fe040df6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2006-04-01  Roger Sayle  <roger@eyesopen.com>
+
+	* gfortran.dg/dependency_14.f90: New test case.
+	* gfortran.dg/dependency_15.f90: Likewise.
+	* gfortran.dg/dependency_16.f90: Likewise.
+
 2006-03-31  Asher Langton  <langton2@llnl.gov>
 
 	PR fortran/25358
diff --git a/gcc/testsuite/gfortran.dg/dependency_14.f90 b/gcc/testsuite/gfortran.dg/dependency_14.f90
new file mode 100644
index 0000000000000000000000000000000000000000..71e962c15dc880ceebc1cd17daf2a0480dba7a8e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dependency_14.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! { dg-options "-O2 -fdump-tree-original" }
+subroutine foo(a,i)
+  integer, dimension (4,4) :: a
+  integer :: i
+
+  where (a(i,1:3) .ne. 0)
+    a(i+1,2:4) = 1
+  endwhere
+end subroutine
+! { dg-final { scan-tree-dump-times "malloc" 0 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gfortran.dg/dependency_15.f90 b/gcc/testsuite/gfortran.dg/dependency_15.f90
new file mode 100644
index 0000000000000000000000000000000000000000..36eb3a4642309ca8fb0200a91e79f3d45bcd5461
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dependency_15.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! { dg-options "-O2 -fdump-tree-original" }
+subroutine foo(a,i)
+  integer, dimension (4,4) :: a
+  integer :: i
+
+  where (a(i,1:3) .ne. 0)
+    a(i-1,2:4) = 1
+  endwhere
+end subroutine
+! { dg-final { scan-tree-dump-times "malloc" 0 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gfortran.dg/dependency_16.f90 b/gcc/testsuite/gfortran.dg/dependency_16.f90
new file mode 100644
index 0000000000000000000000000000000000000000..b669771b898b1c52efa8411444b73b2c4167a0d3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dependency_16.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! { dg-options "-O2 -fdump-tree-original" }
+subroutine foo(a,i)
+  integer, dimension (4,4) :: a
+  integer :: i
+
+  where (a(i+1,1:3) .ne. 0)
+    a(i+2,2:4) = 1
+  endwhere
+end subroutine
+! { dg-final { scan-tree-dump-times "malloc" 0 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }