summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2011-05-26 10:05:05 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2011-05-26 10:05:05 +0000
commit8b3183486328856ccf37574ca2f87ce8773d9e18 (patch)
tree8bca149e3f780e52c9095bee5dec1c249b4481f0 /gcc
parent0d036b6403c426aa98c01a9310d43ab5013524ea (diff)
downloadgcc-8b3183486328856ccf37574ca2f87ce8773d9e18.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@174270 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr49161.c46
-rw-r--r--gcc/tree-vrp.c58
4 files changed, 96 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c60706c275d..14503137b5a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
* config/arm/neon.md ("orn<mode>3_neon"): Canonicalize not.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bf6a2eeed03..27f468d308c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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>
* gcc.target/arm/neon-vorn-vbic.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr49161.c b/gcc/testsuite/gcc.c-torture/execute/pr49161.c
new file mode 100644
index 00000000000..cc822dae8c3
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr49161.c
@@ -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;
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 2d3a6fcad70..8fcf629adde 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -4673,28 +4673,35 @@ find_conditional_asserts (basic_block bb, gimple last)
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. */
static int
compare_case_labels (const void *p1, const void *p2)
{
- const_tree const case1 = *(const_tree const*)p1;
- const_tree const case2 = *(const_tree const*)p2;
- unsigned int uid1 = DECL_UID (CASE_LABEL (case1));
- unsigned int uid2 = DECL_UID (CASE_LABEL (case2));
+ const struct case_info *ci1 = (const struct case_info *) p1;
+ const struct case_info *ci2 = (const struct case_info *) p2;
+ int idx1 = ci1->bb->index;
+ int idx2 = ci2->bb->index;
- if (uid1 < uid2)
+ if (idx1 < idx2)
return -1;
- else if (uid1 == uid2)
+ else if (idx1 == idx2)
{
/* Make sure the default label is first in a group. */
- if (!CASE_LOW (case1))
+ if (!CASE_LOW (ci1->expr))
return -1;
- else if (!CASE_LOW (case2))
+ else if (!CASE_LOW (ci2->expr))
return 1;
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
return 1;
@@ -4715,8 +4722,8 @@ find_switch_asserts (basic_block bb, gimple last)
gimple_stmt_iterator bsi;
tree op;
edge e;
- tree vec2;
- size_t n = gimple_switch_num_labels(last);
+ struct case_info *ci;
+ size_t n = gimple_switch_num_labels (last);
#if GCC_VERSION >= 4000
unsigned int idx;
#else
@@ -4731,36 +4738,38 @@ find_switch_asserts (basic_block bb, gimple last)
return false;
/* 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)
- 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)
{
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);
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)))
+ if (idx + 1 < n && cbb == ci[idx + 1].bb)
{
/* Skip labels until the last of the group. */
do {
++idx;
- } while (idx < n
- && CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx)));
+ } while (idx < n && cbb == ci[idx].bb);
--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));
+ if (CASE_HIGH (ci[idx].expr))
+ max = CASE_HIGH (ci[idx].expr);
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
@@ -4769,7 +4778,7 @@ find_switch_asserts (basic_block bb, gimple last)
continue;
/* 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
SWITCH_EXPR. */
@@ -4787,6 +4796,7 @@ find_switch_asserts (basic_block bb, gimple last)
}
}
+ XDELETEVEC (ci);
return need_assert;
}