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>
|
||||
|
||||
* 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>
|
||||
|
||||
* 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
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
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
|
||||
for which we need to generate ASSERT_EXPRs. Those assertions are
|
||||
inserted by process_assert_insertions.
|
||||
|
||||
TODO. Handle SWITCH_EXPR. */
|
||||
inserted by process_assert_insertions. */
|
||||
|
||||
static bool
|
||||
find_assert_locations (basic_block bb)
|
||||
|
@ -3853,6 +3976,11 @@ find_assert_locations (basic_block bb)
|
|||
&& !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
|
||||
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. */
|
||||
for (son = first_dom_son (CDI_DOMINATORS, bb);
|
||||
son;
|
||||
|
@ -4759,8 +4887,7 @@ vrp_visit_cond_stmt (tree stmt, edge *taken_edge_p)
|
|||
|
||||
*taken_edge_p = NULL;
|
||||
|
||||
/* FIXME. Handle SWITCH_EXPRs. But first, the assert pass needs to
|
||||
add ASSERT_EXPRs for them. */
|
||||
/* FIXME. Handle SWITCH_EXPRs. */
|
||||
if (TREE_CODE (stmt) == SWITCH_EXPR)
|
||||
return SSA_PROP_VARYING;
|
||||
|
||||
|
|
Loading…
Reference in New Issue