Patchwork [fortran] Some fewer temporaries

login
register
mail settings
Submitter Thomas Koenig
Date Nov. 30, 2010, 7:56 a.m.
Message ID <1291103775.4664.10.camel@linux-fd1f.site>
Download mbox | patch
Permalink /patch/73580/
State New
Headers show

Comments

Thomas Koenig - Nov. 30, 2010, 7:56 a.m.
Hello world,

this patch generates fewer temporaries for array assignments by further
improving dependency analysis.

This should be a safe change even for early stage 3. The patch passes a
rather large number of test cases, i.e. the Fortran program generated
with the Perl script below.  (You'll need 4 GB of RAM and a few minutes
to run that test even without any optimization, which is why I don't
propose adding the generated program to the testsuite).

OK for trunk?

	Thomas

2010-11-29  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/45159
	* dependency.c (check_section_vs_section):  Pre-calculate
	the relationship between the strides and the relationship
	between the start values.  Use an integer constant one for
	that purpose.
	Forward dependencies for positive strides apply for where
	the lhs start <= rhs start and lhs stride <= rhs stride
	and vice versa for negative stride.  No need to compare
	end expressions in either case (assume no bounds violation).

2010-11-29  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/45159
	* gfortran.dg/dependency_38.f90:  New test.
Tobias Burnus - Dec. 3, 2010, 9:29 a.m.
Hello Thomas,

> OK for trunk?

OK. I like the patch - while it does a more comprehensive analysis the 
patch is not more complicated than before. You add some complexity, but 
you also do some clean up.

Tobias

> 2010-11-29  Thomas Koenig<tkoenig@gcc.gnu.org>
>
> 	PR fortran/45159
> 	* dependency.c (check_section_vs_section):  Pre-calculate
> 	the relationship between the strides and the relationship
> 	between the start values.  Use an integer constant one for
> 	that purpose.
> 	Forward dependencies for positive strides apply for where
> 	the lhs start<= rhs start and lhs stride<= rhs stride
> 	and vice versa for negative stride.  No need to compare
> 	end expressions in either case (assume no bounds violation).
>
> 2010-11-29  Thomas Koenig<tkoenig@gcc.gnu.org>
>
> 	PR fortran/45159
> 	* gfortran.dg/dependency_38.f90:  New test.
>
>
Thomas Koenig - Dec. 3, 2010, 10:35 a.m.
Hello Tobias,

> Hello Thomas,
> 
> > OK for trunk?
> 
> OK. I like the patch - while it does a more comprehensive analysis the 
> patch is not more complicated than before. You add some complexity, but 
> you also do some clean up.

Sende          fortran/ChangeLog
Sende          fortran/dependency.c
Sende          testsuite/ChangeLog
Hinzufügen     testsuite/gfortran.dg/dependency_38.f90
Übertrage Daten ....
Revision 167413 übertragen.

Thanks a lot for the review!

	Thomas

Patch

Index: dependency.c
===================================================================
--- dependency.c	(Revision 166873)
+++ dependency.c	(Arbeitskopie)
@@ -1071,8 +1071,10 @@  check_section_vs_section (gfc_array_ref *l_ar, gfc
   gfc_expr *r_stride;
   gfc_expr *r_lower;
   gfc_expr *r_upper;
+  gfc_expr *one_expr;
   int r_dir;
-  bool identical_strides;
+  int stride_comparison;
+  int start_comparison;
 
   /* If they are the same range, return without more ado.  */
   if (gfc_is_same_range (l_ar, r_ar, n, 0))
@@ -1126,22 +1128,24 @@  check_section_vs_section (gfc_array_ref *l_ar, gfc
   if (l_dir == 0 || r_dir == 0)
     return GFC_DEP_OVERLAP;
 
-  /* Determine if the strides are equal.  */
+  /* Determine the relationship between the strides.  Set stride_comparison to
+     -2 if the dependency cannot be determined
+     -1 if l_stride < r_stride
+      0 if l_stride == r_stride
+      1 if l_stride > r_stride
+     as determined by gfc_dep_compare_expr.  */
 
-  if (l_stride)
-    {
-      if (r_stride)
-	identical_strides = gfc_dep_compare_expr (l_stride, r_stride) == 0;
-      else
-	identical_strides = gfc_expr_is_one (l_stride, 0) == 1;
-    }
+  one_expr = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
+
+  stride_comparison = gfc_dep_compare_expr (l_stride ? l_stride : one_expr,
+					    r_stride ? r_stride : one_expr);
+
+  if (l_start && r_start)
+    start_comparison = gfc_dep_compare_expr (l_start, r_start);
   else
-    {
-      if (r_stride)
-	identical_strides = gfc_expr_is_one (r_stride, 0) == 1;
-      else
-	identical_strides = true;
-    }
+    start_comparison = -2;
+      
+  gfc_free (one_expr);
 
   /* Determine LHS upper and lower bounds.  */
   if (l_dir == 1)
@@ -1237,61 +1241,60 @@  check_section_vs_section (gfc_array_ref *l_ar, gfc
 
 #undef IS_CONSTANT_INTEGER
 
-  /* Check for forward dependencies x:y vs. x+1:z.  */
-  if (l_dir == 1 && r_dir == 1
-      && l_start && r_start && gfc_dep_compare_expr (l_start, r_start) == -1
-      && l_end && r_end && gfc_dep_compare_expr (l_end, r_end) == -1)
-    {
-      if (identical_strides)
-	return GFC_DEP_FORWARD;
-    }
+  /* Check for forward dependencies x:y vs. x+1:z and x:y:z vs. x:y:z+1. */
 
-  /* Check for forward dependencies x:y:-1 vs. x-1:z:-1.  */
-  if (l_dir == -1 && r_dir == -1
-      && l_start && r_start && gfc_dep_compare_expr (l_start, r_start) == 1
-      && l_end && r_end && gfc_dep_compare_expr (l_end, r_end) == 1)
-    {
-      if (identical_strides)
-	return GFC_DEP_FORWARD;
-    }
+  if (l_dir == 1 && r_dir == 1 &&
+      (start_comparison == 0 || start_comparison == -1)
+      && (stride_comparison == 0 || stride_comparison == -1))
+	  return GFC_DEP_FORWARD;
 
+  /* Check for forward dependencies x:y:-1 vs. x-1:z:-1 and
+     x:y:-1 vs. x:y:-2.  */
+  if (l_dir == -1 && r_dir == -1 && 
+      (start_comparison == 0 || start_comparison == 1)
+      && (stride_comparison == 0 || stride_comparison == 1))
+    return GFC_DEP_FORWARD;
 
-  if (identical_strides)
+  if (stride_comparison == 0 || stride_comparison == -1)
     {
-
       if (l_start && IS_ARRAY_EXPLICIT (l_ar->as))
 	{
 
-	  /* Check for a(low:y:s) vs. a(z:a:s) where a has a lower bound
+	  /* Check for a(low:y:s) vs. a(z:x:s) or
+	     a(low:y:s) vs. a(z:x:s+1) where a has a lower bound
 	     of low, which is always at least a forward dependence.  */
 
 	  if (r_dir == 1
 	      && gfc_dep_compare_expr (l_start, l_ar->as->lower[n]) == 0)
 	    return GFC_DEP_FORWARD;
+	}
+    }
 
-	  /* Check for a(high:y:-s) vs. a(z:a:-s) where a has a higher bound
+  if (stride_comparison == 0 || stride_comparison == 1)
+    {
+      if (l_start && IS_ARRAY_EXPLICIT (l_ar->as))
+	{
+      
+	  /* Check for a(high:y:-s) vs. a(z:x:-s) or
+	     a(high:y:-s vs. a(z:x:-s-1) where a has a higher bound
 	     of high, which is always at least a forward dependence.  */
 
 	  if (r_dir == -1
 	      && gfc_dep_compare_expr (l_start, l_ar->as->upper[n]) == 0)
 	    return GFC_DEP_FORWARD;
 	}
+    }
 
+
+  if (stride_comparison == 0)
+    {
       /* From here, check for backwards dependencies.  */
-      /* x:y vs. x+1:z.  */
-      if (l_dir == 1 && r_dir == 1
-	    && l_start && r_start
-	    && gfc_dep_compare_expr (l_start, r_start) == 1
-	    && l_end && r_end
-	    && gfc_dep_compare_expr (l_end, r_end) == 1)
+      /* x+1:y vs. x:z.  */
+      if (l_dir == 1 && r_dir == 1  && start_comparison == 1)
 	return GFC_DEP_BACKWARD;
 
-      /* x:y:-1 vs. x-1:z:-1.  */
-      if (l_dir == -1 && r_dir == -1
-	    && l_start && r_start
-	    && gfc_dep_compare_expr (l_start, r_start) == -1
-	    && l_end && r_end
-	    && gfc_dep_compare_expr (l_end, r_end) == -1)
+      /* x-1:y:-1 vs. x:z:-1.  */
+      if (l_dir == -1 && r_dir == -1 && start_comparison == -1)
 	return GFC_DEP_BACKWARD;
     }