public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/guojiufu/heads/guojiufu-branch)] only 1 phi in header,  test cases, no INV set
@ 2021-05-31  6:03 Jiu Fu Guo
  0 siblings, 0 replies; only message in thread
From: Jiu Fu Guo @ 2021-05-31  6:03 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:16d024873ec6a896b7b4114a61e5499552713a01

commit 16d024873ec6a896b7b4114a61e5499552713a01
Author: Jiufu Guo <guojiufu@linux.ibm.com>
Date:   Fri May 14 22:29:05 2021 +0800

    only 1 phi in header, test cases, no INV set

Diff:
---
 gcc/testsuite/gcc.dg/loop-split1.c | 82 +++++++++++++++++++++++++++++++++++++-
 gcc/tree-ssa-loop-split.c          | 59 +++++++++++++++------------
 2 files changed, 115 insertions(+), 26 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/loop-split1.c b/gcc/testsuite/gcc.dg/loop-split1.c
index 4c466aa9f54..59c866e4b68 100644
--- a/gcc/testsuite/gcc.dg/loop-split1.c
+++ b/gcc/testsuite/gcc.dg/loop-split1.c
@@ -7,6 +7,13 @@ foo (int *a, int *b, unsigned l, unsigned n)
   while (++l != n)
     a[l] = b[l]  + 1;
 }
+void
+foo_1 (int *a, int *b, unsigned n)
+{
+  unsigned l = 0;
+  while (++l != n)
+    a[l] = b[l]  + 1;
+}
 
 void
 foo1 (int *a, int *b, unsigned l, unsigned n)
@@ -15,6 +22,15 @@ foo1 (int *a, int *b, unsigned l, unsigned n)
     a[l] = b[l]  + 1;
 }
 
+/* No wrap.  */
+void
+foo1_1 (int *a, int *b, unsigned n)
+{
+  unsigned l = 0;
+  while (l++ != n)
+    a[l] = b[l]  + 1;
+}
+
 unsigned
 foo2 (char *a, char *b, unsigned l, unsigned n)
 {
@@ -25,4 +41,68 @@ foo2 (char *a, char *b, unsigned l, unsigned n)
   return l;
 }
 
-/* { dg-final { scan-tree-dump-times "Loop split" 3 "lsplit" } } */
+unsigned
+foo2_1 (char *a, char *b, unsigned l, unsigned n)
+{
+  l = 0;
+  while (++l != n)
+    if (a[l] != b[l])
+      break;
+
+  return l;
+}
+
+unsigned
+foo3 (char *a, char *b, unsigned l, unsigned n)
+{
+  while (l++ != n)
+    if (a[l] != b[l])
+      break;
+
+  return l;
+}
+
+/* No wrap.  */
+unsigned
+foo3_1 (char *a, char *b, unsigned l, unsigned n)
+{
+  l = 0;
+  while (l++ != n)
+    if (a[l] != b[l])
+      break;
+
+  return l;
+}
+
+void bar();
+void foo4(unsigned n,  unsigned i)
+{
+  do
+    {
+      if (i == n)
+        return;
+      bar();
+      ++i;
+    }
+  while (1);
+}
+
+unsigned
+foo5 (double *a, unsigned n, unsigned i)
+{
+  while (a[i] > 0 && i != n)
+    i++;
+
+  return i;
+}
+
+unsigned
+find_skip_diff (char *p, char *q, unsigned n, unsigned i)
+{
+  while (p[i] == q[i] && ++i != n)
+    p++,q++;
+
+  return i;
+}
+
+/* { dg-final { scan-tree-dump-times "Loop split" 7 "lsplit" } } */
diff --git a/gcc/tree-ssa-loop-split.c b/gcc/tree-ssa-loop-split.c
index bd388f0dcc8..11d3582dd3d 100644
--- a/gcc/tree-ssa-loop-split.c
+++ b/gcc/tree-ssa-loop-split.c
@@ -1597,12 +1597,11 @@ split_loop_on_cond (struct loop *loop)
 }
 
 /* Check if the LOOP exit branch likes "if (idx != bound)",
-   and if overflow/wrap may happen on "idx".
-   If INV is not NULL and the branch is "if (bound != idx)", set *INV to true.
-   Return the branch edge which exit loop.  */
+   Return the branch edge which exit loop, if overflow/wrap
+   may happen on "idx".  */
 
 static edge
-get_ne_cond_branch (struct loop *loop, bool *inv)
+get_ne_cond_branch (struct loop *loop)
 {
   int i;
   edge e;
@@ -1622,21 +1621,15 @@ get_ne_cond_branch (struct loop *loop, bool *inv)
 	    || (code == EQ_EXPR && (e->flags & EDGE_TRUE_VALUE))))
 	continue;
 
-      /* Make sure bound is invarant.  */
+      /* Check if bound is invarant.  */
       tree idx = gimple_cond_lhs (cond);
       tree bnd = gimple_cond_rhs (cond);
       if (expr_invariant_in_loop_p (loop, idx))
-	{
-	  std::swap (idx, bnd);
-	  if (inv)
-	    *inv = true;
-	}
+	std::swap (idx, bnd);
       else if (!expr_invariant_in_loop_p (loop, bnd))
 	continue;
 
-
-      /* There is type conversion on idx(or rhs of idx's def).
-	 And there is converting shorter to longer type. */
+      /* By default, unsigned type conversion could cause overflow.  */
       tree type = TREE_TYPE (idx);
       if (!INTEGRAL_TYPE_P (type) || TREE_CODE (idx) != SSA_NAME
 	  || !TYPE_UNSIGNED (type)
@@ -1673,23 +1666,39 @@ get_ne_cond_branch (struct loop *loop, bool *inv)
       if (TREE_CODE (iv.base) == INTEGER_CST)
 	continue;
 
+      /* If no overflow/wrap happen, no need to split.  */
+      class tree_niter_desc niter;
+      if (!number_of_iterations_exit (loop, e, &niter, false, false, NULL))
+	continue;
+      if (niter.control.no_overflow)
+	return NULL;
+
       /* Check loop is simple to split.  */
       gcc_assert (bb != loop->latch);
 
       if (single_pred_p (loop->latch)
 	  && single_pred_edge (loop->latch)->src == bb
-	  && empty_block_p (loop->latch))
+	  && (gsi_end_p (gsi_start_nondebug_bb (loop->latch))))
 	return e;
 
-      /* Splitting is cheap for idx increase header (only i++ or ++I).  */
+      /* Cheap header.  */
       if (bb == loop->header)
 	{
-	  if (get_virtual_phi (loop->header))
+	  if (get_virtual_phi (bb))
+	    continue;
+
+	  /* Only one phi.  */
+	  gphi_iterator psi = gsi_start_phis (bb);
+	  if (gsi_end_p (psi))
+	    continue;
+	  gsi_next (&psi);
+	  if (!gsi_end_p (psi))
 	    continue;
 
+	  /* ++i or ++i */
 	  gimple_stmt_iterator gsi = gsi_start_bb (bb);
 	  if (gsi_end_p (gsi))
-	    return e;
+	    continue;
 
 	  gimple *s1 = gsi_stmt (gsi);
 	  if (!(is_gimple_assign (s1)
@@ -1725,22 +1734,22 @@ split_ne_loop (struct loop *loop, edge cond_e)
   basic_block loop2_cond_exit_bb = get_bb_copy (cond_e->src);
   free_original_copy_tables ();
 
+  gcond *gc = as_a<gcond *> (last_stmt (cond_e->src));
+  gcond *dup_gc = as_a<gcond *> (last_stmt (loop2_cond_exit_bb));
+
   /* Change if (i != n) to LOOP1:if (i > n) and LOOP2:if (i < n) */
-  bool inv = false;
+  bool inv = expr_invariant_in_loop_p (loop, gimple_cond_lhs (gc));
   enum tree_code up_code = inv ? LT_EXPR : GT_EXPR;
   enum tree_code down_code = inv ? GT_EXPR : LT_EXPR;
 
-  gcond *gc = as_a<gcond *> (last_stmt (cond_e->src));
   gimple_cond_set_code (gc, up_code);
-
-  gcond *dup_gc = as_a<gcond *> (last_stmt (loop2_cond_exit_bb));
   gimple_cond_set_code (dup_gc, down_code);
 
   /* Link the exit cond edge to new loop.  */
   gcond *break_cond = as_a<gcond *> (gimple_copy (gc));
   edge pred_e = single_pred_edge (loop->latch);
-  gcc_assert (pred_e);
-  bool simple_loop = pred_e->src == cond_e->src && empty_block_p (loop->latch);
+  bool simple_loop = pred_e && pred_e->src == cond_e->src
+		     && (gsi_end_p (gsi_start_nondebug_bb (loop->latch)));
   if (simple_loop)
     gimple_cond_set_code (break_cond, down_code);
   else
@@ -1764,7 +1773,7 @@ split_ne_loop (struct loop *loop, edge cond_e)
 
   rewrite_into_loop_closed_ssa_1 (NULL, 0, SSA_OP_USE, loop);
   if (dump_file && (dump_flags & TDF_DETAILS))
-    fprintf (dump_file, ";; Loop split on wrap.\n");
+    fprintf (dump_file, ";; Loop split on wrap index.\n");
 
   return true;
 }
@@ -1810,7 +1819,7 @@ split_loop_on_ne_cond (class loop *loop)
   if (num > param_max_peeled_insns)
     return false;
 
-  edge branch_edge = get_ne_cond_branch (loop, NULL);
+  edge branch_edge = get_ne_cond_branch (loop);
   if (branch_edge && split_ne_loop (loop, branch_edge))
     return true;


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-05-31  6:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-31  6:03 [gcc(refs/users/guojiufu/heads/guojiufu-branch)] only 1 phi in header, test cases, no INV set Jiu Fu Guo

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).