public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Jiu Fu Guo <guojiufu@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org
Subject: [gcc(refs/users/guojiufu/heads/guojiufu-branch)] Update according Richi comments
Date: Wed,  2 Jun 2021 04:14:05 +0000 (GMT)	[thread overview]
Message-ID: <20210602041405.8EC1E3857C66@sourceware.org> (raw)

https://gcc.gnu.org/g:252fee171793af1406fe4a44e6800cd53ff9fcbd

commit 252fee171793af1406fe4a44e6800cd53ff9fcbd
Author: Jiufu Guo <guojiufu@linux.ibm.com>
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<edge> 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 || i<N", then it could be transform to:
 L_H:
  if (i>N)
    S;
+ else
+   goto EXIT;
  i++;
  goto L_H;
 L1_H:
  if (i<N)
    S;
+ else
+   goto EXIT;
  i++;
  goto L1_H;


                 reply	other threads:[~2021-06-02  4:14 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210602041405.8EC1E3857C66@sourceware.org \
    --to=guojiufu@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).