tree-scalar-evolution.c (iv_can_overflow_p): New function.

* tree-scalar-evolution.c (iv_can_overflow_p): New function.
	(simple_iv): Use it.

	* gcc.dg/tree-ssa/scev-14.c: new testcase.

From-SVN: r238012
This commit is contained in:
Jan Hubicka 2016-07-05 18:17:12 +02:00 committed by Jan Hubicka
parent 341c5337bf
commit 1e3d54b429
4 changed files with 109 additions and 0 deletions

View File

@ -1,3 +1,8 @@
2016-07-05 Jan Hubicka <jh@suse.cz>
* tree-scalar-evolution.c (iv_can_overflow_p): New function.
(simple_iv): Use it.
2016-07-05 Jan Hubicka <jh@suse.cz>
* tree-ssa-loop-niter.c (nowrap_type_p): Use ANY_INTEGRAL_TYPE_P.

View File

@ -1,3 +1,7 @@
2016-07-05 Jan Hubicka <jh@suse.cz>
* gcc.dg/tree-ssa/scev-14.c: new testcase.
2016-07-05 David Malcolm <dmalcolm@redhat.com>
PR c++/62314

View File

@ -0,0 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
int a[100];
void t(unsigned int n)
{
unsigned int i;
for (i=0; i<n; i++)
a[i]++;
}
/* { dg-final { scan-tree-dump "Overflowness wrto loop niter: No-overflow" "ivopts" } } */
/* { dg-final { scan-tree-dump-not "Overflowness wrto loop niter: Overflow" "ivopts" } } */

View File

@ -3309,6 +3309,91 @@ scev_reset (void)
}
}
/* Return true if the IV calculation in TYPE can overflow based on the knowledge
of the upper bound on the number of iterations of LOOP, the BASE and STEP
of IV.
We do not use information whether TYPE can overflow so it is safe to
use this test even for derived IVs not computed every iteration or
hypotetical IVs to be inserted into code. */
static bool
iv_can_overflow_p (struct loop *loop, tree type, tree base, tree step)
{
widest_int nit;
wide_int base_min, base_max, step_min, step_max, type_min, type_max;
signop sgn = TYPE_SIGN (type);
if (integer_zerop (step))
return false;
if (TREE_CODE (base) == INTEGER_CST)
base_min = base_max = base;
else if (TREE_CODE (base) == SSA_NAME
&& INTEGRAL_TYPE_P (TREE_TYPE (base))
&& get_range_info (base, &base_min, &base_max) == VR_RANGE)
;
else
return true;
if (TREE_CODE (step) == INTEGER_CST)
step_min = step_max = step;
else if (TREE_CODE (step) == SSA_NAME
&& INTEGRAL_TYPE_P (TREE_TYPE (step))
&& get_range_info (step, &step_min, &step_max) == VR_RANGE)
;
else
return true;
if (!get_max_loop_iterations (loop, &nit))
return true;
type_min = wi::min_value (type);
type_max = wi::max_value (type);
/* Just sanity check that we don't see values out of the range of the type.
In this case the arithmetics bellow would overflow. */
gcc_checking_assert (wi::ge_p (base_min, type_min, sgn)
&& wi::le_p (base_max, type_max, sgn));
/* Account the possible increment in the last ieration. */
bool overflow = false;
nit = wi::add (nit, 1, SIGNED, &overflow);
if (overflow)
return true;
/* NIT is typeless and can exceed the precision of the type. In this case
overflow is always possible, because we know STEP is non-zero. */
if (wi::min_precision (nit, UNSIGNED) > TYPE_PRECISION (type))
return true;
wide_int nit2 = wide_int::from (nit, TYPE_PRECISION (type), UNSIGNED);
/* If step can be positive, check that nit*step <= type_max-base.
This can be done by unsigned arithmetic and we only need to watch overflow
in the multiplication. The right hand side can always be represented in
the type. */
if (sgn == UNSIGNED || !wi::neg_p (step_max))
{
bool overflow = false;
if (wi::gtu_p (wi::mul (step_max, nit2, UNSIGNED, &overflow),
type_max - base_max)
|| overflow)
return true;
}
/* If step can be negative, check that nit*(-step) <= base_min-type_min. */
if (sgn == SIGNED && wi::neg_p (step_min))
{
bool overflow = false, overflow2 = false;
if (wi::gtu_p (wi::mul (wi::neg (step_min, &overflow2),
nit2, UNSIGNED, &overflow),
base_min - type_min)
|| overflow || overflow2)
return true;
}
return false;
}
/* Checks whether use of OP in USE_LOOP behaves as a simple affine iv with
respect to WRTO_LOOP and returns its base and step in IV if possible
(see analyze_scalar_evolution_in_loop for more details on USE_LOOP
@ -3377,6 +3462,10 @@ simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op,
iv->no_overflow = !folded_casts && nowrap_type_p (type);
if (!iv->no_overflow
&& !iv_can_overflow_p (wrto_loop, type, iv->base, iv->step))
iv->no_overflow = true;
/* Try to simplify iv base:
(signed T) ((unsigned T)base + step) ;; TREE_TYPE (base) == signed T