From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2066) id 6739F396E861; Wed, 9 Jun 2021 11:19:51 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6739F396E861 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)] Support 1/-1 as step, and add test cases. X-Act-Checkin: gcc X-Git-Author: Jiufu Guo X-Git-Refname: refs/users/guojiufu/heads/guojiufu-branch X-Git-Oldrev: dfce3dcf332789b9685888bc22bca960d3455de9 X-Git-Newrev: 305895dda86c574952345ffe7f26f2284d953c0a Message-Id: <20210609111951.6739F396E861@sourceware.org> Date: Wed, 9 Jun 2021 11:19:51 +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, 09 Jun 2021 11:19:51 -0000 https://gcc.gnu.org/g:305895dda86c574952345ffe7f26f2284d953c0a commit 305895dda86c574952345ffe7f26f2284d953c0a Author: Jiufu Guo Date: Wed Jun 9 17:32:57 2021 +0800 Support 1/-1 as step, and add test cases. Diff: --- gcc/testsuite/gcc.dg/loop-split2.c | 107 +++++++++++++++++++++++++++++++++++-- gcc/testsuite/gcc.dg/loop-split3.c | 62 +++++++++++++++++++++ gcc/tree-ssa-loop-split.c | 30 ++++++----- 3 files changed, 182 insertions(+), 17 deletions(-) diff --git a/gcc/testsuite/gcc.dg/loop-split2.c b/gcc/testsuite/gcc.dg/loop-split2.c index 0d3fded3f61..1c7fd1bede1 100644 --- a/gcc/testsuite/gcc.dg/loop-split2.c +++ b/gcc/testsuite/gcc.dg/loop-split2.c @@ -3,6 +3,7 @@ extern void abort (void); extern void exit (int); +void push (int); #define NI __attribute__ ((noinline)) @@ -17,38 +18,134 @@ unsigned NI bar (int *a, int *b, unsigned char l, unsigned char n) { while (l++ != n) - if (a[l] != b[l]) - break; + { + 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 push (int e) +{ + c[top++] = e; +} + +void reset () +{ + top = 0; + __builtin_memset (c, 0, sizeof (c)); +} -int main() +#define check(a, b) (b == -1 || a == b) + +int +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)); + reset (); + if (bar (a, b, 6, 8) != 9 || !check_c (c, 7, 8, 8, 9, 0, 0)) + abort (); - if (bar (a, b, 3, 8) != 9) + 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 (); - if (bar (a, b, 8, 3) != 4) + 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 (); + + 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 (); + 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(); + 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 ca35eee21b7..0365b6d069e 100644 --- a/gcc/tree-ssa-loop-split.c +++ b/gcc/tree-ssa-loop-split.c @@ -1602,7 +1602,7 @@ split_loop_on_cond (struct loop *loop) Return the branch edge which exit loop, if wrap may happen on "idx". */ static edge -get_ne_cond_branch (struct loop *loop) +get_ne_cond_branch (struct loop *loop, tree *step) { int i; edge e; @@ -1638,9 +1638,8 @@ get_ne_cond_branch (struct loop *loop) /* Avoid to split if bound is MAX/MIN val. */ tree bound_type = TREE_TYPE (bnd); - if (TREE_CODE (bnd) == INTEGER_CST && INTEGRAL_TYPE_P (bound_type) - && (tree_int_cst_equal (bnd, TYPE_MAX_VALUE (bound_type)) - || tree_int_cst_equal (bnd, TYPE_MIN_VALUE (bound_type)))) + if (tree_int_cst_equal (bnd, TYPE_MAX_VALUE (bound_type)) + || tree_int_cst_equal (bnd, TYPE_MIN_VALUE (bound_type))) continue; /* Check if there is possible wrap. */ @@ -1651,6 +1650,10 @@ get_ne_cond_branch (struct loop *loop) return NULL; if (niter.cmp != NE_EXPR) continue; + if (!integer_onep (niter.control.step) + && !integer_minus_onep (niter.control.step)) + continue; + *step = niter.control.step; /* 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 @@ -1701,7 +1704,7 @@ get_ne_cond_branch (struct loop *loop) /* Split the LOOP with NE_EXPR into two loops with GT_EXPR and LT_EXPR. */ static bool -split_ne_loop (struct loop *loop, edge cond_e) +split_ne_loop (struct loop *loop, edge cond_e, tree step) { initialize_original_copy_tables (); @@ -1740,11 +1743,13 @@ split_ne_loop (struct loop *loop, edge cond_e) /* Change if (i != n) to LOOP1:if (i > n) and LOOP2:if (i < n) */ 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; + if (tree_int_cst_sign_bit (step)) + inv = !inv; + enum tree_code first_loop_code = inv ? LT_EXPR : GT_EXPR; + enum tree_code second_loop_code = inv ? GT_EXPR : LT_EXPR; - gimple_cond_set_code (gc, up_code); - gimple_cond_set_code (dup_gc, down_code); + gimple_cond_set_code (gc, first_loop_code); + gimple_cond_set_code (dup_gc, second_loop_code); /* Link the exit cond edge to new loop. */ gcond *break_cond = as_a (gimple_copy (gc)); @@ -1752,7 +1757,7 @@ split_ne_loop (struct loop *loop, edge cond_e) bool simple_loop = pred_e && pred_e->src == cond_e->src && empty_block_p (loop->latch); if (simple_loop) - gimple_cond_set_code (break_cond, down_code); + gimple_cond_set_code (break_cond, second_loop_code); else gimple_cond_make_true (break_cond); @@ -1810,7 +1815,8 @@ The loop with "i