OSDN Git Service

7812ff1bab9486e92a3c64e431a9af0b31ad33b3
[pf3gnuchains/gcc-fork.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 typedef struct reorder_block_def {
56   int flags;
57   int index;
58   basic_block add_jump;
59   edge succ;
60   rtx end;
61   int block_begin;
62   int block_end;
63   rtx eff_head;
64   rtx eff_end;
65 } *reorder_block_def;
66
67 static struct reorder_block_def rbd_init
68 = {
69     0,                  /* flags */
70     0,                  /* index */
71     NULL,               /* add_jump */
72     NULL,               /* succ */
73     NULL_RTX,           /* end */
74     0,                  /* block_begin */
75     0,                  /* block_end */
76     NULL_RTX,           /* eff_head */
77     NULL_RTX            /* eff_end */
78 };
79
80
81 #define REORDER_BLOCK_HEAD      0x1
82 #define REORDER_BLOCK_VISITED   0x2
83   
84 #define REORDER_BLOCK_FLAGS(bb) \
85   ((reorder_block_def) (bb)->aux)->flags
86
87 #define REORDER_BLOCK_INDEX(bb) \
88   ((reorder_block_def) (bb)->aux)->index
89
90 #define REORDER_BLOCK_ADD_JUMP(bb) \
91   ((reorder_block_def) (bb)->aux)->add_jump
92
93 #define REORDER_BLOCK_SUCC(bb) \
94   ((reorder_block_def) (bb)->aux)->succ
95
96 #define REORDER_BLOCK_OLD_END(bb) \
97   ((reorder_block_def) (bb)->aux)->end
98
99 #define REORDER_BLOCK_BEGIN(bb) \
100   ((reorder_block_def) (bb)->aux)->block_begin
101
102 #define REORDER_BLOCK_END(bb) \
103   ((reorder_block_def) (bb)->aux)->block_end
104
105 #define REORDER_BLOCK_EFF_HEAD(bb) \
106   ((reorder_block_def) (bb)->aux)->eff_head
107
108 #define REORDER_BLOCK_EFF_END(bb) \
109   ((reorder_block_def) (bb)->aux)->eff_end
110
111
112 static int reorder_index;
113 static basic_block reorder_last_visited;
114
115 enum reorder_skip_type {REORDER_SKIP_BEFORE, REORDER_SKIP_AFTER,
116                         REORDER_SKIP_BLOCK_END};
117
118
119 /* Local function prototypes.  */
120 static rtx skip_insns_between_block     PARAMS ((basic_block,
121                                                  enum reorder_skip_type));
122 static basic_block get_common_dest      PARAMS ((basic_block, basic_block));
123 static basic_block chain_reorder_blocks PARAMS ((edge, basic_block));
124 static void make_reorder_chain          PARAMS ((basic_block));
125 static void fixup_reorder_chain         PARAMS ((void));
126 #ifdef ENABLE_CHECKING
127 static void verify_insn_chain           PARAMS ((void));
128 #endif
129
130 /* Skip over insns BEFORE or AFTER BB which are typically associated with
131    basic block BB.  */
132
133 static rtx
134 skip_insns_between_block (bb, skip_type)
135      basic_block bb;
136      enum reorder_skip_type skip_type;
137 {
138   rtx insn, last_insn;
139
140   if (skip_type == REORDER_SKIP_BEFORE)
141     {
142       if (bb == ENTRY_BLOCK_PTR)
143         return 0;
144
145       last_insn = bb->head;
146       for (insn = PREV_INSN (bb->head);
147            insn && insn != BASIC_BLOCK (bb->index - 1)->end;
148            last_insn = insn, insn = PREV_INSN (insn))
149         {
150           if (NEXT_INSN (insn) != last_insn)
151             break;
152
153           if (GET_CODE (insn) == NOTE
154               && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END
155               && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
156               && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END)
157             continue;
158           
159           break;
160         }
161     }
162   else
163     {
164       last_insn = bb->end;
165
166       if (bb == EXIT_BLOCK_PTR)
167         return 0;
168
169       for (insn = NEXT_INSN (bb->end); 
170            insn;
171            last_insn = insn, insn = NEXT_INSN (insn))
172         {
173           if (bb->index + 1 != n_basic_blocks
174               && insn == BASIC_BLOCK (bb->index + 1)->head)
175             break;
176
177           if (GET_CODE (insn) == BARRIER
178               || GET_CODE (insn) == JUMP_INSN 
179               || (GET_CODE (insn) == NOTE
180                   && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
181                       || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)))
182             continue;
183
184           if (GET_CODE (insn) == CODE_LABEL
185               && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
186               && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
187                   || GET_CODE (PATTERN
188                                (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
189             {
190               insn = NEXT_INSN (insn);
191               continue;
192             }
193
194           /* Skip to next non-deleted insn.  */
195           if (GET_CODE (insn) == NOTE
196               && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
197                   || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
198             continue; 
199
200           break;
201         }
202
203       if (skip_type == REORDER_SKIP_BLOCK_END)
204         {
205           int found_block_end = 0;
206
207           for (; insn; last_insn = insn, insn = NEXT_INSN (insn))
208             {
209               if (bb->index + 1 != n_basic_blocks
210                   && insn == BASIC_BLOCK (bb->index + 1)->head)
211                 break;
212
213               if (GET_CODE (insn) == NOTE
214                   && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
215                 {
216                   found_block_end = 1;
217                   continue;
218                 }
219
220               if (GET_CODE (insn) == NOTE
221                   && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
222                 continue;
223
224               if (GET_CODE (insn) == NOTE
225                   && NOTE_LINE_NUMBER (insn) >= 0
226                   && NEXT_INSN (insn)
227                   && GET_CODE (NEXT_INSN (insn)) == NOTE
228                   && (NOTE_LINE_NUMBER (NEXT_INSN (insn))
229                       == NOTE_INSN_BLOCK_END))
230                 continue;
231               break;
232             }
233
234           if (! found_block_end)
235             last_insn = 0;
236         }
237     }
238
239   return last_insn;
240 }
241
242
243 /* Return common destination for blocks BB0 and BB1.  */
244
245 static basic_block
246 get_common_dest (bb0, bb1)
247      basic_block bb0, bb1;
248 {
249   edge e0, e1;
250
251   for (e0 = bb0->succ; e0; e0 = e0->succ_next)
252     {
253       for (e1 = bb1->succ; e1; e1 = e1->succ_next)
254         {
255           if (e0->dest == e1->dest)
256             {
257               return e0->dest;
258             }
259         }
260     }
261   return 0;
262 }
263
264
265 /* Move the destination block for edge E after chain end block CEB
266    Adding jumps and labels is deferred until fixup_reorder_chain.  */
267
268 static basic_block
269 chain_reorder_blocks (e, ceb)
270      edge e;
271      basic_block ceb;
272 {
273   basic_block sb = e->src;
274   basic_block db = e->dest;
275   rtx cebe_insn, cebbe_insn, dbh_insn, dbe_insn;
276   edge ee, last_edge;
277
278   enum cond_types {NO_COND, PREDICT_THEN_WITH_ELSE, PREDICT_ELSE,
279                    PREDICT_THEN_NO_ELSE, PREDICT_NOT_THEN_NO_ELSE};
280   enum cond_types cond_type;
281   enum cond_block_types {NO_COND_BLOCK, THEN_BLOCK, ELSE_BLOCK,
282                          NO_ELSE_BLOCK};
283   enum cond_block_types cond_block_type;
284
285   if (rtl_dump_file)
286     fprintf (rtl_dump_file,
287              "Edge from basic block %d to basic block %d last visited %d\n",
288              sb->index, db->index, ceb->index);
289
290   dbh_insn = REORDER_BLOCK_EFF_HEAD (db);
291   cebe_insn = REORDER_BLOCK_EFF_END (ceb);
292   cebbe_insn = skip_insns_between_block (ceb, REORDER_SKIP_BLOCK_END);
293
294   {
295     int block_begins = 0;
296     rtx insn;
297
298     for (insn = dbh_insn; insn && insn != db->end; insn = NEXT_INSN (insn))
299       {
300         if (GET_CODE (insn) == NOTE
301             && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
302           {
303             block_begins += 1;
304             break;
305           }
306       }
307     REORDER_BLOCK_BEGIN (sb) = block_begins;
308   }
309
310   if (cebbe_insn)
311     {
312       int block_ends = 0;
313       rtx insn;
314
315       for (insn = cebe_insn; insn; insn = NEXT_INSN (insn))
316         {
317           if (PREV_INSN (insn) == cebbe_insn)
318             break;
319           if (GET_CODE (insn) == NOTE
320               && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
321             {
322               block_ends += 1;
323               continue;
324             }
325         }
326       REORDER_BLOCK_END (ceb) = block_ends;
327     }
328
329   /* Blocks are in original order.  */
330   if (sb->index == ceb->index
331       && ceb->index + 1 == db->index && NEXT_INSN (cebe_insn))
332     return db;
333
334   /* Get the type of block and type of condition.  */
335   cond_type = NO_COND;
336   cond_block_type = NO_COND_BLOCK;
337   if (GET_CODE (sb->end) == JUMP_INSN && ! simplejump_p (sb->end)
338       && condjump_p (sb->end))
339     {
340       if (e->flags & EDGE_FALLTHRU)
341         cond_block_type = THEN_BLOCK;
342       else if (get_common_dest (sb->succ->dest, sb))
343         cond_block_type = NO_ELSE_BLOCK;
344       else 
345         cond_block_type = ELSE_BLOCK;
346
347       if (sb->succ->succ_next
348           && get_common_dest (sb->succ->dest, sb))
349         {
350           if (cond_block_type == THEN_BLOCK)
351             {
352               if (! (REORDER_BLOCK_FLAGS (sb->succ->succ_next->dest)
353                      & REORDER_BLOCK_VISITED))
354                 cond_type = PREDICT_THEN_NO_ELSE;
355               else
356                 cond_type = PREDICT_NOT_THEN_NO_ELSE;
357             }
358           else if (cond_block_type == NO_ELSE_BLOCK)
359             {
360               if (! (REORDER_BLOCK_FLAGS (sb->succ->dest)
361                      & REORDER_BLOCK_VISITED))
362                 cond_type = PREDICT_NOT_THEN_NO_ELSE;
363               else
364                 cond_type = PREDICT_THEN_NO_ELSE;
365             }
366         }
367       else
368         {
369           if (cond_block_type == THEN_BLOCK)
370             {
371               if (! (REORDER_BLOCK_FLAGS (sb->succ->succ_next->dest)
372                      & REORDER_BLOCK_VISITED))
373                 cond_type = PREDICT_THEN_WITH_ELSE;
374               else
375                 cond_type = PREDICT_ELSE;
376             }
377           else if (cond_block_type == ELSE_BLOCK
378                    && sb->succ->dest != EXIT_BLOCK_PTR)
379             {
380               if (! (REORDER_BLOCK_FLAGS (sb->succ->dest)
381                      & REORDER_BLOCK_VISITED))
382                 cond_type = PREDICT_ELSE;
383               else
384                 cond_type = PREDICT_THEN_WITH_ELSE;
385             }
386         }
387     }
388   
389   if (rtl_dump_file)
390     {
391       static const char * cond_type_str [] = {"not cond jump", "predict then",
392                                               "predict else",
393                                               "predict then w/o else",
394                                               "predict not then w/o else"};
395       static const char * cond_block_type_str [] = {"not then or else block",
396                                                     "then block",
397                                                     "else block",
398                                                     "then w/o else block"};
399
400       fprintf (rtl_dump_file, "     %s (looking at %s)\n",
401                cond_type_str[(int)cond_type],
402                cond_block_type_str[(int)cond_block_type]);
403     }
404
405   /* Reflect that then block will move and we'll jump to it.  */
406   if (cond_block_type != THEN_BLOCK
407       && (cond_type == PREDICT_ELSE
408           || cond_type == PREDICT_NOT_THEN_NO_ELSE))
409     {
410       if (rtl_dump_file)
411         fprintf (rtl_dump_file,
412                  "    then jump from block %d to block %d\n",
413                  sb->index, sb->succ->dest->index);
414
415       /* Jump to reordered then block.  */
416       REORDER_BLOCK_ADD_JUMP (sb) = sb->succ->dest;
417     }
418   
419   /* Reflect that then block will jump back when we have no else.  */
420   if (cond_block_type != THEN_BLOCK
421       && cond_type == PREDICT_NOT_THEN_NO_ELSE)
422     {
423       for (ee = sb->succ->dest->succ;
424            ee && ! (ee->flags & EDGE_FALLTHRU);
425            ee = ee->succ_next)
426         continue;
427
428       if (ee && ! (GET_CODE (sb->succ->dest->end) == JUMP_INSN
429                    && ! simplejump_p (sb->succ->dest->end)))
430         {
431           REORDER_BLOCK_ADD_JUMP (sb->succ->dest) = ee->dest;
432         }
433     }
434
435   /* Reflect that else block will jump back.  */
436   if (cond_block_type == ELSE_BLOCK
437       && (cond_type == PREDICT_THEN_WITH_ELSE || cond_type == PREDICT_ELSE))
438     {
439       last_edge=db->succ;
440
441       if (last_edge
442           && last_edge->dest != EXIT_BLOCK_PTR
443           && GET_CODE (last_edge->dest->head) == CODE_LABEL
444           && ! (GET_CODE (db->end) == JUMP_INSN))
445         {
446           if (rtl_dump_file)
447             fprintf (rtl_dump_file,
448                      "     else jump from block %d to block %d\n",
449                      db->index, last_edge->dest->index);
450
451           REORDER_BLOCK_ADD_JUMP (db) = last_edge->dest;
452         }
453     }
454
455   /* This block's successor has already been reordered. This can happen
456      when we reorder a chain starting at a then or else.  */
457   for (last_edge = db->succ;
458        last_edge && ! (last_edge->flags & EDGE_FALLTHRU);
459        last_edge = last_edge->succ_next)
460     continue;
461
462   if (last_edge
463       && last_edge->dest != EXIT_BLOCK_PTR
464       && (REORDER_BLOCK_FLAGS (last_edge->dest)
465           & REORDER_BLOCK_VISITED))
466     {
467       if (rtl_dump_file)
468         fprintf (rtl_dump_file,
469                  "     end of chain jump from block %d to block %d\n",
470                  db->index, last_edge->dest->index);
471
472       REORDER_BLOCK_ADD_JUMP (db) = last_edge->dest;
473     }
474
475   dbh_insn = REORDER_BLOCK_EFF_HEAD (db);
476   cebe_insn = REORDER_BLOCK_EFF_END (ceb);
477   dbe_insn = REORDER_BLOCK_EFF_END (db);
478
479   /* Leave behind any lexical block markers.  */
480   if (debug_info_level > DINFO_LEVEL_TERSE
481       && ceb->index + 1 < db->index)
482     {
483       rtx insn, last_insn = get_last_insn ();
484       insn = NEXT_INSN (ceb->end);
485       if (! insn)
486         insn = REORDER_BLOCK_OLD_END (ceb);
487
488       if (NEXT_INSN (cebe_insn) == 0)
489           set_last_insn (cebe_insn);
490       for (; insn && insn != db->head/*dbh_insn*/;
491            insn = NEXT_INSN (insn))
492         {
493           if (GET_CODE (insn) == NOTE
494               && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG))
495             {
496               cebe_insn = emit_note_after (NOTE_INSN_BLOCK_BEG, cebe_insn);
497               delete_insn (insn);
498             }
499           if (GET_CODE (insn) == NOTE
500               && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END))
501             {
502               cebe_insn = emit_note_after (NOTE_INSN_BLOCK_END, cebe_insn);
503               delete_insn (insn);
504             }      
505         }
506       set_last_insn (last_insn);
507     }
508
509   /* Rechain predicted block.  */
510   NEXT_INSN (cebe_insn) = dbh_insn;
511   PREV_INSN (dbh_insn) = cebe_insn;
512
513   REORDER_BLOCK_OLD_END (db) = NEXT_INSN (dbe_insn);
514   if (db->index != n_basic_blocks - 1)
515     NEXT_INSN (dbe_insn) = 0;
516
517   return db;
518 }
519
520
521 /* Reorder blocks starting at block BB.  */
522
523 static void
524 make_reorder_chain (bb)
525      basic_block bb;
526 {
527   edge e;
528   basic_block visited_edge = NULL;
529   rtx block_end;
530   int probability;
531
532   if (bb == EXIT_BLOCK_PTR)
533     return;
534
535   /* Find the most probable block.  */
536   e = bb->succ;
537   block_end = bb->end;
538   if (GET_CODE (block_end) == JUMP_INSN && condjump_p (block_end))
539     {
540       rtx note = find_reg_note (block_end, REG_BR_PROB, 0);
541
542       if (note) 
543         probability = INTVAL (XEXP (note, 0));
544       else
545         probability = 0;
546
547       if (probability >= REG_BR_PROB_BASE / 2)
548         e = bb->succ->succ_next;
549     }
550
551   /* Add chosen successor to chain and recurse on it.  */
552   if (e && e->dest != EXIT_BLOCK_PTR
553       && e->dest != e->src
554       && (! (REORDER_BLOCK_FLAGS (e->dest) & REORDER_BLOCK_VISITED)
555           || (REORDER_BLOCK_FLAGS (e->dest) == REORDER_BLOCK_HEAD)))
556     {
557       if (! (REORDER_BLOCK_FLAGS (bb) & REORDER_BLOCK_VISITED))
558         {
559           REORDER_BLOCK_FLAGS (bb) |= REORDER_BLOCK_HEAD;
560           REORDER_BLOCK_INDEX (bb) = reorder_index++;
561           REORDER_BLOCK_FLAGS (bb) |= REORDER_BLOCK_VISITED;
562         }
563
564       if (REORDER_BLOCK_FLAGS (e->dest) & REORDER_BLOCK_VISITED)
565         REORDER_BLOCK_FLAGS (e->dest) &= ~REORDER_BLOCK_HEAD;
566         
567       REORDER_BLOCK_SUCC (bb) = e;
568
569       visited_edge = e->dest;
570
571       reorder_last_visited = chain_reorder_blocks (e, bb);
572
573       if (e->dest
574           && ! (REORDER_BLOCK_FLAGS (e->dest)
575                 & REORDER_BLOCK_VISITED))
576         make_reorder_chain (e->dest);
577     }
578   else
579     {
580       if (! (REORDER_BLOCK_FLAGS (bb) & REORDER_BLOCK_VISITED))
581         {
582           REORDER_BLOCK_INDEX (bb) = reorder_index++;
583           REORDER_BLOCK_FLAGS (bb) |= REORDER_BLOCK_VISITED;
584         }
585     }
586
587   /* Recurse on the successors.  */
588   for (e = bb->succ; e; e = e->succ_next)
589     {
590       if (e->dest && e->dest == EXIT_BLOCK_PTR)
591         continue;
592
593       if (e->dest
594           && e->dest != e->src
595           && e->dest != visited_edge
596           && ! (REORDER_BLOCK_FLAGS (e->dest)
597                 & REORDER_BLOCK_VISITED))
598         {
599           reorder_last_visited
600             = chain_reorder_blocks (e, reorder_last_visited);
601           make_reorder_chain (e->dest);
602         }
603     }
604 }
605
606
607 /* Fixup jumps and labels after reordering basic blocks.  */ 
608
609 static void
610 fixup_reorder_chain ()
611 {
612   int i, j;
613   rtx insn;
614   int orig_num_blocks = n_basic_blocks;
615
616   /* Set the new last insn.  */
617   {
618     int max_val = 0;
619     int max_index = 0;
620     for (j = 0; j < n_basic_blocks; j++) 
621       {
622         int val = REORDER_BLOCK_INDEX (BASIC_BLOCK (j));
623         if (val > max_val)
624           {
625             max_val = val;
626             max_index = j;
627           }
628       }
629     insn = REORDER_BLOCK_EFF_END (BASIC_BLOCK (max_index));
630     NEXT_INSN (insn) = NULL_RTX;
631     set_last_insn (insn);
632   }
633
634   /* Add jumps and labels to fixup blocks.  */
635   for (i = 0; i < orig_num_blocks; i++)
636     {
637       int need_block = 0;
638       basic_block bbi = BASIC_BLOCK (i);
639       if (REORDER_BLOCK_ADD_JUMP (bbi))
640         {
641           rtx label_insn, jump_insn, barrier_insn;
642
643           if (GET_CODE (REORDER_BLOCK_ADD_JUMP (bbi)->head) == CODE_LABEL)
644             label_insn  = REORDER_BLOCK_ADD_JUMP (bbi)->head;
645           else
646             {
647               rtx new_label = gen_label_rtx ();
648               label_insn = emit_label_before (new_label,
649                               REORDER_BLOCK_ADD_JUMP (bbi)->head);
650               REORDER_BLOCK_ADD_JUMP (bbi)->head = label_insn;   
651             }
652
653           if (GET_CODE (bbi->end) != JUMP_INSN)
654             {
655               jump_insn = emit_jump_insn_after (gen_jump (label_insn),
656                                                 bbi->end);
657               bbi->end = jump_insn;
658               need_block = 0;
659             }
660           else
661             {
662               jump_insn = emit_jump_insn_after (gen_jump (label_insn),
663                                                 REORDER_BLOCK_EFF_END (bbi));
664               need_block = 1;
665             }
666
667           JUMP_LABEL (jump_insn) = label_insn;
668           ++LABEL_NUSES (label_insn);
669           barrier_insn = emit_barrier_after (jump_insn);
670
671           /* Add block for jump.  Typically this is when a then is not
672              predicted and we are jumping to the moved then block.  */
673           if (need_block)
674             {
675               basic_block nb;
676
677               VARRAY_GROW (basic_block_info, ++n_basic_blocks);
678               create_basic_block (n_basic_blocks - 1, jump_insn,
679                                   jump_insn, NULL);
680               nb = BASIC_BLOCK (n_basic_blocks - 1);
681               nb->global_live_at_start
682                 = OBSTACK_ALLOC_REG_SET (function_obstack);
683               nb->global_live_at_end
684                 = OBSTACK_ALLOC_REG_SET (function_obstack);
685
686               COPY_REG_SET (nb->global_live_at_start,
687                             bbi->global_live_at_start);
688               COPY_REG_SET (nb->global_live_at_end,
689                             bbi->global_live_at_start);
690               BASIC_BLOCK (nb->index)->local_set = 0;
691
692               nb->aux = xcalloc (1, sizeof (struct reorder_block_def));
693               REORDER_BLOCK_INDEX (nb) = REORDER_BLOCK_INDEX (bbi) + 1;
694               /* Relink to new block.  */
695               nb->succ = bbi->succ;
696               nb->succ->src = nb;
697
698               make_edge (NULL, bbi, nb, 0);
699               bbi->succ->succ_next
700                 = bbi->succ->succ_next->succ_next;
701               nb->succ->succ_next = 0;
702               /* Fix reorder block index to reflect new block.  */
703               for (j = 0; j < n_basic_blocks - 1; j++)
704                 {
705                   basic_block bbj = BASIC_BLOCK (j);
706                   if (REORDER_BLOCK_INDEX (bbj)
707                       >= REORDER_BLOCK_INDEX (bbi) + 1)
708                     REORDER_BLOCK_INDEX (bbj)++;
709                 }
710             }
711         }
712     }
713 }
714
715
716 /* Perform sanity checks on the insn chain.
717    1. Check that next/prev pointers are consistent in both the forward and
718       reverse direction.
719    2. Count insns in chain, going both directions, and check if equal.
720    3. Check that get_last_insn () returns the actual end of chain.  */
721 #ifdef ENABLE_CHECKING
722 static void
723 verify_insn_chain ()
724 {
725   rtx x,
726       prevx,
727       nextx;
728   int insn_cnt1,
729       insn_cnt2;
730
731   prevx = NULL;
732   insn_cnt1 = 1;
733   for (x = get_insns (); x; x = NEXT_INSN (x))
734     {
735       if (PREV_INSN (x) != prevx)
736         {
737           fprintf (stderr, "Forward traversal: insn chain corrupt.\n");
738           fprintf (stderr, "previous insn:\n");
739           debug_rtx (prevx);
740           fprintf (stderr, "current insn:\n");
741           debug_rtx (x);
742           abort ();
743         }
744       ++insn_cnt1;
745       prevx = x;
746     }
747
748   if (prevx != get_last_insn ())
749     {
750       fprintf (stderr, "last_insn corrupt.\n");
751       abort ();
752     }
753
754   nextx = NULL;
755   insn_cnt2 = 1;
756   for (x = get_last_insn (); x; x = PREV_INSN (x))
757     {
758       if (NEXT_INSN (x) != nextx)
759         {
760           fprintf (stderr, "Reverse traversal: insn chain corrupt.\n");
761           fprintf (stderr, "current insn:\n");
762           debug_rtx (x);
763           fprintf (stderr, "next insn:\n");
764           debug_rtx (nextx);
765           abort ();
766         }
767       ++insn_cnt2;
768       nextx = x;
769     }
770
771   if (insn_cnt1 != insn_cnt2)
772     {
773       fprintf (stderr, "insn_cnt1 (%d) not equal to insn_cnt2 (%d).\n",
774                insn_cnt1, insn_cnt2);
775       abort ();
776     }
777 }
778 #endif
779
780 /* Reorder basic blocks.  */
781
782 void
783 reorder_basic_blocks ()
784 {
785   int i, j;
786   struct loops loops_info;
787   int num_loops;
788
789   if (profile_arc_flag)
790     return;
791
792   if (n_basic_blocks <= 1)
793     return;
794
795   /* Exception edges are not currently handled.  */
796   for (i = 0; i < n_basic_blocks; i++)
797     {
798       edge e;
799
800       for (e = BASIC_BLOCK (i)->succ; e && ! (e->flags & EDGE_EH);
801            e = e->succ_next)
802         continue;
803
804       if (e && (e->flags & EDGE_EH))
805         return;
806     }
807
808   reorder_index = 0;
809
810   /* Find natural loops using the CFG.  */
811   num_loops = flow_loops_find (&loops_info);
812
813   /* Dump loop information.  */
814   flow_loops_dump (&loops_info, rtl_dump_file, 0);
815
816   reorder_last_visited = BASIC_BLOCK (0);
817
818   for (i = 0; i < n_basic_blocks; i++)
819     {
820       basic_block bbi = BASIC_BLOCK (i);
821       bbi->aux = xcalloc (1, sizeof (struct reorder_block_def));
822       *((struct reorder_block_def *)bbi->aux) = rbd_init;
823       REORDER_BLOCK_EFF_END (bbi)
824         = skip_insns_between_block (bbi, REORDER_SKIP_AFTER);
825       if (i == 0)
826         REORDER_BLOCK_EFF_HEAD (bbi) = get_insns ();
827       else 
828         {
829           rtx prev_eff_end = REORDER_BLOCK_EFF_END (BASIC_BLOCK (i - 1));
830           REORDER_BLOCK_EFF_HEAD (bbi) = NEXT_INSN (prev_eff_end);
831         }
832     }
833
834   /* If we've not got epilogue in RTL, we must fallthru to the exit.
835      Force the last block to be at the end.  */
836   /* ??? Some ABIs (e.g. MIPS) require the return insn to be at the
837      end of the function for stack unwinding purposes.  */
838
839 #ifndef HAVE_epilogue
840 #define HAVE_epilogue 0
841 #endif
842
843   if (! HAVE_epilogue)
844     {
845       basic_block last = BASIC_BLOCK (n_basic_blocks - 1);
846       REORDER_BLOCK_INDEX (last) = n_basic_blocks - 1;
847       REORDER_BLOCK_FLAGS (last) |= REORDER_BLOCK_VISITED;
848     }
849       
850   make_reorder_chain (BASIC_BLOCK (0));
851
852   fixup_reorder_chain ();
853
854 #ifdef ENABLE_CHECKING
855   verify_insn_chain ();
856 #endif
857
858   /* Put basic_block_info in new order.  */
859   for (i = 0; i < n_basic_blocks - 1; i++)
860     {
861       for (j = i; i != REORDER_BLOCK_INDEX (BASIC_BLOCK (j)); j++)
862         continue;
863
864       if (REORDER_BLOCK_INDEX (BASIC_BLOCK (j)) == i
865           && i != j)
866         {
867           basic_block tempbb;
868           int temprbi;
869           int rbi = REORDER_BLOCK_INDEX (BASIC_BLOCK (j));
870
871           temprbi = BASIC_BLOCK (rbi)->index;
872           BASIC_BLOCK (rbi)->index = BASIC_BLOCK (j)->index;
873           BASIC_BLOCK (j)->index = temprbi;
874           tempbb = BASIC_BLOCK (rbi);
875           BASIC_BLOCK (rbi) = BASIC_BLOCK (j);
876           BASIC_BLOCK (j) = tempbb;
877         }
878     }
879
880 #ifdef ENABLE_CHECKING
881   verify_flow_info ();
882 #endif
883
884   for (i = 0; i < n_basic_blocks; i++)
885     free (BASIC_BLOCK (i)->aux);
886
887   /* Free loop information.  */
888   flow_loops_free (&loops_info);
889
890 }
891