Commit 279f3eb5 by Jeff Law Committed by Richard Biener

re PR tree-optimization/15911 (VRP/DOM does not like TRUTH_AND_EXPR)

2006-10-22  Jeff Law  <law@redhat.com>
	Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/15911
	* tree-vrp.c (extract_code_and_val_from_cond): New function.
	(register_edge_assert_for_1): Likewise.
	(register_edge_assert_for): Handle &&/&/||/| in conditionals.
	(find_conditional_asserts): Adjust for new function signature.
	(find_assert_locations): Likewise.

	* gcc.dg/tree-ssa/vrp30.c: New testcase.

Co-Authored-By: Richard Guenther <rguenther@suse.de>

From-SVN: r117960
parent c0546edb
2006-10-22 Jeff Law <law@redhat.com>
Richard Guenther <rguenther@suse.de>
PR tree-optimization/15911
* tree-vrp.c (extract_code_and_val_from_cond): New function.
(register_edge_assert_for_1): Likewise.
(register_edge_assert_for): Handle &&/&/||/| in conditionals.
(find_conditional_asserts): Adjust for new function signature.
(find_assert_locations): Likewise.
2006-10-22 H.J. Lu <hongjiu.lu@intel.com> 2006-10-22 H.J. Lu <hongjiu.lu@intel.com>
* config/i386/tmmintrin.h: Remove the duplicated content. * config/i386/tmmintrin.h: Remove the duplicated content.
......
2006-10-22 Jeff Law <law@redhat.com>
Richard Guenther <rguenther@suse.de>
PR tree-optimization/15911
* gcc.dg/tree-ssa/vrp30.c: New testcase.
2006-10-22 Nathan Sidwell <nathan@codesourcery.com> 2006-10-22 Nathan Sidwell <nathan@codesourcery.com>
PR c++/20647 PR c++/20647
/* { dg-do link } */
/* { dg-options "-O2" } */
extern int link_error (int);
int tst2 (int x, int y)
{
/* VRP should be able to extract range information for
x and y out of this TRUTH_AND_EXPR. */
if ((x > 5555) && (y < 6666))
{
if (x > 5555)
if (y < 6666)
return 1111;
else
return link_error (2222);
else
if (y < 6666)
return link_error (3333);
else
return link_error (4444);
}
else
return 0;
}
int main()
{
return 0;
}
...@@ -2688,39 +2688,20 @@ register_new_assert_for (tree name, ...@@ -2688,39 +2688,20 @@ register_new_assert_for (tree name,
bitmap_set_bit (need_assert_for, SSA_NAME_VERSION (name)); bitmap_set_bit (need_assert_for, SSA_NAME_VERSION (name));
} }
/* COND is a predicate which uses NAME. Extract a suitable test code
and value and store them into *CODE_P and *VAL_P so the predicate
is normalized to NAME *CODE_P *VAL_P.
/* Try to register an edge assertion for SSA name NAME on edge E for If no extraction was possible, return FALSE, otherwise return TRUE.
the conditional jump pointed to by SI. Return true if an assertion
for NAME could be registered. */ If INVERT is true, then we invert the result stored into *CODE_P. */
static bool static bool
register_edge_assert_for (tree name, edge e, block_stmt_iterator si) extract_code_and_val_from_cond (tree name, tree cond, bool invert,
enum tree_code *code_p, tree *val_p)
{ {
tree val, stmt;
enum tree_code comp_code; enum tree_code comp_code;
tree val;
stmt = bsi_stmt (si);
/* Do not attempt to infer anything in names that flow through
abnormal edges. */
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
return false;
/* If NAME was not found in the sub-graph reachable from E, then
there's nothing to do. */
if (!TEST_BIT (found_in_subgraph, SSA_NAME_VERSION (name)))
return false;
/* We found a use of NAME in the sub-graph rooted at E->DEST.
Register an assertion for NAME according to the value that NAME
takes on edge E. */
if (TREE_CODE (stmt) == COND_EXPR)
{
/* If BB ends in a COND_EXPR then NAME then we should insert
the original predicate on EDGE_TRUE_VALUE and the
opposite predicate on EDGE_FALSE_VALUE. */
tree cond = COND_EXPR_COND (stmt);
bool is_else_edge = (e->flags & EDGE_FALSE_VALUE) != 0;
/* Predicates may be a single SSA name or NAME OP VAL. */ /* Predicates may be a single SSA name or NAME OP VAL. */
if (cond == name) if (cond == name)
...@@ -2729,7 +2710,7 @@ register_edge_assert_for (tree name, edge e, block_stmt_iterator si) ...@@ -2729,7 +2710,7 @@ register_edge_assert_for (tree name, edge e, block_stmt_iterator si)
case we create the predicate NAME == true or case we create the predicate NAME == true or
NAME == false accordingly. */ NAME == false accordingly. */
comp_code = EQ_EXPR; comp_code = EQ_EXPR;
val = (is_else_edge) ? boolean_false_node : boolean_true_node; val = invert ? boolean_false_node : boolean_true_node;
} }
else else
{ {
...@@ -2751,64 +2732,244 @@ register_edge_assert_for (tree name, edge e, block_stmt_iterator si) ...@@ -2751,64 +2732,244 @@ register_edge_assert_for (tree name, edge e, block_stmt_iterator si)
val = TREE_OPERAND (cond, 1); val = TREE_OPERAND (cond, 1);
} }
/* If we are inserting the assertion on the ELSE edge, we /* Invert the comparison code as necessary. */
need to invert the sign comparison. */ if (invert)
if (is_else_edge)
comp_code = invert_tree_comparison (comp_code, 0); comp_code = invert_tree_comparison (comp_code, 0);
/* Do not register always-false predicates. FIXME, this /* VRP does not handle float types. */
works around a limitation in fold() when dealing with if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (val)))
return false;
/* Do not register always-false predicates.
FIXME: this works around a limitation in fold() when dealing with
enumerations. Given 'enum { N1, N2 } x;', fold will not enumerations. Given 'enum { N1, N2 } x;', fold will not
fold 'if (x > N2)' to 'if (0)'. */ fold 'if (x > N2)' to 'if (0)'. */
if ((comp_code == GT_EXPR || comp_code == LT_EXPR) if ((comp_code == GT_EXPR || comp_code == LT_EXPR)
&& (INTEGRAL_TYPE_P (TREE_TYPE (val)) && INTEGRAL_TYPE_P (TREE_TYPE (val)))
|| SCALAR_FLOAT_TYPE_P (TREE_TYPE (val))))
{ {
tree min = TYPE_MIN_VALUE (TREE_TYPE (val)); tree min = TYPE_MIN_VALUE (TREE_TYPE (val));
tree max = TYPE_MAX_VALUE (TREE_TYPE (val)); tree max = TYPE_MAX_VALUE (TREE_TYPE (val));
if (comp_code == GT_EXPR && compare_values (val, max) == 0) if (comp_code == GT_EXPR
&& (!max
|| compare_values (val, max) == 0))
return false; return false;
if (comp_code == LT_EXPR && compare_values (val, min) == 0) if (comp_code == LT_EXPR
&& (!min
|| compare_values (val, min) == 0))
return false; return false;
} }
} }
*code_p = comp_code;
*val_p = val;
return true;
}
/* OP is an operand of a truth value expression which is known to have
a particular value. Register any asserts for OP and for any
operands in OP's defining statement.
If CODE is EQ_EXPR, then we want to register OP is zero (false),
if CODE is NE_EXPR, then we want to register OP is nonzero (true). */
static bool
register_edge_assert_for_1 (tree op, enum tree_code code,
edge e, block_stmt_iterator bsi)
{
bool invert, retval = false;
tree op_def, rhs, val;
/* We only care about SSA_NAMEs. */
if (TREE_CODE (op) != SSA_NAME)
return false;
/* We know that OP will have a zero or nonzero value. If OP is used
more than once go ahead and register an assert for OP.
The FOUND_IN_SUBGRAPH support is not helpful in this situation as
it will always be set for OP (because OP is used in a COND_EXPR in
the subgraph). */
if (!has_single_use (op))
{
val = build_int_cst (TREE_TYPE (op), 0);
register_new_assert_for (op, code, val, NULL, e, bsi);
retval = true;
} }
else
/* Now look at how OP is set. If it's set from a comparison,
a truth operation or some bit operations, then we may be able
to register information about the operands of that assignment. */
op_def = SSA_NAME_DEF_STMT (op);
if (TREE_CODE (op_def) != MODIFY_EXPR)
return retval;
invert = (code == EQ_EXPR ? true : false);
rhs = TREE_OPERAND (op_def, 1);
if (COMPARISON_CLASS_P (rhs))
{ {
/* FIXME. Handle SWITCH_EXPR. */ tree op0 = TREE_OPERAND (rhs, 0);
gcc_unreachable (); tree op1 = TREE_OPERAND (rhs, 1);
/* Conditionally register an assert for each SSA_NAME in the
comparison. */
if (TREE_CODE (op0) == SSA_NAME
&& !has_single_use (op0)
&& extract_code_and_val_from_cond (op0, rhs,
invert, &code, &val))
{
register_new_assert_for (op0, code, val, NULL, e, bsi);
retval = true;
}
/* Similarly for the second operand of the comparison. */
if (TREE_CODE (op1) == SSA_NAME
&& !has_single_use (op1)
&& extract_code_and_val_from_cond (op1, rhs,
invert, &code, &val))
{
register_new_assert_for (op1, code, val, NULL, e, bsi);
retval = true;
} }
}
else if ((code == NE_EXPR
&& (TREE_CODE (rhs) == TRUTH_AND_EXPR
|| TREE_CODE (rhs) == BIT_AND_EXPR))
|| (code == EQ_EXPR
&& (TREE_CODE (rhs) == TRUTH_OR_EXPR
|| TREE_CODE (rhs) == BIT_IOR_EXPR)))
{
/* Recurse on each operand. */
retval |= register_edge_assert_for_1 (TREE_OPERAND (rhs, 0),
code, e, bsi);
retval |= register_edge_assert_for_1 (TREE_OPERAND (rhs, 1),
code, e, bsi);
}
else if (TREE_CODE (rhs) == TRUTH_NOT_EXPR)
{
invert = !invert;
/* Recurse, flipping the tense of INVERT. */
retval |= register_edge_assert_for_1 (TREE_OPERAND (rhs, 0),
invert, e, bsi);
}
else if (TREE_CODE (rhs) == SSA_NAME)
{
/* Recurse through the copy, the tense of INVERT remains
unchanged. */
retval |= register_edge_assert_for_1 (rhs, code, e, bsi);
}
else if (TREE_CODE (rhs) == NOP_EXPR
|| TREE_CODE (rhs) == CONVERT_EXPR
|| TREE_CODE (rhs) == VIEW_CONVERT_EXPR
|| TREE_CODE (rhs) == NON_LVALUE_EXPR)
{
/* Recurse through the type conversion, the tense of INVERT
remains unchanged. */
retval |= register_edge_assert_for_1 (TREE_OPERAND (rhs, 0),
code, e, bsi);
}
return retval;
}
/* Try to register an edge assertion for SSA name NAME on edge E for
the condition COND contributing to the conditional jump pointed to by SI.
Return true if an assertion for NAME could be registered. */
static bool
register_edge_assert_for (tree name, edge e, block_stmt_iterator si, tree cond)
{
tree val;
enum tree_code comp_code;
bool retval = false;
bool is_else_edge = (e->flags & EDGE_FALSE_VALUE) != 0;
/* Do not attempt to infer anything in names that flow through
abnormal edges. */
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
return false;
if (!extract_code_and_val_from_cond (name, cond, is_else_edge,
&comp_code, &val))
return false;
/* Only register an ASSERT_EXPR if NAME was found in the sub-graph
reachable from E. */
if (TEST_BIT (found_in_subgraph, SSA_NAME_VERSION (name)))
{
register_new_assert_for (name, comp_code, val, NULL, e, si); register_new_assert_for (name, comp_code, val, NULL, e, si);
return true; retval = true;
}
/* If COND is effectively an equality test of an SSA_NAME against
the value zero or one, then we may be able to assert values
for SSA_NAMEs which flow into COND. */
/* In the case of NAME == 1 or NAME != 0, for TRUTH_AND_EXPR defining
statement of NAME we can assert both operands of the TRUTH_AND_EXPR
have non-zero value. */
if (((comp_code == EQ_EXPR && integer_onep (val))
|| (comp_code == NE_EXPR && integer_zerop (val))))
{
tree def_stmt = SSA_NAME_DEF_STMT (name);
if (TREE_CODE (def_stmt) == MODIFY_EXPR
&& (TREE_CODE (TREE_OPERAND (def_stmt, 1)) == TRUTH_AND_EXPR
|| TREE_CODE (TREE_OPERAND (def_stmt, 1)) == BIT_AND_EXPR))
{
tree op0 = TREE_OPERAND (TREE_OPERAND (def_stmt, 1), 0);
tree op1 = TREE_OPERAND (TREE_OPERAND (def_stmt, 1), 1);
retval |= register_edge_assert_for_1 (op0, NE_EXPR, e, si);
retval |= register_edge_assert_for_1 (op1, NE_EXPR, e, si);
}
}
/* In the case of NAME == 0 or NAME != 1, for TRUTH_OR_EXPR defining
statement of NAME we can assert both operands of the TRUTH_OR_EXPR
have zero value. */
if (((comp_code == EQ_EXPR && integer_zerop (val))
|| (comp_code == NE_EXPR && integer_onep (val))))
{
tree def_stmt = SSA_NAME_DEF_STMT (name);
if (TREE_CODE (def_stmt) == MODIFY_EXPR
&& (TREE_CODE (TREE_OPERAND (def_stmt, 1)) == TRUTH_OR_EXPR
|| TREE_CODE (TREE_OPERAND (def_stmt, 1)) == BIT_IOR_EXPR))
{
tree op0 = TREE_OPERAND (TREE_OPERAND (def_stmt, 1), 0);
tree op1 = TREE_OPERAND (TREE_OPERAND (def_stmt, 1), 1);
retval |= register_edge_assert_for_1 (op0, EQ_EXPR, e, si);
retval |= register_edge_assert_for_1 (op1, EQ_EXPR, e, si);
}
}
return retval;
} }
static bool find_assert_locations (basic_block bb); static bool find_assert_locations (basic_block bb);
/* Determine whether the outgoing edges of BB should receive an /* Determine whether the outgoing edges of BB should receive an
ASSERT_EXPR for each of the operands of BB's last statement. The ASSERT_EXPR for each of the operands of BB's LAST statement.
last statement of BB must be a COND_EXPR or a SWITCH_EXPR. The last statement of BB must be a COND_EXPR or a SWITCH_EXPR.
If any of the sub-graphs rooted at BB have an interesting use of If any of the sub-graphs rooted at BB have an interesting use of
the predicate operands, an assert location node is added to the the predicate operands, an assert location node is added to the
list of assertions for the corresponding operands. */ list of assertions for the corresponding operands. */
static bool static bool
find_conditional_asserts (basic_block bb) find_conditional_asserts (basic_block bb, tree last)
{ {
bool need_assert; bool need_assert;
block_stmt_iterator last_si; block_stmt_iterator bsi;
tree op, last; tree op;
edge_iterator ei; edge_iterator ei;
edge e; edge e;
ssa_op_iter iter; ssa_op_iter iter;
need_assert = false; need_assert = false;
last_si = bsi_last (bb); bsi = bsi_for_stmt (last);
last = bsi_stmt (last_si);
/* Look for uses of the operands in each of the sub-graphs /* Look for uses of the operands in each of the sub-graphs
rooted at BB. We need to check each of the outgoing edges rooted at BB. We need to check each of the outgoing edges
...@@ -2852,7 +3013,8 @@ find_conditional_asserts (basic_block bb) ...@@ -2852,7 +3013,8 @@ find_conditional_asserts (basic_block bb)
/* Register the necessary assertions for each operand in the /* Register the necessary assertions for each operand in the
conditional predicate. */ conditional predicate. */
FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE) FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE)
need_assert |= register_edge_assert_for (op, e, last_si); need_assert |= register_edge_assert_for (op, e, bsi,
COND_EXPR_COND (last));
} }
/* Finally, indicate that we have found the operands in the /* Finally, indicate that we have found the operands in the
...@@ -3042,7 +3204,7 @@ find_assert_locations (basic_block bb) ...@@ -3042,7 +3204,7 @@ find_assert_locations (basic_block bb)
&& TREE_CODE (last) == COND_EXPR && TREE_CODE (last) == COND_EXPR
&& !fp_predicate (COND_EXPR_COND (last)) && !fp_predicate (COND_EXPR_COND (last))
&& !ZERO_SSA_OPERANDS (last, SSA_OP_USE)) && !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
need_assert |= find_conditional_asserts (bb); need_assert |= find_conditional_asserts (bb, last);
/* Recurse into the dominator children of BB. */ /* Recurse into the dominator children of BB. */
for (son = first_dom_son (CDI_DOMINATORS, bb); for (son = first_dom_son (CDI_DOMINATORS, bb);
......
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