public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/guojiufu/heads/personal-branch)] +-1, < and >
@ 2021-06-14 3:28 Jiu Fu Guo
0 siblings, 0 replies; only message in thread
From: Jiu Fu Guo @ 2021-06-14 3:28 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:8acef3abe4c4c6a5ca25d28b6db5968f9cfcbc47
commit 8acef3abe4c4c6a5ca25d28b6db5968f9cfcbc47
Author: Jiufu Guo <guojiufu@linux.ibm.com>
Date: Sun Jun 13 15:27:01 2021 +0800
+-1, < and >
Diff:
---
gcc/testsuite/gcc.dg/loop-split2.c | 154 +++++++++++++++++++++++++++++++++++++
gcc/testsuite/gcc.dg/loop-split3.c | 62 +++++++++++++++
gcc/tree-ssa-loop-split.c | 79 +++++++++++--------
3 files changed, 264 insertions(+), 31 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..cbbaa037f82
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/loop-split2.c
@@ -0,0 +1,154 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+extern void abort (void);
+extern void exit (int);
+void push (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)
+ {
+ push (l);
+ if (a[l] != b[l])
+ break;
+ push (l+1);
+ }
+ return l;
+}
+
+void NI
+foo_1 (int *a, int *b, unsigned char l, unsigned char n)
+{
+ while (--l != n)
+ a[l] = b[l] + 1;
+}
+
+unsigned NI
+bar_1 (int *a, int *b, unsigned char l, unsigned char n)
+{
+ while (l-- != n)
+ {
+ push (l);
+ if (a[l] != b[l])
+ break;
+ push (l+1);
+ }
+
+ return l;
+}
+
+int a[258];
+int b[258];
+int c[1024];
+static int top = 0;
+void NI push (int e)
+{
+ c[top++] = e;
+}
+
+void NI reset ()
+{
+ top = 0;
+ __builtin_memset (c, 0, sizeof (c));
+}
+
+#define check(a, b) (b == -1 || a == b)
+
+int NI
+check_c (int *c, int a0, int a1, int a2, int a3, int a4, int a5)
+{
+ return check (c[0], a0) && check (c[1], a1) && check (c[2], a2)
+ && check (c[3], a3) && check (c[4], a4) && check (c[5], a5);
+}
+
+int main ()
+{
+ __builtin_memcpy (b, a, sizeof (a));
+#if 0
+ reset ();
+ if (bar (a, b, 6, 8) != 9 || !check_c (c, 7, 8, 8, 9, 0, 0))
+ abort ();
+
+ reset ();
+ if (bar (a, b, 5, 3) != 4 || !check_c (c, 6, 7, 7, 8, 8, 9)
+ || !check_c (c + 496, 254, 255, 255, 256, 0, 1))
+ abort ();
+
+ reset ();
+ if (bar (a, b, 6, 6) != 7 || !check_c (c, 0, 0, 0, 0, 0, 0))
+ abort ();
+
+ reset ();
+ if (bar (a, b, 253, 255) != 0 || !check_c (c, 254, 255, 255, 256,-1,-1))
+ abort ();
+
+ reset ();
+ if (bar (a, b, 253, 0) != 1 || !check_c (c, 254, 255, 255, 256, 0, 1))
+ abort ();
+
+ #endif
+
+ reset ();
+ if (bar_1 (a, b, 6, 8) != 7 || !check_c (c, 5, 6, 4, 5, 3, 4))
+ abort ();
+
+ reset ();
+ if (bar_1 (a, b, 5, 3) != 2 || !check_c (c, 4, 5, 3, 4,-1,-1 ))
+ abort ();
+
+ reset ();
+ if (bar_1 (a, b, 6, 6) != 5)
+ abort ();
+
+ reset ();
+ if (bar_1 (a, b, 2, 255) != 254 || !check_c (c, 1, 2, 0, 1, 255, 256))
+ abort ();
+
+ reset ();
+ if (bar_1 (a, b, 2, 0) != 255 || !check_c (c, 1, 2, 0, 1, 0, 0))
+ abort ();
+
+
+ b[100] += 1;
+ reset ();
+ if (bar (a, b, 90, 110) != 100)
+ abort ();
+
+ reset ();
+ if (bar (a, b, 110, 105) != 100)
+ abort ();
+
+ reset ();
+ if (bar_1 (a, b, 90, 110) != 109)
+ abort ();
+
+ reset ();
+ if (bar_1 (a, b, 2, 90) != 100)
+ abort ();
+#if 0
+ foo (a, b, 99, 99);
+ a[99] = b[99] + 1;
+ for (int i = 0; i < 256; i++)
+ if (a[i] != b[i] + 1)
+ abort();
+
+ foo_1 (a, b, 99, 99);
+ a[99] = b[99] + 1;
+ for (int i = 0; i < 256; i++)
+ if (a[i] != b[i] + 1)
+ abort();
+ #endif
+ exit (0);
+}
+
diff --git a/gcc/testsuite/gcc.dg/loop-split3.c b/gcc/testsuite/gcc.dg/loop-split3.c
new file mode 100644
index 00000000000..ec93ee8bd12
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/loop-split3.c
@@ -0,0 +1,62 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fsplit-loops -fdump-tree-lsplit-details" } */
+
+void
+foo (int *a, int *b, unsigned l, unsigned n)
+{
+ while (--l != n)
+ a[l] = b[l] + 1;
+}
+
+void
+foo1 (int *a, int *b, unsigned l, unsigned n)
+{
+ while (l-- != n)
+ a[l] = b[l] + 1;
+}
+
+unsigned
+foo2 (char *a, char *b, unsigned l, unsigned n)
+{
+ 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;
+}
+
+void
+bar ();
+void
+foo4 (unsigned n, unsigned i)
+{
+ do
+ {
+ if (i == n)
+ return;
+ bar ();
+ --i;
+ }
+ while (1);
+}
+
+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" 6 "lsplit" } } */
diff --git a/gcc/tree-ssa-loop-split.c b/gcc/tree-ssa-loop-split.c
index 209a26d9b53..326af90f766 100644
--- a/gcc/tree-ssa-loop-split.c
+++ b/gcc/tree-ssa-loop-split.c
@@ -1645,6 +1645,7 @@ struct idx_elements
gimple *inc_stmt;
tree idx;
tree bnd;
+ tree step;
tree large_type;
tree small_type;
bool cmp_on_next;
@@ -1727,7 +1728,7 @@ analyze_idx_elements (class loop *loop, edge e, idx_elements &data)
if (rhs_code != PLUS_EXPR)
return false;
tree step = gimple_assign_rhs2 (stmt);
- if (!integer_onep (step))
+ if (TREE_CODE (step) != INTEGER_CST)
return false;
inc_stmt = stmt;
tree prev = gimple_assign_rhs1 (stmt);
@@ -1741,6 +1742,7 @@ analyze_idx_elements (class loop *loop, edge e, idx_elements &data)
data.phi = phi;
data.idx = idx;
data.bnd = bnd;
+ data.step = step;
data.large_type = large_type;
data.small_type = small_type;
data.inc_stmt = inc_stmt;
@@ -1784,7 +1786,7 @@ get_wrap_assumption (class loop *loop, edge *exit, idx_elements &data)
code = swap_tree_comparison (code);
if ((e->flags & EDGE_TRUE_VALUE) && code == EQ_EXPR)
code = NE_EXPR;
- if (code != NE_EXPR && code != LT_EXPR && code != LE_EXPR)
+ if (code != NE_EXPR && code != LT_EXPR && code != GT_EXPR)
continue;
/* Check if idx is iv with base and step. */
@@ -1794,36 +1796,39 @@ get_wrap_assumption (class loop *loop, edge *exit, idx_elements &data)
if (!simple_iv_with_niters (loop, loop_containing_stmt (gc), idx, &iv,
&iv_niters, false))
continue;
- if (!iv.base || !iv.step)
+ if (!iv.base || !iv.step || !tree_int_cst_equal (iv.step, data.step))
+ continue;
+
+ bool is_negative = tree_int_cst_sign_bit (iv.step);
+ enum tree_code expect_code = is_negative ? GT_EXPR : LT_EXPR;
+ if (code != NE_EXPR && code != expect_code)
continue;
/* Update the type for base, bound and the max value of boundary. */
tree base = iv.base;
tree small_type = data.small_type;
tree large_type = data.large_type;
- tree maxv = TYPE_MAX_VALUE (small_type);
+ tree max_min_bnd = is_negative ? TYPE_MIN_VALUE (small_type)
+ : TYPE_MAX_VALUE (small_type);
if (large_type != TREE_TYPE (base))
base = fold_convert (large_type, base);
if (large_type != TREE_TYPE (bnd))
bnd = fold_convert (large_type, bnd);
if (large_type != small_type)
- maxv = fold_convert (large_type, maxv);
+ max_min_bnd = fold_convert (large_type, max_min_bnd);
- /* for "< or <=", there is no wrap if bnd <= max value. */
- tree no_wrap_assump = fold_build2 (LE_EXPR, boolean_type_node, bnd, maxv);
+ /* There is no wrap if bnd <= max value && base <= bnd. */
+ tree no_wrap
+ = fold_build2 (expect_code, boolean_type_node, bnd, max_min_bnd);
+ no_wrap
+ = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, no_wrap,
+ fold_build2 (expect_code, boolean_type_node, base, bnd));
- /* for "!=", to make sure there is no wrap, beside bnd <= max,
- base <= bnd is also required. */
- if (code == NE_EXPR)
- no_wrap_assump
- = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, no_wrap_assump,
- fold_build2 (LE_EXPR, boolean_type_node, base, bnd));
-
- if (integer_zerop (no_wrap_assump))
+ if (integer_zerop (no_wrap))
continue;
*exit = e;
- return no_wrap_assump;
+ return no_wrap;
}
return NULL_TREE;
@@ -1839,9 +1844,6 @@ update_idx_bnd_type (class loop *loop, idx_elements &data)
gphi *phi = data.phi;
tree type = TREE_TYPE (PHI_RESULT (phi));
tree suitable_type = data.large_type;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (suitable_type)
- && (TYPE_UNSIGNED (suitable_type) == TYPE_UNSIGNED (type)))
- return false;
if (TYPE_UNSIGNED (suitable_type))
{
if (TYPE_PRECISION (suitable_type) == TYPE_PRECISION (sizetype))
@@ -1877,7 +1879,16 @@ update_idx_bnd_type (class loop *loop, idx_elements &data)
/* New increase stmt. */
gimple *inc_stmt = data.inc_stmt;
tree step = gimple_assign_rhs2 (inc_stmt);
- step = fold_convert (suitable_type, step);
+ if (tree_int_cst_sign_bit(step))
+ {
+ wide_int v = wi::to_wide (step);
+ v = wide_int::from (v, TYPE_PRECISION (suitable_type),
+ SIGNED);
+
+ step = wide_int_to_tree (suitable_type, v);
+ }
+ else
+ step = fold_convert (suitable_type, step);
new_idx = PHI_RESULT (newphi);
tree_code inc_code = gimple_assign_rhs_code (inc_stmt);
gimple *new_inc = gimple_build_assign (new_next, inc_code, new_idx, step);
@@ -1908,7 +1919,7 @@ update_idx_bnd_type (class loop *loop, idx_elements &data)
tree idx = PHI_RESULT (phi);
type = TREE_TYPE (idx);
stmt = gimple_build_assign (idx, fold_convert (type, new_idx));
- gsi = gsi_start_bb (loop->header);
+ gsi = gsi_start_nondebug_after_labels_bb (loop->header);
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
gsi = gsi_for_stmt (phi);
@@ -1924,7 +1935,8 @@ update_idx_bnd_type (class loop *loop, idx_elements &data)
under the guard that NO_WRAP_COND will not be true. */
static bool
-split_wrap_boundary (class loop *loop, edge e, tree no_wrap_cond)
+split_wrap_boundary (class loop *loop, edge e, tree no_wrap_cond,
+ bool is_negative_step)
{
/* Convert the condition into a suitable gcond. */
gimple_seq stmts = NULL;
@@ -1948,12 +1960,19 @@ split_wrap_boundary (class loop *loop, edge e, tree no_wrap_cond)
gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT);
}
- /* Update gcond code and edge. */
+ /* Update gcond code. */
gcond *gc = as_a<gcond *> (last_stmt (e->src));
enum tree_code code = gimple_cond_code (gc);
enum tree_code new_code;
bool inv = expr_invariant_in_loop_p (loop, gimple_cond_lhs (gc));
- new_code = inv ? GT_EXPR : LT_EXPR;
+ if (is_negative_step)
+ new_code = inv ? LT_EXPR : GT_EXPR;
+ else
+ new_code = inv ? GT_EXPR : LT_EXPR;
+ if (code == NE_EXPR || code == EQ_EXPR)
+ gimple_cond_set_code (gc, new_code);
+
+ /* Swap edge. */
if (code == EQ_EXPR)
{
edge out = EDGE_SUCC (e->src, 0);
@@ -1965,9 +1984,7 @@ split_wrap_boundary (class loop *loop, edge e, tree no_wrap_cond)
out->flags |= EDGE_FALSE_VALUE;
out->flags &= ~EDGE_TRUE_VALUE;
}
- if (code == NE_EXPR || code == EQ_EXPR)
- gimple_cond_set_code (gc, new_code);
-
+
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, ";; Loop split on wrap index.\n");
@@ -2003,9 +2020,9 @@ split_loop_on_wrap (class loop *loop)
{
edge e;
idx_elements data;
- tree no_wrap_assumption = get_wrap_assumption (loop, &e, data);
+ tree no_wrap = get_wrap_assumption (loop, &e, data);
- if (!no_wrap_assumption)
+ if (!no_wrap)
return false;
int num = 0;
@@ -2027,10 +2044,10 @@ split_loop_on_wrap (class loop *loop)
free (bbs);
- if (integer_onep (no_wrap_assumption))
+ if (integer_onep (no_wrap))
return update_idx_bnd_type (loop, data);
- if (split_wrap_boundary (loop, e, no_wrap_assumption))
+ if (split_wrap_boundary (loop, e, no_wrap, tree_int_cst_sign_bit (data.step)))
{
update_idx_bnd_type (loop, data);
return true;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-06-14 3:28 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-14 3:28 [gcc(refs/users/guojiufu/heads/personal-branch)] +-1, < and > 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).