This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch, fortran] Some fewer temporaries


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.


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;
     }
 

Attachment: dep-sub.pl
Description: Perl program

! { dg-do compile }
! { dg-options "-Warray-temporaries" }
! PR 45159 - No temporary should be created for this.
program main
  integer a(100)
  a(10:16:2) = a(10:16:2)
  a(10:16:2) = a(10:19:3)
  a(10:18:2) = a(12:20:2)
  a(1:10) = a(2:20:2)
  a(16:10:-2) = a(16:10:-2)
  a(19:10:-1) = a(19:1:-2)
  a(19:10:-1) = a(18:9:-1)
  a(19:11:-1) = a(18:2:-2)
end program main

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]