Mercurial > hg > CbC > CbC_gcc
annotate gcc/stmt.c @ 158:494b0b89df80 default tip
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 18:13:55 +0900 |
parents | 1830386684a0 |
children |
rev | line source |
---|---|
0 | 1 /* Expands front end tree to back end RTL for GCC |
145 | 2 Copyright (C) 1987-2020 Free Software Foundation, Inc. |
0 | 3 |
4 This file is part of GCC. | |
5 | |
6 GCC is free software; you can redistribute it and/or modify it under | |
7 the terms of the GNU General Public License as published by the Free | |
8 Software Foundation; either version 3, or (at your option) any later | |
9 version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 /* This file handles the generation of rtl code from tree structure | |
21 above the level of expressions, using subroutines in exp*.c and emit-rtl.c. | |
22 The functions whose names start with `expand_' are called by the | |
23 expander to generate RTL instructions for various kinds of constructs. */ | |
24 | |
25 #include "config.h" | |
26 #include "system.h" | |
27 #include "coretypes.h" | |
111 | 28 #include "backend.h" |
29 #include "target.h" | |
0 | 30 #include "rtl.h" |
31 #include "tree.h" | |
111 | 32 #include "gimple.h" |
33 #include "cfghooks.h" | |
34 #include "predict.h" | |
35 #include "memmodel.h" | |
0 | 36 #include "tm_p.h" |
111 | 37 #include "optabs.h" |
38 #include "regs.h" | |
39 #include "emit-rtl.h" | |
40 #include "pretty-print.h" | |
41 #include "diagnostic-core.h" | |
42 | |
43 #include "fold-const.h" | |
44 #include "varasm.h" | |
45 #include "stor-layout.h" | |
46 #include "dojump.h" | |
47 #include "explow.h" | |
48 #include "stmt.h" | |
0 | 49 #include "expr.h" |
50 #include "langhooks.h" | |
111 | 51 #include "cfganal.h" |
52 #include "tree-cfg.h" | |
53 #include "dumpfile.h" | |
54 #include "builtins.h" | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
55 |
0 | 56 |
57 /* Functions and data structures for expanding case statements. */ | |
58 | |
59 /* Case label structure, used to hold info on labels within case | |
60 statements. We handle "range" labels; for a single-value label | |
61 as in C, the high and low limits are the same. | |
62 | |
63 We start with a vector of case nodes sorted in ascending order, and | |
111 | 64 the default label as the last element in the vector. |
0 | 65 |
111 | 66 Switch statements are expanded in jump table form. |
67 | |
68 */ | |
0 | 69 |
145 | 70 class simple_case_node |
111 | 71 { |
145 | 72 public: |
111 | 73 simple_case_node (tree low, tree high, tree code_label): |
74 m_low (low), m_high (high), m_code_label (code_label) | |
75 {} | |
0 | 76 |
111 | 77 /* Lowest index value for this label. */ |
78 tree m_low; | |
79 /* Highest index value for this label. */ | |
80 tree m_high; | |
81 /* Label to jump to when node matches. */ | |
82 tree m_code_label; | |
0 | 83 }; |
84 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
85 static bool check_unique_operand_names (tree, tree, tree); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
86 static char *resolve_operand_name_1 (char *, tree, tree, tree); |
0 | 87 |
88 /* Return the rtx-label that corresponds to a LABEL_DECL, | |
89 creating it if necessary. */ | |
90 | |
111 | 91 rtx_insn * |
0 | 92 label_rtx (tree label) |
93 { | |
94 gcc_assert (TREE_CODE (label) == LABEL_DECL); | |
95 | |
96 if (!DECL_RTL_SET_P (label)) | |
97 { | |
111 | 98 rtx_code_label *r = gen_label_rtx (); |
0 | 99 SET_DECL_RTL (label, r); |
100 if (FORCED_LABEL (label) || DECL_NONLOCAL (label)) | |
101 LABEL_PRESERVE_P (r) = 1; | |
102 } | |
103 | |
111 | 104 return as_a <rtx_insn *> (DECL_RTL (label)); |
0 | 105 } |
106 | |
107 /* As above, but also put it on the forced-reference list of the | |
108 function that contains it. */ | |
111 | 109 rtx_insn * |
0 | 110 force_label_rtx (tree label) |
111 { | |
111 | 112 rtx_insn *ref = label_rtx (label); |
0 | 113 tree function = decl_function_context (label); |
114 | |
115 gcc_assert (function); | |
116 | |
111 | 117 vec_safe_push (forced_labels, ref); |
0 | 118 return ref; |
119 } | |
120 | |
111 | 121 /* As label_rtx, but ensures (in check build), that returned value is |
122 an existing label (i.e. rtx with code CODE_LABEL). */ | |
123 rtx_code_label * | |
124 jump_target_rtx (tree label) | |
125 { | |
126 return as_a <rtx_code_label *> (label_rtx (label)); | |
127 } | |
128 | |
0 | 129 /* Add an unconditional jump to LABEL as the next sequential instruction. */ |
130 | |
131 void | |
132 emit_jump (rtx label) | |
133 { | |
134 do_pending_stack_adjust (); | |
111 | 135 emit_jump_insn (targetm.gen_jump (label)); |
0 | 136 emit_barrier (); |
137 } | |
138 | |
139 /* Handle goto statements and the labels that they can go to. */ | |
140 | |
141 /* Specify the location in the RTL code of a label LABEL, | |
142 which is a LABEL_DECL tree node. | |
143 | |
144 This is used for the kind of label that the user can jump to with a | |
145 goto statement, and for alternatives of a switch or case statement. | |
146 RTL labels generated for loops and conditionals don't go through here; | |
147 they are generated directly at the RTL level, by other functions below. | |
148 | |
149 Note that this has nothing to do with defining label *names*. | |
150 Languages vary in how they do that and what that even means. */ | |
151 | |
152 void | |
153 expand_label (tree label) | |
154 { | |
111 | 155 rtx_code_label *label_r = jump_target_rtx (label); |
0 | 156 |
157 do_pending_stack_adjust (); | |
158 emit_label (label_r); | |
159 if (DECL_NAME (label)) | |
160 LABEL_NAME (DECL_RTL (label)) = IDENTIFIER_POINTER (DECL_NAME (label)); | |
161 | |
162 if (DECL_NONLOCAL (label)) | |
163 { | |
111 | 164 expand_builtin_setjmp_receiver (NULL); |
0 | 165 nonlocal_goto_handler_labels |
111 | 166 = gen_rtx_INSN_LIST (VOIDmode, label_r, |
0 | 167 nonlocal_goto_handler_labels); |
168 } | |
169 | |
170 if (FORCED_LABEL (label)) | |
111 | 171 vec_safe_push<rtx_insn *> (forced_labels, label_r); |
0 | 172 |
173 if (DECL_NONLOCAL (label) || FORCED_LABEL (label)) | |
174 maybe_set_first_label_num (label_r); | |
175 } | |
176 | |
177 /* Parse the output constraint pointed to by *CONSTRAINT_P. It is the | |
178 OPERAND_NUMth output operand, indexed from zero. There are NINPUTS | |
179 inputs and NOUTPUTS outputs to this extended-asm. Upon return, | |
180 *ALLOWS_MEM will be TRUE iff the constraint allows the use of a | |
181 memory operand. Similarly, *ALLOWS_REG will be TRUE iff the | |
182 constraint allows the use of a register operand. And, *IS_INOUT | |
183 will be true if the operand is read-write, i.e., if it is used as | |
184 an input as well as an output. If *CONSTRAINT_P is not in | |
185 canonical form, it will be made canonical. (Note that `+' will be | |
186 replaced with `=' as part of this process.) | |
187 | |
188 Returns TRUE if all went well; FALSE if an error occurred. */ | |
189 | |
190 bool | |
191 parse_output_constraint (const char **constraint_p, int operand_num, | |
192 int ninputs, int noutputs, bool *allows_mem, | |
193 bool *allows_reg, bool *is_inout) | |
194 { | |
195 const char *constraint = *constraint_p; | |
196 const char *p; | |
197 | |
198 /* Assume the constraint doesn't allow the use of either a register | |
199 or memory. */ | |
200 *allows_mem = false; | |
201 *allows_reg = false; | |
202 | |
203 /* Allow the `=' or `+' to not be at the beginning of the string, | |
204 since it wasn't explicitly documented that way, and there is a | |
205 large body of code that puts it last. Swap the character to | |
206 the front, so as not to uglify any place else. */ | |
207 p = strchr (constraint, '='); | |
208 if (!p) | |
209 p = strchr (constraint, '+'); | |
210 | |
211 /* If the string doesn't contain an `=', issue an error | |
212 message. */ | |
213 if (!p) | |
214 { | |
215 error ("output operand constraint lacks %<=%>"); | |
216 return false; | |
217 } | |
218 | |
219 /* If the constraint begins with `+', then the operand is both read | |
220 from and written to. */ | |
221 *is_inout = (*p == '+'); | |
222 | |
223 /* Canonicalize the output constraint so that it begins with `='. */ | |
224 if (p != constraint || *is_inout) | |
225 { | |
226 char *buf; | |
227 size_t c_len = strlen (constraint); | |
228 | |
229 if (p != constraint) | |
230 warning (0, "output constraint %qc for operand %d " | |
231 "is not at the beginning", | |
232 *p, operand_num); | |
233 | |
234 /* Make a copy of the constraint. */ | |
235 buf = XALLOCAVEC (char, c_len + 1); | |
236 strcpy (buf, constraint); | |
237 /* Swap the first character and the `=' or `+'. */ | |
238 buf[p - constraint] = buf[0]; | |
239 /* Make sure the first character is an `='. (Until we do this, | |
240 it might be a `+'.) */ | |
241 buf[0] = '='; | |
242 /* Replace the constraint with the canonicalized string. */ | |
243 *constraint_p = ggc_alloc_string (buf, c_len); | |
244 constraint = *constraint_p; | |
245 } | |
246 | |
247 /* Loop through the constraint string. */ | |
131 | 248 for (p = constraint + 1; *p; ) |
249 { | |
250 switch (*p) | |
251 { | |
252 case '+': | |
253 case '=': | |
254 error ("operand constraint contains incorrectly positioned " | |
255 "%<+%> or %<=%>"); | |
256 return false; | |
0 | 257 |
131 | 258 case '%': |
259 if (operand_num + 1 == ninputs + noutputs) | |
260 { | |
261 error ("%<%%%> constraint used with last operand"); | |
262 return false; | |
263 } | |
264 break; | |
0 | 265 |
131 | 266 case '?': case '!': case '*': case '&': case '#': |
267 case '$': case '^': | |
268 case 'E': case 'F': case 'G': case 'H': | |
269 case 's': case 'i': case 'n': | |
270 case 'I': case 'J': case 'K': case 'L': case 'M': | |
271 case 'N': case 'O': case 'P': case ',': | |
272 break; | |
0 | 273 |
131 | 274 case '0': case '1': case '2': case '3': case '4': |
275 case '5': case '6': case '7': case '8': case '9': | |
276 case '[': | |
277 error ("matching constraint not valid in output operand"); | |
278 return false; | |
0 | 279 |
131 | 280 case '<': case '>': |
281 /* ??? Before flow, auto inc/dec insns are not supposed to exist, | |
282 excepting those that expand_call created. So match memory | |
283 and hope. */ | |
284 *allows_mem = true; | |
285 break; | |
286 | |
287 case 'g': case 'X': | |
288 *allows_reg = true; | |
289 *allows_mem = true; | |
290 break; | |
0 | 291 |
131 | 292 default: |
293 if (!ISALPHA (*p)) | |
294 break; | |
295 enum constraint_num cn = lookup_constraint (p); | |
296 if (reg_class_for_constraint (cn) != NO_REGS | |
297 || insn_extra_address_constraint (cn)) | |
298 *allows_reg = true; | |
299 else if (insn_extra_memory_constraint (cn)) | |
300 *allows_mem = true; | |
301 else | |
302 insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem); | |
0 | 303 break; |
131 | 304 } |
305 | |
306 for (size_t len = CONSTRAINT_LEN (*p, p); len; len--, p++) | |
307 if (*p == '\0') | |
308 break; | |
309 } | |
0 | 310 |
311 return true; | |
312 } | |
313 | |
314 /* Similar, but for input constraints. */ | |
315 | |
316 bool | |
317 parse_input_constraint (const char **constraint_p, int input_num, | |
318 int ninputs, int noutputs, int ninout, | |
319 const char * const * constraints, | |
320 bool *allows_mem, bool *allows_reg) | |
321 { | |
322 const char *constraint = *constraint_p; | |
323 const char *orig_constraint = constraint; | |
324 size_t c_len = strlen (constraint); | |
325 size_t j; | |
326 bool saw_match = false; | |
327 | |
328 /* Assume the constraint doesn't allow the use of either | |
329 a register or memory. */ | |
330 *allows_mem = false; | |
331 *allows_reg = false; | |
332 | |
333 /* Make sure constraint has neither `=', `+', nor '&'. */ | |
334 | |
335 for (j = 0; j < c_len; j += CONSTRAINT_LEN (constraint[j], constraint+j)) | |
336 switch (constraint[j]) | |
337 { | |
338 case '+': case '=': case '&': | |
339 if (constraint == orig_constraint) | |
340 { | |
341 error ("input operand constraint contains %qc", constraint[j]); | |
342 return false; | |
343 } | |
344 break; | |
345 | |
346 case '%': | |
347 if (constraint == orig_constraint | |
348 && input_num + 1 == ninputs - ninout) | |
349 { | |
350 error ("%<%%%> constraint used with last operand"); | |
351 return false; | |
352 } | |
353 break; | |
354 | |
355 case '<': case '>': | |
356 case '?': case '!': case '*': case '#': | |
111 | 357 case '$': case '^': |
0 | 358 case 'E': case 'F': case 'G': case 'H': |
359 case 's': case 'i': case 'n': | |
360 case 'I': case 'J': case 'K': case 'L': case 'M': | |
361 case 'N': case 'O': case 'P': case ',': | |
362 break; | |
363 | |
364 /* Whether or not a numeric constraint allows a register is | |
365 decided by the matching constraint, and so there is no need | |
366 to do anything special with them. We must handle them in | |
367 the default case, so that we don't unnecessarily force | |
368 operands to memory. */ | |
369 case '0': case '1': case '2': case '3': case '4': | |
370 case '5': case '6': case '7': case '8': case '9': | |
371 { | |
372 char *end; | |
373 unsigned long match; | |
374 | |
375 saw_match = true; | |
376 | |
377 match = strtoul (constraint + j, &end, 10); | |
378 if (match >= (unsigned long) noutputs) | |
379 { | |
380 error ("matching constraint references invalid operand number"); | |
381 return false; | |
382 } | |
383 | |
384 /* Try and find the real constraint for this dup. Only do this | |
385 if the matching constraint is the only alternative. */ | |
386 if (*end == '\0' | |
387 && (j == 0 || (j == 1 && constraint[0] == '%'))) | |
388 { | |
389 constraint = constraints[match]; | |
390 *constraint_p = constraint; | |
391 c_len = strlen (constraint); | |
392 j = 0; | |
393 /* ??? At the end of the loop, we will skip the first part of | |
394 the matched constraint. This assumes not only that the | |
395 other constraint is an output constraint, but also that | |
396 the '=' or '+' come first. */ | |
397 break; | |
398 } | |
399 else | |
400 j = end - constraint; | |
401 /* Anticipate increment at end of loop. */ | |
402 j--; | |
403 } | |
404 /* Fall through. */ | |
405 | |
406 case 'g': case 'X': | |
407 *allows_reg = true; | |
408 *allows_mem = true; | |
409 break; | |
410 | |
411 default: | |
412 if (! ISALPHA (constraint[j])) | |
413 { | |
414 error ("invalid punctuation %qc in constraint", constraint[j]); | |
415 return false; | |
416 } | |
111 | 417 enum constraint_num cn = lookup_constraint (constraint + j); |
418 if (reg_class_for_constraint (cn) != NO_REGS | |
419 || insn_extra_address_constraint (cn)) | |
0 | 420 *allows_reg = true; |
111 | 421 else if (insn_extra_memory_constraint (cn) |
422 || insn_extra_special_memory_constraint (cn)) | |
0 | 423 *allows_mem = true; |
424 else | |
111 | 425 insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem); |
0 | 426 break; |
427 } | |
428 | |
429 if (saw_match && !*allows_reg) | |
430 warning (0, "matching constraint does not allow a register"); | |
431 | |
432 return true; | |
433 } | |
434 | |
435 /* Return DECL iff there's an overlap between *REGS and DECL, where DECL | |
436 can be an asm-declared register. Called via walk_tree. */ | |
437 | |
438 static tree | |
439 decl_overlaps_hard_reg_set_p (tree *declp, int *walk_subtrees ATTRIBUTE_UNUSED, | |
440 void *data) | |
441 { | |
442 tree decl = *declp; | |
443 const HARD_REG_SET *const regs = (const HARD_REG_SET *) data; | |
444 | |
111 | 445 if (VAR_P (decl)) |
0 | 446 { |
447 if (DECL_HARD_REGISTER (decl) | |
448 && REG_P (DECL_RTL (decl)) | |
449 && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER) | |
450 { | |
451 rtx reg = DECL_RTL (decl); | |
452 | |
453 if (overlaps_hard_reg_set_p (*regs, GET_MODE (reg), REGNO (reg))) | |
454 return decl; | |
455 } | |
456 walk_subtrees = 0; | |
457 } | |
458 else if (TYPE_P (decl) || TREE_CODE (decl) == PARM_DECL) | |
459 walk_subtrees = 0; | |
460 return NULL_TREE; | |
461 } | |
462 | |
463 /* If there is an overlap between *REGS and DECL, return the first overlap | |
464 found. */ | |
465 tree | |
466 tree_overlaps_hard_reg_set (tree decl, HARD_REG_SET *regs) | |
467 { | |
468 return walk_tree (&decl, decl_overlaps_hard_reg_set_p, regs, NULL); | |
469 } | |
470 | |
471 | |
472 /* A subroutine of expand_asm_operands. Check that all operand names | |
473 are unique. Return true if so. We rely on the fact that these names | |
474 are identifiers, and so have been canonicalized by get_identifier, | |
475 so all we need are pointer comparisons. */ | |
476 | |
477 static bool | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
478 check_unique_operand_names (tree outputs, tree inputs, tree labels) |
0 | 479 { |
111 | 480 tree i, j, i_name = NULL_TREE; |
0 | 481 |
482 for (i = outputs; i ; i = TREE_CHAIN (i)) | |
483 { | |
111 | 484 i_name = TREE_PURPOSE (TREE_PURPOSE (i)); |
0 | 485 if (! i_name) |
486 continue; | |
487 | |
488 for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j)) | |
489 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j)))) | |
490 goto failure; | |
491 } | |
492 | |
493 for (i = inputs; i ; i = TREE_CHAIN (i)) | |
494 { | |
111 | 495 i_name = TREE_PURPOSE (TREE_PURPOSE (i)); |
0 | 496 if (! i_name) |
497 continue; | |
498 | |
499 for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j)) | |
500 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j)))) | |
501 goto failure; | |
502 for (j = outputs; j ; j = TREE_CHAIN (j)) | |
503 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j)))) | |
504 goto failure; | |
505 } | |
506 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
507 for (i = labels; i ; i = TREE_CHAIN (i)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
508 { |
111 | 509 i_name = TREE_PURPOSE (i); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
510 if (! i_name) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
511 continue; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
512 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
513 for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
514 if (simple_cst_equal (i_name, TREE_PURPOSE (j))) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
515 goto failure; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
516 for (j = inputs; j ; j = TREE_CHAIN (j)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
517 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j)))) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
518 goto failure; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
519 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
520 |
0 | 521 return true; |
522 | |
523 failure: | |
145 | 524 error ("duplicate %<asm%> operand name %qs", TREE_STRING_POINTER (i_name)); |
0 | 525 return false; |
526 } | |
527 | |
111 | 528 /* Resolve the names of the operands in *POUTPUTS and *PINPUTS to numbers, |
529 and replace the name expansions in STRING and in the constraints to | |
530 those numbers. This is generally done in the front end while creating | |
531 the ASM_EXPR generic tree that eventually becomes the GIMPLE_ASM. */ | |
0 | 532 |
533 tree | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
534 resolve_asm_operand_names (tree string, tree outputs, tree inputs, tree labels) |
0 | 535 { |
536 char *buffer; | |
537 char *p; | |
538 const char *c; | |
539 tree t; | |
540 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
541 check_unique_operand_names (outputs, inputs, labels); |
0 | 542 |
543 /* Substitute [<name>] in input constraint strings. There should be no | |
544 named operands in output constraints. */ | |
545 for (t = inputs; t ; t = TREE_CHAIN (t)) | |
546 { | |
547 c = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))); | |
548 if (strchr (c, '[') != NULL) | |
549 { | |
550 p = buffer = xstrdup (c); | |
551 while ((p = strchr (p, '[')) != NULL) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
552 p = resolve_operand_name_1 (p, outputs, inputs, NULL); |
0 | 553 TREE_VALUE (TREE_PURPOSE (t)) |
554 = build_string (strlen (buffer), buffer); | |
555 free (buffer); | |
556 } | |
557 } | |
558 | |
559 /* Now check for any needed substitutions in the template. */ | |
560 c = TREE_STRING_POINTER (string); | |
561 while ((c = strchr (c, '%')) != NULL) | |
562 { | |
563 if (c[1] == '[') | |
564 break; | |
565 else if (ISALPHA (c[1]) && c[2] == '[') | |
566 break; | |
567 else | |
568 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
569 c += 1 + (c[1] == '%'); |
0 | 570 continue; |
571 } | |
572 } | |
573 | |
574 if (c) | |
575 { | |
576 /* OK, we need to make a copy so we can perform the substitutions. | |
577 Assume that we will not need extra space--we get to remove '[' | |
578 and ']', which means we cannot have a problem until we have more | |
579 than 999 operands. */ | |
580 buffer = xstrdup (TREE_STRING_POINTER (string)); | |
581 p = buffer + (c - TREE_STRING_POINTER (string)); | |
582 | |
583 while ((p = strchr (p, '%')) != NULL) | |
584 { | |
585 if (p[1] == '[') | |
586 p += 1; | |
587 else if (ISALPHA (p[1]) && p[2] == '[') | |
588 p += 2; | |
589 else | |
590 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
591 p += 1 + (p[1] == '%'); |
0 | 592 continue; |
593 } | |
594 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
595 p = resolve_operand_name_1 (p, outputs, inputs, labels); |
0 | 596 } |
597 | |
598 string = build_string (strlen (buffer), buffer); | |
599 free (buffer); | |
600 } | |
601 | |
602 return string; | |
603 } | |
604 | |
605 /* A subroutine of resolve_operand_names. P points to the '[' for a | |
606 potential named operand of the form [<name>]. In place, replace | |
607 the name and brackets with a number. Return a pointer to the | |
608 balance of the string after substitution. */ | |
609 | |
610 static char * | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
611 resolve_operand_name_1 (char *p, tree outputs, tree inputs, tree labels) |
0 | 612 { |
613 char *q; | |
614 int op; | |
615 tree t; | |
616 | |
617 /* Collect the operand name. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
618 q = strchr (++p, ']'); |
0 | 619 if (!q) |
620 { | |
621 error ("missing close brace for named operand"); | |
622 return strchr (p, '\0'); | |
623 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
624 *q = '\0'; |
0 | 625 |
626 /* Resolve the name to a number. */ | |
627 for (op = 0, t = outputs; t ; t = TREE_CHAIN (t), op++) | |
628 { | |
629 tree name = TREE_PURPOSE (TREE_PURPOSE (t)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
630 if (name && strcmp (TREE_STRING_POINTER (name), p) == 0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
631 goto found; |
0 | 632 } |
633 for (t = inputs; t ; t = TREE_CHAIN (t), op++) | |
634 { | |
635 tree name = TREE_PURPOSE (TREE_PURPOSE (t)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
636 if (name && strcmp (TREE_STRING_POINTER (name), p) == 0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
637 goto found; |
0 | 638 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
639 for (t = labels; t ; t = TREE_CHAIN (t), op++) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
640 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
641 tree name = TREE_PURPOSE (t); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
642 if (name && strcmp (TREE_STRING_POINTER (name), p) == 0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
643 goto found; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
644 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
645 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
646 error ("undefined named operand %qs", identifier_to_locale (p)); |
0 | 647 op = 0; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
648 |
0 | 649 found: |
650 /* Replace the name with the number. Unfortunately, not all libraries | |
651 get the return value of sprintf correct, so search for the end of the | |
652 generated string by hand. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
653 sprintf (--p, "%d", op); |
0 | 654 p = strchr (p, '\0'); |
655 | |
656 /* Verify the no extra buffer space assumption. */ | |
657 gcc_assert (p <= q); | |
658 | |
659 /* Shift the rest of the buffer down to fill the gap. */ | |
660 memmove (p, q + 1, strlen (q + 1) + 1); | |
661 | |
662 return p; | |
663 } | |
664 | |
665 | |
666 /* Generate RTL to return directly from the current function. | |
667 (That is, we bypass any return value.) */ | |
668 | |
669 void | |
670 expand_naked_return (void) | |
671 { | |
111 | 672 rtx_code_label *end_label; |
0 | 673 |
674 clear_pending_stack_adjust (); | |
675 do_pending_stack_adjust (); | |
676 | |
677 end_label = naked_return_label; | |
678 if (end_label == 0) | |
679 end_label = naked_return_label = gen_label_rtx (); | |
680 | |
681 emit_jump (end_label); | |
682 } | |
683 | |
111 | 684 /* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE. PROB |
685 is the probability of jumping to LABEL. */ | |
686 static void | |
687 do_jump_if_equal (machine_mode mode, rtx op0, rtx op1, rtx_code_label *label, | |
688 int unsignedp, profile_probability prob) | |
689 { | |
690 do_compare_rtx_and_jump (op0, op1, EQ, unsignedp, mode, | |
691 NULL_RTX, NULL, label, prob); | |
692 } | |
693 | |
694 /* Return the sum of probabilities of outgoing edges of basic block BB. */ | |
695 | |
696 static profile_probability | |
697 get_outgoing_edge_probs (basic_block bb) | |
698 { | |
699 edge e; | |
700 edge_iterator ei; | |
701 profile_probability prob_sum = profile_probability::never (); | |
702 if (!bb) | |
703 return profile_probability::never (); | |
704 FOR_EACH_EDGE (e, ei, bb->succs) | |
705 prob_sum += e->probability; | |
706 return prob_sum; | |
707 } | |
708 | |
709 /* Computes the conditional probability of jumping to a target if the branch | |
710 instruction is executed. | |
711 TARGET_PROB is the estimated probability of jumping to a target relative | |
712 to some basic block BB. | |
713 BASE_PROB is the probability of reaching the branch instruction relative | |
714 to the same basic block BB. */ | |
715 | |
716 static inline profile_probability | |
717 conditional_probability (profile_probability target_prob, | |
718 profile_probability base_prob) | |
719 { | |
720 return target_prob / base_prob; | |
721 } | |
722 | |
723 /* Generate a dispatch tabler, switching on INDEX_EXPR and jumping to | |
724 one of the labels in CASE_LIST or to the DEFAULT_LABEL. | |
725 MINVAL, MAXVAL, and RANGE are the extrema and range of the case | |
726 labels in CASE_LIST. STMT_BB is the basic block containing the statement. | |
727 | |
728 First, a jump insn is emitted. First we try "casesi". If that | |
729 fails, try "tablejump". A target *must* have one of them (or both). | |
730 | |
731 Then, a table with the target labels is emitted. | |
732 | |
733 The process is unaware of the CFG. The caller has to fix up | |
734 the CFG itself. This is done in cfgexpand.c. */ | |
0 | 735 |
736 static void | |
111 | 737 emit_case_dispatch_table (tree index_expr, tree index_type, |
738 auto_vec<simple_case_node> &case_list, | |
739 rtx default_label, | |
740 edge default_edge, tree minval, tree maxval, | |
741 tree range, basic_block stmt_bb) | |
0 | 742 { |
111 | 743 int i, ncases; |
744 rtx *labelvec; | |
745 rtx_insn *fallback_label = label_rtx (case_list[0].m_code_label); | |
746 rtx_code_label *table_label = gen_label_rtx (); | |
747 bool has_gaps = false; | |
748 profile_probability default_prob = default_edge ? default_edge->probability | |
749 : profile_probability::never (); | |
750 profile_probability base = get_outgoing_edge_probs (stmt_bb); | |
751 bool try_with_tablejump = false; | |
0 | 752 |
111 | 753 profile_probability new_default_prob = conditional_probability (default_prob, |
754 base); | |
0 | 755 |
111 | 756 if (! try_casesi (index_type, index_expr, minval, range, |
757 table_label, default_label, fallback_label, | |
758 new_default_prob)) | |
0 | 759 { |
111 | 760 /* Index jumptables from zero for suitable values of minval to avoid |
761 a subtraction. For the rationale see: | |
762 "http://gcc.gnu.org/ml/gcc-patches/2001-10/msg01234.html". */ | |
763 if (optimize_insn_for_speed_p () | |
764 && compare_tree_int (minval, 0) > 0 | |
765 && compare_tree_int (minval, 3) < 0) | |
766 { | |
767 minval = build_int_cst (index_type, 0); | |
768 range = maxval; | |
769 has_gaps = true; | |
770 } | |
771 try_with_tablejump = true; | |
0 | 772 } |
773 | |
111 | 774 /* Get table of labels to jump to, in order of case index. */ |
0 | 775 |
111 | 776 ncases = tree_to_shwi (range) + 1; |
777 labelvec = XALLOCAVEC (rtx, ncases); | |
778 memset (labelvec, 0, ncases * sizeof (rtx)); | |
0 | 779 |
111 | 780 for (unsigned j = 0; j < case_list.length (); j++) |
0 | 781 { |
111 | 782 simple_case_node *n = &case_list[j]; |
783 /* Compute the low and high bounds relative to the minimum | |
784 value since that should fit in a HOST_WIDE_INT while the | |
785 actual values may not. */ | |
786 HOST_WIDE_INT i_low | |
787 = tree_to_uhwi (fold_build2 (MINUS_EXPR, index_type, | |
788 n->m_low, minval)); | |
789 HOST_WIDE_INT i_high | |
790 = tree_to_uhwi (fold_build2 (MINUS_EXPR, index_type, | |
791 n->m_high, minval)); | |
792 HOST_WIDE_INT i; | |
0 | 793 |
111 | 794 for (i = i_low; i <= i_high; i ++) |
795 labelvec[i] | |
796 = gen_rtx_LABEL_REF (Pmode, label_rtx (n->m_code_label)); | |
797 } | |
0 | 798 |
111 | 799 /* The dispatch table may contain gaps, including at the beginning of |
800 the table if we tried to avoid the minval subtraction. We fill the | |
801 dispatch table slots associated with the gaps with the default case label. | |
802 However, in the event the default case is unreachable, we then use | |
803 any label from one of the case statements. */ | |
804 rtx gap_label = (default_label) ? default_label : fallback_label; | |
0 | 805 |
111 | 806 for (i = 0; i < ncases; i++) |
807 if (labelvec[i] == 0) | |
808 { | |
809 has_gaps = true; | |
810 labelvec[i] = gen_rtx_LABEL_REF (Pmode, gap_label); | |
811 } | |
0 | 812 |
111 | 813 if (has_gaps && default_label) |
0 | 814 { |
111 | 815 /* There is at least one entry in the jump table that jumps |
816 to default label. The default label can either be reached | |
817 through the indirect jump or the direct conditional jump | |
818 before that. Split the probability of reaching the | |
819 default label among these two jumps. */ | |
820 new_default_prob | |
821 = conditional_probability (default_prob.apply_scale (1, 2), base); | |
822 default_prob = default_prob.apply_scale (1, 2); | |
823 base -= default_prob; | |
0 | 824 } |
825 else | |
826 { | |
111 | 827 base -= default_prob; |
828 default_prob = profile_probability::never (); | |
0 | 829 } |
830 | |
111 | 831 if (default_edge) |
832 default_edge->probability = default_prob; | |
0 | 833 |
111 | 834 /* We have altered the probability of the default edge. So the probabilities |
835 of all other edges need to be adjusted so that it sums up to | |
836 REG_BR_PROB_BASE. */ | |
837 if (base > profile_probability::never ()) | |
0 | 838 { |
111 | 839 edge e; |
840 edge_iterator ei; | |
841 FOR_EACH_EDGE (e, ei, stmt_bb->succs) | |
842 e->probability /= base; | |
0 | 843 } |
844 | |
111 | 845 if (try_with_tablejump) |
0 | 846 { |
111 | 847 bool ok = try_tablejump (index_type, index_expr, minval, range, |
848 table_label, default_label, new_default_prob); | |
849 gcc_assert (ok); | |
0 | 850 } |
111 | 851 /* Output the table. */ |
852 emit_label (table_label); | |
0 | 853 |
131 | 854 if (CASE_VECTOR_PC_RELATIVE |
855 || (flag_pic && targetm.asm_out.generate_pic_addr_diff_vec ())) | |
111 | 856 emit_jump_table_data (gen_rtx_ADDR_DIFF_VEC (CASE_VECTOR_MODE, |
857 gen_rtx_LABEL_REF (Pmode, | |
858 table_label), | |
859 gen_rtvec_v (ncases, labelvec), | |
860 const0_rtx, const0_rtx)); | |
0 | 861 else |
111 | 862 emit_jump_table_data (gen_rtx_ADDR_VEC (CASE_VECTOR_MODE, |
863 gen_rtvec_v (ncases, labelvec))); | |
0 | 864 |
111 | 865 /* Record no drop-through after the table. */ |
866 emit_barrier (); | |
0 | 867 } |
868 | |
111 | 869 /* Terminate a case Ada or switch (C) statement |
0 | 870 in which ORIG_INDEX is the expression to be tested. |
871 If ORIG_TYPE is not NULL, it is the original ORIG_INDEX | |
872 type as given in the source before any compiler conversions. | |
873 Generate the code to test it and jump to the right place. */ | |
874 | |
875 void | |
111 | 876 expand_case (gswitch *stmt) |
0 | 877 { |
878 tree minval = NULL_TREE, maxval = NULL_TREE, range = NULL_TREE; | |
111 | 879 rtx_code_label *default_label; |
880 unsigned int count; | |
0 | 881 int i; |
111 | 882 int ncases = gimple_switch_num_labels (stmt); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
883 tree index_expr = gimple_switch_index (stmt); |
0 | 884 tree index_type = TREE_TYPE (index_expr); |
111 | 885 tree elt; |
886 basic_block bb = gimple_bb (stmt); | |
145 | 887 gimple *def_stmt; |
0 | 888 |
111 | 889 auto_vec<simple_case_node> case_list; |
0 | 890 |
111 | 891 /* An ERROR_MARK occurs for various reasons including invalid data type. |
892 ??? Can this still happen, with GIMPLE and all? */ | |
893 if (index_type == error_mark_node) | |
894 return; | |
0 | 895 |
111 | 896 /* cleanup_tree_cfg removes all SWITCH_EXPR with their index |
897 expressions being INTEGER_CST. */ | |
898 gcc_assert (TREE_CODE (index_expr) != INTEGER_CST); | |
0 | 899 |
111 | 900 /* Optimization of switch statements with only one label has already |
901 occurred, so we should never see them at this point. */ | |
902 gcc_assert (ncases > 1); | |
0 | 903 |
904 do_pending_stack_adjust (); | |
905 | |
111 | 906 /* Find the default case target label. */ |
907 tree default_lab = CASE_LABEL (gimple_switch_default_label (stmt)); | |
908 default_label = jump_target_rtx (default_lab); | |
131 | 909 basic_block default_bb = label_to_block (cfun, default_lab); |
111 | 910 edge default_edge = find_edge (bb, default_bb); |
0 | 911 |
111 | 912 /* Get upper and lower bounds of case values. */ |
913 elt = gimple_switch_label (stmt, 1); | |
914 minval = fold_convert (index_type, CASE_LOW (elt)); | |
915 elt = gimple_switch_label (stmt, ncases - 1); | |
916 if (CASE_HIGH (elt)) | |
917 maxval = fold_convert (index_type, CASE_HIGH (elt)); | |
918 else | |
919 maxval = fold_convert (index_type, CASE_LOW (elt)); | |
0 | 920 |
145 | 921 /* Try to narrow the index type if it's larger than a word. |
922 That is mainly for -O0 where an equivalent optimization | |
923 done by forward propagation is not run and is aimed at | |
924 avoiding a call to a comparison routine of libgcc. */ | |
925 if (TYPE_PRECISION (index_type) > BITS_PER_WORD | |
926 && TREE_CODE (index_expr) == SSA_NAME | |
927 && (def_stmt = SSA_NAME_DEF_STMT (index_expr)) | |
928 && is_gimple_assign (def_stmt) | |
929 && gimple_assign_rhs_code (def_stmt) == NOP_EXPR) | |
930 { | |
931 tree inner_index_expr = gimple_assign_rhs1 (def_stmt); | |
932 tree inner_index_type = TREE_TYPE (inner_index_expr); | |
933 | |
934 if (INTEGRAL_TYPE_P (inner_index_type) | |
935 && TYPE_PRECISION (inner_index_type) <= BITS_PER_WORD | |
936 && int_fits_type_p (minval, inner_index_type) | |
937 && int_fits_type_p (maxval, inner_index_type)) | |
938 { | |
939 index_expr = inner_index_expr; | |
940 index_type = inner_index_type; | |
941 minval = fold_convert (index_type, minval); | |
942 maxval = fold_convert (index_type, maxval); | |
943 } | |
944 } | |
945 | |
111 | 946 /* Compute span of values. */ |
947 range = fold_build2 (MINUS_EXPR, index_type, maxval, minval); | |
0 | 948 |
111 | 949 /* Listify the labels queue and gather some numbers to decide |
950 how to expand this switch(). */ | |
951 count = 0; | |
0 | 952 |
111 | 953 for (i = ncases - 1; i >= 1; --i) |
954 { | |
955 elt = gimple_switch_label (stmt, i); | |
956 tree low = CASE_LOW (elt); | |
957 gcc_assert (low); | |
958 tree high = CASE_HIGH (elt); | |
959 gcc_assert (! high || tree_int_cst_lt (low, high)); | |
960 tree lab = CASE_LABEL (elt); | |
0 | 961 |
111 | 962 /* Count the elements. |
963 A range counts double, since it requires two compares. */ | |
964 count++; | |
965 if (high) | |
966 count++; | |
0 | 967 |
111 | 968 /* The bounds on the case range, LOW and HIGH, have to be converted |
969 to case's index type TYPE. Note that the original type of the | |
970 case index in the source code is usually "lost" during | |
971 gimplification due to type promotion, but the case labels retain the | |
972 original type. Make sure to drop overflow flags. */ | |
973 low = fold_convert (index_type, low); | |
974 if (TREE_OVERFLOW (low)) | |
975 low = wide_int_to_tree (index_type, wi::to_wide (low)); | |
0 | 976 |
111 | 977 /* The canonical from of a case label in GIMPLE is that a simple case |
978 has an empty CASE_HIGH. For the casesi and tablejump expanders, | |
979 the back ends want simple cases to have high == low. */ | |
980 if (! high) | |
981 high = low; | |
982 high = fold_convert (index_type, high); | |
983 if (TREE_OVERFLOW (high)) | |
984 high = wide_int_to_tree (index_type, wi::to_wide (high)); | |
0 | 985 |
111 | 986 case_list.safe_push (simple_case_node (low, high, lab)); |
0 | 987 } |
988 | |
111 | 989 /* cleanup_tree_cfg removes all SWITCH_EXPR with a single |
990 destination, such as one with a default case only. | |
991 It also removes cases that are out of range for the switch | |
992 type, so we should never get a zero here. */ | |
993 gcc_assert (count > 0); | |
0 | 994 |
111 | 995 rtx_insn *before_case = get_last_insn (); |
0 | 996 |
145 | 997 /* If the default case is unreachable, then set default_label to NULL |
998 so that we omit the range check when generating the dispatch table. | |
999 We also remove the edge to the unreachable default case. The block | |
1000 itself will be automatically removed later. */ | |
1001 if (EDGE_COUNT (default_edge->dest->succs) == 0 | |
1002 && gimple_seq_unreachable_p (bb_seq (default_edge->dest))) | |
0 | 1003 { |
145 | 1004 default_label = NULL; |
1005 remove_edge (default_edge); | |
1006 default_edge = NULL; | |
0 | 1007 } |
1008 | |
145 | 1009 emit_case_dispatch_table (index_expr, index_type, |
1010 case_list, default_label, default_edge, | |
1011 minval, maxval, range, bb); | |
1012 | |
111 | 1013 reorder_insns (NEXT_INSN (before_case), get_last_insn (), before_case); |
0 | 1014 |
111 | 1015 free_temp_slots (); |
0 | 1016 } |
1017 | |
111 | 1018 /* Expand the dispatch to a short decrement chain if there are few cases |
1019 to dispatch to. Likewise if neither casesi nor tablejump is available, | |
1020 or if flag_jump_tables is set. Otherwise, expand as a casesi or a | |
1021 tablejump. The index mode is always the mode of integer_type_node. | |
1022 Trap if no case matches the index. | |
0 | 1023 |
111 | 1024 DISPATCH_INDEX is the index expression to switch on. It should be a |
1025 memory or register operand. | |
1026 | |
1027 DISPATCH_TABLE is a set of case labels. The set should be sorted in | |
1028 ascending order, be contiguous, starting with value 0, and contain only | |
1029 single-valued case labels. */ | |
0 | 1030 |
111 | 1031 void |
1032 expand_sjlj_dispatch_table (rtx dispatch_index, | |
1033 vec<tree> dispatch_table) | |
0 | 1034 { |
111 | 1035 tree index_type = integer_type_node; |
1036 machine_mode index_mode = TYPE_MODE (index_type); | |
0 | 1037 |
111 | 1038 int ncases = dispatch_table.length (); |
0 | 1039 |
111 | 1040 do_pending_stack_adjust (); |
1041 rtx_insn *before_case = get_last_insn (); | |
0 | 1042 |
111 | 1043 /* Expand as a decrement-chain if there are 5 or fewer dispatch |
1044 labels. This covers more than 98% of the cases in libjava, | |
1045 and seems to be a reasonable compromise between the "old way" | |
1046 of expanding as a decision tree or dispatch table vs. the "new | |
1047 way" with decrement chain or dispatch table. */ | |
1048 if (dispatch_table.length () <= 5 | |
1049 || (!targetm.have_casesi () && !targetm.have_tablejump ()) | |
1050 || !flag_jump_tables) | |
0 | 1051 { |
111 | 1052 /* Expand the dispatch as a decrement chain: |
0 | 1053 |
111 | 1054 "switch(index) {case 0: do_0; case 1: do_1; ...; case N: do_N;}" |
0 | 1055 |
111 | 1056 ==> |
0 | 1057 |
111 | 1058 if (index == 0) do_0; else index--; |
1059 if (index == 0) do_1; else index--; | |
1060 ... | |
1061 if (index == 0) do_N; else index--; | |
0 | 1062 |
111 | 1063 This is more efficient than a dispatch table on most machines. |
1064 The last "index--" is redundant but the code is trivially dead | |
1065 and will be cleaned up by later passes. */ | |
1066 rtx index = copy_to_mode_reg (index_mode, dispatch_index); | |
1067 rtx zero = CONST0_RTX (index_mode); | |
1068 for (int i = 0; i < ncases; i++) | |
1069 { | |
1070 tree elt = dispatch_table[i]; | |
1071 rtx_code_label *lab = jump_target_rtx (CASE_LABEL (elt)); | |
1072 do_jump_if_equal (index_mode, index, zero, lab, 0, | |
1073 profile_probability::uninitialized ()); | |
1074 force_expand_binop (index_mode, sub_optab, | |
1075 index, CONST1_RTX (index_mode), | |
1076 index, 0, OPTAB_DIRECT); | |
0 | 1077 } |
1078 } | |
1079 else | |
1080 { | |
111 | 1081 /* Similar to expand_case, but much simpler. */ |
1082 auto_vec<simple_case_node> case_list; | |
1083 tree index_expr = make_tree (index_type, dispatch_index); | |
1084 tree minval = build_int_cst (index_type, 0); | |
1085 tree maxval = CASE_LOW (dispatch_table.last ()); | |
1086 tree range = maxval; | |
1087 rtx_code_label *default_label = gen_label_rtx (); | |
0 | 1088 |
111 | 1089 for (int i = ncases - 1; i >= 0; --i) |
1090 { | |
1091 tree elt = dispatch_table[i]; | |
1092 tree high = CASE_HIGH (elt); | |
1093 if (high == NULL_TREE) | |
1094 high = CASE_LOW (elt); | |
1095 case_list.safe_push (simple_case_node (CASE_LOW (elt), high, | |
1096 CASE_LABEL (elt))); | |
0 | 1097 } |
1098 | |
111 | 1099 emit_case_dispatch_table (index_expr, index_type, |
1100 case_list, default_label, NULL, | |
1101 minval, maxval, range, | |
1102 BLOCK_FOR_INSN (before_case)); | |
1103 emit_label (default_label); | |
1104 } | |
0 | 1105 |
111 | 1106 /* Dispatching something not handled? Trap! */ |
1107 expand_builtin_trap (); | |
0 | 1108 |
111 | 1109 reorder_insns (NEXT_INSN (before_case), get_last_insn (), before_case); |
0 | 1110 |
111 | 1111 free_temp_slots (); |
1112 } | |
0 | 1113 |
111 | 1114 |