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

--- Comment #10 from Richard Biener <rguenth at gcc dot gnu.org> ---
And we compute the "noloop" condition as

        noloop = fold_build2 (GT_EXPR, boolean_type_node,
                              iv0->base,
                              fold_build2 (PLUS_EXPR, type1,
                                           iv1->base, tmod));

where tmod is 47 (that's STEP - DELTA %[fl] STEP in the IVs type - mind,
DELTA is unsigned!).

So the noloop condition is

(long int) ((int) d.3_5 + 40) + 1 >= (long int) ((int) d.3_5 + 76)

which is wrong, it should compute true.

What's fishy here is the negative DELTA (so there is IV overflow in that
compute) and then the use of unsigned FLOOR_MOD to compute the adjustment
for the final value and the noloop condition (I'm not sure why that needs
the mod adjustment at all?!).

I'm going to test the naiive

diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
index 9518bf969cd..1be4b552206 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -1200,17 +1200,6 @@ number_of_iterations_lt_to_ne (tree type, affine_iv
*iv0,
 affine_iv *iv1,
          if (integer_zerop (assumption))
            return false;
        }
-      if (mpz_cmp (mmod, bnds->below) < 0)
-       noloop = boolean_false_node;
-      else if (POINTER_TYPE_P (type))
-       noloop = fold_build2 (GT_EXPR, boolean_type_node,
-                             iv0->base,
-                             fold_build_pointer_plus (iv1->base, tmod));
-      else
-       noloop = fold_build2 (GT_EXPR, boolean_type_node,
-                             iv0->base,
-                             fold_build2 (PLUS_EXPR, type1,
-                                          iv1->base, tmod));
     }
   else
     {
@@ -1226,21 +1215,15 @@ number_of_iterations_lt_to_ne (tree type, affine_iv
*iv0, affine_iv *iv1,
          if (integer_zerop (assumption))
            return false;
        }
-      if (mpz_cmp (mmod, bnds->below) < 0)
-       noloop = boolean_false_node;
-      else if (POINTER_TYPE_P (type))
-       noloop = fold_build2 (GT_EXPR, boolean_type_node,
-                             fold_build_pointer_plus (iv0->base,
-                                                      fold_build1
(NEGATE_EXPR,
-                                                                   type1,
tmod)),
-                             iv1->base);
-      else
-       noloop = fold_build2 (GT_EXPR, boolean_type_node,
-                             fold_build2 (MINUS_EXPR, type1,
-                                          iv0->base, tmod),
-                             iv1->base);
     }

+  /* IV0 < IV1 does not loop if IV0->base >= IV1->base.  */
+  if (mpz_cmp (mmod, bnds->below) < 0)
+    noloop = boolean_false_node;
+  else
+    noloop = fold_build2 (GE_EXPR, boolean_type_node,
+                         iv0->base, iv1->base);
+
   if (!integer_nonzerop (assumption))
     niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
                                      niter->assumptions,

Reply via email to