public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/guojiufu/heads/guojiufu-branch)] Update according Richi comments
@ 2021-06-02 4:14 Jiu Fu Guo
0 siblings, 0 replies; only message in thread
From: Jiu Fu Guo @ 2021-06-02 4:14 UTC (permalink / raw)
To: gcc-cvs
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;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-06-02 4:14 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-02 4:14 [gcc(refs/users/guojiufu/heads/guojiufu-branch)] Update according Richi comments 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).