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 ...