From patchwork Sat Jun 13 14:24:17 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom de Vries X-Patchwork-Id: 483884 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 8A81214027F for ; Sun, 14 Jun 2015 00:24:40 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=ian3Jynq; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=aHw46EujMZ/StpvXpQ1Mli3+KSpt9sSxiFk2beuBwhAGmY Wog2RYxte32L0ROrY9lyh5hvG6UyVvMvwLNl3dzvO5Tpm/qnIzgka6Lt1355yhqT zvq7cO5M0XPyi93dwr4DFKyTMWYZNqazukhLuVK58TqmPw/VFhedmka7llQGM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=t4EYZZfMFvhk6zNd/+f51VXWWnA=; b=ian3Jynq+BbqPmZSV9Y4 RTFzDn/uDbvdxHPcBBo+5DNMK+dd3wLQw2fBg3BpD8qEiMa8Sib5jzPlgezJ5Ned cMXLDxrSowpQ95fEhNv5OgQoXg2zapkd0fHYVQ+xA5WARKgiTcnC/pxu2p4FJrgK CLB3fcOXFEe2ATZzrRFl1oA= Received: (qmail 79884 invoked by alias); 13 Jun 2015 14:24:30 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 79849 invoked by uid 89); 13 Jun 2015 14:24:27 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: relay1.mentorg.com Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 13 Jun 2015 14:24:25 +0000 Received: from nat-ies.mentorg.com ([192.94.31.2] helo=SVR-IES-FEM-01.mgc.mentorg.com) by relay1.mentorg.com with esmtp id 1Z3mM8-0003Ga-Qe from Tom_deVries@mentor.com for gcc-patches@gcc.gnu.org; Sat, 13 Jun 2015 07:24:21 -0700 Received: from [127.0.0.1] (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.3.224.2; Sat, 13 Jun 2015 15:24:19 +0100 Message-ID: <557C3D11.8080303@mentor.com> Date: Sat, 13 Jun 2015 16:24:17 +0200 From: Tom de Vries User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: GCC Patches Subject: [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 * 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 *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: - : - # graphite_IV.5_46 = PHI <0(5), graphite_IV.5_47(11)> - : - _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