mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
d23c0a32ab
commit
7190fdc190
|
|
@ -1,3 +1,10 @@
|
||||||
|
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>
|
2013-11-07 Richard Biener <rguenther@suse.de>
|
||||||
Jakub Jelinek <jakub@redhat.com>
|
Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
2013-11-07 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_1.c: Add -fno-tree-vrp to dg-options.
|
||||||
* gcc.dg/unroll_2.c: Likewise.
|
* gcc.dg/unroll_2.c: Likewise.
|
||||||
* gcc.dg/unroll_3.c: Likewise.
|
* gcc.dg/unroll_3.c: Likewise.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* { 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 "diagnostic-core.h"
|
||||||
#include "tree-inline.h"
|
#include "tree-inline.h"
|
||||||
#include "tree-pass.h"
|
#include "tree-pass.h"
|
||||||
|
#include "tree-ssanames.h"
|
||||||
|
|
||||||
|
|
||||||
#define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
|
#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. */
|
in TYPE to MIN and MAX. */
|
||||||
|
|
||||||
static void
|
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)
|
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 the expression is a constant, we know its value exactly. */
|
||||||
if (integer_zerop (var))
|
if (integer_zerop (var))
|
||||||
{
|
{
|
||||||
|
|
@ -130,9 +134,73 @@ determine_value_range (tree type, tree var, mpz_t off,
|
||||||
return;
|
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
|
/* If the computation may wrap, we know nothing about the value, except for
|
||||||
the range of the type. */
|
the range of the type. */
|
||||||
get_type_static_bounds (type, min, max);
|
|
||||||
if (!nowrap_type_p (type))
|
if (!nowrap_type_p (type))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -405,8 +473,8 @@ bound_difference (struct loop *loop, tree x, tree y, bounds *bnds)
|
||||||
mpz_init (maxx);
|
mpz_init (maxx);
|
||||||
mpz_init (miny);
|
mpz_init (miny);
|
||||||
mpz_init (maxy);
|
mpz_init (maxy);
|
||||||
determine_value_range (type, varx, offx, minx, maxx);
|
determine_value_range (loop, type, varx, offx, minx, maxx);
|
||||||
determine_value_range (type, vary, offy, miny, maxy);
|
determine_value_range (loop, type, vary, offy, miny, maxy);
|
||||||
|
|
||||||
mpz_sub (bnds->below, minx, maxy);
|
mpz_sub (bnds->below, minx, maxy);
|
||||||
mpz_sub (bnds->up, maxx, miny);
|
mpz_sub (bnds->up, maxx, miny);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue