Commit f3c5f3a3 by Bin Cheng Committed by Bin Cheng

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
parent e8ae63bb
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> 2015-09-16 Jeff Law <law@redhat.com>
PR tree-optimization/47679 PR tree-optimization/47679
......
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> 2015-09-16 John Marino <gnugcc@marino.st>
* gfortran.dg/read_dir.f90: XFAIL this testcase on DragonFly. * gfortran.dg/read_dir.f90: XFAIL this testcase on DragonFly.
......
/* { 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" } } */
/* { 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" } } */
/* { 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" } } */
...@@ -3234,8 +3234,10 @@ bool ...@@ -3234,8 +3234,10 @@ bool
simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op, simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op,
affine_iv *iv, bool allow_nonconstant_step) affine_iv *iv, bool allow_nonconstant_step)
{ {
tree type, ev; enum tree_code code;
bool folded_casts; tree type, ev, base, e, stop;
wide_int extreme;
bool folded_casts, overflow;
iv->base = NULL_TREE; iv->base = NULL_TREE;
iv->step = NULL_TREE; iv->step = NULL_TREE;
...@@ -3276,6 +3278,82 @@ simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op, ...@@ -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) iv->no_overflow = (!folded_casts && ANY_INTEGRAL_TYPE_P (type)
&& TYPE_OVERFLOW_UNDEFINED (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; return true;
} }
......
...@@ -1926,7 +1926,7 @@ expand_simple_operations (tree expr, tree stop) ...@@ -1926,7 +1926,7 @@ expand_simple_operations (tree expr, tree stop)
expression (or EXPR unchanged, if no simplification was possible). */ expression (or EXPR unchanged, if no simplification was possible). */
static tree static tree
tree_simplify_using_condition_1 (tree cond, tree expr) tree_simplify_using_condition_1 (tree cond, tree expr, tree stop)
{ {
bool changed; bool changed;
tree e, te, e0, e1, e2, notcond; tree e, te, e0, e1, e2, notcond;
...@@ -1941,17 +1941,17 @@ tree_simplify_using_condition_1 (tree cond, tree expr) ...@@ -1941,17 +1941,17 @@ tree_simplify_using_condition_1 (tree cond, tree expr)
{ {
changed = false; 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) if (TREE_OPERAND (expr, 0) != e0)
changed = true; 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) if (TREE_OPERAND (expr, 1) != e1)
changed = true; changed = true;
if (code == COND_EXPR) 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) if (TREE_OPERAND (expr, 2) != e2)
changed = true; changed = true;
} }
...@@ -2014,7 +2014,7 @@ tree_simplify_using_condition_1 (tree cond, tree expr) ...@@ -2014,7 +2014,7 @@ tree_simplify_using_condition_1 (tree cond, tree expr)
return boolean_true_node; return boolean_true_node;
} }
te = expand_simple_operations (expr); te = expand_simple_operations (expr, stop);
/* Check whether COND ==> EXPR. */ /* Check whether COND ==> EXPR. */
notcond = invert_truthvalue (cond); notcond = invert_truthvalue (cond);
...@@ -2038,19 +2038,19 @@ tree_simplify_using_condition_1 (tree cond, tree expr) ...@@ -2038,19 +2038,19 @@ tree_simplify_using_condition_1 (tree cond, tree expr)
the loop do not cause us to fail. */ the loop do not cause us to fail. */
static tree 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. /* Tries to simplify EXPR using the conditions on entry to LOOP.
Returns the simplified expression (or EXPR unchanged, if no Returns the simplified expression (or EXPR unchanged, if no
simplification was possible).*/ simplification was possible). */
static tree tree
simplify_using_initial_conditions (struct loop *loop, tree expr) simplify_using_initial_conditions (struct loop *loop, tree expr, tree stop)
{ {
edge e; edge e;
basic_block bb; basic_block bb;
...@@ -2082,7 +2082,7 @@ simplify_using_initial_conditions (struct loop *loop, tree expr) ...@@ -2082,7 +2082,7 @@ simplify_using_initial_conditions (struct loop *loop, tree expr)
gimple_cond_rhs (stmt)); gimple_cond_rhs (stmt));
if (e->flags & EDGE_FALSE_VALUE) if (e->flags & EDGE_FALSE_VALUE)
cond = invert_truthvalue (cond); 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. */ /* Break if EXPR is simplified to const values. */
if (expr && (integer_zerop (expr) || integer_nonzerop (expr))) if (expr && (integer_zerop (expr) || integer_nonzerop (expr)))
break; break;
...@@ -4114,6 +4114,9 @@ loop_exits_before_overflow (tree base, tree step, ...@@ -4114,6 +4114,9 @@ loop_exits_before_overflow (tree base, tree step,
help of analyzed loop control IV. This is done only for IVs with help of analyzed loop control IV. This is done only for IVs with
constant step because otherwise we don't have the information. */ constant step because otherwise we don't have the information. */
if (TREE_CODE (step) == INTEGER_CST) if (TREE_CODE (step) == INTEGER_CST)
{
tree stop = (TREE_CODE (base) == SSA_NAME) ? base : NULL;
for (civ = loop->control_ivs; civ; civ = civ->next) for (civ = loop->control_ivs; civ; civ = civ->next)
{ {
enum tree_code code; enum tree_code code;
...@@ -4167,83 +4170,11 @@ loop_exits_before_overflow (tree base, tree step, ...@@ -4167,83 +4170,11 @@ loop_exits_before_overflow (tree base, tree step,
} }
extreme = fold_build2 (MINUS_EXPR, type, extreme, step); extreme = fold_build2 (MINUS_EXPR, type, extreme, step);
e = fold_build2 (code, boolean_type_node, base, extreme); e = fold_build2 (code, boolean_type_node, base, extreme);
e = simplify_using_initial_conditions (loop, e); e = simplify_using_initial_conditions (loop, e, stop);
if (integer_zerop (e)) if (integer_zerop (e))
return true; return true;
continue;
} }
/* Similar to above, only in this case we have:
{civ_base, step} = {(signed T)((unsigned T)base + step), step}
&& TREE_TYPE (civ_base) = signed T.
We prove that below condition is satisfied:
(signed T)((unsigned T)base + step)
== (signed T)(unsigned T)base + step
== base + 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.
This is necessary to handle cases as below:
int foo (int *a, signed char s, signed char l)
{
signed char i;
for (i = s; i < l; i++)
a[i] = 0;
return 0;
} }
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;
} }
return false; return false;
......
...@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see
#define GCC_TREE_SSA_LOOP_NITER_H #define GCC_TREE_SSA_LOOP_NITER_H
extern tree expand_simple_operations (tree, tree = NULL); 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 loop_only_exit_p (const struct loop *, const_edge);
extern bool number_of_iterations_exit (struct loop *, edge, extern bool number_of_iterations_exit (struct loop *, edge,
struct tree_niter_desc *niter, bool, struct tree_niter_desc *niter, bool,
......
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