Re: [gomp4][PATCH] Handle casts in bound in try_transform_to_exit_first_loop_alt
On 22/06/15 16:36, Richard Biener wrote: On Thu, 18 Jun 2015, Tom de Vries wrote: 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? I assume the above also handles the reverse, (int) (_6 + -1)? AFAIU, niter.niter is always unsigned. In this case what happens if _6 == INT_MAX + 1? nit is INT_MAX but (int) _6 is INT_MIN. Likewise what happens if _6 + -1 under-/overflows? While playing around with underflow/overflow cases, I ran into PR66652, which reproduces on trunk. I've submitted for trunk: - https://gcc.gnu.org/ml/gcc-patches/2015-06/msg02084.html , which fixes PR66652, and should handle all overflow concerns. - https://gcc.gnu.org/ml/gcc-patches/2015-06/msg02085.html , which deals with the case that nit is not defined by assignment nit = n - 1, in other words, with the case that this patch is trying to address. I'll revert this patch on gomp-4_0-branch, and commit these patches instead (in addition to https://gcc.gnu.org/ml/gcc-patches/2015-06/msg01768.html, which fixes low iteration count reduction loops handled by transform_to_exit_first_loop_alt). Thanks, - Tom
Re: [gomp4][PATCH] Handle casts in bound in try_transform_to_exit_first_loop_alt
On Thu, 18 Jun 2015, Tom de Vries wrote: 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? I assume the above also handles the reverse, (int) (_6 + -1)? In this case what happens if _6 == INT_MAX + 1? nit is INT_MAX but (int) _6 is INT_MIN. Likewise what happens if _6 + -1 under-/overflows? Richard. Thanks, - Tom -- Richard Biener rguent...@suse.de SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Dilip Upmanyu, Graham Norton, HRB 21284 (AG Nuernberg)
[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 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 000..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 000..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. */ vecedge_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
[PATCH] Handle casts in bound in try_transform_to_exit_first_loop_alt
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 000..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 000..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. */ vecedge_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