On Thu, 2 Sep 2021, Jiufu Guo wrote: > When transform > {iv0.base, iv0.step} LT/LE {iv1.base, iv1.step} > to > {iv0.base, iv0.step - iv1.step} LT/LE {iv1.base, 0} > > There would be error if 'iv0.step - iv1.step' in negative, > for which means run until wrap/overflow. > > For example: > {1, +, 1} <= {4, +, 3} => {1, +, -2} <= {4, +, 0} > > This patch avoid this kind transform. > > Bootstrap and regtest pass on ppc64le. > Is this ok for trunk?
This looks like PR100740, see the discussion starting at https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571570.html We seem to be at a dead end figuring what's exactly required to make the transform valid and I have my doubts that arguing with overflow we're not running in circles. My last attempt was + if (code != NE_EXPR) + { + if (TREE_CODE (step) != INTEGER_CST) + return false; + if (!iv0->no_overflow || !iv1->no_overflow) + return false; + /* The new IV does not overflow if the step has the same + sign and is less in magnitude. */ + if (tree_int_cst_sign_bit (iv0->step) != tree_int_cst_sign_bit (step) + || wi::geu_p (wi::abs (wi::to_wide (step)), + wi::abs (wi::to_wide (iv0->step)))) + return false; + } where your patch at least misses { 1, +, -1 } < { -3, + , -3 } transforming to { 1, +, +2 } < -3, thus a positive step but we're still iterating unti wrap? That is, the sign of the combined step cannot really be the issue at hand. Bin argued my condition is too strict and I agreed, see https://gcc.gnu.org/pipermail/gcc-patches/2021-July/574334.html which is the last mail in the thread sofar (still without a fix :/) Somewhere it was said that we eventually should simply put preconditions into ->assumptions rather than trying to check ->no_overflow and friends, not sure if that's really applicable here. Richard. > BR. > Jiufu > > gcc/ChangeLog: > > 2021-09-02 Jiufu Guo <guoji...@linux.ibm.com> > > PR tree-optimization/102131 > * tree-ssa-loop-niter.c (number_of_iterations_cond): > Avoid transform until wrap condition > > gcc/testsuite/ChangeLog: > > 2021-09-02 Jiufu Guo <guoji...@linux.ibm.com> > > PR tree-optimization/102131 > * gcc.dg/pr102131.c: New test. > > --- > gcc/tree-ssa-loop-niter.c | 18 +++++++++ > gcc/testsuite/gcc.dg/pr102131.c | 69 +++++++++++++++++++++++++++++++++ > 2 files changed, 87 insertions(+) > create mode 100644 gcc/testsuite/gcc.dg/pr102131.c > > diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c > index 7af92d1c893..52ce517af89 100644 > --- a/gcc/tree-ssa-loop-niter.c > +++ b/gcc/tree-ssa-loop-niter.c > @@ -1866,6 +1866,24 @@ number_of_iterations_cond (class loop *loop, > || !iv0->no_overflow || !iv1->no_overflow)) > return false; > > + /* GT/GE has been transformed to LT/LE already. > + cmp_code could be LT, LE or NE > + > + For LE/LT transform > + {iv0.base, iv0.step} LT/LE {iv1.base, iv1.step} > + to > + {iv0.base, iv0.step - iv1.step} LT/LE {iv1.base, 0} > + Negative iv0.step - iv1.step means decreasing until wrap, > + then the transform is not accurate. > + > + For example: > + {1, +, 1} <= {4, +, 3} > + is not same with > + {1, +, -2} <= {4, +, 0} > + */ > + if ((code == LE_EXPR || code == LT_EXPR) && tree_int_cst_sign_bit > (step)) > + return false; > + > iv0->step = step; > if (!POINTER_TYPE_P (type)) > iv0->no_overflow = false; > diff --git a/gcc/testsuite/gcc.dg/pr102131.c b/gcc/testsuite/gcc.dg/pr102131.c > new file mode 100644 > index 00000000000..0fcfaa132da > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr102131.c > @@ -0,0 +1,69 @@ > +/* { dg-do run } */ > + > +unsigned int a; > +int > +fun1 () > +{ > + unsigned b = 0; > + int c = 1; > + for (; b < 3; b++) > + { > + while (c < b) > + __builtin_abort (); > + for (a = 0; a < 3; a++) > + c++; > + } > + return 0; > +} > + > +unsigned b; > +int > +fun2 () > +{ > + unsigned c = 0; > + for (a = 0; a < 2; a++) > + for (b = 0; b < 2; b++) > + if (++c < a) > + __builtin_abort (); > + return 0; > +} > + > +int > +fun3 (void) > +{ > + unsigned a, b, c = 0; > + for (a = 0; a < 10; a++) > + { > + for (b = 0; b < 2; b++) > + { > + c++; > + if (c < a) > + { > + __builtin_abort (); > + } > + } > + } > + return 0; > +} > + > +int > +fun4 () > +{ > + unsigned i; > + for (i = 0; i < 3; ++i) > + { > + if (i > i * 2) > + __builtin_abort (); > + } > + return 0; > +} > + > +int > +main () > +{ > + fun1 (); > + fun2 (); > + fun3 (); > + fun4 (); > + return 0; > +} > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)