summaryrefslogtreecommitdiffstats
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 0000000000..80f89fd418
--- /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 @@
1From a6f15e84e042ffb95afa499d2bd2d6b2758f85f9 Mon Sep 17 00:00:00 2001
2From: jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
3Date: Thu, 26 May 2011 10:20:34 +0000
4Subject: [PATCH] PR tree-optimization/49161
5 * tree-vrp.c (struct case_info): New type.
6 (compare_case_labels): Sort case_info structs instead of
7 trees, and not primarily by CASE_LABEL uids but by
8 label_for_block indexes.
9 (find_switch_asserts): Put case labels into struct case_info
10 array instead of TREE_VEC, adjust sorting, compare label_for_block
11 values instead of CASE_LABELs.
12
13 * gcc.c-torture/execute/pr49161.c: New test.
14
15
16git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch@174272 138bc75d-0d04-0410-961f-82ee72b054a4
17
18index 2c4fdd4..b5d9fd3 100644
19new file mode 100644
20index 0000000..cc822da
21--- /dev/null
22+++ b/gcc/testsuite/gcc.c-torture/execute/pr49161.c
23@@ -0,0 +1,46 @@
24+/* PR tree-optimization/49161 */
25+
26+extern void abort (void);
27+
28+int c;
29+
30+__attribute__((noinline, noclone)) void
31+bar (int x)
32+{
33+ if (x != c++)
34+ abort ();
35+}
36+
37+__attribute__((noinline, noclone)) void
38+foo (int x)
39+{
40+ switch (x)
41+ {
42+ case 3: goto l1;
43+ case 4: goto l2;
44+ case 6: goto l3;
45+ default: return;
46+ }
47+l1:
48+ goto l4;
49+l2:
50+ goto l4;
51+l3:
52+ bar (-1);
53+l4:
54+ bar (0);
55+ if (x != 4)
56+ bar (1);
57+ if (x != 3)
58+ bar (-1);
59+ bar (2);
60+}
61+
62+int
63+main ()
64+{
65+ foo (3);
66+ if (c != 3)
67+ abort ();
68+ return 0;
69+}
70diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
71index 7bff5fa..6914a08 100644
72--- a/gcc/tree-vrp.c
73+++ b/gcc/tree-vrp.c
74@@ -4672,28 +4672,35 @@ find_conditional_asserts (basic_block bb, gimple last)
75 return need_assert;
76 }
77
78-/* Compare two case labels sorting first by the destination label uid
79+struct case_info
80+{
81+ tree expr;
82+ basic_block bb;
83+};
84+
85+/* Compare two case labels sorting first by the destination bb index
86 and then by the case value. */
87
88 static int
89 compare_case_labels (const void *p1, const void *p2)
90 {
91- const_tree const case1 = *(const_tree const*)p1;
92- const_tree const case2 = *(const_tree const*)p2;
93- unsigned int uid1 = DECL_UID (CASE_LABEL (case1));
94- unsigned int uid2 = DECL_UID (CASE_LABEL (case2));
95+ const struct case_info *ci1 = (const struct case_info *) p1;
96+ const struct case_info *ci2 = (const struct case_info *) p2;
97+ int idx1 = ci1->bb->index;
98+ int idx2 = ci2->bb->index;
99
100- if (uid1 < uid2)
101+ if (idx1 < idx2)
102 return -1;
103- else if (uid1 == uid2)
104+ else if (idx1 == idx2)
105 {
106 /* Make sure the default label is first in a group. */
107- if (!CASE_LOW (case1))
108+ if (!CASE_LOW (ci1->expr))
109 return -1;
110- else if (!CASE_LOW (case2))
111+ else if (!CASE_LOW (ci2->expr))
112 return 1;
113 else
114- return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2));
115+ return tree_int_cst_compare (CASE_LOW (ci1->expr),
116+ CASE_LOW (ci2->expr));
117 }
118 else
119 return 1;
120@@ -4714,8 +4721,8 @@ find_switch_asserts (basic_block bb, gimple last)
121 gimple_stmt_iterator bsi;
122 tree op;
123 edge e;
124- tree vec2;
125- size_t n = gimple_switch_num_labels(last);
126+ struct case_info *ci;
127+ size_t n = gimple_switch_num_labels (last);
128 #if GCC_VERSION >= 4000
129 unsigned int idx;
130 #else
131@@ -4730,36 +4737,38 @@ find_switch_asserts (basic_block bb, gimple last)
132 return false;
133
134 /* Build a vector of case labels sorted by destination label. */
135- vec2 = make_tree_vec (n);
136+ ci = XNEWVEC (struct case_info, n);
137 for (idx = 0; idx < n; ++idx)
138- TREE_VEC_ELT (vec2, idx) = gimple_switch_label (last, idx);
139- qsort (&TREE_VEC_ELT (vec2, 0), n, sizeof (tree), compare_case_labels);
140+ {
141+ ci[idx].expr = gimple_switch_label (last, idx);
142+ ci[idx].bb = label_to_block (CASE_LABEL (ci[idx].expr));
143+ }
144+ qsort (ci, n, sizeof (struct case_info), compare_case_labels);
145
146 for (idx = 0; idx < n; ++idx)
147 {
148 tree min, max;
149- tree cl = TREE_VEC_ELT (vec2, idx);
150+ tree cl = ci[idx].expr;
151+ basic_block cbb = ci[idx].bb;
152
153 min = CASE_LOW (cl);
154 max = CASE_HIGH (cl);
155
156 /* If there are multiple case labels with the same destination
157 we need to combine them to a single value range for the edge. */
158- if (idx + 1 < n
159- && CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx + 1)))
160+ if (idx + 1 < n && cbb == ci[idx + 1].bb)
161 {
162 /* Skip labels until the last of the group. */
163 do {
164 ++idx;
165- } while (idx < n
166- && CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx)));
167+ } while (idx < n && cbb == ci[idx].bb);
168 --idx;
169
170 /* Pick up the maximum of the case label range. */
171- if (CASE_HIGH (TREE_VEC_ELT (vec2, idx)))
172- max = CASE_HIGH (TREE_VEC_ELT (vec2, idx));
173+ if (CASE_HIGH (ci[idx].expr))
174+ max = CASE_HIGH (ci[idx].expr);
175 else
176- max = CASE_LOW (TREE_VEC_ELT (vec2, idx));
177+ max = CASE_LOW (ci[idx].expr);
178 }
179
180 /* Nothing to do if the range includes the default label until we
181@@ -4768,7 +4777,7 @@ find_switch_asserts (basic_block bb, gimple last)
182 continue;
183
184 /* Find the edge to register the assert expr on. */
185- e = find_edge (bb, label_to_block (CASE_LABEL (cl)));
186+ e = find_edge (bb, cbb);
187
188 /* Register the necessary assertions for the operand in the
189 SWITCH_EXPR. */
190@@ -4786,6 +4795,7 @@ find_switch_asserts (basic_block bb, gimple last)
191 }
192 }
193
194+ XDELETEVEC (ci);
195 return need_assert;
196 }
197
198--
1991.7.0.4
200