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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |amker at gcc dot gnu.org

--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> ---
Hmm, for

b.2_2 = (unsigned char) b_lsm.6_13;
_3 = b.2_2 + 3;
_4 = (char) _3;

we analyze the evolution of _4 to {-4, +, 3}_1 (we're using an existing
upper bound for niter of 2).  Eventually the bound we derive for this exit
causes us to disregard the other exit.

That upper bound of niter is from the main loop exit test at CD-DCE time.

Specifically multiple_of_p computes 249 % 3 is 0 and 0 % 3 is 0.  It passes
wrong 'type', which doesn't end up mattering because the code seems
to look for mismatched type & type top/bottom(!?)

    case INTEGER_CST:
      if (TREE_CODE (bottom) != INTEGER_CST
          || integer_zerop (bottom)
          || (TYPE_UNSIGNED (type)
              && (tree_int_cst_sgn (top) < 0
                  || tree_int_cst_sgn (bottom) < 0)))
        return 0;
      return wi::multiple_of_p (wi::to_widest (top), wi::to_widest (bottom),
                                SIGNED);

but then, we do

  if (!niter->control.no_overflow
      && (integer_onep (s)
          || (multiple_of_p (niter_type, fold_convert (niter_type, iv->base),
s,
                             false)
              && multiple_of_p (niter_type, fold_convert (niter_type, final),
s,
                                false))))

so look for the multiple in unsigned arithmetic but then assume overflow
does not happen in signed arithmetic.  That means the changes to
number_of_iterations_ne were wrong.  Note the simplistic fix for
PR100499 regressed some testcases.

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 386d5732ea0..cdf34d81d90 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -14211,8 +14211,8 @@ multiple_of_p (tree type, const_tree top, const_tree
bottom, bool nowrap)
       if (TREE_CODE (bottom) != INTEGER_CST
          || integer_zerop (bottom)
          || (TYPE_UNSIGNED (type)
-             && (tree_int_cst_sgn (top) < 0
-                 || tree_int_cst_sgn (bottom) < 0)))
+             && (tree_int_cst_sign_bit (top)
+                 || tree_int_cst_sign_bit (bottom))))
        return 0;
       return wi::multiple_of_p (wi::to_widest (top), wi::to_widest (bottom),
                                SIGNED);
diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
index 318d10c8fac..b8a628ea829 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -1051,9 +1051,9 @@ number_of_iterations_ne (class loop *loop, tree type,
affine_iv *iv,
      along with condition 1) or 1').  */
   if (!niter->control.no_overflow
       && (integer_onep (s)
-         || (multiple_of_p (type, fold_convert (niter_type, iv->base), s,
+         || (multiple_of_p (niter_type, fold_convert (niter_type, iv->base),
s,
                             false)
-             && multiple_of_p (type, fold_convert (niter_type, final), s,
+             && multiple_of_p (niter_type, fold_convert (niter_type, final),
s,
                                false))))
     {
       tree t, cond, relaxed_cond = boolean_false_node;

fixes this PR but I need to understand what multiple_of_p is doing here ...

Reply via email to