re PR tree-optimization/49161 (Fix VRP on switch stmts)
PR tree-optimization/49161 * tree-vrp.c (struct case_info): New type. (compare_case_labels): Sort case_info structs instead of trees, and not primarily by CASE_LABEL uids but by label_for_block indexes. (find_switch_asserts): Put case labels into struct case_info array instead of TREE_VEC, adjust sorting, compare label_for_block values instead of CASE_LABELs. * gcc.c-torture/execute/pr49161.c: New test. From-SVN: r174270
This commit is contained in:
parent
0dd5327a46
commit
1aa9438fdb
@ -1,3 +1,14 @@
|
|||||||
|
2011-05-26 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
PR tree-optimization/49161
|
||||||
|
* tree-vrp.c (struct case_info): New type.
|
||||||
|
(compare_case_labels): Sort case_info structs instead of
|
||||||
|
trees, and not primarily by CASE_LABEL uids but by
|
||||||
|
label_for_block indexes.
|
||||||
|
(find_switch_asserts): Put case labels into struct case_info
|
||||||
|
array instead of TREE_VEC, adjust sorting, compare label_for_block
|
||||||
|
values instead of CASE_LABELs.
|
||||||
|
|
||||||
2011-05-26 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
|
2011-05-26 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
|
||||||
|
|
||||||
* config/arm/neon.md ("orn<mode>3_neon"): Canonicalize not.
|
* config/arm/neon.md ("orn<mode>3_neon"): Canonicalize not.
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2011-05-26 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
PR tree-optimization/49161
|
||||||
|
* gcc.c-torture/execute/pr49161.c: New test.
|
||||||
|
|
||||||
2011-05-26 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
|
2011-05-26 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
|
||||||
|
|
||||||
* gcc.target/arm/neon-vorn-vbic.c: New test.
|
* gcc.target/arm/neon-vorn-vbic.c: New test.
|
||||||
|
46
gcc/testsuite/gcc.c-torture/execute/pr49161.c
Normal file
46
gcc/testsuite/gcc.c-torture/execute/pr49161.c
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* PR tree-optimization/49161 */
|
||||||
|
|
||||||
|
extern void abort (void);
|
||||||
|
|
||||||
|
int c;
|
||||||
|
|
||||||
|
__attribute__((noinline, noclone)) void
|
||||||
|
bar (int x)
|
||||||
|
{
|
||||||
|
if (x != c++)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noinline, noclone)) void
|
||||||
|
foo (int x)
|
||||||
|
{
|
||||||
|
switch (x)
|
||||||
|
{
|
||||||
|
case 3: goto l1;
|
||||||
|
case 4: goto l2;
|
||||||
|
case 6: goto l3;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
l1:
|
||||||
|
goto l4;
|
||||||
|
l2:
|
||||||
|
goto l4;
|
||||||
|
l3:
|
||||||
|
bar (-1);
|
||||||
|
l4:
|
||||||
|
bar (0);
|
||||||
|
if (x != 4)
|
||||||
|
bar (1);
|
||||||
|
if (x != 3)
|
||||||
|
bar (-1);
|
||||||
|
bar (2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
foo (3);
|
||||||
|
if (c != 3)
|
||||||
|
abort ();
|
||||||
|
return 0;
|
||||||
|
}
|
@ -4673,28 +4673,35 @@ find_conditional_asserts (basic_block bb, gimple last)
|
|||||||
return need_assert;
|
return need_assert;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare two case labels sorting first by the destination label uid
|
struct case_info
|
||||||
|
{
|
||||||
|
tree expr;
|
||||||
|
basic_block bb;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Compare two case labels sorting first by the destination bb index
|
||||||
and then by the case value. */
|
and then by the case value. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compare_case_labels (const void *p1, const void *p2)
|
compare_case_labels (const void *p1, const void *p2)
|
||||||
{
|
{
|
||||||
const_tree const case1 = *(const_tree const*)p1;
|
const struct case_info *ci1 = (const struct case_info *) p1;
|
||||||
const_tree const case2 = *(const_tree const*)p2;
|
const struct case_info *ci2 = (const struct case_info *) p2;
|
||||||
unsigned int uid1 = DECL_UID (CASE_LABEL (case1));
|
int idx1 = ci1->bb->index;
|
||||||
unsigned int uid2 = DECL_UID (CASE_LABEL (case2));
|
int idx2 = ci2->bb->index;
|
||||||
|
|
||||||
if (uid1 < uid2)
|
if (idx1 < idx2)
|
||||||
return -1;
|
return -1;
|
||||||
else if (uid1 == uid2)
|
else if (idx1 == idx2)
|
||||||
{
|
{
|
||||||
/* Make sure the default label is first in a group. */
|
/* Make sure the default label is first in a group. */
|
||||||
if (!CASE_LOW (case1))
|
if (!CASE_LOW (ci1->expr))
|
||||||
return -1;
|
return -1;
|
||||||
else if (!CASE_LOW (case2))
|
else if (!CASE_LOW (ci2->expr))
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2));
|
return tree_int_cst_compare (CASE_LOW (ci1->expr),
|
||||||
|
CASE_LOW (ci2->expr));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
@ -4715,8 +4722,8 @@ find_switch_asserts (basic_block bb, gimple last)
|
|||||||
gimple_stmt_iterator bsi;
|
gimple_stmt_iterator bsi;
|
||||||
tree op;
|
tree op;
|
||||||
edge e;
|
edge e;
|
||||||
tree vec2;
|
struct case_info *ci;
|
||||||
size_t n = gimple_switch_num_labels(last);
|
size_t n = gimple_switch_num_labels (last);
|
||||||
#if GCC_VERSION >= 4000
|
#if GCC_VERSION >= 4000
|
||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
#else
|
#else
|
||||||
@ -4731,36 +4738,38 @@ find_switch_asserts (basic_block bb, gimple last)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Build a vector of case labels sorted by destination label. */
|
/* Build a vector of case labels sorted by destination label. */
|
||||||
vec2 = make_tree_vec (n);
|
ci = XNEWVEC (struct case_info, n);
|
||||||
for (idx = 0; idx < n; ++idx)
|
for (idx = 0; idx < n; ++idx)
|
||||||
TREE_VEC_ELT (vec2, idx) = gimple_switch_label (last, idx);
|
{
|
||||||
qsort (&TREE_VEC_ELT (vec2, 0), n, sizeof (tree), compare_case_labels);
|
ci[idx].expr = gimple_switch_label (last, idx);
|
||||||
|
ci[idx].bb = label_to_block (CASE_LABEL (ci[idx].expr));
|
||||||
|
}
|
||||||
|
qsort (ci, n, sizeof (struct case_info), compare_case_labels);
|
||||||
|
|
||||||
for (idx = 0; idx < n; ++idx)
|
for (idx = 0; idx < n; ++idx)
|
||||||
{
|
{
|
||||||
tree min, max;
|
tree min, max;
|
||||||
tree cl = TREE_VEC_ELT (vec2, idx);
|
tree cl = ci[idx].expr;
|
||||||
|
basic_block cbb = ci[idx].bb;
|
||||||
|
|
||||||
min = CASE_LOW (cl);
|
min = CASE_LOW (cl);
|
||||||
max = CASE_HIGH (cl);
|
max = CASE_HIGH (cl);
|
||||||
|
|
||||||
/* If there are multiple case labels with the same destination
|
/* If there are multiple case labels with the same destination
|
||||||
we need to combine them to a single value range for the edge. */
|
we need to combine them to a single value range for the edge. */
|
||||||
if (idx + 1 < n
|
if (idx + 1 < n && cbb == ci[idx + 1].bb)
|
||||||
&& CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx + 1)))
|
|
||||||
{
|
{
|
||||||
/* Skip labels until the last of the group. */
|
/* Skip labels until the last of the group. */
|
||||||
do {
|
do {
|
||||||
++idx;
|
++idx;
|
||||||
} while (idx < n
|
} while (idx < n && cbb == ci[idx].bb);
|
||||||
&& CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx)));
|
|
||||||
--idx;
|
--idx;
|
||||||
|
|
||||||
/* Pick up the maximum of the case label range. */
|
/* Pick up the maximum of the case label range. */
|
||||||
if (CASE_HIGH (TREE_VEC_ELT (vec2, idx)))
|
if (CASE_HIGH (ci[idx].expr))
|
||||||
max = CASE_HIGH (TREE_VEC_ELT (vec2, idx));
|
max = CASE_HIGH (ci[idx].expr);
|
||||||
else
|
else
|
||||||
max = CASE_LOW (TREE_VEC_ELT (vec2, idx));
|
max = CASE_LOW (ci[idx].expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nothing to do if the range includes the default label until we
|
/* Nothing to do if the range includes the default label until we
|
||||||
@ -4769,7 +4778,7 @@ find_switch_asserts (basic_block bb, gimple last)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Find the edge to register the assert expr on. */
|
/* Find the edge to register the assert expr on. */
|
||||||
e = find_edge (bb, label_to_block (CASE_LABEL (cl)));
|
e = find_edge (bb, cbb);
|
||||||
|
|
||||||
/* Register the necessary assertions for the operand in the
|
/* Register the necessary assertions for the operand in the
|
||||||
SWITCH_EXPR. */
|
SWITCH_EXPR. */
|
||||||
@ -4787,6 +4796,7 @@ find_switch_asserts (basic_block bb, gimple last)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XDELETEVEC (ci);
|
||||||
return need_assert;
|
return need_assert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user