summaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99473.patch
diff options
context:
space:
mode:
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.patch409
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 @@
12010-02-04 Tom de Vries <tom@codesourcery.com>
2
3 gcc/
4 stmt.c (set_jump_prob): Fix assert condition.
5
62010-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
112010-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
262010-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'
40Index: 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,
350Index: 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" } } */
380Index: 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" } } */