https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88044

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|WAITING                     |NEW

--- Comment #14 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I've put logging into tree-ssa-loop-niters.c, looking for when before/after
r266171 code would make a difference in the returned value, the only case it
triggers on is (all types integer(kind=4) i.e. signed 32-bit integer):
code LE_EXPR
iv0->base 0
iv0->step 0
iv1->base -1
iv1->step 1
every_iteration false
The loop starts with:
  <bb 7> [local count: 8656061039]:
  # n_63 = PHI <0(6), _28(23)>
  _19 = n_63 + -1;
and ends with
  _28 = n_63 + 1;
  if (_28 == 4)
    goto <bb 21>; [12.36%]
  else
    goto <bb 23>; [87.64%]

  <bb 23> [local count: 7582748748]:
  goto <bb 7>; [100.00%]
and besides the exit at the end has also:
  <bb 16> [local count: 3548985018]:
  if (_19 > 0)
    goto <bb 17>; [0.04%]
  else
    goto <bb 28>; [99.96%]

  <bb 17> [local count: 1419591]:
  _gfortran_stop_numeric (1, 0);

  <bb 18> [local count: 5106238449]:
  if (_19 < 0)
    goto <bb 19>; [0.04%]
  else
    goto <bb 29>; [99.96%]

  <bb 29> [local count: 5104195957]:
  goto <bb 20>; [100.00%]

  <bb 19> [local count: 2042498]:
  _gfortran_stop_numeric (2, 0);
in the middle, so two other loop exits.  But, neither bb16, nor bb18 are
executed every iteration, if they were, then because _19 is -1 in the first
iteration would always stop 2 and not iterate further.

We have:
  /* If the test is not executed every iteration, wrapping may make the test
     to pass again.
     TODO: the overflow case can be still used as unreliable estimate of upper
     bound.  But we have no API to pass it down to number of iterations code
     and, at present, it will not use it anyway.  */
  if (!every_iteration
      && (!iv0->no_overflow || !iv1->no_overflow
          || code == NE_EXPR || code == EQ_EXPR))
    return false;
at the start, but that doesn't trigger here, because code is not equality
comparison and no_overflow is set on both IVs.  If there would be an overflow,
then maybe it would be right to derive number of iterations from that.
But the condition that returns true is that iv0->base code iv1->base is false,
if that isn't done in every iteration, it means nothing for the number of
iteration analysis.

The following patch works for me:
2019-01-18  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/88044
        * tree-ssa-loop-niter.c (number_of_iterations_cond): If condition
        is false in the first iteration, but !every_iteration, return false
        instead of true with niter->niter zero.

--- gcc/tree-ssa-loop-niter.c.jj        2019-01-10 11:43:02.254577008 +0100
+++ gcc/tree-ssa-loop-niter.c   2019-01-18 19:51:00.245504728 +0100
@@ -1824,6 +1824,8 @@ number_of_iterations_cond (struct loop *
   tree tem = fold_binary (code, boolean_type_node, iv0->base, iv1->base);
   if (tem && integer_zerop (tem))
     {
+      if (!every_iteration)
+       return false;
       niter->niter = build_int_cst (unsigned_type_for (type), 0);
       niter->max = 0;
       return true;

Reply via email to