tree-optimization/104519 - adjust PR100499 niter fix

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.

2022-02-15  Richard Biener  <rguenther@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.
This commit is contained in:
Richard Biener 2022-02-15 09:40:59 +01:00
parent c4c0aa6089
commit d8b6da8dd1
3 changed files with 22 additions and 10 deletions

View file

@ -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);

View file

@ -0,0 +1,10 @@
/* { dg-do run } */
signed char a, b;
int main()
{
for (b = -7; b; b += 3)
if (a)
__builtin_abort();
return 0;
}

View file

@ -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;