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]

[gomp4][PATCH] Handle casts in bound in try_transform_to_exit_first_loop_alt


On 13/06/15 16:24, Tom de Vries wrote:
Hi,

this patch allows try_transform_to_exit_first_loop_alt to succeed when
handling cases where the expression representing the number of
iterations contains a cast.

Currently, transform_to_exit_first_loop_alt testcase
gfortran/parloops-exit-first-loop-alt.f95 will fail.

The nit is _19, which is defined as follows:
...
_20 = _6 + -1;
_19 = (unsigned int) _20;
...
And transform_to_exit_first_loop_alt currently only handles nits with
defining stmt 'nit = x - 1', for which it finds alt_bound 'x'.

The patch:
- uses try_get_loop_niter to get nit as a nested tree expression
   '(unsigned int) (_6 + -1)'
- strips the outer nops (assuming no change in value)
- uses '(unsigned int)_6' as the alt_bound, and
- gimplifies the expression.

Bootstrapped and reg-tested on x86_64.


Cleaned up whitespace in testcases.

Committed to gomp-4_0-branch as atttached.

OK for trunk?


Thanks,
- Tom

Handle casts in bound in transform_to_exit_first_loop_alt

2015-06-13  Tom de Vries  <tom@codesourcery.com>

	* tree-parloops.c (transform_to_exit_first_loop_alt): Add update_stmt
	for cond_stmt.
	(try_get_loop_niter): Declare forward.
	(try_transform_to_exit_first_loop_alt): Use try_get_loop_niter to get
	updated number of iterations.  Extract alt_bount, and instantiate it.

	* testsuite/libgomp.fortran/parloops-exit-first-loop-alt-2.f95: New test.
	* testsuite/libgomp.fortran/parloops-exit-first-loop-alt.f95: New test.

	* gfortran.dg/parloops-exit-first-loop-alt-2.f95: New test.
	* gfortran.dg/parloops-exit-first-loop-alt.f95: New test.
---
 .../gfortran.dg/parloops-exit-first-loop-alt-2.f95 | 24 +++++++++
 .../gfortran.dg/parloops-exit-first-loop-alt.f95   | 25 +++++++++
 gcc/tree-parloops.c                                | 59 +++++++++++++---------
 .../parloops-exit-first-loop-alt-2.f95             | 40 +++++++++++++++
 .../parloops-exit-first-loop-alt.f95               | 41 +++++++++++++++
 5 files changed, 164 insertions(+), 25 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/parloops-exit-first-loop-alt-2.f95
 create mode 100644 gcc/testsuite/gfortran.dg/parloops-exit-first-loop-alt.f95
 create mode 100644 libgomp/testsuite/libgomp.fortran/parloops-exit-first-loop-alt-2.f95
 create mode 100644 libgomp/testsuite/libgomp.fortran/parloops-exit-first-loop-alt.f95

diff --git a/gcc/testsuite/gfortran.dg/parloops-exit-first-loop-alt-2.f95 b/gcc/testsuite/gfortran.dg/parloops-exit-first-loop-alt-2.f95
new file mode 100644
index 0000000..f26a6e3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/parloops-exit-first-loop-alt-2.f95
@@ -0,0 +1,24 @@
+! { dg-additional-options "-O2" }
+! { dg-require-effective-target pthread }
+! { dg-additional-options "-ftree-parallelize-loops=2" }
+! { dg-additional-options "-fdump-tree-parloops" }
+
+! Constant bound, vector addition.
+
+subroutine foo ()
+  integer, parameter :: n = 1000
+  integer, dimension (0:n-1) :: a, b, c
+  common a, b, c
+  integer :: ii
+
+  do ii = 0, n - 1
+     c(ii) = a(ii) + b(ii) + 25
+  end do
+end subroutine foo
+
+! Three times plus 25:
+! - once in f._loopfn.0
+! - once in the parallel
+! - once in the low iteration count loop
+! Crucially, none for a peeled off last iteration following the parallel.
+! { dg-final { scan-tree-dump-times "(?n) \\+ 25;" 3 "parloops" } }
diff --git a/gcc/testsuite/gfortran.dg/parloops-exit-first-loop-alt.f95 b/gcc/testsuite/gfortran.dg/parloops-exit-first-loop-alt.f95
new file mode 100644
index 0000000..6dc8a38
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/parloops-exit-first-loop-alt.f95
@@ -0,0 +1,25 @@
+! { dg-additional-options "-O2" }
+! { dg-require-effective-target pthread }
+! { dg-additional-options "-ftree-parallelize-loops=2" }
+! { dg-additional-options "-fdump-tree-parloops" }
+
+! Variable bound, vector addition.
+
+subroutine foo (nr)
+  integer, intent(in) :: nr
+  integer, parameter :: n = 1000
+  integer, dimension (0:n-1) :: a, b, c
+  common a, b, c
+  integer :: ii
+
+  do ii = 0, nr - 1
+     c(ii) = a(ii) + b(ii) + 25
+  end do
+end subroutine foo
+
+! Three times plus 25:
+! - once in f._loopfn.0
+! - once in the parallel
+! - once in the low iteration count loop
+! Crucially, none for a peeled off last iteration following the parallel.
+! { dg-final { scan-tree-dump-times "(?n) \\+ 25;" 3 "parloops" } }
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index 209cf0c..678e458 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -1684,6 +1684,7 @@ transform_to_exit_first_loop_alt (struct loop *loop,
 
   /* Set the new loop bound.  */
   gimple_cond_set_rhs (cond_stmt, bound);
+  update_stmt (cond_stmt);
 
   /* Repair the ssa.  */
   vec<edge_var_map> *v = redirect_edge_var_map_vector (post_inc_edge);
@@ -1761,6 +1762,8 @@ transform_to_exit_first_loop_alt (struct loop *loop,
   calculate_dominance_info (CDI_DOMINATORS);
 }
 
+static bool try_get_loop_niter (loop_p, struct tree_niter_desc *);
+
 /* Tries to moves the exit condition of LOOP to the beginning of its header
    without duplication of the loop body.  NIT is the number of iterations of the
    loop.  REDUCTION_LIST describes the reductions in LOOP.  Return true if
@@ -1826,36 +1829,42 @@ try_transform_to_exit_first_loop_alt (struct loop *loop,
 	  else if (integer_minus_onep (op2))
 	    alt_bound = op1;
 	}
+    }
 
-      /* There is a number of test-cases for which we don't get an alt_bound
-	 here: they're listed here, with the lhs of the last stmt as the nit:
-
-	 libgomp.graphite/force-parallel-1.c:
-	 _21 = (signed long) N_6(D);
-	 _19 = _21 + -1;
-	 _7 = (unsigned long) _19;
-
-	 libgomp.graphite/force-parallel-2.c:
-	 _33 = (signed long) N_9(D);
-	 _16 = _33 + -1;
-	 _37 = (unsigned long) _16;
+  if (alt_bound == NULL_TREE)
+    {
+      struct tree_niter_desc niter;
+      if (try_get_loop_niter (loop, &niter))
+	{
+	  tree new_nit = niter.niter;
+	  STRIP_NOPS (new_nit);
+	  if (TREE_CODE (new_nit) == PLUS_EXPR)
+	    {
+	      tree op1 = TREE_OPERAND (new_nit, 0);
+	      tree op2 = TREE_OPERAND (new_nit, 1);
+	      if (integer_minus_onep (op1))
+		alt_bound = op2;
+	      else if (integer_minus_onep (op2))
+		alt_bound = op1;
+	    }
+	}
 
-	 libgomp.graphite/force-parallel-5.c:
-	 <bb 6>:
-	 # graphite_IV.5_46 = PHI <0(5), graphite_IV.5_47(11)>
-	 <bb 7>:
-	 _33 = (unsigned long) graphite_IV.5_46;
+      if (alt_bound != NULL_TREE)
+	{
+	  alt_bound = fold_convert (TREE_TYPE (niter.niter), alt_bound);
 
-	 g++.dg/tree-ssa/pr34355.C:
-	 _2 = (unsigned int) i_9;
-	 _3 = 4 - _2;
+	  gimple_seq pre = NULL, post = NULL;
+	  push_gimplify_context (true);
+	  gimplify_expr (&alt_bound, &pre, &post, is_gimple_reg,
+			 fb_rvalue);
+	  pop_gimplify_context (NULL);
 
-	 gcc.dg/pr53849.c:
-	 _5 = d.0_11 + -2;
-	 _18 = (unsigned int) _5;
+	  gimple_seq_add_seq (&pre, post);
 
-	 We will be able to handle some of these cases, if we can determine when
-	 it's safe to look past casts.  */
+	  gimple_stmt_iterator gsi
+	    = gsi_last_bb (loop_preheader_edge (loop)->src);
+	  gsi_insert_seq_after (&gsi, pre, GSI_CONTINUE_LINKING);
+	}
     }
 
   if (alt_bound == NULL_TREE)
diff --git a/libgomp/testsuite/libgomp.fortran/parloops-exit-first-loop-alt-2.f95 b/libgomp/testsuite/libgomp.fortran/parloops-exit-first-loop-alt-2.f95
new file mode 100644
index 0000000..56add65
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/parloops-exit-first-loop-alt-2.f95
@@ -0,0 +1,40 @@
+! { dg-do run }
+! { dg-additional-options "-O2" }
+! { dg-additional-options "-ftree-parallelize-loops=2" }
+
+! Constant bound, vector addition.
+
+subroutine foo ()
+  integer, parameter :: n = 1000
+  integer, dimension (0:n-1) :: a, b, c
+  common a, b, c
+  integer :: ii
+
+  do ii = 0, n - 1
+     c(ii) = a(ii) + b(ii)
+  end do
+end subroutine foo
+
+program main
+  integer, parameter :: n = 1000
+  integer, parameter :: distrib = 10
+  integer, dimension (0:n-1) :: a, b, c
+  common a, b, c
+  integer :: i, j, k
+
+  do j = 0, ((n / distrib) -1)
+     do i = 0, distrib - 1
+	k = i + (distrib * j)
+	a(k) = k
+	b(k) = MODULO ((k * 3), 7)
+	c(k) = k * 2;
+     end do
+  end do
+
+  call foo ()
+
+  do i = 0, n - 1
+     if (c(i) .ne. (i + MODULO ((i * 3), 7))) call abort
+  end do
+
+end program
diff --git a/libgomp/testsuite/libgomp.fortran/parloops-exit-first-loop-alt.f95 b/libgomp/testsuite/libgomp.fortran/parloops-exit-first-loop-alt.f95
new file mode 100644
index 0000000..72b3c8d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/parloops-exit-first-loop-alt.f95
@@ -0,0 +1,41 @@
+! { dg-do run }
+! { dg-additional-options "-O2" }
+! { dg-additional-options "-ftree-parallelize-loops=2" }
+
+! Variable bound, vector addition.
+
+subroutine foo (nr)
+  integer, intent(in) :: nr
+  integer, parameter :: n = 1000
+  integer, dimension (0:n-1) :: a, b, c
+  common a, b, c
+  integer :: ii
+
+  do ii = 0, nr - 1
+     c(ii) = a(ii) + b(ii)
+  end do
+end subroutine foo
+
+program main
+  integer, parameter :: n = 1000
+  integer, parameter :: distrib = 10
+  integer, dimension (0:n-1) :: a, b, c
+  common a, b, c
+  integer :: i, j, k
+
+  do j = 0, ((n / distrib) -1)
+     do i = 0, distrib - 1
+	k = i + (distrib * j)
+	a(k) = k
+	b(k) = MODULO ((k * 3), 7)
+	c(k) = k * 2;
+     end do
+  end do
+
+  call foo (n)
+
+  do i = 0, n - 1
+     if (c(i) .ne. (i + MODULO ((i * 3), 7))) call abort
+  end do
+
+end program
-- 
1.9.1


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