summaryrefslogtreecommitdiff
path: root/meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0349-PR-tree-optimization-49161.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0349-PR-tree-optimization-49161.patch')
-rw-r--r--meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0349-PR-tree-optimization-49161.patch200
1 files changed, 200 insertions, 0 deletions
diff --git a/meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0349-PR-tree-optimization-49161.patch b/meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0349-PR-tree-optimization-49161.patch
new file mode 100644
index 000000000..80f89fd41
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0349-PR-tree-optimization-49161.patch
@@ -0,0 +1,200 @@
+From a6f15e84e042ffb95afa499d2bd2d6b2758f85f9 Mon Sep 17 00:00:00 2001
+From: jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 26 May 2011 10:20:34 +0000
+Subject: [PATCH] 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/branches/gcc-4_6-branch@174272 138bc75d-0d04-0410-961f-82ee72b054a4
+
+index 2c4fdd4..b5d9fd3 100644
+new file mode 100644
+index 0000000..cc822da
+--- /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 7bff5fa..6914a08 100644
+--- a/gcc/tree-vrp.c
++++ b/gcc/tree-vrp.c
+@@ -4672,28 +4672,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;
+@@ -4714,8 +4721,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
+@@ -4730,36 +4737,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
+@@ -4768,7 +4777,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. */
+@@ -4786,6 +4795,7 @@ find_switch_asserts (basic_block bb, gimple last)
+ }
+ }
+
++ XDELETEVEC (ci);
+ return need_assert;
+ }
+
+--
+1.7.0.4
+