Commit 7190fdc1 by Jakub Jelinek Committed by Jakub Jelinek

tree-ssa-loop-niter.c: Include tree-ssanames.h.

	* tree-ssa-loop-niter.c: Include tree-ssanames.h.
	(determine_value_range): Add loop argument.  Use get_range_info to
	improve range.
	(bound_difference): Adjust caller.

	* gcc.dg/tree-ssa/loop-39.c: New test.

From-SVN: r204516
parent d23c0a32
2013-11-07 Jakub Jelinek <jakub@redhat.com>
* tree-ssa-loop-niter.c: Include tree-ssanames.h.
(determine_value_range): Add loop argument. Use get_range_info to
improve range.
(bound_difference): Adjust caller.
2013-11-07 Richard Biener <rguenther@suse.de>
Jakub Jelinek <jakub@redhat.com>
2013-11-07 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/tree-ssa/loop-39.c: New test.
* gcc.dg/unroll_1.c: Add -fno-tree-vrp to dg-options.
* gcc.dg/unroll_2.c: Likewise.
* gcc.dg/unroll_3.c: Likewise.
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-sccp-details" } */
int
foo (unsigned int n)
{
int i, r = 1;
if (n > 0)
{
asm ("");
if (n < 10)
{
asm ("");
do
{
--n;
r *= 2;
}
while (n > 0);
}
}
return r + n;
}
/* { dg-final { scan-tree-dump "# of iterations \[^\n\r]*, bounded by 8" "sccp" } } */
/* { dg-final { cleanup-tree-dump "sccp" } } */
......@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "tree-inline.h"
#include "tree-pass.h"
#include "tree-ssanames.h"
#define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
......@@ -119,9 +120,12 @@ split_to_var_and_offset (tree expr, tree *var, mpz_t offset)
in TYPE to MIN and MAX. */
static void
determine_value_range (tree type, tree var, mpz_t off,
determine_value_range (struct loop *loop, tree type, tree var, mpz_t off,
mpz_t min, mpz_t max)
{
double_int minv, maxv;
enum value_range_type rtype = VR_VARYING;
/* If the expression is a constant, we know its value exactly. */
if (integer_zerop (var))
{
......@@ -130,9 +134,73 @@ determine_value_range (tree type, tree var, mpz_t off,
return;
}
get_type_static_bounds (type, min, max);
/* See if we have some range info from VRP. */
if (TREE_CODE (var) == SSA_NAME && INTEGRAL_TYPE_P (type))
{
edge e = loop_preheader_edge (loop);
gimple_stmt_iterator gsi;
/* Either for VAR itself... */
rtype = get_range_info (var, &minv, &maxv);
/* Or for PHI results in loop->header where VAR is used as
PHI argument from the loop preheader edge. */
for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple phi = gsi_stmt (gsi);
double_int minc, maxc;
if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var
&& (get_range_info (gimple_phi_result (phi), &minc, &maxc)
== VR_RANGE))
{
if (rtype != VR_RANGE)
{
rtype = VR_RANGE;
minv = minc;
maxv = maxc;
}
else
{
minv = minv.max (minc, TYPE_UNSIGNED (type));
maxv = maxv.min (maxc, TYPE_UNSIGNED (type));
gcc_assert (minv.cmp (maxv, TYPE_UNSIGNED (type)) <= 0);
}
}
}
if (rtype == VR_RANGE)
{
mpz_t minm, maxm;
gcc_assert (minv.cmp (maxv, TYPE_UNSIGNED (type)) <= 0);
mpz_init (minm);
mpz_init (maxm);
mpz_set_double_int (minm, minv, TYPE_UNSIGNED (type));
mpz_set_double_int (maxm, maxv, TYPE_UNSIGNED (type));
mpz_add (minm, minm, off);
mpz_add (maxm, maxm, off);
/* If the computation may not wrap or off is zero, then this
is always fine. If off is negative and minv + off isn't
smaller than type's minimum, or off is positive and
maxv + off isn't bigger than type's maximum, use the more
precise range too. */
if (nowrap_type_p (type)
|| mpz_sgn (off) == 0
|| (mpz_sgn (off) < 0 && mpz_cmp (minm, min) >= 0)
|| (mpz_sgn (off) > 0 && mpz_cmp (maxm, max) <= 0))
{
mpz_set (min, minm);
mpz_set (max, maxm);
mpz_clear (minm);
mpz_clear (maxm);
return;
}
mpz_clear (minm);
mpz_clear (maxm);
}
}
/* If the computation may wrap, we know nothing about the value, except for
the range of the type. */
get_type_static_bounds (type, min, max);
if (!nowrap_type_p (type))
return;
......@@ -405,8 +473,8 @@ bound_difference (struct loop *loop, tree x, tree y, bounds *bnds)
mpz_init (maxx);
mpz_init (miny);
mpz_init (maxy);
determine_value_range (type, varx, offx, minx, maxx);
determine_value_range (type, vary, offy, miny, maxy);
determine_value_range (loop, type, varx, offx, minx, maxx);
determine_value_range (loop, type, vary, offy, miny, maxy);
mpz_sub (bnds->below, minx, maxy);
mpz_sub (bnds->up, maxx, miny);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment