The following adjusts the PR100499 niter fix to use the appropriate types when checking whether the difference between the final and base values of the IV are a multiple of the step. It also gets rid of an always false condition in multiple_of_p which lead me to a wrong solution first.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. 2022-02-15 Richard Biener <rguent...@suse.de> PR tree-optimization/104519 * fold-const.cc (multiple_of_p): Remove never true condition. * tree-ssa-loop-niter.cc (number_of_iterations_ne): Use the appropriate types for determining whether the difference of final and base is a multiple of the step. * gcc.dg/torture/pr104519.c: New testcase. --- gcc/fold-const.cc | 6 +----- gcc/tree-ssa-loop-niter.cc | 16 +++++++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 386d5732ea0..9d9939642f6 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -14208,11 +14208,7 @@ multiple_of_p (tree type, const_tree top, const_tree bottom, bool nowrap) && multiple_of_p (type, TREE_OPERAND (top, 2), bottom, nowrap)); 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))) + if (TREE_CODE (bottom) != INTEGER_CST || integer_zerop (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..9bb5097379b 100644 --- a/gcc/tree-ssa-loop-niter.cc +++ b/gcc/tree-ssa-loop-niter.cc @@ -1048,13 +1048,19 @@ number_of_iterations_ne (class loop *loop, tree type, affine_iv *iv, which the loop exits immediately, and the iv does not overflow. Also note, we prove condition 2) by checking base and final seperately - along with condition 1) or 1'). */ + along with condition 1) or 1'). Since we ensure the difference + computation of c does not wrap with cond below and the adjusted s + will fit a signed type as well as an unsigned we can safely do + this using the type of the IV if it is not pointer typed. */ + tree mtype = type; + if (POINTER_TYPE_P (type)) + mtype = niter_type; if (!niter->control.no_overflow && (integer_onep (s) - || (multiple_of_p (type, fold_convert (niter_type, iv->base), s, - false) - && multiple_of_p (type, fold_convert (niter_type, final), s, - false)))) + || (multiple_of_p (mtype, fold_convert (mtype, iv->base), + fold_convert (mtype, s), false) + && multiple_of_p (mtype, fold_convert (mtype, final), + fold_convert (mtype, s), false)))) { tree t, cond, relaxed_cond = boolean_false_node; -- 2.34.1