tree-ssa-loop-niter.c (tree_simplify_using_condition_1): New parameter.

* tree-ssa-loop-niter.c (tree_simplify_using_condition_1): New
	parameter.
	(tree_simplify_using_condition): Ditto.
	(simplify_using_initial_conditions): Ditto.
	(loop_exits_before_overflow): Pass new argument to function
	simplify_using_initial_conditions.  Remove case for type conversions
	simplification.
	* tree-ssa-loop-niter.h (simplify_using_initial_conditions): New
	parameter.
	* tree-scalar-evolution.c (simple_iv): Simplify type conversions
	in iv base using loop initial conditions.

	gcc/testsuite/ChangeLog
	* gcc.dg/tree-ssa/loop-bound-2.c: New test.
	* gcc.dg/tree-ssa/loop-bound-4.c: New test.
	* gcc.dg/tree-ssa/loop-bound-6.c: New test.

From-SVN: r227843
This commit is contained in:
Bin Cheng 2015-09-17 03:08:41 +00:00 committed by Bin Cheng
parent e8ae63bb6c
commit f3c5f3a325
8 changed files with 234 additions and 134 deletions

View File

@ -1,3 +1,17 @@
2015-09-17 Bin Cheng <bin.cheng@arm.com>
* tree-ssa-loop-niter.c (tree_simplify_using_condition_1): New
parameter.
(tree_simplify_using_condition): Ditto.
(simplify_using_initial_conditions): Ditto.
(loop_exits_before_overflow): Pass new argument to function
simplify_using_initial_conditions. Remove case for type conversions
simplification.
* tree-ssa-loop-niter.h (simplify_using_initial_conditions): New
parameter.
* tree-scalar-evolution.c (simple_iv): Simplify type conversions
in iv base using loop initial conditions.
2015-09-16 Jeff Law <law@redhat.com>
PR tree-optimization/47679

View File

@ -1,3 +1,9 @@
2015-09-17 Bin Cheng <bin.cheng@arm.com>
* gcc.dg/tree-ssa/loop-bound-2.c: New test.
* gcc.dg/tree-ssa/loop-bound-4.c: New test.
* gcc.dg/tree-ssa/loop-bound-6.c: New test.
2015-09-16 John Marino <gnugcc@marino.st>
* gfortran.dg/read_dir.f90: XFAIL this testcase on DragonFly.

View File

@ -0,0 +1,23 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
int *a;
int
foo (signed char s, signed char l)
{
signed char i;
int sum = 0;
for (i = s; i < l; i++)
{
sum += a[i];
}
return sum;
}
/* Check loop niter bound information. */
/* { dg-final { scan-tree-dump "bounded by 254" "ivopts" } } */
/* { dg-final { scan-tree-dump-not "bounded by 255" "ivopts" } } */
/* { dg-final { scan-tree-dump-not "zero if " "ivopts" } } */

View File

@ -0,0 +1,23 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
int *a;
int
foo (signed char s, signed char l)
{
signed char i;
int sum = 0;
for (i = s; i > l; i--)
{
sum += a[i];
}
return sum;
}
/* Check loop niter bound information. */
/* { dg-final { scan-tree-dump "bounded by 254" "ivopts" } } */
/* { dg-final { scan-tree-dump-not "bounded by 255" "ivopts" } } */
/* { dg-final { scan-tree-dump-not "zero if " "ivopts" } } */

View File

@ -0,0 +1,23 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
int *a;
int
foo (signed char s)
{
signed char i;
int sum = 0;
for (i = s; i > 0; i--)
{
sum += a[i];
}
return sum;
}
/* Check loop niter bound information. */
/* { dg-final { scan-tree-dump "bounded by 126" "ivopts" } } */
/* { dg-final { scan-tree-dump-not "bounded by 127" "ivopts" } } */
/* { dg-final { scan-tree-dump-not "zero if " "ivopts" } } */

View File

@ -3234,8 +3234,10 @@ bool
simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op,
affine_iv *iv, bool allow_nonconstant_step)
{
tree type, ev;
bool folded_casts;
enum tree_code code;
tree type, ev, base, e, stop;
wide_int extreme;
bool folded_casts, overflow;
iv->base = NULL_TREE;
iv->step = NULL_TREE;
@ -3276,6 +3278,82 @@ simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op,
iv->no_overflow = (!folded_casts && ANY_INTEGRAL_TYPE_P (type)
&& TYPE_OVERFLOW_UNDEFINED (type));
/* Try to simplify iv base:
(signed T) ((unsigned T)base + step) ;; TREE_TYPE (base) == signed T
== (signed T)(unsigned T)base + step
== base + step
If we can prove operation (base + step) doesn't overflow or underflow.
Specifically, we try to prove below conditions are satisfied:
base <= UPPER_BOUND (type) - step ;;step > 0
base >= LOWER_BOUND (type) - step ;;step < 0
This is done by proving the reverse conditions are false using loop's
initial conditions.
The is necessary to make loop niter, or iv overflow analysis easier
for below example:
int foo (int *a, signed char s, signed char l)
{
signed char i;
for (i = s; i < l; i++)
a[i] = 0;
return 0;
}
Note variable I is firstly converted to type unsigned char, incremented,
then converted back to type signed char. */
if (wrto_loop->num != use_loop->num)
return true;
if (!CONVERT_EXPR_P (iv->base) || TREE_CODE (iv->step) != INTEGER_CST)
return true;
type = TREE_TYPE (iv->base);
e = TREE_OPERAND (iv->base, 0);
if (TREE_CODE (e) != PLUS_EXPR
|| TREE_CODE (TREE_OPERAND (e, 1)) != INTEGER_CST
|| !tree_int_cst_equal (iv->step,
fold_convert (type, TREE_OPERAND (e, 1))))
return true;
e = TREE_OPERAND (e, 0);
if (!CONVERT_EXPR_P (e))
return true;
base = TREE_OPERAND (e, 0);
if (!useless_type_conversion_p (type, TREE_TYPE (base)))
return true;
if (tree_int_cst_sign_bit (iv->step))
{
code = LT_EXPR;
extreme = wi::min_value (type);
}
else
{
code = GT_EXPR;
extreme = wi::max_value (type);
}
overflow = false;
extreme = wi::sub (extreme, iv->step, TYPE_SIGN (type), &overflow);
if (overflow)
return true;
e = fold_build2 (code, boolean_type_node, base,
wide_int_to_tree (type, extreme));
stop = (TREE_CODE (base) == SSA_NAME) ? base : NULL;
e = simplify_using_initial_conditions (use_loop, e, stop);
if (!integer_zerop (e))
return true;
if (POINTER_TYPE_P (TREE_TYPE (base)))
code = POINTER_PLUS_EXPR;
else
code = PLUS_EXPR;
iv->base = fold_build2 (code, TREE_TYPE (base), base, iv->step);
return true;
}

View File

@ -1926,7 +1926,7 @@ expand_simple_operations (tree expr, tree stop)
expression (or EXPR unchanged, if no simplification was possible). */
static tree
tree_simplify_using_condition_1 (tree cond, tree expr)
tree_simplify_using_condition_1 (tree cond, tree expr, tree stop)
{
bool changed;
tree e, te, e0, e1, e2, notcond;
@ -1941,17 +1941,17 @@ tree_simplify_using_condition_1 (tree cond, tree expr)
{
changed = false;
e0 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 0));
e0 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 0), stop);
if (TREE_OPERAND (expr, 0) != e0)
changed = true;
e1 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 1));
e1 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 1), stop);
if (TREE_OPERAND (expr, 1) != e1)
changed = true;
if (code == COND_EXPR)
{
e2 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 2));
e2 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 2), stop);
if (TREE_OPERAND (expr, 2) != e2)
changed = true;
}
@ -2014,7 +2014,7 @@ tree_simplify_using_condition_1 (tree cond, tree expr)
return boolean_true_node;
}
te = expand_simple_operations (expr);
te = expand_simple_operations (expr, stop);
/* Check whether COND ==> EXPR. */
notcond = invert_truthvalue (cond);
@ -2038,19 +2038,19 @@ tree_simplify_using_condition_1 (tree cond, tree expr)
the loop do not cause us to fail. */
static tree
tree_simplify_using_condition (tree cond, tree expr)
tree_simplify_using_condition (tree cond, tree expr, tree stop)
{
cond = expand_simple_operations (cond);
cond = expand_simple_operations (cond, stop);
return tree_simplify_using_condition_1 (cond, expr);
return tree_simplify_using_condition_1 (cond, expr, stop);
}
/* Tries to simplify EXPR using the conditions on entry to LOOP.
Returns the simplified expression (or EXPR unchanged, if no
simplification was possible).*/
simplification was possible). */
static tree
simplify_using_initial_conditions (struct loop *loop, tree expr)
tree
simplify_using_initial_conditions (struct loop *loop, tree expr, tree stop)
{
edge e;
basic_block bb;
@ -2082,7 +2082,7 @@ simplify_using_initial_conditions (struct loop *loop, tree expr)
gimple_cond_rhs (stmt));
if (e->flags & EDGE_FALSE_VALUE)
cond = invert_truthvalue (cond);
expr = tree_simplify_using_condition (cond, expr);
expr = tree_simplify_using_condition (cond, expr, stop);
/* Break if EXPR is simplified to const values. */
if (expr && (integer_zerop (expr) || integer_nonzerop (expr)))
break;
@ -4114,137 +4114,68 @@ loop_exits_before_overflow (tree base, tree step,
help of analyzed loop control IV. This is done only for IVs with
constant step because otherwise we don't have the information. */
if (TREE_CODE (step) == INTEGER_CST)
for (civ = loop->control_ivs; civ; civ = civ->next)
{
enum tree_code code;
tree stepped, extreme, civ_type = TREE_TYPE (civ->step);
{
tree stop = (TREE_CODE (base) == SSA_NAME) ? base : NULL;
/* Have to consider type difference because operand_equal_p ignores
that for constants. */
if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (civ_type)
|| element_precision (type) != element_precision (civ_type))
continue;
/* Only consider control IV with same step. */
if (!operand_equal_p (step, civ->step, 0))
continue;
/* Done proving if this is a no-overflow control IV. */
if (operand_equal_p (base, civ->base, 0))
return true;
/* If this is a before stepping control IV, in other words, we have
{civ_base, step} = {base + step, step}
Because civ {base + step, step} doesn't overflow during loop
iterations, {base, step} will not overflow if we can prove the
operation "base + step" does not overflow. Specifically, we try
to prove below conditions are satisfied:
base <= UPPER_BOUND (type) - step ;;step > 0
base >= LOWER_BOUND (type) - step ;;step < 0
by proving the reverse conditions are false using loop's initial
condition. */
if (POINTER_TYPE_P (TREE_TYPE (base)))
code = POINTER_PLUS_EXPR;
else
code = PLUS_EXPR;
stepped = fold_build2 (code, TREE_TYPE (base), base, step);
if (operand_equal_p (stepped, civ->base, 0))
{
if (tree_int_cst_sign_bit (step))
{
code = LT_EXPR;
extreme = lower_bound_in_type (type, type);
}
else
{
code = GT_EXPR;
extreme = upper_bound_in_type (type, type);
}
extreme = fold_build2 (MINUS_EXPR, type, extreme, step);
e = fold_build2 (code, boolean_type_node, base, extreme);
e = simplify_using_initial_conditions (loop, e);
if (integer_zerop (e))
return true;
for (civ = loop->control_ivs; civ; civ = civ->next)
{
enum tree_code code;
tree stepped, extreme, civ_type = TREE_TYPE (civ->step);
/* Have to consider type difference because operand_equal_p ignores
that for constants. */
if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (civ_type)
|| element_precision (type) != element_precision (civ_type))
continue;
}
/* Similar to above, only in this case we have:
/* Only consider control IV with same step. */
if (!operand_equal_p (step, civ->step, 0))
continue;
{civ_base, step} = {(signed T)((unsigned T)base + step), step}
&& TREE_TYPE (civ_base) = signed T.
/* Done proving if this is a no-overflow control IV. */
if (operand_equal_p (base, civ->base, 0))
return true;
We prove that below condition is satisfied:
/* If this is a before stepping control IV, in other words, we have
(signed T)((unsigned T)base + step)
== (signed T)(unsigned T)base + step
== base + step
{civ_base, step} = {base + step, step}
because of exact the same reason as above. This also proves
there is no overflow in the operation "base + step", thus the
induction variable {base, step} during loop iterations.
Because civ {base + step, step} doesn't overflow during loop
iterations, {base, step} will not overflow if we can prove the
operation "base + step" does not overflow. Specifically, we try
to prove below conditions are satisfied:
This is necessary to handle cases as below:
base <= UPPER_BOUND (type) - step ;;step > 0
base >= LOWER_BOUND (type) - step ;;step < 0
int foo (int *a, signed char s, signed char l)
{
signed char i;
for (i = s; i < l; i++)
a[i] = 0;
return 0;
}
by proving the reverse conditions are false using loop's initial
condition. */
if (POINTER_TYPE_P (TREE_TYPE (base)))
code = POINTER_PLUS_EXPR;
else
code = PLUS_EXPR;
The variable I is firstly converted to type unsigned char,
incremented, then converted back to type signed char. */
if (!CONVERT_EXPR_P (civ->base) || TREE_TYPE (civ->base) != type)
continue;
e = TREE_OPERAND (civ->base, 0);
if (TREE_CODE (e) != PLUS_EXPR
|| TREE_CODE (TREE_OPERAND (e, 1)) != INTEGER_CST
|| !operand_equal_p (step,
fold_convert (type,
TREE_OPERAND (e, 1)), 0))
continue;
e = TREE_OPERAND (e, 0);
if (!CONVERT_EXPR_P (e) || !operand_equal_p (e, unsigned_base, 0))
continue;
e = TREE_OPERAND (e, 0);
/* It may still be possible to prove no overflow even if condition
"operand_equal_p (e, base, 0)" isn't satisfied here, like below
example:
e : ssa_var ; unsigned long type
base : (int) ssa_var
unsigned_base : (unsigned int) ssa_var
Unfortunately this is a rare case observed during GCC profiled
bootstrap. See PR66638 for more information.
For now, we just skip the possibility. */
if (!operand_equal_p (e, base, 0))
continue;
if (tree_int_cst_sign_bit (step))
{
code = LT_EXPR;
extreme = lower_bound_in_type (type, type);
}
else
{
code = GT_EXPR;
extreme = upper_bound_in_type (type, type);
}
extreme = fold_build2 (MINUS_EXPR, type, extreme, step);
e = fold_build2 (code, boolean_type_node, base, extreme);
e = simplify_using_initial_conditions (loop, e);
if (integer_zerop (e))
return true;
}
stepped = fold_build2 (code, TREE_TYPE (base), base, step);
if (operand_equal_p (stepped, civ->base, 0))
{
if (tree_int_cst_sign_bit (step))
{
code = LT_EXPR;
extreme = lower_bound_in_type (type, type);
}
else
{
code = GT_EXPR;
extreme = upper_bound_in_type (type, type);
}
extreme = fold_build2 (MINUS_EXPR, type, extreme, step);
e = fold_build2 (code, boolean_type_node, base, extreme);
e = simplify_using_initial_conditions (loop, e, stop);
if (integer_zerop (e))
return true;
}
}
}
return false;
}

View File

@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see
#define GCC_TREE_SSA_LOOP_NITER_H
extern tree expand_simple_operations (tree, tree = NULL);
extern tree simplify_using_initial_conditions (struct loop *,
tree, tree = NULL);
extern bool loop_only_exit_p (const struct loop *, const_edge);
extern bool number_of_iterations_exit (struct loop *, edge,
struct tree_niter_desc *niter, bool,