bb-reorder.c (scope_def): New struct.
[gcc.git] / gcc / bb-reorder.c
1 /* Basic block reordering routines for the GNU compiler.
2 Copyright (C) 2000 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* References:
22
23 "Profile Guided Code Positioning"
24 Pettis and Hanson; PLDI '90.
25 */
26
27 #include "config.h"
28 #include "system.h"
29 #include "tree.h"
30 #include "rtl.h"
31 #include "tm_p.h"
32 #include "basic-block.h"
33 #include "insn-config.h"
34 #include "regs.h"
35 #include "hard-reg-set.h"
36 #include "flags.h"
37 #include "output.h"
38 #include "function.h"
39 #include "except.h"
40 #include "toplev.h"
41 #include "recog.h"
42 #include "insn-flags.h"
43 #include "expr.h"
44 #include "obstack.h"
45
46
47 /* The contents of the current function definition are allocated
48 in this obstack, and all are freed at the end of the function.
49 For top-level functions, this is temporary_obstack.
50 Separate obstacks are made for nested functions. */
51
52 extern struct obstack *function_obstack;
53
54
55 /* Structure to hold information about lexical scopes. */
56 typedef struct scope_def
57 {
58 int level;
59
60 /* The NOTE_INSN_BLOCK_BEG that started this scope. */
61 rtx note_beg;
62
63 /* The NOTE_INSN_BLOCK_END that ended this scope. */
64 rtx note_end;
65
66 /* The bb containing note_beg (if any). */
67 basic_block bb_beg;
68
69 /* The bb containing note_end (if any). */
70 basic_block bb_end;
71
72 /* List of basic blocks contained within this scope. */
73 basic_block *bbs;
74
75 /* Number of blocks contained within this scope. */
76 int num_bbs;
77
78 /* The outer scope or NULL if outermost scope. */
79 struct scope_def *outer;
80
81 /* The first inner scope or NULL if innermost scope. */
82 struct scope_def *inner;
83
84 /* The last inner scope or NULL if innermost scope. */
85 struct scope_def *inner_last;
86
87 /* Link to the next (sibling) scope. */
88 struct scope_def *next;
89 } *scope;
90
91 /* Structure to hold information about the scope forest. */
92 typedef struct
93 {
94 /* Number of trees in forest. */
95 int num_trees;
96
97 /* List of tree roots. */
98 scope *trees;
99 } scope_forest_info;
100
101
102 typedef struct reorder_block_def {
103 int flags;
104 int index;
105 basic_block add_jump;
106 edge succ;
107 rtx end;
108 int block_begin;
109 int block_end;
110 rtx eff_head;
111 rtx eff_end;
112 scope scope;
113 } *reorder_block_def;
114
115 static struct reorder_block_def rbd_init
116 = {
117 0, /* flags */
118 0, /* index */
119 NULL, /* add_jump */
120 NULL, /* succ */
121 NULL_RTX, /* end */
122 0, /* block_begin */
123 0, /* block_end */
124 NULL_RTX, /* eff_head */
125 NULL_RTX, /* eff_end */
126 NULL /* scope */
127 };
128
129
130 #define REORDER_BLOCK_HEAD 0x1
131 #define REORDER_BLOCK_VISITED 0x2
132
133 #define REORDER_BLOCK_FLAGS(bb) \
134 ((reorder_block_def) (bb)->aux)->flags
135
136 #define REORDER_BLOCK_INDEX(bb) \
137 ((reorder_block_def) (bb)->aux)->index
138
139 #define REORDER_BLOCK_ADD_JUMP(bb) \
140 ((reorder_block_def) (bb)->aux)->add_jump
141
142 #define REORDER_BLOCK_SUCC(bb) \
143 ((reorder_block_def) (bb)->aux)->succ
144
145 #define REORDER_BLOCK_OLD_END(bb) \
146 ((reorder_block_def) (bb)->aux)->end
147
148 #define REORDER_BLOCK_BEGIN(bb) \
149 ((reorder_block_def) (bb)->aux)->block_begin
150
151 #define REORDER_BLOCK_END(bb) \
152 ((reorder_block_def) (bb)->aux)->block_end
153
154 #define REORDER_BLOCK_EFF_HEAD(bb) \
155 ((reorder_block_def) (bb)->aux)->eff_head
156
157 #define REORDER_BLOCK_EFF_END(bb) \
158 ((reorder_block_def) (bb)->aux)->eff_end
159
160 #define REORDER_BLOCK_SCOPE(bb) \
161 ((reorder_block_def) (bb)->aux)->scope
162
163
164 static int reorder_index;
165 static basic_block reorder_last_visited;
166
167 enum reorder_skip_type {REORDER_SKIP_BEFORE, REORDER_SKIP_AFTER,
168 REORDER_SKIP_BLOCK_END};
169
170
171 /* Local function prototypes. */
172 static rtx skip_insns_between_block PARAMS ((basic_block,
173 enum reorder_skip_type));
174 static basic_block get_common_dest PARAMS ((basic_block, basic_block));
175 static basic_block chain_reorder_blocks PARAMS ((edge, basic_block));
176 static void make_reorder_chain PARAMS ((basic_block));
177 static void fixup_reorder_chain PARAMS ((void));
178 #ifdef ENABLE_CHECKING
179 static void verify_insn_chain PARAMS ((void));
180 #endif
181 static void relate_bbs_with_scopes PARAMS ((scope));
182 static scope make_new_scope PARAMS ((int, rtx));
183 static void build_scope_forest PARAMS ((scope_forest_info *));
184 static void remove_scope_notes PARAMS ((void));
185 static void insert_intra_1 PARAMS ((scope, rtx *));
186 static void insert_intra_bb_scope_notes PARAMS ((basic_block));
187 static void insert_inter_bb_scope_notes PARAMS ((basic_block, basic_block));
188 static void rebuild_scope_notes PARAMS ((scope_forest_info *));
189 static void free_scope_forest_1 PARAMS ((scope));
190 static void free_scope_forest PARAMS ((scope_forest_info *));
191 void dump_scope_forest PARAMS ((scope_forest_info *));
192 static void dump_scope_forest_1 PARAMS ((scope, int));
193
194 /* Skip over insns BEFORE or AFTER BB which are typically associated with
195 basic block BB. */
196
197 static rtx
198 skip_insns_between_block (bb, skip_type)
199 basic_block bb;
200 enum reorder_skip_type skip_type;
201 {
202 rtx insn, last_insn;
203
204 if (skip_type == REORDER_SKIP_BEFORE)
205 {
206 if (bb == ENTRY_BLOCK_PTR)
207 return 0;
208
209 last_insn = bb->head;
210 for (insn = PREV_INSN (bb->head);
211 insn && insn != BASIC_BLOCK (bb->index - 1)->end;
212 last_insn = insn, insn = PREV_INSN (insn))
213 {
214 if (NEXT_INSN (insn) != last_insn)
215 break;
216
217 if (GET_CODE (insn) == NOTE
218 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END
219 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
220 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END)
221 continue;
222
223 break;
224 }
225 }
226 else
227 {
228 last_insn = bb->end;
229
230 if (bb == EXIT_BLOCK_PTR)
231 return 0;
232
233 for (insn = NEXT_INSN (bb->end);
234 insn;
235 last_insn = insn, insn = NEXT_INSN (insn))
236 {
237 if (bb->index + 1 != n_basic_blocks
238 && insn == BASIC_BLOCK (bb->index + 1)->head)
239 break;
240
241 if (GET_CODE (insn) == BARRIER
242 || GET_CODE (insn) == JUMP_INSN
243 || (GET_CODE (insn) == NOTE
244 && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
245 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)))
246 continue;
247
248 if (GET_CODE (insn) == CODE_LABEL
249 && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
250 && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
251 || GET_CODE (PATTERN
252 (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
253 {
254 insn = NEXT_INSN (insn);
255 continue;
256 }
257
258 /* Skip to next non-deleted insn. */
259 if (GET_CODE (insn) == NOTE
260 && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
261 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
262 continue;
263
264 break;
265 }
266
267 if (skip_type == REORDER_SKIP_BLOCK_END)
268 {
269 int found_block_end = 0;
270
271 for (; insn; last_insn = insn, insn = NEXT_INSN (insn))
272 {
273 if (bb->index + 1 != n_basic_blocks
274 && insn == BASIC_BLOCK (bb->index + 1)->head)
275 break;
276
277 if (GET_CODE (insn) == NOTE
278 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
279 {
280 found_block_end = 1;
281 continue;
282 }
283
284 if (GET_CODE (insn) == NOTE
285 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
286 continue;
287
288 if (GET_CODE (insn) == NOTE
289 && NOTE_LINE_NUMBER (insn) >= 0
290 && NEXT_INSN (insn)
291 && GET_CODE (NEXT_INSN (insn)) == NOTE
292 && (NOTE_LINE_NUMBER (NEXT_INSN (insn))
293 == NOTE_INSN_BLOCK_END))
294 continue;
295 break;
296 }
297
298 if (! found_block_end)
299 last_insn = 0;
300 }
301 }
302
303 return last_insn;
304 }
305
306
307 /* Return common destination for blocks BB0 and BB1. */
308
309 static basic_block
310 get_common_dest (bb0, bb1)
311 basic_block bb0, bb1;
312 {
313 edge e0, e1;
314
315 for (e0 = bb0->succ; e0; e0 = e0->succ_next)
316 {
317 for (e1 = bb1->succ; e1; e1 = e1->succ_next)
318 {
319 if (e0->dest == e1->dest)
320 {
321 return e0->dest;
322 }
323 }
324 }
325 return 0;
326 }
327
328
329 /* Move the destination block for edge E after chain end block CEB
330 Adding jumps and labels is deferred until fixup_reorder_chain. */
331
332 static basic_block
333 chain_reorder_blocks (e, ceb)
334 edge e;
335 basic_block ceb;
336 {
337 basic_block sb = e->src;
338 basic_block db = e->dest;
339 rtx cebe_insn, cebbe_insn, dbh_insn, dbe_insn;
340 edge ee, last_edge;
341
342 enum cond_types {NO_COND, PREDICT_THEN_WITH_ELSE, PREDICT_ELSE,
343 PREDICT_THEN_NO_ELSE, PREDICT_NOT_THEN_NO_ELSE};
344 enum cond_types cond_type;
345 enum cond_block_types {NO_COND_BLOCK, THEN_BLOCK, ELSE_BLOCK,
346 NO_ELSE_BLOCK};
347 enum cond_block_types cond_block_type;
348
349 if (rtl_dump_file)
350 fprintf (rtl_dump_file,
351 "Edge from basic block %d to basic block %d last visited %d\n",
352 sb->index, db->index, ceb->index);
353
354 dbh_insn = REORDER_BLOCK_EFF_HEAD (db);
355 cebe_insn = REORDER_BLOCK_EFF_END (ceb);
356 cebbe_insn = skip_insns_between_block (ceb, REORDER_SKIP_BLOCK_END);
357
358 {
359 int block_begins = 0;
360 rtx insn;
361
362 for (insn = dbh_insn; insn && insn != db->end; insn = NEXT_INSN (insn))
363 {
364 if (GET_CODE (insn) == NOTE
365 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
366 {
367 block_begins += 1;
368 break;
369 }
370 }
371 REORDER_BLOCK_BEGIN (sb) = block_begins;
372 }
373
374 if (cebbe_insn)
375 {
376 int block_ends = 0;
377 rtx insn;
378
379 for (insn = cebe_insn; insn; insn = NEXT_INSN (insn))
380 {
381 if (PREV_INSN (insn) == cebbe_insn)
382 break;
383 if (GET_CODE (insn) == NOTE
384 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
385 {
386 block_ends += 1;
387 continue;
388 }
389 }
390 REORDER_BLOCK_END (ceb) = block_ends;
391 }
392
393 /* Blocks are in original order. */
394 if (sb->index == ceb->index
395 && ceb->index + 1 == db->index && NEXT_INSN (cebe_insn))
396 return db;
397
398 /* Get the type of block and type of condition. */
399 cond_type = NO_COND;
400 cond_block_type = NO_COND_BLOCK;
401 if (GET_CODE (sb->end) == JUMP_INSN && ! simplejump_p (sb->end)
402 && condjump_p (sb->end))
403 {
404 if (e->flags & EDGE_FALLTHRU)
405 cond_block_type = THEN_BLOCK;
406 else if (get_common_dest (sb->succ->dest, sb))
407 cond_block_type = NO_ELSE_BLOCK;
408 else
409 cond_block_type = ELSE_BLOCK;
410
411 if (sb->succ->succ_next
412 && get_common_dest (sb->succ->dest, sb))
413 {
414 if (cond_block_type == THEN_BLOCK)
415 {
416 if (! (REORDER_BLOCK_FLAGS (sb->succ->succ_next->dest)
417 & REORDER_BLOCK_VISITED))
418 cond_type = PREDICT_THEN_NO_ELSE;
419 else
420 cond_type = PREDICT_NOT_THEN_NO_ELSE;
421 }
422 else if (cond_block_type == NO_ELSE_BLOCK)
423 {
424 if (! (REORDER_BLOCK_FLAGS (sb->succ->dest)
425 & REORDER_BLOCK_VISITED))
426 cond_type = PREDICT_NOT_THEN_NO_ELSE;
427 else
428 cond_type = PREDICT_THEN_NO_ELSE;
429 }
430 }
431 else
432 {
433 if (cond_block_type == THEN_BLOCK)
434 {
435 if (! (REORDER_BLOCK_FLAGS (sb->succ->succ_next->dest)
436 & REORDER_BLOCK_VISITED))
437 cond_type = PREDICT_THEN_WITH_ELSE;
438 else
439 cond_type = PREDICT_ELSE;
440 }
441 else if (cond_block_type == ELSE_BLOCK
442 && sb->succ->dest != EXIT_BLOCK_PTR)
443 {
444 if (! (REORDER_BLOCK_FLAGS (sb->succ->dest)
445 & REORDER_BLOCK_VISITED))
446 cond_type = PREDICT_ELSE;
447 else
448 cond_type = PREDICT_THEN_WITH_ELSE;
449 }
450 }
451 }
452
453 if (rtl_dump_file)
454 {
455 static const char * cond_type_str [] = {"not cond jump", "predict then",
456 "predict else",
457 "predict then w/o else",
458 "predict not then w/o else"};
459 static const char * cond_block_type_str [] = {"not then or else block",
460 "then block",
461 "else block",
462 "then w/o else block"};
463
464 fprintf (rtl_dump_file, " %s (looking at %s)\n",
465 cond_type_str[(int)cond_type],
466 cond_block_type_str[(int)cond_block_type]);
467 }
468
469 /* Reflect that then block will move and we'll jump to it. */
470 if (cond_block_type != THEN_BLOCK
471 && (cond_type == PREDICT_ELSE
472 || cond_type == PREDICT_NOT_THEN_NO_ELSE))
473 {
474 if (rtl_dump_file)
475 fprintf (rtl_dump_file,
476 " then jump from block %d to block %d\n",
477 sb->index, sb->succ->dest->index);
478
479 /* Jump to reordered then block. */
480 REORDER_BLOCK_ADD_JUMP (sb) = sb->succ->dest;
481 }
482
483 /* Reflect that then block will jump back when we have no else. */
484 if (cond_block_type != THEN_BLOCK
485 && cond_type == PREDICT_NOT_THEN_NO_ELSE)
486 {
487 for (ee = sb->succ->dest->succ;
488 ee && ! (ee->flags & EDGE_FALLTHRU);
489 ee = ee->succ_next)
490 continue;
491
492 if (ee && ! (GET_CODE (sb->succ->dest->end) == JUMP_INSN
493 && ! simplejump_p (sb->succ->dest->end)))
494 {
495 REORDER_BLOCK_ADD_JUMP (sb->succ->dest) = ee->dest;
496 }
497 }
498
499 /* Reflect that else block will jump back. */
500 if (cond_block_type == ELSE_BLOCK
501 && (cond_type == PREDICT_THEN_WITH_ELSE || cond_type == PREDICT_ELSE))
502 {
503 last_edge=db->succ;
504
505 if (last_edge
506 && last_edge->dest != EXIT_BLOCK_PTR
507 && GET_CODE (last_edge->dest->head) == CODE_LABEL
508 && ! (GET_CODE (db->end) == JUMP_INSN))
509 {
510 if (rtl_dump_file)
511 fprintf (rtl_dump_file,
512 " else jump from block %d to block %d\n",
513 db->index, last_edge->dest->index);
514
515 REORDER_BLOCK_ADD_JUMP (db) = last_edge->dest;
516 }
517 }
518
519 /* This block's successor has already been reordered. This can happen
520 when we reorder a chain starting at a then or else. */
521 for (last_edge = db->succ;
522 last_edge && ! (last_edge->flags & EDGE_FALLTHRU);
523 last_edge = last_edge->succ_next)
524 continue;
525
526 if (last_edge
527 && last_edge->dest != EXIT_BLOCK_PTR
528 && (REORDER_BLOCK_FLAGS (last_edge->dest)
529 & REORDER_BLOCK_VISITED))
530 {
531 if (rtl_dump_file)
532 fprintf (rtl_dump_file,
533 " end of chain jump from block %d to block %d\n",
534 db->index, last_edge->dest->index);
535
536 REORDER_BLOCK_ADD_JUMP (db) = last_edge->dest;
537 }
538
539 dbh_insn = REORDER_BLOCK_EFF_HEAD (db);
540 cebe_insn = REORDER_BLOCK_EFF_END (ceb);
541 dbe_insn = REORDER_BLOCK_EFF_END (db);
542
543 /* Leave behind any lexical block markers. */
544 if (0 && debug_info_level > DINFO_LEVEL_TERSE
545 && ceb->index + 1 < db->index)
546 {
547 rtx insn, last_insn = get_last_insn ();
548 insn = NEXT_INSN (ceb->end);
549 if (! insn)
550 insn = REORDER_BLOCK_OLD_END (ceb);
551
552 if (NEXT_INSN (cebe_insn) == 0)
553 set_last_insn (cebe_insn);
554 for (; insn && insn != db->head/*dbh_insn*/;
555 insn = NEXT_INSN (insn))
556 {
557 if (GET_CODE (insn) == NOTE
558 && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG))
559 {
560 cebe_insn = emit_note_after (NOTE_INSN_BLOCK_BEG, cebe_insn);
561 delete_insn (insn);
562 }
563 if (GET_CODE (insn) == NOTE
564 && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END))
565 {
566 cebe_insn = emit_note_after (NOTE_INSN_BLOCK_END, cebe_insn);
567 delete_insn (insn);
568 }
569 }
570 set_last_insn (last_insn);
571 }
572
573 /* Rechain predicted block. */
574 NEXT_INSN (cebe_insn) = dbh_insn;
575 PREV_INSN (dbh_insn) = cebe_insn;
576
577 REORDER_BLOCK_OLD_END (db) = NEXT_INSN (dbe_insn);
578 if (db->index != n_basic_blocks - 1)
579 NEXT_INSN (dbe_insn) = 0;
580
581 return db;
582 }
583
584
585 /* Reorder blocks starting at block BB. */
586
587 static void
588 make_reorder_chain (bb)
589 basic_block bb;
590 {
591 edge e;
592 basic_block visited_edge = NULL;
593 rtx block_end;
594 int probability;
595
596 if (bb == EXIT_BLOCK_PTR)
597 return;
598
599 /* Find the most probable block. */
600 e = bb->succ;
601 block_end = bb->end;
602 if (GET_CODE (block_end) == JUMP_INSN && condjump_p (block_end))
603 {
604 rtx note = find_reg_note (block_end, REG_BR_PROB, 0);
605
606 if (note)
607 probability = INTVAL (XEXP (note, 0));
608 else
609 probability = 0;
610
611 if (probability >= REG_BR_PROB_BASE / 2)
612 e = bb->succ->succ_next;
613 }
614
615 /* Add chosen successor to chain and recurse on it. */
616 if (e && e->dest != EXIT_BLOCK_PTR
617 && e->dest != e->src
618 && (! (REORDER_BLOCK_FLAGS (e->dest) & REORDER_BLOCK_VISITED)
619 || (REORDER_BLOCK_FLAGS (e->dest) == REORDER_BLOCK_HEAD)))
620 {
621 if (! (REORDER_BLOCK_FLAGS (bb) & REORDER_BLOCK_VISITED))
622 {
623 REORDER_BLOCK_FLAGS (bb) |= REORDER_BLOCK_HEAD;
624 REORDER_BLOCK_INDEX (bb) = reorder_index++;
625 REORDER_BLOCK_FLAGS (bb) |= REORDER_BLOCK_VISITED;
626 }
627
628 if (REORDER_BLOCK_FLAGS (e->dest) & REORDER_BLOCK_VISITED)
629 REORDER_BLOCK_FLAGS (e->dest) &= ~REORDER_BLOCK_HEAD;
630
631 REORDER_BLOCK_SUCC (bb) = e;
632
633 visited_edge = e->dest;
634
635 reorder_last_visited = chain_reorder_blocks (e, bb);
636
637 if (e->dest
638 && ! (REORDER_BLOCK_FLAGS (e->dest)
639 & REORDER_BLOCK_VISITED))
640 make_reorder_chain (e->dest);
641 }
642 else
643 {
644 if (! (REORDER_BLOCK_FLAGS (bb) & REORDER_BLOCK_VISITED))
645 {
646 REORDER_BLOCK_INDEX (bb) = reorder_index++;
647 REORDER_BLOCK_FLAGS (bb) |= REORDER_BLOCK_VISITED;
648 }
649 }
650
651 /* Recurse on the successors. */
652 for (e = bb->succ; e; e = e->succ_next)
653 {
654 if (e->dest && e->dest == EXIT_BLOCK_PTR)
655 continue;
656
657 if (e->dest
658 && e->dest != e->src
659 && e->dest != visited_edge
660 && ! (REORDER_BLOCK_FLAGS (e->dest)
661 & REORDER_BLOCK_VISITED))
662 {
663 reorder_last_visited
664 = chain_reorder_blocks (e, reorder_last_visited);
665 make_reorder_chain (e->dest);
666 }
667 }
668 }
669
670
671 /* Fixup jumps and labels after reordering basic blocks. */
672
673 static void
674 fixup_reorder_chain ()
675 {
676 int i, j;
677 rtx insn;
678 int orig_num_blocks = n_basic_blocks;
679
680 /* Set the new last insn. */
681 {
682 int max_val = 0;
683 int max_index = 0;
684 for (j = 0; j < n_basic_blocks; j++)
685 {
686 int val = REORDER_BLOCK_INDEX (BASIC_BLOCK (j));
687 if (val > max_val)
688 {
689 max_val = val;
690 max_index = j;
691 }
692 }
693 insn = REORDER_BLOCK_EFF_END (BASIC_BLOCK (max_index));
694 NEXT_INSN (insn) = NULL_RTX;
695 set_last_insn (insn);
696 }
697
698 /* Add jumps and labels to fixup blocks. */
699 for (i = 0; i < orig_num_blocks; i++)
700 {
701 int need_block = 0;
702 basic_block bbi = BASIC_BLOCK (i);
703 if (REORDER_BLOCK_ADD_JUMP (bbi))
704 {
705 rtx label_insn, jump_insn, barrier_insn;
706
707 if (GET_CODE (REORDER_BLOCK_ADD_JUMP (bbi)->head) == CODE_LABEL)
708 label_insn = REORDER_BLOCK_ADD_JUMP (bbi)->head;
709 else
710 {
711 rtx new_label = gen_label_rtx ();
712 label_insn = emit_label_before (new_label,
713 REORDER_BLOCK_ADD_JUMP (bbi)->head);
714 REORDER_BLOCK_ADD_JUMP (bbi)->head = label_insn;
715 }
716
717 if (GET_CODE (bbi->end) != JUMP_INSN)
718 {
719 jump_insn = emit_jump_insn_after (gen_jump (label_insn),
720 bbi->end);
721 bbi->end = jump_insn;
722 need_block = 0;
723 }
724 else
725 {
726 jump_insn = emit_jump_insn_after (gen_jump (label_insn),
727 REORDER_BLOCK_EFF_END (bbi));
728 need_block = 1;
729 }
730
731 JUMP_LABEL (jump_insn) = label_insn;
732 ++LABEL_NUSES (label_insn);
733 barrier_insn = emit_barrier_after (jump_insn);
734
735 /* Add block for jump. Typically this is when a then is not
736 predicted and we are jumping to the moved then block. */
737 if (need_block)
738 {
739 basic_block nb;
740
741 VARRAY_GROW (basic_block_info, ++n_basic_blocks);
742 create_basic_block (n_basic_blocks - 1, jump_insn,
743 jump_insn, NULL);
744 nb = BASIC_BLOCK (n_basic_blocks - 1);
745 nb->global_live_at_start
746 = OBSTACK_ALLOC_REG_SET (function_obstack);
747 nb->global_live_at_end
748 = OBSTACK_ALLOC_REG_SET (function_obstack);
749
750 COPY_REG_SET (nb->global_live_at_start,
751 bbi->global_live_at_start);
752 COPY_REG_SET (nb->global_live_at_end,
753 bbi->global_live_at_start);
754 BASIC_BLOCK (nb->index)->local_set = 0;
755
756 nb->aux = xcalloc (1, sizeof (struct reorder_block_def));
757 REORDER_BLOCK_INDEX (nb) = REORDER_BLOCK_INDEX (bbi) + 1;
758 /* Relink to new block. */
759 nb->succ = bbi->succ;
760 nb->succ->src = nb;
761
762 make_edge (NULL, bbi, nb, 0);
763 bbi->succ->succ_next
764 = bbi->succ->succ_next->succ_next;
765 nb->succ->succ_next = 0;
766 /* Fix reorder block index to reflect new block. */
767 for (j = 0; j < n_basic_blocks - 1; j++)
768 {
769 basic_block bbj = BASIC_BLOCK (j);
770 if (REORDER_BLOCK_INDEX (bbj)
771 >= REORDER_BLOCK_INDEX (bbi) + 1)
772 REORDER_BLOCK_INDEX (bbj)++;
773 }
774 REORDER_BLOCK_SCOPE (nb) = REORDER_BLOCK_SCOPE (bbi);
775 REORDER_BLOCK_EFF_HEAD (nb) = nb->head;
776 REORDER_BLOCK_EFF_END (nb) = barrier_insn;
777 }
778 else
779 REORDER_BLOCK_EFF_END (bbi) = barrier_insn;
780 }
781 }
782 }
783
784
785 /* Perform sanity checks on the insn chain.
786 1. Check that next/prev pointers are consistent in both the forward and
787 reverse direction.
788 2. Count insns in chain, going both directions, and check if equal.
789 3. Check that get_last_insn () returns the actual end of chain. */
790 #ifdef ENABLE_CHECKING
791 static void
792 verify_insn_chain ()
793 {
794 rtx x,
795 prevx,
796 nextx;
797 int insn_cnt1,
798 insn_cnt2;
799
800 prevx = NULL;
801 insn_cnt1 = 1;
802 for (x = get_insns (); x; x = NEXT_INSN (x))
803 {
804 if (PREV_INSN (x) != prevx)
805 {
806 fprintf (stderr, "Forward traversal: insn chain corrupt.\n");
807 fprintf (stderr, "previous insn:\n");
808 debug_rtx (prevx);
809 fprintf (stderr, "current insn:\n");
810 debug_rtx (x);
811 abort ();
812 }
813 ++insn_cnt1;
814 prevx = x;
815 }
816
817 if (prevx != get_last_insn ())
818 {
819 fprintf (stderr, "last_insn corrupt.\n");
820 abort ();
821 }
822
823 nextx = NULL;
824 insn_cnt2 = 1;
825 for (x = get_last_insn (); x; x = PREV_INSN (x))
826 {
827 if (NEXT_INSN (x) != nextx)
828 {
829 fprintf (stderr, "Reverse traversal: insn chain corrupt.\n");
830 fprintf (stderr, "current insn:\n");
831 debug_rtx (x);
832 fprintf (stderr, "next insn:\n");
833 debug_rtx (nextx);
834 abort ();
835 }
836 ++insn_cnt2;
837 nextx = x;
838 }
839
840 if (insn_cnt1 != insn_cnt2)
841 {
842 fprintf (stderr, "insn_cnt1 (%d) not equal to insn_cnt2 (%d).\n",
843 insn_cnt1, insn_cnt2);
844 abort ();
845 }
846 }
847 #endif
848
849 static rtx
850 get_next_bb_note (x)
851 rtx x;
852 {
853 while (x)
854 {
855 if (GET_CODE (x) == NOTE
856 && NOTE_LINE_NUMBER (x) == NOTE_INSN_BASIC_BLOCK)
857 return x;
858 x = NEXT_INSN (x);
859 }
860 return NULL;
861 }
862
863
864 static rtx
865 get_prev_bb_note (x)
866 rtx x;
867 {
868 while (x)
869 {
870 if (GET_CODE (x) == NOTE
871 && NOTE_LINE_NUMBER (x) == NOTE_INSN_BASIC_BLOCK)
872 return x;
873 x = PREV_INSN (x);
874 }
875 return NULL;
876 }
877
878
879 /* Determine and record the relationships between basic blocks and
880 scopes in scope tree S. */
881
882 static void
883 relate_bbs_with_scopes (s)
884 scope s;
885 {
886 scope p;
887 int i, bbi1, bbi2, bbs_spanned;
888 rtx bbnote;
889
890 for (p = s->inner; p; p = p->next)
891 relate_bbs_with_scopes (p);
892
893 bbi1 = bbi2 = -1;
894 bbs_spanned = 0;
895
896 /* If the begin and end notes are both inside the same basic block,
897 or if they are both outside of basic blocks, then we know immediately
898 how they are related. Otherwise, we need to poke around to make the
899 determination. */
900 if (s->bb_beg != s->bb_end)
901 {
902 if (s->bb_beg && s->bb_end)
903 {
904 /* Both notes are in different bbs. This implies that all the
905 basic blocks spanned by the pair of notes are contained in
906 this scope. */
907 bbi1 = s->bb_beg->index;
908 bbi2 = s->bb_end->index;
909 bbs_spanned = 1;
910 }
911 else if (! s->bb_beg)
912 {
913 /* First note is outside of a bb. If the scope spans more than
914 one basic block, then they all are contained within this
915 scope. Otherwise, this scope is contained within the basic
916 block. */
917 bbnote = get_next_bb_note (s->note_beg);
918 if (! bbnote)
919 abort ();
920 if (NOTE_BASIC_BLOCK (bbnote) == s->bb_end)
921 {
922 bbs_spanned = 0;
923 s->bb_beg = NOTE_BASIC_BLOCK (bbnote);
924 }
925 else
926 {
927 bbi1 = NOTE_BASIC_BLOCK (bbnote)->index;
928 bbi2 = s->bb_end->index;
929 s->bb_end = NULL;
930 bbs_spanned = 1;
931 }
932 }
933 else /* ! s->bb_end */
934 {
935 /* Second note is outside of a bb. If the scope spans more than
936 one basic block, then they all are contained within this
937 scope. Otherwise, this scope is contained within the basic
938 block. */
939 bbnote = get_prev_bb_note (s->note_end);
940 if (! bbnote)
941 abort ();
942 if (NOTE_BASIC_BLOCK (bbnote) == s->bb_beg)
943 {
944 bbs_spanned = 0;
945 s->bb_end = NOTE_BASIC_BLOCK (bbnote);
946 }
947 else
948 {
949 bbi1 = s->bb_beg->index;
950 bbi2 = NOTE_BASIC_BLOCK (bbnote)->index;
951 s->bb_beg = NULL;
952 bbs_spanned = 1;
953 }
954 }
955 }
956 else
957 {
958 if (s->bb_beg)
959 /* Both notes are in the same bb, which implies the block
960 contains this scope. */
961 bbs_spanned = 0;
962 else
963 {
964 rtx x1, x2;
965 /* Both notes are outside of any bbs. This implies that all the
966 basic blocks spanned by the pair of notes are contained in
967 this scope.
968 There is a degenerate case to consider. If the notes do not
969 span any basic blocks, then it is an empty scope that can
970 safely be deleted or ignored. Mark these with level = -1. */
971
972 x1 = get_next_bb_note (s->note_beg);
973 x2 = get_prev_bb_note (s->note_end);
974 if (! (x1 && x2))
975 {
976 s->level = -1;
977 bbs_spanned = 0;
978 }
979 else
980 {
981 bbi1 = NOTE_BASIC_BLOCK (x1)->index;
982 bbi2 = NOTE_BASIC_BLOCK (x2)->index;
983 bbs_spanned = 1;
984 }
985 }
986 }
987
988
989 /* If the scope spans one or more basic blocks, we record them. We
990 only record the bbs that are immediately contained within this
991 scope. Note that if a scope is contained within a bb, we can tell
992 by checking that bb_beg = bb_end and that they are non-null. */
993 if (bbs_spanned)
994 {
995 int j = 0;
996
997 s->num_bbs = 0;
998 for (i = bbi1; i <= bbi2; i++)
999 if (! REORDER_BLOCK_SCOPE (BASIC_BLOCK (i)))
1000 s->num_bbs++;
1001
1002 s->bbs = xcalloc (s->num_bbs, sizeof (struct basic_block_def));
1003 for (i = bbi1; i <= bbi2; i++)
1004 {
1005 basic_block curr_bb = BASIC_BLOCK (i);
1006 if (! REORDER_BLOCK_SCOPE (curr_bb))
1007 {
1008 s->bbs[j++] = curr_bb;
1009 REORDER_BLOCK_SCOPE (curr_bb) = s;
1010 }
1011 }
1012 }
1013 else
1014 s->num_bbs = 0;
1015 }
1016
1017
1018 /* Allocate and initialize a new scope structure with scope level LEVEL,
1019 and record the NOTE beginning the scope. */
1020
1021 static scope
1022 make_new_scope (level, note)
1023 int level;
1024 rtx note;
1025 {
1026 scope new_scope = xcalloc (1, sizeof (struct scope_def));
1027 new_scope->level = level;
1028 new_scope->note_beg = note;
1029 new_scope->note_end = NULL;
1030 new_scope->bb_beg = NULL;
1031 new_scope->bb_end = NULL;
1032 new_scope->inner = NULL;
1033 new_scope->inner_last = NULL;
1034 new_scope->outer = NULL;
1035 new_scope->next = NULL;
1036 new_scope->num_bbs = 0;
1037 new_scope->bbs = NULL;
1038 return new_scope;
1039 }
1040
1041
1042 /* Build a forest representing the scope structure of the function.
1043 Return a pointer to a structure describing the forest. */
1044
1045 static void
1046 build_scope_forest (forest)
1047 scope_forest_info *forest;
1048 {
1049 rtx x;
1050 int level, bbi, i;
1051 basic_block curr_bb;
1052 scope root, curr_scope;
1053
1054 forest->num_trees = 0;
1055 forest->trees = NULL;
1056 level = -1;
1057 root = NULL;
1058 curr_bb = NULL;
1059 bbi = 0;
1060 for (x = get_insns (); x; x = NEXT_INSN (x))
1061 {
1062 if (bbi < n_basic_blocks && x == BASIC_BLOCK (bbi)->head)
1063 curr_bb = BASIC_BLOCK (bbi);
1064
1065 if (GET_CODE (x) == NOTE)
1066 {
1067 if (NOTE_LINE_NUMBER (x) == NOTE_INSN_BLOCK_BEG)
1068 {
1069 if (root)
1070 {
1071 scope new_scope;
1072 if (! curr_scope)
1073 abort();
1074 level++;
1075 new_scope = make_new_scope (level, x);
1076 new_scope->outer = curr_scope;
1077 new_scope->next = NULL;
1078 if (! curr_scope->inner)
1079 {
1080 curr_scope->inner = new_scope;
1081 curr_scope->inner_last = new_scope;
1082 }
1083 else
1084 {
1085 curr_scope->inner_last->next = new_scope;
1086 curr_scope->inner_last = new_scope;
1087 }
1088 curr_scope = curr_scope->inner_last;
1089 }
1090 else
1091 {
1092 int ntrees = forest->num_trees;
1093 level++;
1094 curr_scope = make_new_scope (level, x);
1095 root = curr_scope;
1096 if (ntrees == 0)
1097 forest->trees = xcalloc (1, sizeof (scope));
1098 else
1099 forest->trees = xrealloc (forest->trees,
1100 sizeof (scope) * (ntrees + 1));
1101 forest->trees[forest->num_trees++] = root;
1102 }
1103 curr_scope->bb_beg = curr_bb;
1104 }
1105 else if (NOTE_LINE_NUMBER (x) == NOTE_INSN_BLOCK_END)
1106 {
1107 curr_scope->bb_end = curr_bb;
1108 curr_scope->note_end = x;
1109 level--;
1110 curr_scope = curr_scope->outer;
1111 if (level == -1)
1112 root = NULL;
1113 }
1114 } /* if note */
1115
1116 if (curr_bb && curr_bb->end == x)
1117 {
1118 curr_bb = NULL;
1119 bbi++;
1120 }
1121
1122 } /* for */
1123
1124 for (i = 0; i < forest->num_trees; i++)
1125 relate_bbs_with_scopes (forest->trees[i]);
1126 }
1127
1128
1129 /* Remove all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes from
1130 the insn chain. */
1131
1132 static void
1133 remove_scope_notes ()
1134 {
1135 rtx x, next;
1136 basic_block currbb = NULL;
1137
1138 for (x = get_insns (); x; x = next)
1139 {
1140 next = NEXT_INSN (x);
1141 if (GET_CODE (x) == NOTE
1142 && NOTE_LINE_NUMBER (x) == NOTE_INSN_BASIC_BLOCK)
1143 currbb = NOTE_BASIC_BLOCK (x);
1144
1145 if (GET_CODE (x) == NOTE
1146 && (NOTE_LINE_NUMBER (x) == NOTE_INSN_BLOCK_BEG
1147 || NOTE_LINE_NUMBER (x) == NOTE_INSN_BLOCK_END))
1148 {
1149 /* Check if the scope end happens to be the end of a bb. */
1150 if (currbb && x == currbb->end
1151 && NOTE_LINE_NUMBER (x) == NOTE_INSN_BLOCK_END)
1152 currbb->end = PREV_INSN (x);
1153
1154 if (PREV_INSN (x))
1155 {
1156 NEXT_INSN (PREV_INSN (x)) = next;
1157 PREV_INSN (next) = PREV_INSN (x);
1158
1159 NEXT_INSN (x) = NULL;
1160 PREV_INSN (x) = NULL;
1161 }
1162 else
1163 abort ();
1164 }
1165 }
1166 }
1167
1168
1169 /* Insert scope note pairs for a contained scope tree S after insn IP. */
1170 static void
1171 insert_intra_1 (s, ip)
1172 scope s;
1173 rtx *ip;
1174 {
1175 scope p;
1176
1177 if (NOTE_BLOCK (s->note_beg))
1178 {
1179 *ip = emit_note_after (NOTE_INSN_BLOCK_BEG, *ip);
1180 NOTE_BLOCK (*ip) = NOTE_BLOCK (s->note_beg);
1181 }
1182
1183 for (p = s->inner; p; p = p->next)
1184 insert_intra_1 (p, ip);
1185
1186 if (NOTE_BLOCK (s->note_beg))
1187 {
1188 *ip = emit_note_after (NOTE_INSN_BLOCK_END, *ip);
1189 NOTE_BLOCK (*ip) = NOTE_BLOCK (s->note_end);
1190 }
1191 }
1192
1193
1194 /* Insert NOTE_INSN_BLOCK_END notes and NOTE_INSN_BLOCK_BEG notes for
1195 scopes that are contained within BB. */
1196
1197 static void
1198 insert_intra_bb_scope_notes (bb)
1199 basic_block bb;
1200 {
1201 scope s = REORDER_BLOCK_SCOPE (bb);
1202 scope p;
1203 rtx ip;
1204
1205 if (! s)
1206 return;
1207
1208 ip = bb->head;
1209 if (GET_CODE (ip) == CODE_LABEL)
1210 ip = NEXT_INSN (ip);
1211
1212 for (p = s->inner; p; p = p->next)
1213 {
1214 if (p->bb_beg != NULL && p->bb_beg == p->bb_end && p->bb_beg == bb)
1215 insert_intra_1 (p, &ip);
1216 }
1217 }
1218
1219
1220 /* Given two consecutive basic blocks BB1 and BB2 with different scopes,
1221 insert NOTE_INSN_BLOCK_END notes after BB1 and NOTE_INSN_BLOCK_BEG
1222 notes before BB2 such that the notes are correctly balanced. If BB1 or
1223 BB2 is NULL, we are inserting scope notes for the first and last basic
1224 blocks, respectively. */
1225
1226 static void
1227 insert_inter_bb_scope_notes (bb1, bb2)
1228 basic_block bb1;
1229 basic_block bb2;
1230 {
1231 rtx ip;
1232 scope com;
1233
1234 /* It is possible that a basic block is not contained in any scope.
1235 In that case, we either open or close a scope but not both. */
1236 if (bb1 && bb2)
1237 {
1238 scope s1 = REORDER_BLOCK_SCOPE (bb1);
1239 scope s2 = REORDER_BLOCK_SCOPE (bb2);
1240 if (! s1 && ! s2)
1241 return;
1242 if (! s1)
1243 bb1 = NULL;
1244 else if (! s2)
1245 bb2 = NULL;
1246 }
1247
1248 /* Find common ancestor scope. */
1249 if (bb1 && bb2)
1250 {
1251 scope s1 = REORDER_BLOCK_SCOPE (bb1);
1252 scope s2 = REORDER_BLOCK_SCOPE (bb2);
1253 while (s1 != s2)
1254 {
1255 if (! (s1 && s2))
1256 abort ();
1257 if (s1->level > s2->level)
1258 s1 = s1->outer;
1259 else if (s2->level > s1->level)
1260 s2 = s2->outer;
1261 else
1262 {
1263 s1 = s1->outer;
1264 s2 = s2->outer;
1265 }
1266 }
1267 com = s1;
1268 }
1269 else
1270 com = NULL;
1271
1272 /* Close scopes. */
1273 if (bb1)
1274 {
1275 scope s = REORDER_BLOCK_SCOPE (bb1);
1276 ip = REORDER_BLOCK_EFF_END (bb1);
1277 while (s != com)
1278 {
1279 if (NOTE_BLOCK (s->note_beg))
1280 {
1281 ip = emit_note_after (NOTE_INSN_BLOCK_END, ip);
1282 NOTE_BLOCK (ip) = NOTE_BLOCK (s->note_end);
1283 }
1284 s = s->outer;
1285 }
1286 }
1287
1288 /* Open scopes. */
1289 if (bb2)
1290 {
1291 scope s = REORDER_BLOCK_SCOPE (bb2);
1292 ip = bb2->head;
1293 while (s != com)
1294 {
1295 if (NOTE_BLOCK (s->note_beg))
1296 {
1297 ip = emit_note_before (NOTE_INSN_BLOCK_BEG, ip);
1298 NOTE_BLOCK (ip) = NOTE_BLOCK (s->note_beg);
1299 }
1300 s = s->outer;
1301 }
1302 }
1303 }
1304
1305
1306 /* Rebuild all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes based
1307 on the scope forest and the newly reordered basic blocks. */
1308
1309 static void
1310 rebuild_scope_notes (forest)
1311 scope_forest_info *forest;
1312 {
1313 int i;
1314
1315 if (forest->num_trees == 0)
1316 return;
1317
1318 /* Start by opening the scopes before the first basic block. */
1319 insert_inter_bb_scope_notes (NULL, BASIC_BLOCK (0));
1320
1321 /* Then, open and close scopes as needed between blocks. */
1322 for (i = 0; i < n_basic_blocks - 1; i++)
1323 {
1324 basic_block bb1 = BASIC_BLOCK (i);
1325 basic_block bb2 = BASIC_BLOCK (i + 1);
1326 if (REORDER_BLOCK_SCOPE (bb1) != REORDER_BLOCK_SCOPE (bb2))
1327 insert_inter_bb_scope_notes (bb1, bb2);
1328 insert_intra_bb_scope_notes (bb1);
1329 }
1330
1331 /* Finally, close the scopes after the last basic block. */
1332 insert_inter_bb_scope_notes (BASIC_BLOCK (n_basic_blocks - 1), NULL);
1333 insert_intra_bb_scope_notes (BASIC_BLOCK (n_basic_blocks - 1));
1334 }
1335
1336
1337 /* Free the storage associated with the scope tree at S. */
1338
1339 static void
1340 free_scope_forest_1 (s)
1341 scope s;
1342 {
1343 scope p, next;
1344
1345 for (p = s->inner; p; p = next)
1346 {
1347 next = p->next;
1348 free_scope_forest_1 (p);
1349 }
1350
1351 if (s->bbs)
1352 free (s->bbs);
1353 free (s);
1354 }
1355
1356
1357 /* Free the storage associated with the scope forest. */
1358
1359 static void
1360 free_scope_forest (forest)
1361 scope_forest_info *forest;
1362 {
1363 int i;
1364 for (i = 0; i < forest->num_trees; i++)
1365 free_scope_forest_1 (forest->trees[i]);
1366 }
1367
1368
1369 /* Visualize the scope forest. */
1370
1371 void
1372 dump_scope_forest (forest)
1373 scope_forest_info *forest;
1374 {
1375 if (forest->num_trees == 0)
1376 fprintf (stderr, "\n< Empty scope forest >\n");
1377 else
1378 {
1379 int i;
1380 fprintf (stderr, "\n< Scope forest >\n");
1381 for (i = 0; i < forest->num_trees; i++)
1382 dump_scope_forest_1 (forest->trees[i], 0);
1383 }
1384 }
1385
1386
1387 /* Recursive portion of dump_scope_forest. */
1388
1389 static void
1390 dump_scope_forest_1 (s, indent)
1391 scope s;
1392 int indent;
1393 {
1394 scope p;
1395 int i;
1396
1397 if (s->bb_beg != NULL && s->bb_beg == s->bb_end
1398 && REORDER_BLOCK_SCOPE (s->bb_beg)
1399 && REORDER_BLOCK_SCOPE (s->bb_beg)->level + 1 == s->level)
1400 {
1401 fprintf (stderr, "%*s", indent, "");
1402 fprintf (stderr, "BB%d:\n", s->bb_beg->index);
1403 }
1404
1405 fprintf (stderr, "%*s", indent, "");
1406 fprintf (stderr, "{ level %d (block %p)\n", s->level,
1407 NOTE_BLOCK (s->note_beg));
1408
1409 fprintf (stderr, "%*s%s", indent, "", "bbs:");
1410 for (i = 0; i < s->num_bbs; i++)
1411 fprintf (stderr, " %d", s->bbs[i]->index);
1412 fprintf (stderr, "\n");
1413
1414 for (p = s->inner; p; p = p->next)
1415 dump_scope_forest_1 (p, indent + 2);
1416
1417 fprintf (stderr, "%*s", indent, "");
1418 fprintf (stderr, "}\n");
1419 }
1420
1421
1422 /* Reorder basic blocks. */
1423
1424 void
1425 reorder_basic_blocks ()
1426 {
1427 int i, j;
1428 struct loops loops_info;
1429 int num_loops;
1430 scope_forest_info forest;
1431
1432 if (profile_arc_flag)
1433 return;
1434
1435 if (n_basic_blocks <= 1)
1436 return;
1437
1438 /* Exception edges are not currently handled. */
1439 for (i = 0; i < n_basic_blocks; i++)
1440 {
1441 edge e;
1442
1443 for (e = BASIC_BLOCK (i)->succ; e && ! (e->flags & EDGE_EH);
1444 e = e->succ_next)
1445 continue;
1446
1447 if (e && (e->flags & EDGE_EH))
1448 return;
1449 }
1450
1451 reorder_index = 0;
1452
1453 /* Find natural loops using the CFG. */
1454 num_loops = flow_loops_find (&loops_info);
1455
1456 /* Dump loop information. */
1457 flow_loops_dump (&loops_info, rtl_dump_file, 0);
1458
1459 reorder_last_visited = BASIC_BLOCK (0);
1460
1461 for (i = 0; i < n_basic_blocks; i++)
1462 {
1463 basic_block bbi = BASIC_BLOCK (i);
1464 bbi->aux = xcalloc (1, sizeof (struct reorder_block_def));
1465 *((struct reorder_block_def *)bbi->aux) = rbd_init;
1466 }
1467
1468 build_scope_forest (&forest);
1469 remove_scope_notes ();
1470
1471 for (i = 0; i < n_basic_blocks; i++)
1472 {
1473 basic_block bbi = BASIC_BLOCK (i);
1474 REORDER_BLOCK_EFF_END (bbi)
1475 = skip_insns_between_block (bbi, REORDER_SKIP_AFTER);
1476 if (i == 0)
1477 REORDER_BLOCK_EFF_HEAD (bbi) = get_insns ();
1478 else
1479 {
1480 rtx prev_eff_end = REORDER_BLOCK_EFF_END (BASIC_BLOCK (i - 1));
1481 REORDER_BLOCK_EFF_HEAD (bbi) = NEXT_INSN (prev_eff_end);
1482 }
1483 }
1484
1485 /* If we've not got epilogue in RTL, we must fallthru to the exit.
1486 Force the last block to be at the end. */
1487 /* ??? Some ABIs (e.g. MIPS) require the return insn to be at the
1488 end of the function for stack unwinding purposes. */
1489
1490 #ifndef HAVE_epilogue
1491 #define HAVE_epilogue 0
1492 #endif
1493
1494 if (! HAVE_epilogue)
1495 {
1496 basic_block last = BASIC_BLOCK (n_basic_blocks - 1);
1497 REORDER_BLOCK_INDEX (last) = n_basic_blocks - 1;
1498 REORDER_BLOCK_FLAGS (last) |= REORDER_BLOCK_VISITED;
1499 }
1500
1501 make_reorder_chain (BASIC_BLOCK (0));
1502
1503 fixup_reorder_chain ();
1504
1505 #ifdef ENABLE_CHECKING
1506 verify_insn_chain ();
1507 #endif
1508
1509 /* Put basic_block_info in new order. */
1510 for (i = 0; i < n_basic_blocks - 1; i++)
1511 {
1512 for (j = i; i != REORDER_BLOCK_INDEX (BASIC_BLOCK (j)); j++)
1513 continue;
1514
1515 if (REORDER_BLOCK_INDEX (BASIC_BLOCK (j)) == i
1516 && i != j)
1517 {
1518 basic_block tempbb;
1519 int temprbi;
1520 int rbi = REORDER_BLOCK_INDEX (BASIC_BLOCK (j));
1521
1522 temprbi = BASIC_BLOCK (rbi)->index;
1523 BASIC_BLOCK (rbi)->index = BASIC_BLOCK (j)->index;
1524 BASIC_BLOCK (j)->index = temprbi;
1525 tempbb = BASIC_BLOCK (rbi);
1526 BASIC_BLOCK (rbi) = BASIC_BLOCK (j);
1527 BASIC_BLOCK (j) = tempbb;
1528 }
1529 }
1530
1531 rebuild_scope_notes (&forest);
1532 free_scope_forest (&forest);
1533 reorder_blocks ();
1534
1535 #ifdef ENABLE_CHECKING
1536 verify_flow_info ();
1537 #endif
1538
1539 for (i = 0; i < n_basic_blocks; i++)
1540 free (BASIC_BLOCK (i)->aux);
1541
1542 /* Free loop information. */
1543 flow_loops_free (&loops_info);
1544
1545 }
1546