Mercurial > hg > CbC > CbC_gcc
annotate gcc/cfglayout.c @ 60:bd49c42ec43e
remove unnecessary files
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 15 Feb 2010 17:39:45 +0900 |
parents | 77e2b8dfacca |
children | b7f97abdc517 |
rev | line source |
---|---|
0 | 1 /* Basic block reordering routines for the GNU compiler. |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2 Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
0 | 3 Free Software Foundation, Inc. |
4 | |
5 This file is part of GCC. | |
6 | |
7 GCC is free software; you can redistribute it and/or modify it under | |
8 the terms of the GNU General Public License as published by the Free | |
9 Software Foundation; either version 3, or (at your option) any later | |
10 version. | |
11 | |
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GCC; see the file COPYING3. If not see | |
19 <http://www.gnu.org/licenses/>. */ | |
20 | |
21 #include "config.h" | |
22 #include "system.h" | |
23 #include "coretypes.h" | |
24 #include "tm.h" | |
25 #include "tree.h" | |
26 #include "rtl.h" | |
27 #include "hard-reg-set.h" | |
28 #include "obstack.h" | |
29 #include "basic-block.h" | |
30 #include "insn-config.h" | |
31 #include "output.h" | |
32 #include "function.h" | |
33 #include "cfglayout.h" | |
34 #include "cfgloop.h" | |
35 #include "target.h" | |
36 #include "ggc.h" | |
37 #include "alloc-pool.h" | |
38 #include "flags.h" | |
39 #include "tree-pass.h" | |
40 #include "df.h" | |
41 #include "vecprim.h" | |
42 | |
43 /* Holds the interesting trailing notes for the function. */ | |
44 rtx cfg_layout_function_footer; | |
45 rtx cfg_layout_function_header; | |
46 | |
47 static rtx skip_insns_after_block (basic_block); | |
48 static void record_effective_endpoints (void); | |
49 static rtx label_for_bb (basic_block); | |
50 static void fixup_reorder_chain (void); | |
51 | |
52 static void change_scope (rtx, tree, tree); | |
53 | |
54 void verify_insn_chain (void); | |
55 static void fixup_fallthru_exit_predecessor (void); | |
56 static tree insn_scope (const_rtx); | |
57 | |
58 rtx | |
59 unlink_insn_chain (rtx first, rtx last) | |
60 { | |
61 rtx prevfirst = PREV_INSN (first); | |
62 rtx nextlast = NEXT_INSN (last); | |
63 | |
64 PREV_INSN (first) = NULL; | |
65 NEXT_INSN (last) = NULL; | |
66 if (prevfirst) | |
67 NEXT_INSN (prevfirst) = nextlast; | |
68 if (nextlast) | |
69 PREV_INSN (nextlast) = prevfirst; | |
70 else | |
71 set_last_insn (prevfirst); | |
72 if (!prevfirst) | |
73 set_first_insn (nextlast); | |
74 return first; | |
75 } | |
76 | |
77 /* Skip over inter-block insns occurring after BB which are typically | |
78 associated with BB (e.g., barriers). If there are any such insns, | |
79 we return the last one. Otherwise, we return the end of BB. */ | |
80 | |
81 static rtx | |
82 skip_insns_after_block (basic_block bb) | |
83 { | |
84 rtx insn, last_insn, next_head, prev; | |
85 | |
86 next_head = NULL_RTX; | |
87 if (bb->next_bb != EXIT_BLOCK_PTR) | |
88 next_head = BB_HEAD (bb->next_bb); | |
89 | |
90 for (last_insn = insn = BB_END (bb); (insn = NEXT_INSN (insn)) != 0; ) | |
91 { | |
92 if (insn == next_head) | |
93 break; | |
94 | |
95 switch (GET_CODE (insn)) | |
96 { | |
97 case BARRIER: | |
98 last_insn = insn; | |
99 continue; | |
100 | |
101 case NOTE: | |
102 switch (NOTE_KIND (insn)) | |
103 { | |
104 case NOTE_INSN_BLOCK_END: | |
105 gcc_unreachable (); | |
106 continue; | |
107 default: | |
108 continue; | |
109 break; | |
110 } | |
111 break; | |
112 | |
113 case CODE_LABEL: | |
114 if (NEXT_INSN (insn) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
115 && JUMP_TABLE_DATA_P (NEXT_INSN (insn))) |
0 | 116 { |
117 insn = NEXT_INSN (insn); | |
118 last_insn = insn; | |
119 continue; | |
120 } | |
121 break; | |
122 | |
123 default: | |
124 break; | |
125 } | |
126 | |
127 break; | |
128 } | |
129 | |
130 /* It is possible to hit contradictory sequence. For instance: | |
131 | |
132 jump_insn | |
133 NOTE_INSN_BLOCK_BEG | |
134 barrier | |
135 | |
136 Where barrier belongs to jump_insn, but the note does not. This can be | |
137 created by removing the basic block originally following | |
138 NOTE_INSN_BLOCK_BEG. In such case reorder the notes. */ | |
139 | |
140 for (insn = last_insn; insn != BB_END (bb); insn = prev) | |
141 { | |
142 prev = PREV_INSN (insn); | |
143 if (NOTE_P (insn)) | |
144 switch (NOTE_KIND (insn)) | |
145 { | |
146 case NOTE_INSN_BLOCK_END: | |
147 gcc_unreachable (); | |
148 break; | |
149 case NOTE_INSN_DELETED: | |
150 case NOTE_INSN_DELETED_LABEL: | |
151 continue; | |
152 default: | |
153 reorder_insns (insn, insn, last_insn); | |
154 } | |
155 } | |
156 | |
157 return last_insn; | |
158 } | |
159 | |
160 /* Locate or create a label for a given basic block. */ | |
161 | |
162 static rtx | |
163 label_for_bb (basic_block bb) | |
164 { | |
165 rtx label = BB_HEAD (bb); | |
166 | |
167 if (!LABEL_P (label)) | |
168 { | |
169 if (dump_file) | |
170 fprintf (dump_file, "Emitting label for block %d\n", bb->index); | |
171 | |
172 label = block_label (bb); | |
173 } | |
174 | |
175 return label; | |
176 } | |
177 | |
178 /* Locate the effective beginning and end of the insn chain for each | |
179 block, as defined by skip_insns_after_block above. */ | |
180 | |
181 static void | |
182 record_effective_endpoints (void) | |
183 { | |
184 rtx next_insn; | |
185 basic_block bb; | |
186 rtx insn; | |
187 | |
188 for (insn = get_insns (); | |
189 insn | |
190 && NOTE_P (insn) | |
191 && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK; | |
192 insn = NEXT_INSN (insn)) | |
193 continue; | |
194 /* No basic blocks at all? */ | |
195 gcc_assert (insn); | |
196 | |
197 if (PREV_INSN (insn)) | |
198 cfg_layout_function_header = | |
199 unlink_insn_chain (get_insns (), PREV_INSN (insn)); | |
200 else | |
201 cfg_layout_function_header = NULL_RTX; | |
202 | |
203 next_insn = get_insns (); | |
204 FOR_EACH_BB (bb) | |
205 { | |
206 rtx end; | |
207 | |
208 if (PREV_INSN (BB_HEAD (bb)) && next_insn != BB_HEAD (bb)) | |
209 bb->il.rtl->header = unlink_insn_chain (next_insn, | |
210 PREV_INSN (BB_HEAD (bb))); | |
211 end = skip_insns_after_block (bb); | |
212 if (NEXT_INSN (BB_END (bb)) && BB_END (bb) != end) | |
213 bb->il.rtl->footer = unlink_insn_chain (NEXT_INSN (BB_END (bb)), end); | |
214 next_insn = NEXT_INSN (BB_END (bb)); | |
215 } | |
216 | |
217 cfg_layout_function_footer = next_insn; | |
218 if (cfg_layout_function_footer) | |
219 cfg_layout_function_footer = unlink_insn_chain (cfg_layout_function_footer, get_last_insn ()); | |
220 } | |
221 | |
222 /* Data structures representing mapping of INSN_LOCATOR into scope blocks, line | |
223 numbers and files. In order to be GGC friendly we need to use separate | |
224 varrays. This also slightly improve the memory locality in binary search. | |
225 The _locs array contains locators where the given property change. The | |
226 block_locators_blocks contains the scope block that is used for all insn | |
227 locator greater than corresponding block_locators_locs value and smaller | |
228 than the following one. Similarly for the other properties. */ | |
229 static VEC(int,heap) *block_locators_locs; | |
230 static GTY(()) VEC(tree,gc) *block_locators_blocks; | |
231 static VEC(int,heap) *locations_locators_locs; | |
232 DEF_VEC_O(location_t); | |
233 DEF_VEC_ALLOC_O(location_t,heap); | |
234 static VEC(location_t,heap) *locations_locators_vals; | |
235 int prologue_locator; | |
236 int epilogue_locator; | |
237 | |
238 /* Hold current location information and last location information, so the | |
239 datastructures are built lazily only when some instructions in given | |
240 place are needed. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
241 static location_t curr_location, last_location; |
0 | 242 static tree curr_block, last_block; |
243 static int curr_rtl_loc = -1; | |
244 | |
245 /* Allocate insn locator datastructure. */ | |
246 void | |
247 insn_locators_alloc (void) | |
248 { | |
249 prologue_locator = epilogue_locator = 0; | |
250 | |
251 block_locators_locs = VEC_alloc (int, heap, 32); | |
252 block_locators_blocks = VEC_alloc (tree, gc, 32); | |
253 locations_locators_locs = VEC_alloc (int, heap, 32); | |
254 locations_locators_vals = VEC_alloc (location_t, heap, 32); | |
255 | |
256 last_location = -1; | |
257 curr_location = -1; | |
258 curr_block = NULL; | |
259 last_block = NULL; | |
260 curr_rtl_loc = 0; | |
261 } | |
262 | |
263 /* At the end of emit stage, clear current location. */ | |
264 void | |
265 insn_locators_finalize (void) | |
266 { | |
267 if (curr_rtl_loc >= 0) | |
268 epilogue_locator = curr_insn_locator (); | |
269 curr_rtl_loc = -1; | |
270 } | |
271 | |
272 /* Allocate insn locator datastructure. */ | |
273 void | |
274 insn_locators_free (void) | |
275 { | |
276 prologue_locator = epilogue_locator = 0; | |
277 | |
278 VEC_free (int, heap, block_locators_locs); | |
279 VEC_free (tree,gc, block_locators_blocks); | |
280 VEC_free (int, heap, locations_locators_locs); | |
281 VEC_free (location_t, heap, locations_locators_vals); | |
282 } | |
283 | |
284 | |
285 /* Set current location. */ | |
286 void | |
287 set_curr_insn_source_location (location_t location) | |
288 { | |
289 /* IV opts calls into RTL expansion to compute costs of operations. At this | |
290 time locators are not initialized. */ | |
291 if (curr_rtl_loc == -1) | |
292 return; | |
293 curr_location = location; | |
294 } | |
295 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
296 /* Get current location. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
297 location_t |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
298 get_curr_insn_source_location (void) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
299 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
300 return curr_location; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
301 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
302 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
303 /* Set current scope block. */ |
0 | 304 void |
305 set_curr_insn_block (tree b) | |
306 { | |
307 /* IV opts calls into RTL expansion to compute costs of operations. At this | |
308 time locators are not initialized. */ | |
309 if (curr_rtl_loc == -1) | |
310 return; | |
311 if (b) | |
312 curr_block = b; | |
313 } | |
314 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
315 /* Get current scope block. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
316 tree |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
317 get_curr_insn_block (void) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
318 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
319 return curr_block; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
320 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
321 |
0 | 322 /* Return current insn locator. */ |
323 int | |
324 curr_insn_locator (void) | |
325 { | |
326 if (curr_rtl_loc == -1) | |
327 return 0; | |
328 if (last_block != curr_block) | |
329 { | |
330 curr_rtl_loc++; | |
331 VEC_safe_push (int, heap, block_locators_locs, curr_rtl_loc); | |
332 VEC_safe_push (tree, gc, block_locators_blocks, curr_block); | |
333 last_block = curr_block; | |
334 } | |
335 if (last_location != curr_location) | |
336 { | |
337 curr_rtl_loc++; | |
338 VEC_safe_push (int, heap, locations_locators_locs, curr_rtl_loc); | |
339 VEC_safe_push (location_t, heap, locations_locators_vals, &curr_location); | |
340 last_location = curr_location; | |
341 } | |
342 return curr_rtl_loc; | |
343 } | |
344 | |
345 static unsigned int | |
346 into_cfg_layout_mode (void) | |
347 { | |
348 cfg_layout_initialize (0); | |
349 return 0; | |
350 } | |
351 | |
352 static unsigned int | |
353 outof_cfg_layout_mode (void) | |
354 { | |
355 basic_block bb; | |
356 | |
357 FOR_EACH_BB (bb) | |
358 if (bb->next_bb != EXIT_BLOCK_PTR) | |
359 bb->aux = bb->next_bb; | |
360 | |
361 cfg_layout_finalize (); | |
362 | |
363 return 0; | |
364 } | |
365 | |
366 struct rtl_opt_pass pass_into_cfg_layout_mode = | |
367 { | |
368 { | |
369 RTL_PASS, | |
370 "into_cfglayout", /* name */ | |
371 NULL, /* gate */ | |
372 into_cfg_layout_mode, /* execute */ | |
373 NULL, /* sub */ | |
374 NULL, /* next */ | |
375 0, /* static_pass_number */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
376 TV_NONE, /* tv_id */ |
0 | 377 0, /* properties_required */ |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
378 PROP_cfglayout, /* properties_provided */ |
0 | 379 0, /* properties_destroyed */ |
380 0, /* todo_flags_start */ | |
381 TODO_dump_func, /* todo_flags_finish */ | |
382 } | |
383 }; | |
384 | |
385 struct rtl_opt_pass pass_outof_cfg_layout_mode = | |
386 { | |
387 { | |
388 RTL_PASS, | |
389 "outof_cfglayout", /* name */ | |
390 NULL, /* gate */ | |
391 outof_cfg_layout_mode, /* execute */ | |
392 NULL, /* sub */ | |
393 NULL, /* next */ | |
394 0, /* static_pass_number */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
395 TV_NONE, /* tv_id */ |
0 | 396 0, /* properties_required */ |
397 0, /* properties_provided */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
398 PROP_cfglayout, /* properties_destroyed */ |
0 | 399 0, /* todo_flags_start */ |
400 TODO_dump_func, /* todo_flags_finish */ | |
401 } | |
402 }; | |
403 | |
404 /* Return scope resulting from combination of S1 and S2. */ | |
405 static tree | |
406 choose_inner_scope (tree s1, tree s2) | |
407 { | |
408 if (!s1) | |
409 return s2; | |
410 if (!s2) | |
411 return s1; | |
412 if (BLOCK_NUMBER (s1) > BLOCK_NUMBER (s2)) | |
413 return s1; | |
414 return s2; | |
415 } | |
416 | |
417 /* Emit lexical block notes needed to change scope from S1 to S2. */ | |
418 | |
419 static void | |
420 change_scope (rtx orig_insn, tree s1, tree s2) | |
421 { | |
422 rtx insn = orig_insn; | |
423 tree com = NULL_TREE; | |
424 tree ts1 = s1, ts2 = s2; | |
425 tree s; | |
426 | |
427 while (ts1 != ts2) | |
428 { | |
429 gcc_assert (ts1 && ts2); | |
430 if (BLOCK_NUMBER (ts1) > BLOCK_NUMBER (ts2)) | |
431 ts1 = BLOCK_SUPERCONTEXT (ts1); | |
432 else if (BLOCK_NUMBER (ts1) < BLOCK_NUMBER (ts2)) | |
433 ts2 = BLOCK_SUPERCONTEXT (ts2); | |
434 else | |
435 { | |
436 ts1 = BLOCK_SUPERCONTEXT (ts1); | |
437 ts2 = BLOCK_SUPERCONTEXT (ts2); | |
438 } | |
439 } | |
440 com = ts1; | |
441 | |
442 /* Close scopes. */ | |
443 s = s1; | |
444 while (s != com) | |
445 { | |
446 rtx note = emit_note_before (NOTE_INSN_BLOCK_END, insn); | |
447 NOTE_BLOCK (note) = s; | |
448 s = BLOCK_SUPERCONTEXT (s); | |
449 } | |
450 | |
451 /* Open scopes. */ | |
452 s = s2; | |
453 while (s != com) | |
454 { | |
455 insn = emit_note_before (NOTE_INSN_BLOCK_BEG, insn); | |
456 NOTE_BLOCK (insn) = s; | |
457 s = BLOCK_SUPERCONTEXT (s); | |
458 } | |
459 } | |
460 | |
461 /* Return lexical scope block locator belongs to. */ | |
462 static tree | |
463 locator_scope (int loc) | |
464 { | |
465 int max = VEC_length (int, block_locators_locs); | |
466 int min = 0; | |
467 | |
468 /* When block_locators_locs was initialized, the pro- and epilogue | |
469 insns didn't exist yet and can therefore not be found this way. | |
470 But we know that they belong to the outer most block of the | |
471 current function. | |
472 Without this test, the prologue would be put inside the block of | |
473 the first valid instruction in the function and when that first | |
474 insn is part of an inlined function then the low_pc of that | |
475 inlined function is messed up. Likewise for the epilogue and | |
476 the last valid instruction. */ | |
477 if (loc == prologue_locator || loc == epilogue_locator) | |
478 return DECL_INITIAL (cfun->decl); | |
479 | |
480 if (!max || !loc) | |
481 return NULL; | |
482 while (1) | |
483 { | |
484 int pos = (min + max) / 2; | |
485 int tmp = VEC_index (int, block_locators_locs, pos); | |
486 | |
487 if (tmp <= loc && min != pos) | |
488 min = pos; | |
489 else if (tmp > loc && max != pos) | |
490 max = pos; | |
491 else | |
492 { | |
493 min = pos; | |
494 break; | |
495 } | |
496 } | |
497 return VEC_index (tree, block_locators_blocks, min); | |
498 } | |
499 | |
500 /* Return lexical scope block insn belongs to. */ | |
501 static tree | |
502 insn_scope (const_rtx insn) | |
503 { | |
504 return locator_scope (INSN_LOCATOR (insn)); | |
505 } | |
506 | |
507 /* Return line number of the statement specified by the locator. */ | |
508 location_t | |
509 locator_location (int loc) | |
510 { | |
511 int max = VEC_length (int, locations_locators_locs); | |
512 int min = 0; | |
513 | |
514 while (1) | |
515 { | |
516 int pos = (min + max) / 2; | |
517 int tmp = VEC_index (int, locations_locators_locs, pos); | |
518 | |
519 if (tmp <= loc && min != pos) | |
520 min = pos; | |
521 else if (tmp > loc && max != pos) | |
522 max = pos; | |
523 else | |
524 { | |
525 min = pos; | |
526 break; | |
527 } | |
528 } | |
529 return *VEC_index (location_t, locations_locators_vals, min); | |
530 } | |
531 | |
532 /* Return source line of the statement that produced this insn. */ | |
533 int | |
534 locator_line (int loc) | |
535 { | |
536 expanded_location xloc; | |
537 if (!loc) | |
538 return 0; | |
539 else | |
540 xloc = expand_location (locator_location (loc)); | |
541 return xloc.line; | |
542 } | |
543 | |
544 /* Return line number of the statement that produced this insn. */ | |
545 int | |
546 insn_line (const_rtx insn) | |
547 { | |
548 return locator_line (INSN_LOCATOR (insn)); | |
549 } | |
550 | |
551 /* Return source file of the statement specified by LOC. */ | |
552 const char * | |
553 locator_file (int loc) | |
554 { | |
555 expanded_location xloc; | |
556 if (!loc) | |
557 return 0; | |
558 else | |
559 xloc = expand_location (locator_location (loc)); | |
560 return xloc.file; | |
561 } | |
562 | |
563 /* Return source file of the statement that produced this insn. */ | |
564 const char * | |
565 insn_file (const_rtx insn) | |
566 { | |
567 return locator_file (INSN_LOCATOR (insn)); | |
568 } | |
569 | |
570 /* Return true if LOC1 and LOC2 locators have the same location and scope. */ | |
571 bool | |
572 locator_eq (int loc1, int loc2) | |
573 { | |
574 if (loc1 == loc2) | |
575 return true; | |
576 if (locator_location (loc1) != locator_location (loc2)) | |
577 return false; | |
578 return locator_scope (loc1) == locator_scope (loc2); | |
579 } | |
580 | |
581 /* Rebuild all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes based | |
582 on the scope tree and the newly reordered instructions. */ | |
583 | |
584 void | |
585 reemit_insn_block_notes (void) | |
586 { | |
587 tree cur_block = DECL_INITIAL (cfun->decl); | |
588 rtx insn, note; | |
589 | |
590 insn = get_insns (); | |
591 if (!active_insn_p (insn)) | |
592 insn = next_active_insn (insn); | |
593 for (; insn; insn = next_active_insn (insn)) | |
594 { | |
595 tree this_block; | |
596 | |
597 /* Avoid putting scope notes between jump table and its label. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
598 if (JUMP_TABLE_DATA_P (insn)) |
0 | 599 continue; |
600 | |
601 this_block = insn_scope (insn); | |
602 /* For sequences compute scope resulting from merging all scopes | |
603 of instructions nested inside. */ | |
604 if (GET_CODE (PATTERN (insn)) == SEQUENCE) | |
605 { | |
606 int i; | |
607 rtx body = PATTERN (insn); | |
608 | |
609 this_block = NULL; | |
610 for (i = 0; i < XVECLEN (body, 0); i++) | |
611 this_block = choose_inner_scope (this_block, | |
612 insn_scope (XVECEXP (body, 0, i))); | |
613 } | |
614 if (! this_block) | |
615 continue; | |
616 | |
617 if (this_block != cur_block) | |
618 { | |
619 change_scope (insn, cur_block, this_block); | |
620 cur_block = this_block; | |
621 } | |
622 } | |
623 | |
624 /* change_scope emits before the insn, not after. */ | |
625 note = emit_note (NOTE_INSN_DELETED); | |
626 change_scope (note, cur_block, DECL_INITIAL (cfun->decl)); | |
627 delete_insn (note); | |
628 | |
629 reorder_blocks (); | |
630 } | |
631 | |
632 | |
633 /* Link the basic blocks in the correct order, compacting the basic | |
634 block queue while at it. This also clears the visited flag on | |
635 all basic blocks. If STAY_IN_CFGLAYOUT_MODE is false, this function | |
636 also clears the basic block header and footer fields. | |
637 | |
638 This function is usually called after a pass (e.g. tracer) finishes | |
639 some transformations while in cfglayout mode. The required sequence | |
640 of the basic blocks is in a linked list along the bb->aux field. | |
641 This functions re-links the basic block prev_bb and next_bb pointers | |
642 accordingly, and it compacts and renumbers the blocks. */ | |
643 | |
644 void | |
645 relink_block_chain (bool stay_in_cfglayout_mode) | |
646 { | |
647 basic_block bb, prev_bb; | |
648 int index; | |
649 | |
650 /* Maybe dump the re-ordered sequence. */ | |
651 if (dump_file) | |
652 { | |
653 fprintf (dump_file, "Reordered sequence:\n"); | |
654 for (bb = ENTRY_BLOCK_PTR->next_bb, index = NUM_FIXED_BLOCKS; | |
655 bb; | |
656 bb = (basic_block) bb->aux, index++) | |
657 { | |
658 fprintf (dump_file, " %i ", index); | |
659 if (get_bb_original (bb)) | |
660 fprintf (dump_file, "duplicate of %i ", | |
661 get_bb_original (bb)->index); | |
662 else if (forwarder_block_p (bb) | |
663 && !LABEL_P (BB_HEAD (bb))) | |
664 fprintf (dump_file, "compensation "); | |
665 else | |
666 fprintf (dump_file, "bb %i ", bb->index); | |
667 fprintf (dump_file, " [%i]\n", bb->frequency); | |
668 } | |
669 } | |
670 | |
671 /* Now reorder the blocks. */ | |
672 prev_bb = ENTRY_BLOCK_PTR; | |
673 bb = ENTRY_BLOCK_PTR->next_bb; | |
674 for (; bb; prev_bb = bb, bb = (basic_block) bb->aux) | |
675 { | |
676 bb->prev_bb = prev_bb; | |
677 prev_bb->next_bb = bb; | |
678 } | |
679 prev_bb->next_bb = EXIT_BLOCK_PTR; | |
680 EXIT_BLOCK_PTR->prev_bb = prev_bb; | |
681 | |
682 /* Then, clean up the aux and visited fields. */ | |
683 FOR_ALL_BB (bb) | |
684 { | |
685 bb->aux = NULL; | |
686 bb->il.rtl->visited = 0; | |
687 if (!stay_in_cfglayout_mode) | |
688 bb->il.rtl->header = bb->il.rtl->footer = NULL; | |
689 } | |
690 | |
691 /* Maybe reset the original copy tables, they are not valid anymore | |
692 when we renumber the basic blocks in compact_blocks. If we are | |
693 are going out of cfglayout mode, don't re-allocate the tables. */ | |
694 free_original_copy_tables (); | |
695 if (stay_in_cfglayout_mode) | |
696 initialize_original_copy_tables (); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
697 |
0 | 698 /* Finally, put basic_block_info in the new order. */ |
699 compact_blocks (); | |
700 } | |
701 | |
702 | |
703 /* Given a reorder chain, rearrange the code to match. */ | |
704 | |
705 static void | |
706 fixup_reorder_chain (void) | |
707 { | |
708 basic_block bb; | |
709 rtx insn = NULL; | |
710 | |
711 if (cfg_layout_function_header) | |
712 { | |
713 set_first_insn (cfg_layout_function_header); | |
714 insn = cfg_layout_function_header; | |
715 while (NEXT_INSN (insn)) | |
716 insn = NEXT_INSN (insn); | |
717 } | |
718 | |
719 /* First do the bulk reordering -- rechain the blocks without regard to | |
720 the needed changes to jumps and labels. */ | |
721 | |
722 for (bb = ENTRY_BLOCK_PTR->next_bb; bb; bb = (basic_block) bb->aux) | |
723 { | |
724 if (bb->il.rtl->header) | |
725 { | |
726 if (insn) | |
727 NEXT_INSN (insn) = bb->il.rtl->header; | |
728 else | |
729 set_first_insn (bb->il.rtl->header); | |
730 PREV_INSN (bb->il.rtl->header) = insn; | |
731 insn = bb->il.rtl->header; | |
732 while (NEXT_INSN (insn)) | |
733 insn = NEXT_INSN (insn); | |
734 } | |
735 if (insn) | |
736 NEXT_INSN (insn) = BB_HEAD (bb); | |
737 else | |
738 set_first_insn (BB_HEAD (bb)); | |
739 PREV_INSN (BB_HEAD (bb)) = insn; | |
740 insn = BB_END (bb); | |
741 if (bb->il.rtl->footer) | |
742 { | |
743 NEXT_INSN (insn) = bb->il.rtl->footer; | |
744 PREV_INSN (bb->il.rtl->footer) = insn; | |
745 while (NEXT_INSN (insn)) | |
746 insn = NEXT_INSN (insn); | |
747 } | |
748 } | |
749 | |
750 NEXT_INSN (insn) = cfg_layout_function_footer; | |
751 if (cfg_layout_function_footer) | |
752 PREV_INSN (cfg_layout_function_footer) = insn; | |
753 | |
754 while (NEXT_INSN (insn)) | |
755 insn = NEXT_INSN (insn); | |
756 | |
757 set_last_insn (insn); | |
758 #ifdef ENABLE_CHECKING | |
759 verify_insn_chain (); | |
760 #endif | |
761 | |
762 /* Now add jumps and labels as needed to match the blocks new | |
763 outgoing edges. */ | |
764 | |
765 for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = (basic_block) bb->aux) | |
766 { | |
767 edge e_fall, e_taken, e; | |
768 rtx bb_end_insn; | |
769 basic_block nb; | |
770 edge_iterator ei; | |
771 | |
772 if (EDGE_COUNT (bb->succs) == 0) | |
773 continue; | |
774 | |
775 /* Find the old fallthru edge, and another non-EH edge for | |
776 a taken jump. */ | |
777 e_taken = e_fall = NULL; | |
778 | |
779 FOR_EACH_EDGE (e, ei, bb->succs) | |
780 if (e->flags & EDGE_FALLTHRU) | |
781 e_fall = e; | |
782 else if (! (e->flags & EDGE_EH)) | |
783 e_taken = e; | |
784 | |
785 bb_end_insn = BB_END (bb); | |
786 if (JUMP_P (bb_end_insn)) | |
787 { | |
788 if (any_condjump_p (bb_end_insn)) | |
789 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
790 /* This might happen if the conditional jump has side |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
791 effects and could therefore not be optimized away. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
792 Make the basic block to end with a barrier in order |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
793 to prevent rtl_verify_flow_info from complaining. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
794 if (!e_fall) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
795 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
796 gcc_assert (!onlyjump_p (bb_end_insn)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
797 bb->il.rtl->footer = emit_barrier_after (bb_end_insn); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
798 continue; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
799 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
800 |
0 | 801 /* If the old fallthru is still next, nothing to do. */ |
802 if (bb->aux == e_fall->dest | |
803 || e_fall->dest == EXIT_BLOCK_PTR) | |
804 continue; | |
805 | |
806 /* The degenerated case of conditional jump jumping to the next | |
807 instruction can happen for jumps with side effects. We need | |
808 to construct a forwarder block and this will be done just | |
809 fine by force_nonfallthru below. */ | |
810 if (!e_taken) | |
811 ; | |
812 | |
813 /* There is another special case: if *neither* block is next, | |
814 such as happens at the very end of a function, then we'll | |
815 need to add a new unconditional jump. Choose the taken | |
816 edge based on known or assumed probability. */ | |
817 else if (bb->aux != e_taken->dest) | |
818 { | |
819 rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0); | |
820 | |
821 if (note | |
822 && INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2 | |
823 && invert_jump (bb_end_insn, | |
824 (e_fall->dest == EXIT_BLOCK_PTR | |
825 ? NULL_RTX | |
826 : label_for_bb (e_fall->dest)), 0)) | |
827 { | |
828 e_fall->flags &= ~EDGE_FALLTHRU; | |
829 #ifdef ENABLE_CHECKING | |
830 gcc_assert (could_fall_through | |
831 (e_taken->src, e_taken->dest)); | |
832 #endif | |
833 e_taken->flags |= EDGE_FALLTHRU; | |
834 update_br_prob_note (bb); | |
835 e = e_fall, e_fall = e_taken, e_taken = e; | |
836 } | |
837 } | |
838 | |
839 /* If the "jumping" edge is a crossing edge, and the fall | |
840 through edge is non-crossing, leave things as they are. */ | |
841 else if ((e_taken->flags & EDGE_CROSSING) | |
842 && !(e_fall->flags & EDGE_CROSSING)) | |
843 continue; | |
844 | |
845 /* Otherwise we can try to invert the jump. This will | |
846 basically never fail, however, keep up the pretense. */ | |
847 else if (invert_jump (bb_end_insn, | |
848 (e_fall->dest == EXIT_BLOCK_PTR | |
849 ? NULL_RTX | |
850 : label_for_bb (e_fall->dest)), 0)) | |
851 { | |
852 e_fall->flags &= ~EDGE_FALLTHRU; | |
853 #ifdef ENABLE_CHECKING | |
854 gcc_assert (could_fall_through | |
855 (e_taken->src, e_taken->dest)); | |
856 #endif | |
857 e_taken->flags |= EDGE_FALLTHRU; | |
858 update_br_prob_note (bb); | |
859 continue; | |
860 } | |
861 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
862 else if (extract_asm_operands (PATTERN (bb_end_insn)) != NULL) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
863 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
864 /* If the old fallthru is still next, nothing to do. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
865 if (bb->aux == e_fall->dest |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
866 || e_fall->dest == EXIT_BLOCK_PTR) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
867 continue; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
868 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
869 /* Otherwise we'll have to use the fallthru fixup below. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
870 } |
0 | 871 else |
872 { | |
873 /* Otherwise we have some return, switch or computed | |
874 jump. In the 99% case, there should not have been a | |
875 fallthru edge. */ | |
876 gcc_assert (returnjump_p (bb_end_insn) || !e_fall); | |
877 continue; | |
878 } | |
879 } | |
880 else | |
881 { | |
882 /* No fallthru implies a noreturn function with EH edges, or | |
883 something similarly bizarre. In any case, we don't need to | |
884 do anything. */ | |
885 if (! e_fall) | |
886 continue; | |
887 | |
888 /* If the fallthru block is still next, nothing to do. */ | |
889 if (bb->aux == e_fall->dest) | |
890 continue; | |
891 | |
892 /* A fallthru to exit block. */ | |
893 if (e_fall->dest == EXIT_BLOCK_PTR) | |
894 continue; | |
895 } | |
896 | |
897 /* We got here if we need to add a new jump insn. */ | |
898 nb = force_nonfallthru (e_fall); | |
899 if (nb) | |
900 { | |
901 nb->il.rtl->visited = 1; | |
902 nb->aux = bb->aux; | |
903 bb->aux = nb; | |
904 /* Don't process this new block. */ | |
905 bb = nb; | |
906 | |
907 /* Make sure new bb is tagged for correct section (same as | |
908 fall-thru source, since you cannot fall-throu across | |
909 section boundaries). */ | |
910 BB_COPY_PARTITION (e_fall->src, single_pred (bb)); | |
911 if (flag_reorder_blocks_and_partition | |
912 && targetm.have_named_sections | |
913 && JUMP_P (BB_END (bb)) | |
914 && !any_condjump_p (BB_END (bb)) | |
915 && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING)) | |
916 add_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX); | |
917 } | |
918 } | |
919 | |
920 relink_block_chain (/*stay_in_cfglayout_mode=*/false); | |
921 | |
922 /* Annoying special case - jump around dead jumptables left in the code. */ | |
923 FOR_EACH_BB (bb) | |
924 { | |
925 edge e; | |
926 edge_iterator ei; | |
927 | |
928 FOR_EACH_EDGE (e, ei, bb->succs) | |
929 if (e->flags & EDGE_FALLTHRU) | |
930 break; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
931 |
0 | 932 if (e && !can_fallthru (e->src, e->dest)) |
933 force_nonfallthru (e); | |
934 } | |
935 | |
936 /* Ensure goto_locus from edges has some instructions with that locus | |
937 in RTL. */ | |
938 if (!optimize) | |
939 FOR_EACH_BB (bb) | |
940 { | |
941 edge e; | |
942 edge_iterator ei; | |
943 | |
944 FOR_EACH_EDGE (e, ei, bb->succs) | |
945 if (e->goto_locus && !(e->flags & EDGE_ABNORMAL)) | |
946 { | |
947 basic_block nb; | |
948 rtx end; | |
949 | |
950 insn = BB_END (e->src); | |
951 end = PREV_INSN (BB_HEAD (e->src)); | |
952 while (insn != end | |
953 && (!INSN_P (insn) || INSN_LOCATOR (insn) == 0)) | |
954 insn = PREV_INSN (insn); | |
955 if (insn != end | |
956 && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus)) | |
957 continue; | |
958 if (simplejump_p (BB_END (e->src)) | |
959 && INSN_LOCATOR (BB_END (e->src)) == 0) | |
960 { | |
961 INSN_LOCATOR (BB_END (e->src)) = e->goto_locus; | |
962 continue; | |
963 } | |
964 if (e->dest != EXIT_BLOCK_PTR) | |
965 { | |
966 insn = BB_HEAD (e->dest); | |
967 end = NEXT_INSN (BB_END (e->dest)); | |
968 while (insn != end && !INSN_P (insn)) | |
969 insn = NEXT_INSN (insn); | |
970 if (insn != end && INSN_LOCATOR (insn) | |
971 && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus)) | |
972 continue; | |
973 } | |
974 nb = split_edge (e); | |
975 if (!INSN_P (BB_END (nb))) | |
976 BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb), | |
977 nb); | |
978 INSN_LOCATOR (BB_END (nb)) = e->goto_locus; | |
979 } | |
980 } | |
981 } | |
982 | |
983 /* Perform sanity checks on the insn chain. | |
984 1. Check that next/prev pointers are consistent in both the forward and | |
985 reverse direction. | |
986 2. Count insns in chain, going both directions, and check if equal. | |
987 3. Check that get_last_insn () returns the actual end of chain. */ | |
988 | |
989 void | |
990 verify_insn_chain (void) | |
991 { | |
992 rtx x, prevx, nextx; | |
993 int insn_cnt1, insn_cnt2; | |
994 | |
995 for (prevx = NULL, insn_cnt1 = 1, x = get_insns (); | |
996 x != 0; | |
997 prevx = x, insn_cnt1++, x = NEXT_INSN (x)) | |
998 gcc_assert (PREV_INSN (x) == prevx); | |
999 | |
1000 gcc_assert (prevx == get_last_insn ()); | |
1001 | |
1002 for (nextx = NULL, insn_cnt2 = 1, x = get_last_insn (); | |
1003 x != 0; | |
1004 nextx = x, insn_cnt2++, x = PREV_INSN (x)) | |
1005 gcc_assert (NEXT_INSN (x) == nextx); | |
1006 | |
1007 gcc_assert (insn_cnt1 == insn_cnt2); | |
1008 } | |
1009 | |
1010 /* If we have assembler epilogues, the block falling through to exit must | |
1011 be the last one in the reordered chain when we reach final. Ensure | |
1012 that this condition is met. */ | |
1013 static void | |
1014 fixup_fallthru_exit_predecessor (void) | |
1015 { | |
1016 edge e; | |
1017 edge_iterator ei; | |
1018 basic_block bb = NULL; | |
1019 | |
1020 /* This transformation is not valid before reload, because we might | |
1021 separate a call from the instruction that copies the return | |
1022 value. */ | |
1023 gcc_assert (reload_completed); | |
1024 | |
1025 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds) | |
1026 if (e->flags & EDGE_FALLTHRU) | |
1027 bb = e->src; | |
1028 | |
1029 if (bb && bb->aux) | |
1030 { | |
1031 basic_block c = ENTRY_BLOCK_PTR->next_bb; | |
1032 | |
1033 /* If the very first block is the one with the fall-through exit | |
1034 edge, we have to split that block. */ | |
1035 if (c == bb) | |
1036 { | |
1037 bb = split_block (bb, NULL)->dest; | |
1038 bb->aux = c->aux; | |
1039 c->aux = bb; | |
1040 bb->il.rtl->footer = c->il.rtl->footer; | |
1041 c->il.rtl->footer = NULL; | |
1042 } | |
1043 | |
1044 while (c->aux != bb) | |
1045 c = (basic_block) c->aux; | |
1046 | |
1047 c->aux = bb->aux; | |
1048 while (c->aux) | |
1049 c = (basic_block) c->aux; | |
1050 | |
1051 c->aux = bb; | |
1052 bb->aux = NULL; | |
1053 } | |
1054 } | |
1055 | |
1056 /* In case there are more than one fallthru predecessors of exit, force that | |
1057 there is only one. */ | |
1058 | |
1059 static void | |
1060 force_one_exit_fallthru (void) | |
1061 { | |
1062 edge e, predecessor = NULL; | |
1063 bool more = false; | |
1064 edge_iterator ei; | |
1065 basic_block forwarder, bb; | |
1066 | |
1067 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds) | |
1068 if (e->flags & EDGE_FALLTHRU) | |
1069 { | |
1070 if (predecessor == NULL) | |
1071 predecessor = e; | |
1072 else | |
1073 { | |
1074 more = true; | |
1075 break; | |
1076 } | |
1077 } | |
1078 | |
1079 if (!more) | |
1080 return; | |
1081 | |
1082 /* Exit has several fallthru predecessors. Create a forwarder block for | |
1083 them. */ | |
1084 forwarder = split_edge (predecessor); | |
1085 for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); ) | |
1086 { | |
1087 if (e->src == forwarder | |
1088 || !(e->flags & EDGE_FALLTHRU)) | |
1089 ei_next (&ei); | |
1090 else | |
1091 redirect_edge_and_branch_force (e, forwarder); | |
1092 } | |
1093 | |
1094 /* Fix up the chain of blocks -- make FORWARDER immediately precede the | |
1095 exit block. */ | |
1096 FOR_EACH_BB (bb) | |
1097 { | |
1098 if (bb->aux == NULL && bb != forwarder) | |
1099 { | |
1100 bb->aux = forwarder; | |
1101 break; | |
1102 } | |
1103 } | |
1104 } | |
1105 | |
1106 /* Return true in case it is possible to duplicate the basic block BB. */ | |
1107 | |
1108 /* We do not want to declare the function in a header file, since it should | |
1109 only be used through the cfghooks interface, and we do not want to move | |
1110 it to cfgrtl.c since it would require also moving quite a lot of related | |
1111 code. */ | |
1112 extern bool cfg_layout_can_duplicate_bb_p (const_basic_block); | |
1113 | |
1114 bool | |
1115 cfg_layout_can_duplicate_bb_p (const_basic_block bb) | |
1116 { | |
1117 /* Do not attempt to duplicate tablejumps, as we need to unshare | |
1118 the dispatch table. This is difficult to do, as the instructions | |
1119 computing jump destination may be hoisted outside the basic block. */ | |
1120 if (tablejump_p (BB_END (bb), NULL, NULL)) | |
1121 return false; | |
1122 | |
1123 /* Do not duplicate blocks containing insns that can't be copied. */ | |
1124 if (targetm.cannot_copy_insn_p) | |
1125 { | |
1126 rtx insn = BB_HEAD (bb); | |
1127 while (1) | |
1128 { | |
1129 if (INSN_P (insn) && targetm.cannot_copy_insn_p (insn)) | |
1130 return false; | |
1131 if (insn == BB_END (bb)) | |
1132 break; | |
1133 insn = NEXT_INSN (insn); | |
1134 } | |
1135 } | |
1136 | |
1137 return true; | |
1138 } | |
1139 | |
1140 rtx | |
1141 duplicate_insn_chain (rtx from, rtx to) | |
1142 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1143 rtx insn, last, copy; |
0 | 1144 |
1145 /* Avoid updating of boundaries of previous basic block. The | |
1146 note will get removed from insn stream in fixup. */ | |
1147 last = emit_note (NOTE_INSN_DELETED); | |
1148 | |
1149 /* Create copy at the end of INSN chain. The chain will | |
1150 be reordered later. */ | |
1151 for (insn = from; insn != NEXT_INSN (to); insn = NEXT_INSN (insn)) | |
1152 { | |
1153 switch (GET_CODE (insn)) | |
1154 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1155 case DEBUG_INSN: |
0 | 1156 case INSN: |
1157 case CALL_INSN: | |
1158 case JUMP_INSN: | |
1159 /* Avoid copying of dispatch tables. We never duplicate | |
1160 tablejumps, so this can hit only in case the table got | |
1161 moved far from original jump. */ | |
1162 if (GET_CODE (PATTERN (insn)) == ADDR_VEC | |
1163 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC) | |
1164 break; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1165 copy = emit_copy_of_insn_after (insn, get_last_insn ()); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1166 maybe_copy_epilogue_insn (insn, copy); |
0 | 1167 break; |
1168 | |
1169 case CODE_LABEL: | |
1170 break; | |
1171 | |
1172 case BARRIER: | |
1173 emit_barrier (); | |
1174 break; | |
1175 | |
1176 case NOTE: | |
1177 switch (NOTE_KIND (insn)) | |
1178 { | |
1179 /* In case prologue is empty and function contain label | |
1180 in first BB, we may want to copy the block. */ | |
1181 case NOTE_INSN_PROLOGUE_END: | |
1182 | |
1183 case NOTE_INSN_DELETED: | |
1184 case NOTE_INSN_DELETED_LABEL: | |
1185 /* No problem to strip these. */ | |
1186 case NOTE_INSN_FUNCTION_BEG: | |
1187 /* There is always just single entry to function. */ | |
1188 case NOTE_INSN_BASIC_BLOCK: | |
1189 break; | |
1190 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1191 case NOTE_INSN_EPILOGUE_BEG: |
0 | 1192 case NOTE_INSN_SWITCH_TEXT_SECTIONS: |
1193 emit_note_copy (insn); | |
1194 break; | |
1195 | |
1196 default: | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1197 /* All other notes should have already been eliminated. */ |
0 | 1198 gcc_unreachable (); |
1199 } | |
1200 break; | |
1201 default: | |
1202 gcc_unreachable (); | |
1203 } | |
1204 } | |
1205 insn = NEXT_INSN (last); | |
1206 delete_insn (last); | |
1207 return insn; | |
1208 } | |
1209 /* Create a duplicate of the basic block BB. */ | |
1210 | |
1211 /* We do not want to declare the function in a header file, since it should | |
1212 only be used through the cfghooks interface, and we do not want to move | |
1213 it to cfgrtl.c since it would require also moving quite a lot of related | |
1214 code. */ | |
1215 extern basic_block cfg_layout_duplicate_bb (basic_block); | |
1216 | |
1217 basic_block | |
1218 cfg_layout_duplicate_bb (basic_block bb) | |
1219 { | |
1220 rtx insn; | |
1221 basic_block new_bb; | |
1222 | |
1223 insn = duplicate_insn_chain (BB_HEAD (bb), BB_END (bb)); | |
1224 new_bb = create_basic_block (insn, | |
1225 insn ? get_last_insn () : NULL, | |
1226 EXIT_BLOCK_PTR->prev_bb); | |
1227 | |
1228 BB_COPY_PARTITION (new_bb, bb); | |
1229 if (bb->il.rtl->header) | |
1230 { | |
1231 insn = bb->il.rtl->header; | |
1232 while (NEXT_INSN (insn)) | |
1233 insn = NEXT_INSN (insn); | |
1234 insn = duplicate_insn_chain (bb->il.rtl->header, insn); | |
1235 if (insn) | |
1236 new_bb->il.rtl->header = unlink_insn_chain (insn, get_last_insn ()); | |
1237 } | |
1238 | |
1239 if (bb->il.rtl->footer) | |
1240 { | |
1241 insn = bb->il.rtl->footer; | |
1242 while (NEXT_INSN (insn)) | |
1243 insn = NEXT_INSN (insn); | |
1244 insn = duplicate_insn_chain (bb->il.rtl->footer, insn); | |
1245 if (insn) | |
1246 new_bb->il.rtl->footer = unlink_insn_chain (insn, get_last_insn ()); | |
1247 } | |
1248 | |
1249 return new_bb; | |
1250 } | |
1251 | |
1252 | |
1253 /* Main entry point to this module - initialize the datastructures for | |
1254 CFG layout changes. It keeps LOOPS up-to-date if not null. | |
1255 | |
1256 FLAGS is a set of additional flags to pass to cleanup_cfg(). */ | |
1257 | |
1258 void | |
1259 cfg_layout_initialize (unsigned int flags) | |
1260 { | |
1261 rtx x; | |
1262 basic_block bb; | |
1263 | |
1264 initialize_original_copy_tables (); | |
1265 | |
1266 cfg_layout_rtl_register_cfg_hooks (); | |
1267 | |
1268 record_effective_endpoints (); | |
1269 | |
1270 /* Make sure that the targets of non local gotos are marked. */ | |
1271 for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1)) | |
1272 { | |
1273 bb = BLOCK_FOR_INSN (XEXP (x, 0)); | |
1274 bb->flags |= BB_NON_LOCAL_GOTO_TARGET; | |
1275 } | |
1276 | |
1277 cleanup_cfg (CLEANUP_CFGLAYOUT | flags); | |
1278 } | |
1279 | |
1280 /* Splits superblocks. */ | |
1281 void | |
1282 break_superblocks (void) | |
1283 { | |
1284 sbitmap superblocks; | |
1285 bool need = false; | |
1286 basic_block bb; | |
1287 | |
1288 superblocks = sbitmap_alloc (last_basic_block); | |
1289 sbitmap_zero (superblocks); | |
1290 | |
1291 FOR_EACH_BB (bb) | |
1292 if (bb->flags & BB_SUPERBLOCK) | |
1293 { | |
1294 bb->flags &= ~BB_SUPERBLOCK; | |
1295 SET_BIT (superblocks, bb->index); | |
1296 need = true; | |
1297 } | |
1298 | |
1299 if (need) | |
1300 { | |
1301 rebuild_jump_labels (get_insns ()); | |
1302 find_many_sub_basic_blocks (superblocks); | |
1303 } | |
1304 | |
1305 free (superblocks); | |
1306 } | |
1307 | |
1308 /* Finalize the changes: reorder insn list according to the sequence specified | |
1309 by aux pointers, enter compensation code, rebuild scope forest. */ | |
1310 | |
1311 void | |
1312 cfg_layout_finalize (void) | |
1313 { | |
1314 #ifdef ENABLE_CHECKING | |
1315 verify_flow_info (); | |
1316 #endif | |
1317 force_one_exit_fallthru (); | |
1318 rtl_register_cfg_hooks (); | |
1319 if (reload_completed | |
1320 #ifdef HAVE_epilogue | |
1321 && !HAVE_epilogue | |
1322 #endif | |
1323 ) | |
1324 fixup_fallthru_exit_predecessor (); | |
1325 fixup_reorder_chain (); | |
1326 | |
1327 rebuild_jump_labels (get_insns ()); | |
1328 delete_dead_jumptables (); | |
1329 | |
1330 #ifdef ENABLE_CHECKING | |
1331 verify_insn_chain (); | |
1332 verify_flow_info (); | |
1333 #endif | |
1334 } | |
1335 | |
1336 /* Checks whether all N blocks in BBS array can be copied. */ | |
1337 bool | |
1338 can_copy_bbs_p (basic_block *bbs, unsigned n) | |
1339 { | |
1340 unsigned i; | |
1341 edge e; | |
1342 int ret = true; | |
1343 | |
1344 for (i = 0; i < n; i++) | |
1345 bbs[i]->flags |= BB_DUPLICATED; | |
1346 | |
1347 for (i = 0; i < n; i++) | |
1348 { | |
1349 /* In case we should redirect abnormal edge during duplication, fail. */ | |
1350 edge_iterator ei; | |
1351 FOR_EACH_EDGE (e, ei, bbs[i]->succs) | |
1352 if ((e->flags & EDGE_ABNORMAL) | |
1353 && (e->dest->flags & BB_DUPLICATED)) | |
1354 { | |
1355 ret = false; | |
1356 goto end; | |
1357 } | |
1358 | |
1359 if (!can_duplicate_block_p (bbs[i])) | |
1360 { | |
1361 ret = false; | |
1362 break; | |
1363 } | |
1364 } | |
1365 | |
1366 end: | |
1367 for (i = 0; i < n; i++) | |
1368 bbs[i]->flags &= ~BB_DUPLICATED; | |
1369 | |
1370 return ret; | |
1371 } | |
1372 | |
1373 /* Duplicates N basic blocks stored in array BBS. Newly created basic blocks | |
1374 are placed into array NEW_BBS in the same order. Edges from basic blocks | |
1375 in BBS are also duplicated and copies of those of them | |
1376 that lead into BBS are redirected to appropriate newly created block. The | |
1377 function assigns bbs into loops (copy of basic block bb is assigned to | |
1378 bb->loop_father->copy loop, so this must be set up correctly in advance) | |
1379 and updates dominators locally (LOOPS structure that contains the information | |
1380 about dominators is passed to enable this). | |
1381 | |
1382 BASE is the superloop to that basic block belongs; if its header or latch | |
1383 is copied, we do not set the new blocks as header or latch. | |
1384 | |
1385 Created copies of N_EDGES edges in array EDGES are stored in array NEW_EDGES, | |
1386 also in the same order. | |
1387 | |
1388 Newly created basic blocks are put after the basic block AFTER in the | |
1389 instruction stream, and the order of the blocks in BBS array is preserved. */ | |
1390 | |
1391 void | |
1392 copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs, | |
1393 edge *edges, unsigned num_edges, edge *new_edges, | |
1394 struct loop *base, basic_block after) | |
1395 { | |
1396 unsigned i, j; | |
1397 basic_block bb, new_bb, dom_bb; | |
1398 edge e; | |
1399 | |
1400 /* Duplicate bbs, update dominators, assign bbs to loops. */ | |
1401 for (i = 0; i < n; i++) | |
1402 { | |
1403 /* Duplicate. */ | |
1404 bb = bbs[i]; | |
1405 new_bb = new_bbs[i] = duplicate_block (bb, NULL, after); | |
1406 after = new_bb; | |
1407 bb->flags |= BB_DUPLICATED; | |
1408 /* Possibly set loop header. */ | |
1409 if (bb->loop_father->header == bb && bb->loop_father != base) | |
1410 new_bb->loop_father->header = new_bb; | |
1411 /* Or latch. */ | |
1412 if (bb->loop_father->latch == bb && bb->loop_father != base) | |
1413 new_bb->loop_father->latch = new_bb; | |
1414 } | |
1415 | |
1416 /* Set dominators. */ | |
1417 for (i = 0; i < n; i++) | |
1418 { | |
1419 bb = bbs[i]; | |
1420 new_bb = new_bbs[i]; | |
1421 | |
1422 dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb); | |
1423 if (dom_bb->flags & BB_DUPLICATED) | |
1424 { | |
1425 dom_bb = get_bb_copy (dom_bb); | |
1426 set_immediate_dominator (CDI_DOMINATORS, new_bb, dom_bb); | |
1427 } | |
1428 } | |
1429 | |
1430 /* Redirect edges. */ | |
1431 for (j = 0; j < num_edges; j++) | |
1432 new_edges[j] = NULL; | |
1433 for (i = 0; i < n; i++) | |
1434 { | |
1435 edge_iterator ei; | |
1436 new_bb = new_bbs[i]; | |
1437 bb = bbs[i]; | |
1438 | |
1439 FOR_EACH_EDGE (e, ei, new_bb->succs) | |
1440 { | |
1441 for (j = 0; j < num_edges; j++) | |
1442 if (edges[j] && edges[j]->src == bb && edges[j]->dest == e->dest) | |
1443 new_edges[j] = e; | |
1444 | |
1445 if (!(e->dest->flags & BB_DUPLICATED)) | |
1446 continue; | |
1447 redirect_edge_and_branch_force (e, get_bb_copy (e->dest)); | |
1448 } | |
1449 } | |
1450 | |
1451 /* Clear information about duplicates. */ | |
1452 for (i = 0; i < n; i++) | |
1453 bbs[i]->flags &= ~BB_DUPLICATED; | |
1454 } | |
1455 | |
1456 #include "gt-cfglayout.h" |