Changes on V1: * Add more test case * Add comment for exit-condition transform * Removing duplicate setting on niter->control
This patch reset niter->control, niter->bound and niter->cmp in number_of_iterations_until_wrap. Bootstrap and test pass on ppc64 and x86, and pass the test cases in PR. Is this ok for trunk? One thing, in this patch, the IVbase is still keep as biasing by 1 step. BR. Jiufu Guo gcc/ChangeLog: 2021-09-02 Jiufu Guo <guoji...@linux.ibm.com> PR tree-optimization/102087 * tree-ssa-loop-niter.c (number_of_iterations_until_wrap): Update bound/cmp/control for niter. gcc/testsuite/ChangeLog: 2021-09-02 Jiufu Guo <guoji...@linux.ibm.com> PR tree-optimization/102087 * gcc.dg/pr102087.c: New test. --- gcc/tree-ssa-loop-niter.c | 16 ++++++++++++++- gcc/testsuite/gcc.dg/pr102087.c | 35 +++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/pr102087.c diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 7af92d1c893..75109407124 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -1482,7 +1482,7 @@ number_of_iterations_until_wrap (class loop *, tree type, affine_iv *iv0, affine_iv *iv1, class tree_niter_desc *niter) { tree niter_type = unsigned_type_for (type); - tree step, num, assumptions, may_be_zero; + tree step, num, assumptions, may_be_zero, span; wide_int high, low, max, min; may_be_zero = fold_build2 (LE_EXPR, boolean_type_node, iv1->base, iv0->base); @@ -1557,6 +1557,20 @@ number_of_iterations_until_wrap (class loop *, tree type, affine_iv *iv0, niter->control.no_overflow = false; + /* Update bound and exit condition as: + bound = niter * STEP + (IVbase - STEP). + { IVbase - STEP, +, STEP } != bound + Here, biasing IVbase by 1 step makes 'bound' be the value before wrap. + */ + niter->control.base = fold_build2 (MINUS_EXPR, niter_type, + niter->control.base, niter->control.step); + span = fold_build2 (MULT_EXPR, niter_type, niter->niter, + fold_convert (niter_type, niter->control.step)); + niter->bound = fold_build2 (PLUS_EXPR, niter_type, span, + fold_convert (niter_type, niter->control.base)); + niter->bound = fold_convert (type, niter->bound); + niter->cmp = NE_EXPR; + return true; } diff --git a/gcc/testsuite/gcc.dg/pr102087.c b/gcc/testsuite/gcc.dg/pr102087.c new file mode 100644 index 00000000000..fc60cbda066 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr102087.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +unsigned __attribute__ ((noinline)) +foo (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) +{ + while (n < ++l) + *a++ = *b++ + 1; + return l; +} + +volatile int a[1]; +unsigned b; +int c; + +int +check () +{ + int d; + for (; b > 1; b++) + for (c = 0; c < 2; c++) + for (d = 0; d < 2; d++) + a[0]; + return 0; +} + +char **Gif_ClipImage_gfi_0; +int Gif_ClipImage_y, Gif_ClipImage_shift; +void +Gif_ClipImage () +{ + for (; Gif_ClipImage_y >= Gif_ClipImage_shift; Gif_ClipImage_y++) + Gif_ClipImage_gfi_0[Gif_ClipImage_shift] + = Gif_ClipImage_gfi_0[Gif_ClipImage_y]; +} -- 2.17.1