re PR tree-optimization/21258 (Teach VRP to pick up a constant from case label.)
2007-04-13 Richard Guenther <rguenther@suse.de> PR tree-optimization/21258 * tree-vrp.c (compare_case_labels): New helper. (find_switch_asserts): New function. (find_assert_locations): Call it for SWITCH_EXPRs. * gcc.dg/tree-ssa/vrp34.c: New testcase. From-SVN: r123778
This commit is contained in:
parent
27ac40e2a0
commit
9bb6aa4304
|
@ -1,3 +1,10 @@
|
||||||
|
2007-04-13 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
|
PR tree-optimization/21258
|
||||||
|
* tree-vrp.c (compare_case_labels): New helper.
|
||||||
|
(find_switch_asserts): New function.
|
||||||
|
(find_assert_locations): Call it for SWITCH_EXPRs.
|
||||||
|
|
||||||
2007-04-13 Uros Bizjak <ubizjak@gmail.com>
|
2007-04-13 Uros Bizjak <ubizjak@gmail.com>
|
||||||
|
|
||||||
* config/i386/i386.h (X87_FLOAT_MODE_P): Check for TARGET_80387.
|
* config/i386/i386.h (X87_FLOAT_MODE_P): Check for TARGET_80387.
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2007-04-13 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
|
PR tree-optimization/21258
|
||||||
|
* gcc.dg/tree-ssa/vrp34.c: New testcase.
|
||||||
|
|
||||||
2007-04-12 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
|
2007-04-12 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
|
||||||
|
|
||||||
* gfortran.dg/c_by_val.c: Use GCC extensions instead of including
|
* gfortran.dg/c_by_val.c: Use GCC extensions instead of including
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||||
|
|
||||||
|
void bar (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
foo (int a)
|
||||||
|
{
|
||||||
|
switch (a)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
if (a >= 3)
|
||||||
|
if (a <= 5)
|
||||||
|
bar ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* { dg-final { scan-tree-dump "Folding predicate a_. > 2 to 1" "vrp1" } } */
|
||||||
|
/* { dg-final { scan-tree-dump "Folding predicate a_. <= 5 to 1" "vrp1" } } */
|
||||||
|
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
139
gcc/tree-vrp.c
139
gcc/tree-vrp.c
|
@ -3593,7 +3593,7 @@ 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.
|
ASSERT_EXPR for each of the operands of BB's LAST statement.
|
||||||
The last statement of BB must be a COND_EXPR or a SWITCH_EXPR.
|
The last statement of BB must be a COND_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
|
||||||
|
@ -3666,6 +3666,131 @@ find_conditional_asserts (basic_block bb, tree last)
|
||||||
return need_assert;
|
return need_assert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compare two case labels sorting first by the destination label uid
|
||||||
|
and then by the case value. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
compare_case_labels (const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
tree case1 = *(tree *)p1;
|
||||||
|
tree case2 = *(tree *)p2;
|
||||||
|
unsigned int uid1 = DECL_UID (CASE_LABEL (case1));
|
||||||
|
unsigned int uid2 = DECL_UID (CASE_LABEL (case2));
|
||||||
|
|
||||||
|
if (uid1 < uid2)
|
||||||
|
return -1;
|
||||||
|
else if (uid1 == uid2)
|
||||||
|
{
|
||||||
|
/* Make sure the default label is first in a group. */
|
||||||
|
if (!CASE_LOW (case1))
|
||||||
|
return -1;
|
||||||
|
else if (!CASE_LOW (case2))
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine whether the outgoing edges of BB should receive an
|
||||||
|
ASSERT_EXPR for each of the operands of BB's LAST statement.
|
||||||
|
The last statement of BB must be a SWITCH_EXPR.
|
||||||
|
|
||||||
|
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
|
||||||
|
list of assertions for the corresponding operands. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
find_switch_asserts (basic_block bb, tree last)
|
||||||
|
{
|
||||||
|
bool need_assert;
|
||||||
|
block_stmt_iterator bsi;
|
||||||
|
tree op, cond;
|
||||||
|
edge e;
|
||||||
|
tree vec = SWITCH_LABELS (last), vec2;
|
||||||
|
size_t n = TREE_VEC_LENGTH (vec);
|
||||||
|
unsigned int idx;
|
||||||
|
|
||||||
|
need_assert = false;
|
||||||
|
bsi = bsi_for_stmt (last);
|
||||||
|
op = TREE_OPERAND (last, 0);
|
||||||
|
if (TREE_CODE (op) != SSA_NAME)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Build a vector of case labels sorted by destination label. */
|
||||||
|
vec2 = make_tree_vec (n);
|
||||||
|
for (idx = 0; idx < n; ++idx)
|
||||||
|
TREE_VEC_ELT (vec2, idx) = TREE_VEC_ELT (vec, idx);
|
||||||
|
qsort (&TREE_VEC_ELT (vec2, 0), n, sizeof (tree), compare_case_labels);
|
||||||
|
|
||||||
|
for (idx = 0; idx < n; ++idx)
|
||||||
|
{
|
||||||
|
tree min, max;
|
||||||
|
tree cl = TREE_VEC_ELT (vec2, idx);
|
||||||
|
|
||||||
|
min = CASE_LOW (cl);
|
||||||
|
max = CASE_HIGH (cl);
|
||||||
|
|
||||||
|
/* If there are multiple case labels with the same destination
|
||||||
|
we need to combine them to a single value range for the edge. */
|
||||||
|
if (idx + 1 < n
|
||||||
|
&& CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx + 1)))
|
||||||
|
{
|
||||||
|
/* Skip labels until the last of the group. */
|
||||||
|
do {
|
||||||
|
++idx;
|
||||||
|
} while (idx < n
|
||||||
|
&& CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx)));
|
||||||
|
--idx;
|
||||||
|
|
||||||
|
/* Pick up the maximum of the case label range. */
|
||||||
|
if (CASE_HIGH (TREE_VEC_ELT (vec2, idx)))
|
||||||
|
max = CASE_HIGH (TREE_VEC_ELT (vec2, idx));
|
||||||
|
else
|
||||||
|
max = CASE_LOW (TREE_VEC_ELT (vec2, idx));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing to do if the range includes the default label until we
|
||||||
|
can register anti-ranges. */
|
||||||
|
if (min == NULL_TREE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Find the edge to register the assert expr on. */
|
||||||
|
e = find_edge (bb, label_to_block (CASE_LABEL (cl)));
|
||||||
|
|
||||||
|
/* Remove the SWITCH_EXPR operand from the FOUND_IN_SUBGRAPH bitmap.
|
||||||
|
Otherwise, when we finish traversing each of the sub-graphs, we
|
||||||
|
won't know whether the variables were found in the sub-graphs or
|
||||||
|
if they had been found in a block upstream from BB. */
|
||||||
|
RESET_BIT (found_in_subgraph, SSA_NAME_VERSION (op));
|
||||||
|
|
||||||
|
/* Traverse the strictly dominated sub-graph rooted at E->DEST
|
||||||
|
to determine if any of the operands in the conditional
|
||||||
|
predicate are used. */
|
||||||
|
if (e->dest != bb)
|
||||||
|
need_assert |= find_assert_locations (e->dest);
|
||||||
|
|
||||||
|
/* Register the necessary assertions for the operand in the
|
||||||
|
SWITCH_EXPR. */
|
||||||
|
cond = build2 (max ? GE_EXPR : EQ_EXPR, boolean_type_node,
|
||||||
|
op, fold_convert (TREE_TYPE (op), min));
|
||||||
|
need_assert |= register_edge_assert_for (op, e, bsi, cond);
|
||||||
|
if (max)
|
||||||
|
{
|
||||||
|
cond = build2 (LE_EXPR, boolean_type_node,
|
||||||
|
op, fold_convert (TREE_TYPE (op), max));
|
||||||
|
need_assert |= register_edge_assert_for (op, e, bsi, cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, indicate that we have found the operand in the
|
||||||
|
SWITCH_EXPR. */
|
||||||
|
SET_BIT (found_in_subgraph, SSA_NAME_VERSION (op));
|
||||||
|
|
||||||
|
return need_assert;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Traverse all the statements in block BB looking for statements that
|
/* Traverse all the statements in block BB looking for statements that
|
||||||
may generate useful assertions for the SSA names in their operand.
|
may generate useful assertions for the SSA names in their operand.
|
||||||
|
@ -3728,9 +3853,7 @@ find_conditional_asserts (basic_block bb, tree last)
|
||||||
|
|
||||||
If this function returns true, then it means that there are names
|
If this function returns true, then it means that there are names
|
||||||
for which we need to generate ASSERT_EXPRs. Those assertions are
|
for which we need to generate ASSERT_EXPRs. Those assertions are
|
||||||
inserted by process_assert_insertions.
|
inserted by process_assert_insertions. */
|
||||||
|
|
||||||
TODO. Handle SWITCH_EXPR. */
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
find_assert_locations (basic_block bb)
|
find_assert_locations (basic_block bb)
|
||||||
|
@ -3853,6 +3976,11 @@ find_assert_locations (basic_block bb)
|
||||||
&& !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
|
&& !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
|
||||||
need_assert |= find_conditional_asserts (bb, last);
|
need_assert |= find_conditional_asserts (bb, last);
|
||||||
|
|
||||||
|
if (last
|
||||||
|
&& TREE_CODE (last) == SWITCH_EXPR
|
||||||
|
&& !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
|
||||||
|
need_assert |= find_switch_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);
|
||||||
son;
|
son;
|
||||||
|
@ -4759,8 +4887,7 @@ vrp_visit_cond_stmt (tree stmt, edge *taken_edge_p)
|
||||||
|
|
||||||
*taken_edge_p = NULL;
|
*taken_edge_p = NULL;
|
||||||
|
|
||||||
/* FIXME. Handle SWITCH_EXPRs. But first, the assert pass needs to
|
/* FIXME. Handle SWITCH_EXPRs. */
|
||||||
add ASSERT_EXPRs for them. */
|
|
||||||
if (TREE_CODE (stmt) == SWITCH_EXPR)
|
if (TREE_CODE (stmt) == SWITCH_EXPR)
|
||||||
return SSA_PROP_VARYING;
|
return SSA_PROP_VARYING;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue