tree-ssa-loop-niter.c (implies_nonnegative_p): New function.
* tree-ssa-loop-niter.c (implies_nonnegative_p): New function. (derive_constant_upper_bound): Derive more precise upper bound in common cases. Return type changed to double_int. (record_estimate): Reflect the changed return type of derive_constant_upper_bound. * double-int.c (double_int_zext, double_int_sext): Fix. * gcc.dg/tree-ssa/loop-18.c: New test. From-SVN: r114674
This commit is contained in:
parent
ec6c739264
commit
0ad1d5a1d2
@ -1,3 +1,12 @@
|
||||
2006-06-15 Zdenek Dvorak <dvorakz@suse.cz>
|
||||
|
||||
* tree-ssa-loop-niter.c (implies_nonnegative_p): New function.
|
||||
(derive_constant_upper_bound): Derive more precise upper bound in
|
||||
common cases. Return type changed to double_int.
|
||||
(record_estimate): Reflect the changed return type of
|
||||
derive_constant_upper_bound.
|
||||
* double-int.c (double_int_zext, double_int_sext): Fix.
|
||||
|
||||
2006-06-15 Paolo Bonzini <bonzini@gnu.org>
|
||||
|
||||
* configure.ac (CFLAGS): Get them from the toplevel or from the
|
||||
|
@ -72,8 +72,8 @@ double_int_zext (double_int cst, unsigned prec)
|
||||
double_int mask = double_int_mask (prec);
|
||||
double_int r;
|
||||
|
||||
r.low = cst.low & ~mask.low;
|
||||
r.high = cst.high & ~mask.high;
|
||||
r.low = cst.low & mask.low;
|
||||
r.high = cst.high & mask.high;
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -96,13 +96,13 @@ double_int_sext (double_int cst, unsigned prec)
|
||||
}
|
||||
if (((snum >> (prec - 1)) & 1) == 1)
|
||||
{
|
||||
r.low = cst.low | mask.low;
|
||||
r.high = cst.high | mask.high;
|
||||
r.low = cst.low | ~mask.low;
|
||||
r.high = cst.high | ~mask.high;
|
||||
}
|
||||
else
|
||||
{
|
||||
r.low = cst.low & ~mask.low;
|
||||
r.high = cst.high & ~mask.high;
|
||||
r.low = cst.low & mask.low;
|
||||
r.high = cst.high & mask.high;
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -1,3 +1,7 @@
|
||||
2006-06-15 Zdenek Dvorak <dvorakz@suse.cz>
|
||||
|
||||
* gcc.dg/tree-ssa/loop-18.c: New test.
|
||||
|
||||
2006-06-14 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/27665
|
||||
|
24
gcc/testsuite/gcc.dg/tree-ssa/loop-18.c
Normal file
24
gcc/testsuite/gcc.dg/tree-ssa/loop-18.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* A test for # of iterations estimation. We know that I does not overflow,
|
||||
thus we can perform strength reduction (even though the 32-bit variable
|
||||
i is first extended to 64-bit type). */
|
||||
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
/* { dg-do compile { target x86_64-*-* } } */
|
||||
|
||||
unsigned bar(void);
|
||||
|
||||
void foo(unsigned *p, unsigned n)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
p[i] = bar ();
|
||||
}
|
||||
|
||||
/* Check that the memory reference was replaced with MEM, and that there is no
|
||||
multiplication. */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "MEM" 1 "optimized" } } */
|
||||
/* { dg-final { scan-tree-dump-times "\[^\\n\\r\]*= \\* " 0 "optimized" } } */
|
||||
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
@ -1470,22 +1470,137 @@ find_loop_niter_by_eval (struct loop *loop, edge *exit)
|
||||
|
||||
*/
|
||||
|
||||
/* Returns a constant upper bound on the value of expression VAL. The
|
||||
condition ADDITIONAL must be satisfied (for example, if VAL is
|
||||
"(unsigned) n" and ADDITIONAL is "n > 0", then we can derive that
|
||||
VAL is at most (unsigned) MAX_INT).
|
||||
/* Returns true if we can prove that COND ==> VAL >= 0. */
|
||||
|
||||
TODO -- actually do something nontrivial here. */
|
||||
|
||||
static tree
|
||||
derive_constant_upper_bound (tree val, tree additional ATTRIBUTE_UNUSED)
|
||||
static bool
|
||||
implies_nonnegative_p (tree cond, tree val)
|
||||
{
|
||||
tree type = TREE_TYPE (val);
|
||||
tree unsigned_type = unsigned_type_for (type);
|
||||
tree compare;
|
||||
|
||||
if (TREE_CODE (val) != INTEGER_CST)
|
||||
val = upper_bound_in_type (type, type);
|
||||
return fold_convert (unsigned_type, val);
|
||||
if (tree_expr_nonnegative_p (val))
|
||||
return true;
|
||||
|
||||
if (nonzero_p (cond))
|
||||
return false;
|
||||
|
||||
compare = fold_build2 (GE_EXPR,
|
||||
boolean_type_node, val, build_int_cst (type, 0));
|
||||
compare = tree_simplify_using_condition_1 (cond, compare);
|
||||
|
||||
return nonzero_p (compare);
|
||||
}
|
||||
|
||||
/* Returns a constant upper bound on the value of expression VAL. VAL
|
||||
is considered to be unsigned. If its type is signed, its value must
|
||||
be nonnegative.
|
||||
|
||||
The condition ADDITIONAL must be satisfied (for example, if VAL is
|
||||
"(unsigned) n" and ADDITIONAL is "n > 0", then we can derive that
|
||||
VAL is at most (unsigned) MAX_INT). */
|
||||
|
||||
static double_int
|
||||
derive_constant_upper_bound (tree val, tree additional)
|
||||
{
|
||||
tree type = TREE_TYPE (val);
|
||||
tree op0, op1, subtype, maxt;
|
||||
double_int bnd, max, mmax, cst;
|
||||
|
||||
if (INTEGRAL_TYPE_P (type))
|
||||
maxt = TYPE_MAX_VALUE (type);
|
||||
else
|
||||
maxt = upper_bound_in_type (type, type);
|
||||
|
||||
max = tree_to_double_int (maxt);
|
||||
|
||||
switch (TREE_CODE (val))
|
||||
{
|
||||
case INTEGER_CST:
|
||||
return tree_to_double_int (val);
|
||||
|
||||
case NOP_EXPR:
|
||||
case CONVERT_EXPR:
|
||||
op0 = TREE_OPERAND (val, 0);
|
||||
subtype = TREE_TYPE (op0);
|
||||
if (!TYPE_UNSIGNED (subtype)
|
||||
/* If TYPE is also signed, the fact that VAL is nonnegative implies
|
||||
that OP0 is nonnegative. */
|
||||
&& TYPE_UNSIGNED (type)
|
||||
&& !implies_nonnegative_p (additional, op0))
|
||||
{
|
||||
/* If we cannot prove that the casted expression is nonnegative,
|
||||
we cannot establish more useful upper bound than the precision
|
||||
of the type gives us. */
|
||||
return max;
|
||||
}
|
||||
|
||||
/* We now know that op0 is an nonnegative value. Try deriving an upper
|
||||
bound for it. */
|
||||
bnd = derive_constant_upper_bound (op0, additional);
|
||||
|
||||
/* If the bound does not fit in TYPE, max. value of TYPE could be
|
||||
attained. */
|
||||
if (double_int_ucmp (max, bnd) < 0)
|
||||
return max;
|
||||
|
||||
return bnd;
|
||||
|
||||
case PLUS_EXPR:
|
||||
case MINUS_EXPR:
|
||||
op0 = TREE_OPERAND (val, 0);
|
||||
op1 = TREE_OPERAND (val, 1);
|
||||
|
||||
if (TREE_CODE (op1) != INTEGER_CST
|
||||
|| !implies_nonnegative_p (additional, op0))
|
||||
return max;
|
||||
|
||||
/* Canonicalize to OP0 - CST. */
|
||||
cst = tree_to_double_int (op1);
|
||||
if (TREE_CODE (val) == PLUS_EXPR)
|
||||
cst = double_int_neg (cst);
|
||||
|
||||
bnd = derive_constant_upper_bound (op0, additional);
|
||||
|
||||
if (double_int_negative_p (cst))
|
||||
{
|
||||
cst = double_int_neg (cst);
|
||||
/* Avoid CST == 0x80000... */
|
||||
if (double_int_negative_p (cst))
|
||||
return max;;
|
||||
|
||||
/* Case OP0 + CST. We need to check that
|
||||
BND <= MAX (type) - CST. */
|
||||
|
||||
mmax = double_int_add (max, double_int_neg (cst));
|
||||
if (double_int_ucmp (bnd, mmax) > 0)
|
||||
return max;
|
||||
|
||||
return double_int_add (bnd, cst);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (double_int_ucmp (bnd, cst) < 0)
|
||||
return max;
|
||||
|
||||
bnd = double_int_add (bnd, double_int_neg (cst));
|
||||
}
|
||||
|
||||
return bnd;
|
||||
|
||||
case FLOOR_DIV_EXPR:
|
||||
case EXACT_DIV_EXPR:
|
||||
op0 = TREE_OPERAND (val, 0);
|
||||
op1 = TREE_OPERAND (val, 1);
|
||||
if (TREE_CODE (op1) != INTEGER_CST
|
||||
|| tree_int_cst_sign_bit (op1))
|
||||
return max;
|
||||
|
||||
bnd = derive_constant_upper_bound (op0, additional);
|
||||
return double_int_udiv (bnd, tree_to_double_int (op1), FLOOR_DIV_EXPR);
|
||||
|
||||
default:
|
||||
return max;
|
||||
}
|
||||
}
|
||||
|
||||
/* Records that AT_STMT is executed at most BOUND times in LOOP. The
|
||||
@ -1495,7 +1610,9 @@ void
|
||||
record_estimate (struct loop *loop, tree bound, tree additional, tree at_stmt)
|
||||
{
|
||||
struct nb_iter_bound *elt = xmalloc (sizeof (struct nb_iter_bound));
|
||||
tree c_bound = derive_constant_upper_bound (bound, additional);
|
||||
double_int i_bound = derive_constant_upper_bound (bound, additional);
|
||||
tree c_bound = double_int_to_tree (unsigned_type_for (TREE_TYPE (bound)),
|
||||
i_bound);
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user