From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2066) id 8EC1E3857C66; Wed, 2 Jun 2021 04:14:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8EC1E3857C66 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Jiu Fu Guo To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/guojiufu/heads/guojiufu-branch)] Update according Richi comments X-Act-Checkin: gcc X-Git-Author: Jiufu Guo X-Git-Refname: refs/users/guojiufu/heads/guojiufu-branch X-Git-Oldrev: 3db06dd76539b5fdcbb8a71ad1b8fb861b96d3d6 X-Git-Newrev: 252fee171793af1406fe4a44e6800cd53ff9fcbd Message-Id: <20210602041405.8EC1E3857C66@sourceware.org> Date: Wed, 2 Jun 2021 04:14:05 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Jun 2021 04:14:05 -0000 https://gcc.gnu.org/g:252fee171793af1406fe4a44e6800cd53ff9fcbd commit 252fee171793af1406fe4a44e6800cd53ff9fcbd Author: Jiufu Guo Date: Mon May 31 17:19:10 2021 +0800 Update according Richi comments Diff: --- gcc/testsuite/gcc.dg/loop-split2.c | 54 ++++++++++++++++++++++++++++++++++++ gcc/tree-ssa-loop-split.c | 57 +++++++++++++++++++++++++------------- 2 files changed, 91 insertions(+), 20 deletions(-) diff --git a/gcc/testsuite/gcc.dg/loop-split2.c b/gcc/testsuite/gcc.dg/loop-split2.c new file mode 100644 index 00000000000..a10d0ebbf2d --- /dev/null +++ b/gcc/testsuite/gcc.dg/loop-split2.c @@ -0,0 +1,54 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -fdump-tree-lsplit-details" } */ + +extern void abort (void); +extern void exit (int); + +#define NI __attribute__ ((noinline)) + +void NI +foo (int *a, int *b, unsigned char l, unsigned char n) +{ + while (++l != n) + a[l] = b[l] + 1; +} + +unsigned NI +bar (int *a, int *b, unsigned char l, unsigned char n) +{ + while (l++ != n) + if (a[l] != b[l]) + break; + + return l; +} + +int a[258]; +int b[258]; + +int main() +{ + __builtin_memcpy (b, a, sizeof (a)); + + if (bar (a, b, 3, 8) != 9) + abort (); + + if (bar (a, b, 8, 3) != 4) + abort (); + + b[100] += 1; + if (bar (a, b, 90, 110) != 100) + abort (); + + if (bar (a, b, 110, 105) != 100) + abort (); + + foo (a, b, 99, 99); + a[99] = b[99] + 1; + for (int i = 0; i < 127; i++) + if (a[i] != b[i] + 1) + abort(); + + exit (0); +} + diff --git a/gcc/tree-ssa-loop-split.c b/gcc/tree-ssa-loop-split.c index 5c1742b5ff4..0428b0abea6 100644 --- a/gcc/tree-ssa-loop-split.c +++ b/gcc/tree-ssa-loop-split.c @@ -230,8 +230,10 @@ easy_exit_values (class loop *loop) conditional). I.e. the second loop can now be entered either via the original entry or via NEW_E, so the entry values of LOOP2 phi nodes are either the original ones or those at the exit - of LOOP1. Insert new phi nodes in LOOP2 pre-header reflecting - this. The loops need to fulfill easy_exit_values(). */ + of LOOP1. Selecting the previous value instead next value as the + exit value of LOOP1 if USE_PREV is true. Insert new phi nodes in + LOOP2 pre-header reflecting this. The loops need to fulfill + easy_exit_values(). */ static void connect_loop_phis (class loop *loop1, class loop *loop2, edge new_e, @@ -1596,9 +1598,8 @@ split_loop_on_cond (struct loop *loop) return do_split; } -/* Check if the LOOP exit branch likes "if (idx != bound)", - Return the branch edge which exit loop, if overflow/wrap - may happen on "idx". */ +/* Check if the LOOP exit branch is like "if (idx != bound)", + Return the branch edge which exit loop, if wrap may happen on "idx". */ static edge get_ne_cond_branch (struct loop *loop) @@ -1609,7 +1610,7 @@ get_ne_cond_branch (struct loop *loop) auto_vec edges = get_loop_exit_edges (loop); FOR_EACH_VEC_ELT (edges, i, e) { - /* Check if there is possible wrap/overflow. */ + /* Check if there is possible wrap. */ class tree_niter_desc niter; if (!number_of_iterations_exit (loop, e, &niter, false, false)) continue; @@ -1618,40 +1619,50 @@ get_ne_cond_branch (struct loop *loop) if (niter.cmp != NE_EXPR) continue; - /* Check loop is simple to split. */ + /* If exit edge is just before the empty latch, it is easy to link + the split loops: just jump from the exit edge of one loop to the + header of new loop. */ if (single_pred_p (loop->latch) && single_pred_edge (loop->latch)->src == e->src - && (gsi_end_p (gsi_start_nondebug_bb (loop->latch)))) + && empty_block_p (loop->latch)) return e; - /* Simple header. */ + /* If exit edge is at end of header, and header contains i++ or ++i, + only, it is simple to link the split loops: jump from the end of + one loop header to the new loop header, and use unchanged PHI + result of first loop as the entry PHI value of the second loop. */ if (e->src == loop->header) { - if (get_virtual_phi (e->src)) - continue; - /* Only one phi. */ gphi_iterator psi = gsi_start_phis (e->src); if (gsi_end_p (psi)) continue; + gphi *phi = psi.phi (); gsi_next (&psi); if (!gsi_end_p (psi)) continue; - /* ++i or ++i */ - gimple_stmt_iterator gsi = gsi_start_bb (e->src); - if (gsi_end_p (gsi)) - continue; - + /* Get the idx from last stmt (the gcond) of e->src. */ gimple *gc = last_stmt (e->src); + gcc_assert (gimple_code (gc) == GIMPLE_COND); tree idx = gimple_cond_lhs (gc); if (expr_invariant_in_loop_p (loop, idx)) idx = gimple_cond_rhs (gc); + tree next = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop)); + tree prev = PHI_RESULT (phi); + if (idx != prev && idx != next) + continue; + + /* ++i or ++i */ + gimple_stmt_iterator gsi + = gsi_start_nondebug_after_labels_bb (e->src); + if (gsi_end_p (gsi)) + continue; + gimple *s1 = gsi_stmt (gsi); - if (!(is_gimple_assign (s1) && idx - && (idx == gimple_assign_lhs (s1) - || idx == gimple_assign_rhs1 (s1)))) + if (!is_gimple_assign (s1) || gimple_assign_lhs (s1) != next + || gimple_assign_rhs1 (s1) != prev) continue; gsi_next (&gsi); @@ -1730,6 +1741,8 @@ split_ne_loop (struct loop *loop, edge cond_e) L_H: if (i!=N) S; + else + goto EXIT; i++; goto L_H; @@ -1738,11 +1751,15 @@ The "i!=N" is like "i>N || iN) S; + else + goto EXIT; i++; goto L_H; L1_H: if (i