diff options
Diffstat (limited to 'meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99473.patch')
-rw-r--r-- | meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99473.patch | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99473.patch b/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99473.patch new file mode 100644 index 000000000..3ac7f7f6f --- /dev/null +++ b/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99473.patch | |||
@@ -0,0 +1,409 @@ | |||
1 | 2010-02-04 Tom de Vries <tom@codesourcery.com> | ||
2 | |||
3 | gcc/ | ||
4 | stmt.c (set_jump_prob): Fix assert condition. | ||
5 | |||
6 | 2010-01-27 Tom de Vries <tom@codesourcery.com> | ||
7 | |||
8 | gcc/ | ||
9 | stmt.c (rtx_seq_cost): Use insn_rtx_cost instead of rtx_cost. | ||
10 | |||
11 | 2010-01-26 Tom de Vries <tom@codesourcery.com> | ||
12 | |||
13 | gcc/ | ||
14 | * stmt.c (struct case_bit_test): Add rev_hi and rev_lo field. | ||
15 | * stmt.c (emit_case_bit_test_jump): New function. | ||
16 | * stmt.c (rtx_seq_cost): New function. | ||
17 | * stmt.c (choose_case_bit_test_expand_method): New function. | ||
18 | * stmt.c (set_bit): New function. | ||
19 | * stmt.c (emit_case_bit_test): Adjust comment. | ||
20 | * stmt.c (emit_case_bit_test): Set and update rev_hi and rev_lo fields. | ||
21 | * stmt.c (emit_case_bit_test): Use set_bit. | ||
22 | * stmt.c (emit_case_bit_test): Use choose_case_bit_test_expand_method. | ||
23 | * stmt.c (emit_case_bit_test): Use emit_case_bit_test_jump. | ||
24 | * testsuite/gcc.dg/switch-bittest.c: New test. | ||
25 | |||
26 | 2010-01-25 Tom de Vries <tom@codesourcery.com> | ||
27 | |||
28 | gcc/ | ||
29 | * stmt.c (emit_case_bit_tests): Change prototype. | ||
30 | * stmt.c (struct case_bit_test): Add prob field. | ||
31 | * stmt.c (get_label_prob): New function. | ||
32 | * stmt.c (set_jump_prob): New function. | ||
33 | * stmt.c (emit_case_bit_tests): Use get_label_prob. | ||
34 | * stmt.c (emit_case_bit_tests): Set prob field. | ||
35 | * stmt.c (emit_case_bit_tests): Use set_jump_prob. | ||
36 | * stmt.c (expand_case): Add new args to emit_case_bit_tests invocation. | ||
37 | * testsuite/gcc.dg/switch-prob.c: Add test. | ||
38 | |||
39 | === modified file 'gcc/stmt.c' | ||
40 | Index: gcc-4_5-branch/gcc/stmt.c | ||
41 | =================================================================== | ||
42 | --- gcc-4_5-branch.orig/gcc/stmt.c | ||
43 | +++ gcc-4_5-branch/gcc/stmt.c | ||
44 | @@ -117,7 +117,8 @@ static void expand_value_return (rtx); | ||
45 | static int estimate_case_costs (case_node_ptr); | ||
46 | static bool lshift_cheap_p (void); | ||
47 | static int case_bit_test_cmp (const void *, const void *); | ||
48 | -static void emit_case_bit_tests (tree, tree, tree, tree, case_node_ptr, rtx); | ||
49 | +static void emit_case_bit_tests (tree, tree, tree, tree, case_node_ptr, tree, | ||
50 | + rtx, basic_block); | ||
51 | static void balance_case_nodes (case_node_ptr *, case_node_ptr); | ||
52 | static int node_has_low_bound (case_node_ptr, tree); | ||
53 | static int node_has_high_bound (case_node_ptr, tree); | ||
54 | @@ -2107,8 +2108,11 @@ struct case_bit_test | ||
55 | { | ||
56 | HOST_WIDE_INT hi; | ||
57 | HOST_WIDE_INT lo; | ||
58 | + HOST_WIDE_INT rev_hi; | ||
59 | + HOST_WIDE_INT rev_lo; | ||
60 | rtx label; | ||
61 | int bits; | ||
62 | + int prob; | ||
63 | }; | ||
64 | |||
65 | /* Determine whether "1 << x" is relatively cheap in word_mode. */ | ||
66 | @@ -2148,10 +2152,193 @@ case_bit_test_cmp (const void *p1, const | ||
67 | return CODE_LABEL_NUMBER (d2->label) - CODE_LABEL_NUMBER (d1->label); | ||
68 | } | ||
69 | |||
70 | +/* Emit a bit test and a conditional jump. */ | ||
71 | + | ||
72 | +static void | ||
73 | +emit_case_bit_test_jump (unsigned int count, rtx index, rtx label, | ||
74 | + unsigned int method, HOST_WIDE_INT hi, | ||
75 | + HOST_WIDE_INT lo, HOST_WIDE_INT rev_hi, | ||
76 | + HOST_WIDE_INT rev_lo) | ||
77 | +{ | ||
78 | + rtx expr; | ||
79 | + | ||
80 | + if (method == 1) | ||
81 | + { | ||
82 | + /* (1 << index). */ | ||
83 | + if (count == 0) | ||
84 | + index = expand_binop (word_mode, ashl_optab, const1_rtx, | ||
85 | + index, NULL_RTX, 1, OPTAB_WIDEN); | ||
86 | + /* CST. */ | ||
87 | + expr = immed_double_const (lo, hi, word_mode); | ||
88 | + /* ((1 << index) & CST). */ | ||
89 | + expr = expand_binop (word_mode, and_optab, index, expr, | ||
90 | + NULL_RTX, 1, OPTAB_WIDEN); | ||
91 | + /* if (((1 << index) & CST)). */ | ||
92 | + emit_cmp_and_jump_insns (expr, const0_rtx, NE, NULL_RTX, | ||
93 | + word_mode, 1, label); | ||
94 | + } | ||
95 | + else if (method == 2) | ||
96 | + { | ||
97 | + /* (bit_reverse (CST)) */ | ||
98 | + expr = immed_double_const (rev_lo, rev_hi, word_mode); | ||
99 | + /* ((bit_reverse (CST)) << index) */ | ||
100 | + expr = expand_binop (word_mode, ashl_optab, expr, | ||
101 | + index, NULL_RTX, 1, OPTAB_WIDEN); | ||
102 | + /* if (((bit_reverse (CST)) << index) < 0). */ | ||
103 | + emit_cmp_and_jump_insns (expr, const0_rtx, LT, NULL_RTX, | ||
104 | + word_mode, 0, label); | ||
105 | + } | ||
106 | + else | ||
107 | + gcc_unreachable (); | ||
108 | +} | ||
109 | + | ||
110 | +/* Return the cost of rtx sequence SEQ. The sequence is supposed to contain one | ||
111 | + jump, which has no effect in the cost. */ | ||
112 | + | ||
113 | +static unsigned int | ||
114 | +rtx_seq_cost (rtx seq) | ||
115 | +{ | ||
116 | + rtx one; | ||
117 | + unsigned int nr_branches = 0; | ||
118 | + unsigned int sum = 0, cost; | ||
119 | + | ||
120 | + for (one = seq; one != NULL_RTX; one = NEXT_INSN (one)) | ||
121 | + if (JUMP_P (one)) | ||
122 | + nr_branches++; | ||
123 | + else | ||
124 | + { | ||
125 | + cost = insn_rtx_cost (PATTERN (one), optimize_insn_for_speed_p ()); | ||
126 | + if (dump_file) | ||
127 | + { | ||
128 | + print_rtl_single (dump_file, one); | ||
129 | + fprintf (dump_file, "cost: %u\n", cost); | ||
130 | + } | ||
131 | + sum += cost; | ||
132 | + } | ||
133 | + | ||
134 | + gcc_assert (nr_branches == 1); | ||
135 | + | ||
136 | + if (dump_file) | ||
137 | + fprintf (dump_file, "total cost: %u\n", sum); | ||
138 | + return sum; | ||
139 | +} | ||
140 | + | ||
141 | +/* Generate the rtx sequences for 2 bit test expansion methods, measure the cost | ||
142 | + and choose the cheapest. */ | ||
143 | + | ||
144 | +static unsigned int | ||
145 | +choose_case_bit_test_expand_method (rtx label) | ||
146 | +{ | ||
147 | + rtx seq, index; | ||
148 | + unsigned int cost[2]; | ||
149 | + static bool method_known = false; | ||
150 | + static unsigned int method; | ||
151 | + | ||
152 | + /* If already known, return the method. */ | ||
153 | + if (method_known) | ||
154 | + return method; | ||
155 | + | ||
156 | + index = gen_rtx_REG (word_mode, 10000); | ||
157 | + | ||
158 | + for (method = 1; method <= 2; ++method) | ||
159 | + { | ||
160 | + start_sequence (); | ||
161 | + emit_case_bit_test_jump (0, index, label, method, 0, 0x0f0f0f0f, 0, | ||
162 | + 0x0f0f0f0f); | ||
163 | + seq = get_insns (); | ||
164 | + end_sequence (); | ||
165 | + cost[method - 1] = rtx_seq_cost (seq); | ||
166 | + } | ||
167 | + | ||
168 | + /* Determine method based on heuristic. */ | ||
169 | + method = ((cost[1] < cost[0]) ? 1 : 0) + 1; | ||
170 | + | ||
171 | + /* Save and return method. */ | ||
172 | + method_known = true; | ||
173 | + return method; | ||
174 | +} | ||
175 | + | ||
176 | +/* Get the edge probability of the edge from SRC to LABEL_DECL. */ | ||
177 | + | ||
178 | +static int | ||
179 | +get_label_prob (basic_block src, tree label_decl) | ||
180 | +{ | ||
181 | + basic_block dest; | ||
182 | + int prob = 0, nr_prob = 0; | ||
183 | + unsigned int i; | ||
184 | + edge e; | ||
185 | + | ||
186 | + if (label_decl == NULL_TREE) | ||
187 | + return 0; | ||
188 | + | ||
189 | + dest = VEC_index (basic_block, label_to_block_map, | ||
190 | + LABEL_DECL_UID (label_decl)); | ||
191 | + | ||
192 | + for (i = 0; i < EDGE_COUNT (src->succs); ++i) | ||
193 | + { | ||
194 | + e = EDGE_SUCC (src, i); | ||
195 | + | ||
196 | + if (e->dest != dest) | ||
197 | + continue; | ||
198 | + | ||
199 | + prob += e->probability; | ||
200 | + nr_prob++; | ||
201 | + } | ||
202 | + | ||
203 | + gcc_assert (nr_prob == 1); | ||
204 | + | ||
205 | + return prob; | ||
206 | +} | ||
207 | + | ||
208 | +/* Add probability note with scaled PROB to JUMP and update INV_SCALE. This | ||
209 | + function is intended to be used with a series of conditional jumps to L[i] | ||
210 | + where the probabilities p[i] to get to L[i] are known, and the jump | ||
211 | + probabilities j[i] need to be computed. | ||
212 | + | ||
213 | + The algorithm to calculate the probabilities is | ||
214 | + | ||
215 | + scale = REG_BR_PROB_BASE; | ||
216 | + for (i = 0; i < n; ++i) | ||
217 | + { | ||
218 | + j[i] = p[i] * scale / REG_BR_PROB_BASE; | ||
219 | + f[i] = REG_BR_PROB_BASE - j[i]; | ||
220 | + scale = scale / (f[i] / REG_BR_PROB_BASE); | ||
221 | + } | ||
222 | + | ||
223 | + The implementation uses inv_scale (REG_BR_PROB_BASE / scale) instead of | ||
224 | + scale, because scale tends to grow bigger than REG_BR_PROB_BASE. */ | ||
225 | + | ||
226 | +static void | ||
227 | +set_jump_prob (rtx jump, int prob, int *inv_scale) | ||
228 | +{ | ||
229 | + /* j[i] = p[i] * scale / REG_BR_PROB_BASE. */ | ||
230 | + int jump_prob = prob * REG_BR_PROB_BASE / *inv_scale; | ||
231 | + /* f[i] = REG_BR_PROB_BASE - j[i]. */ | ||
232 | + int fallthrough_prob = REG_BR_PROB_BASE - jump_prob; | ||
233 | + | ||
234 | + gcc_assert (jump_prob <= REG_BR_PROB_BASE); | ||
235 | + add_reg_note (jump, REG_BR_PROB, GEN_INT (jump_prob)); | ||
236 | + | ||
237 | + /* scale = scale / (f[i] / REG_BR_PROB_BASE). */ | ||
238 | + *inv_scale = *inv_scale * fallthrough_prob / REG_BR_PROB_BASE; | ||
239 | +} | ||
240 | + | ||
241 | +/* Set bit in hwi hi/lo pair. */ | ||
242 | + | ||
243 | +static void | ||
244 | +set_bit (HOST_WIDE_INT *hi, HOST_WIDE_INT *lo, unsigned int j) | ||
245 | +{ | ||
246 | + if (j >= HOST_BITS_PER_WIDE_INT) | ||
247 | + *hi |= (HOST_WIDE_INT) 1 << (j - HOST_BITS_PER_INT); | ||
248 | + else | ||
249 | + *lo |= (HOST_WIDE_INT) 1 << j; | ||
250 | +} | ||
251 | + | ||
252 | /* Expand a switch statement by a short sequence of bit-wise | ||
253 | comparisons. "switch(x)" is effectively converted into | ||
254 | - "if ((1 << (x-MINVAL)) & CST)" where CST and MINVAL are | ||
255 | - integer constants. | ||
256 | + "if ((1 << (x-MINVAL)) & CST)" or | ||
257 | + "if (((bit_reverse (CST)) << (x-MINVAL)) < 0)", where CST | ||
258 | + and MINVAL are integer constants. | ||
259 | |||
260 | INDEX_EXPR is the value being switched on, which is of | ||
261 | type INDEX_TYPE. MINVAL is the lowest case value of in | ||
262 | @@ -2165,14 +2352,17 @@ case_bit_test_cmp (const void *p1, const | ||
263 | |||
264 | static void | ||
265 | emit_case_bit_tests (tree index_type, tree index_expr, tree minval, | ||
266 | - tree range, case_node_ptr nodes, rtx default_label) | ||
267 | + tree range, case_node_ptr nodes, tree default_label_decl, | ||
268 | + rtx default_label, basic_block bb) | ||
269 | { | ||
270 | struct case_bit_test test[MAX_CASE_BIT_TESTS]; | ||
271 | enum machine_mode mode; | ||
272 | rtx expr, index, label; | ||
273 | unsigned int i,j,lo,hi; | ||
274 | struct case_node *n; | ||
275 | - unsigned int count; | ||
276 | + unsigned int count, method; | ||
277 | + int inv_scale = REG_BR_PROB_BASE; | ||
278 | + int default_prob = get_label_prob (bb, default_label_decl); | ||
279 | |||
280 | count = 0; | ||
281 | for (n = nodes; n; n = n->right) | ||
282 | @@ -2187,8 +2377,11 @@ emit_case_bit_tests (tree index_type, tr | ||
283 | gcc_assert (count < MAX_CASE_BIT_TESTS); | ||
284 | test[i].hi = 0; | ||
285 | test[i].lo = 0; | ||
286 | + test[i].rev_hi = 0; | ||
287 | + test[i].rev_lo = 0; | ||
288 | test[i].label = label; | ||
289 | test[i].bits = 1; | ||
290 | + test[i].prob = get_label_prob (bb, n->code_label); | ||
291 | count++; | ||
292 | } | ||
293 | else | ||
294 | @@ -2199,10 +2392,11 @@ emit_case_bit_tests (tree index_type, tr | ||
295 | hi = tree_low_cst (fold_build2 (MINUS_EXPR, index_type, | ||
296 | n->high, minval), 1); | ||
297 | for (j = lo; j <= hi; j++) | ||
298 | - if (j >= HOST_BITS_PER_WIDE_INT) | ||
299 | - test[i].hi |= (HOST_WIDE_INT) 1 << (j - HOST_BITS_PER_INT); | ||
300 | - else | ||
301 | - test[i].lo |= (HOST_WIDE_INT) 1 << j; | ||
302 | + { | ||
303 | + set_bit (&test[i].hi, &test[i].lo, j); | ||
304 | + set_bit (&test[i].rev_hi, &test[i].rev_lo, | ||
305 | + GET_MODE_BITSIZE (word_mode) - j - 1); | ||
306 | + } | ||
307 | } | ||
308 | |||
309 | qsort (test, count, sizeof(*test), case_bit_test_cmp); | ||
310 | @@ -2216,20 +2410,20 @@ emit_case_bit_tests (tree index_type, tr | ||
311 | mode = TYPE_MODE (index_type); | ||
312 | expr = expand_normal (range); | ||
313 | if (default_label) | ||
314 | - emit_cmp_and_jump_insns (index, expr, GTU, NULL_RTX, mode, 1, | ||
315 | - default_label); | ||
316 | + { | ||
317 | + emit_cmp_and_jump_insns (index, expr, GTU, NULL_RTX, mode, 1, | ||
318 | + default_label); | ||
319 | + set_jump_prob (get_last_insn (), default_prob / 2, &inv_scale); | ||
320 | + } | ||
321 | |||
322 | index = convert_to_mode (word_mode, index, 0); | ||
323 | - index = expand_binop (word_mode, ashl_optab, const1_rtx, | ||
324 | - index, NULL_RTX, 1, OPTAB_WIDEN); | ||
325 | |||
326 | + method = choose_case_bit_test_expand_method (test[0].label); | ||
327 | for (i = 0; i < count; i++) | ||
328 | { | ||
329 | - expr = immed_double_const (test[i].lo, test[i].hi, word_mode); | ||
330 | - expr = expand_binop (word_mode, and_optab, index, expr, | ||
331 | - NULL_RTX, 1, OPTAB_WIDEN); | ||
332 | - emit_cmp_and_jump_insns (expr, const0_rtx, NE, NULL_RTX, | ||
333 | - word_mode, 1, test[i].label); | ||
334 | + emit_case_bit_test_jump (i, index, test[i].label, method, test[i].hi, | ||
335 | + test[i].lo, test[i].rev_hi, test[i].rev_lo); | ||
336 | + set_jump_prob (get_last_insn (), test[i].prob, &inv_scale); | ||
337 | } | ||
338 | |||
339 | if (default_label) | ||
340 | @@ -2400,7 +2594,8 @@ expand_case (gimple stmt) | ||
341 | range = maxval; | ||
342 | } | ||
343 | emit_case_bit_tests (index_type, index_expr, minval, range, | ||
344 | - case_list, default_label); | ||
345 | + case_list, default_label_decl, default_label, | ||
346 | + gimple_bb (stmt)); | ||
347 | } | ||
348 | |||
349 | /* If range of values is much bigger than number of values, | ||
350 | Index: gcc-4_5-branch/gcc/testsuite/gcc.dg/switch-bittest.c | ||
351 | =================================================================== | ||
352 | --- /dev/null | ||
353 | +++ gcc-4_5-branch/gcc/testsuite/gcc.dg/switch-bittest.c | ||
354 | @@ -0,0 +1,25 @@ | ||
355 | +/* { dg-do compile } */ | ||
356 | +/* { dg-options "-O2 -fdump-rtl-expand" } */ | ||
357 | + | ||
358 | +const char * | ||
359 | +f (const char *p) | ||
360 | +{ | ||
361 | + while (1) | ||
362 | + { | ||
363 | + switch (*p) | ||
364 | + { | ||
365 | + case 9: | ||
366 | + case 10: | ||
367 | + case 13: | ||
368 | + case 32: | ||
369 | + break; | ||
370 | + default: | ||
371 | + return p; | ||
372 | + } | ||
373 | + } | ||
374 | +} | ||
375 | + | ||
376 | +/* { dg-final { scan-rtl-dump-times "jump_insn" 4 "expand" { target mips*-*-* } } } */ | ||
377 | +/* { dg-final { scan-rtl-dump-times "REG_BR_PROB" 2 "expand" { target mips*-*-* } } } */ | ||
378 | +/* { dg-final { scan-rtl-dump-times "lt " 1 "expand" { target mips*-*-* } } } */ | ||
379 | +/* { dg-final { cleanup-rtl-dump "expand" } } */ | ||
380 | Index: gcc-4_5-branch/gcc/testsuite/gcc.dg/switch-prob.c | ||
381 | =================================================================== | ||
382 | --- /dev/null | ||
383 | +++ gcc-4_5-branch/gcc/testsuite/gcc.dg/switch-prob.c | ||
384 | @@ -0,0 +1,25 @@ | ||
385 | +/* { dg-do compile } */ | ||
386 | +/* { dg-options "-O2 -fdump-rtl-expand" } */ | ||
387 | + | ||
388 | +const char * | ||
389 | +f (const char *p) | ||
390 | +{ | ||
391 | + while (1) | ||
392 | + { | ||
393 | + switch (*p) | ||
394 | + { | ||
395 | + case 9: | ||
396 | + case 10: | ||
397 | + case 13: | ||
398 | + case 32: | ||
399 | + break; | ||
400 | + default: | ||
401 | + return p; | ||
402 | + } | ||
403 | + } | ||
404 | +} | ||
405 | + | ||
406 | +/* { dg-final { scan-rtl-dump-times "jump_insn" 4 "expand" { target mips*-*-* } } } */ | ||
407 | +/* { dg-final { scan-rtl-dump-times "REG_BR_PROB" 2 "expand" { target mips*-*-* } } } */ | ||
408 | +/* { dg-final { scan-rtl-dump-times "heuristics" 0 "expand" { target mips*-*-* } } } */ | ||
409 | +/* { dg-final { cleanup-rtl-dump "expand" } } */ | ||