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