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.
OK for trunk?
Thanks,
- Tom
Handle casts in bound in transform_to_exit_first_loop_alt
2015-06-13 Tom de Vries <t...@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..a785bf9
--- /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..3873ca2a
--- /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 3495ac1..6e10901 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -1678,6 +1678,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);
@@ -1755,6 +1756,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
@@ -1820,36 +1823,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..0bae6ba
--- /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..edb6581
--- /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