00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #include "config.h"
00049 #include "system.h"
00050 #ifdef SGI_MONGOOSE
00051
00052 #include "rtl.h"
00053 #endif
00054 #include "tree.h"
00055 #ifndef SGI_MONGOOSE
00056 #include "rtl.h"
00057 #endif
00058 #include "hard-reg-set.h"
00059 #include "basic-block.h"
00060 #include "regs.h"
00061 #include "flags.h"
00062 #include "output.h"
00063 #include "function.h"
00064 #include "except.h"
00065 #include "toplev.h"
00066 #include "tm_p.h"
00067 #include "obstack.h"
00068
00069
00070
00071 struct obstack flow_obstack;
00072 static char *flow_firstobj;
00073
00074
00075
00076 int n_basic_blocks;
00077
00078
00079
00080 int last_basic_block;
00081
00082
00083
00084 int n_edges;
00085
00086
00087
00088 edge first_deleted_edge;
00089 static basic_block first_deleted_block;
00090
00091
00092
00093 varray_type basic_block_info;
00094
00095
00096
00097 struct basic_block_def entry_exit_blocks[2]
00098 = {{NULL,
00099 NULL,
00100 NULL,
00101 NULL,
00102 NULL,
00103 NULL,
00104 NULL,
00105 NULL,
00106 NULL,
00107 NULL,
00108 NULL,
00109 ENTRY_BLOCK,
00110 NULL,
00111 EXIT_BLOCK_PTR,
00112 0,
00113 NULL,
00114 0,
00115 0,
00116 0
00117 },
00118 {
00119 NULL,
00120 NULL,
00121 NULL,
00122 NULL,
00123 NULL,
00124 NULL,
00125 NULL,
00126 NULL,
00127 NULL,
00128 NULL,
00129 NULL,
00130 EXIT_BLOCK,
00131 ENTRY_BLOCK_PTR,
00132 NULL,
00133 0,
00134 NULL,
00135 0,
00136 0,
00137 0
00138 }
00139 };
00140
00141 void debug_flow_info PARAMS ((void));
00142 static void free_edge PARAMS ((edge));
00143
00144
00145
00146 void
00147 init_flow ()
00148 {
00149 static int initialized;
00150
00151 first_deleted_edge = 0;
00152 first_deleted_block = 0;
00153 n_edges = 0;
00154
00155 if (!initialized)
00156 {
00157 gcc_obstack_init (&flow_obstack);
00158 flow_firstobj = (char *) obstack_alloc (&flow_obstack, 0);
00159 initialized = 1;
00160 }
00161 else
00162 {
00163 obstack_free (&flow_obstack, flow_firstobj);
00164 flow_firstobj = (char *) obstack_alloc (&flow_obstack, 0);
00165 }
00166 }
00167
00168
00169
00170
00171 static void
00172 free_edge (e)
00173 edge e;
00174 {
00175 n_edges--;
00176 memset (e, 0, sizeof *e);
00177 e->succ_next = first_deleted_edge;
00178 first_deleted_edge = e;
00179 }
00180
00181
00182
00183 void
00184 clear_edges ()
00185 {
00186 basic_block bb;
00187 edge e;
00188
00189 FOR_EACH_BB (bb)
00190 {
00191 edge e = bb->succ;
00192
00193 while (e)
00194 {
00195 edge next = e->succ_next;
00196
00197 free_edge (e);
00198 e = next;
00199 }
00200
00201 bb->succ = NULL;
00202 bb->pred = NULL;
00203 }
00204
00205 e = ENTRY_BLOCK_PTR->succ;
00206 while (e)
00207 {
00208 edge next = e->succ_next;
00209
00210 free_edge (e);
00211 e = next;
00212 }
00213
00214 EXIT_BLOCK_PTR->pred = NULL;
00215 ENTRY_BLOCK_PTR->succ = NULL;
00216
00217 if (n_edges)
00218 abort ();
00219 }
00220
00221
00222
00223 basic_block
00224 alloc_block ()
00225 {
00226 basic_block bb;
00227
00228 if (first_deleted_block)
00229 {
00230 bb = first_deleted_block;
00231 first_deleted_block = (basic_block) bb->succ;
00232 bb->succ = NULL;
00233 }
00234 else
00235 {
00236 bb = (basic_block) obstack_alloc (&flow_obstack, sizeof *bb);
00237 memset (bb, 0, sizeof *bb);
00238 }
00239 return bb;
00240 }
00241
00242
00243 void
00244 link_block (b, after)
00245 basic_block b, after;
00246 {
00247 b->next_bb = after->next_bb;
00248 b->prev_bb = after;
00249 after->next_bb = b;
00250 b->next_bb->prev_bb = b;
00251 }
00252
00253
00254 void
00255 unlink_block (b)
00256 basic_block b;
00257 {
00258 b->next_bb->prev_bb = b->prev_bb;
00259 b->prev_bb->next_bb = b->next_bb;
00260 }
00261
00262
00263 void
00264 compact_blocks ()
00265 {
00266 int i;
00267 basic_block bb;
00268
00269 i = 0;
00270 FOR_EACH_BB (bb)
00271 {
00272 BASIC_BLOCK (i) = bb;
00273 bb->index = i;
00274 i++;
00275 }
00276
00277 if (i != n_basic_blocks)
00278 abort ();
00279
00280 last_basic_block = n_basic_blocks;
00281 }
00282
00283
00284
00285
00286 void
00287 expunge_block (b)
00288 basic_block b;
00289 {
00290 unlink_block (b);
00291 BASIC_BLOCK (b->index) = NULL;
00292 n_basic_blocks--;
00293
00294
00295 memset (b, 0, sizeof *b);
00296 b->index = -3;
00297 b->succ = (edge) first_deleted_block;
00298 first_deleted_block = (basic_block) b;
00299 }
00300
00301
00302
00303
00304
00305 edge
00306 unchecked_make_edge (src, dst, flags)
00307 basic_block src, dst;
00308 int flags;
00309 {
00310 edge e;
00311
00312 if (first_deleted_edge)
00313 {
00314 e = first_deleted_edge;
00315 first_deleted_edge = e->succ_next;
00316 }
00317 else
00318 {
00319 e = (edge) obstack_alloc (&flow_obstack, sizeof *e);
00320 memset (e, 0, sizeof *e);
00321 }
00322 n_edges++;
00323
00324 e->succ_next = src->succ;
00325 e->pred_next = dst->pred;
00326 e->src = src;
00327 e->dest = dst;
00328 e->flags = flags;
00329
00330 src->succ = e;
00331 dst->pred = e;
00332
00333 return e;
00334 }
00335
00336
00337
00338 edge
00339 cached_make_edge (edge_cache, src, dst, flags)
00340 sbitmap *edge_cache;
00341 basic_block src, dst;
00342 int flags;
00343 {
00344 int use_edge_cache;
00345 edge e;
00346
00347
00348
00349 use_edge_cache = (edge_cache
00350 && src != ENTRY_BLOCK_PTR && dst != EXIT_BLOCK_PTR);
00351
00352
00353 switch (use_edge_cache)
00354 {
00355 default:
00356
00357 if (! TEST_BIT (edge_cache[src->index], dst->index))
00358 break;
00359
00360
00361 if (flags == 0)
00362 return NULL;
00363
00364
00365 case 0:
00366 for (e = src->succ; e; e = e->succ_next)
00367 if (e->dest == dst)
00368 {
00369 e->flags |= flags;
00370 return NULL;
00371 }
00372 break;
00373 }
00374
00375 e = unchecked_make_edge (src, dst, flags);
00376
00377 if (use_edge_cache)
00378 SET_BIT (edge_cache[src->index], dst->index);
00379
00380 return e;
00381 }
00382
00383
00384
00385
00386 edge
00387 make_edge (src, dest, flags)
00388 basic_block src, dest;
00389 int flags;
00390 {
00391 return cached_make_edge (NULL, src, dest, flags);
00392 }
00393
00394
00395
00396
00397 edge
00398 make_single_succ_edge (src, dest, flags)
00399 basic_block src, dest;
00400 int flags;
00401 {
00402 edge e = make_edge (src, dest, flags);
00403
00404 e->probability = REG_BR_PROB_BASE;
00405 e->count = src->count;
00406 return e;
00407 }
00408
00409
00410
00411 void
00412 remove_edge (e)
00413 edge e;
00414 {
00415 edge last_pred = NULL;
00416 edge last_succ = NULL;
00417 edge tmp;
00418 basic_block src, dest;
00419
00420 src = e->src;
00421 dest = e->dest;
00422 for (tmp = src->succ; tmp && tmp != e; tmp = tmp->succ_next)
00423 last_succ = tmp;
00424
00425 if (!tmp)
00426 abort ();
00427 if (last_succ)
00428 last_succ->succ_next = e->succ_next;
00429 else
00430 src->succ = e->succ_next;
00431
00432 for (tmp = dest->pred; tmp && tmp != e; tmp = tmp->pred_next)
00433 last_pred = tmp;
00434
00435 if (!tmp)
00436 abort ();
00437 if (last_pred)
00438 last_pred->pred_next = e->pred_next;
00439 else
00440 dest->pred = e->pred_next;
00441
00442 free_edge (e);
00443 }
00444
00445
00446
00447 void
00448 redirect_edge_succ (e, new_succ)
00449 edge e;
00450 basic_block new_succ;
00451 {
00452 edge *pe;
00453
00454
00455 for (pe = &e->dest->pred; *pe != e; pe = &(*pe)->pred_next)
00456 continue;
00457 *pe = (*pe)->pred_next;
00458
00459
00460 e->pred_next = new_succ->pred;
00461 new_succ->pred = e;
00462 e->dest = new_succ;
00463 }
00464
00465
00466
00467 edge
00468 redirect_edge_succ_nodup (e, new_succ)
00469 edge e;
00470 basic_block new_succ;
00471 {
00472 edge s;
00473
00474
00475 for (s = e->src->succ; s; s = s->succ_next)
00476 if (s->dest == new_succ && s != e)
00477 break;
00478
00479 if (s)
00480 {
00481 s->flags |= e->flags;
00482 s->probability += e->probability;
00483 if (s->probability > REG_BR_PROB_BASE)
00484 s->probability = REG_BR_PROB_BASE;
00485 s->count += e->count;
00486 remove_edge (e);
00487 e = s;
00488 }
00489 else
00490 redirect_edge_succ (e, new_succ);
00491
00492 return e;
00493 }
00494
00495
00496
00497 void
00498 redirect_edge_pred (e, new_pred)
00499 edge e;
00500 basic_block new_pred;
00501 {
00502 edge *pe;
00503
00504
00505 for (pe = &e->src->succ; *pe != e; pe = &(*pe)->succ_next)
00506 continue;
00507
00508 *pe = (*pe)->succ_next;
00509
00510
00511 e->succ_next = new_pred->succ;
00512 new_pred->succ = e;
00513 e->src = new_pred;
00514 }
00515
00516 void
00517 clear_bb_flags ()
00518 {
00519 basic_block bb;
00520
00521 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
00522 bb->flags = 0;
00523 }
00524
00525 void
00526 dump_flow_info (file)
00527 FILE *file;
00528 {
00529 int i;
00530 int max_regno = max_reg_num ();
00531 basic_block bb;
00532 static const char * const reg_class_names[] = REG_CLASS_NAMES;
00533
00534 fprintf (file, "%d registers.\n", max_regno);
00535 for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
00536 if (REG_N_REFS (i))
00537 {
00538 enum reg_class class, altclass;
00539
00540 fprintf (file, "\nRegister %d used %d times across %d insns",
00541 i, REG_N_REFS (i), REG_LIVE_LENGTH (i));
00542 if (REG_BASIC_BLOCK (i) >= 0)
00543 fprintf (file, " in block %d", REG_BASIC_BLOCK (i));
00544 if (REG_N_SETS (i))
00545 fprintf (file, "; set %d time%s", REG_N_SETS (i),
00546 (REG_N_SETS (i) == 1) ? "" : "s");
00547 if (regno_reg_rtx[i] != NULL && REG_USERVAR_P (regno_reg_rtx[i]))
00548 fprintf (file, "; user var");
00549 if (REG_N_DEATHS (i) != 1)
00550 fprintf (file, "; dies in %d places", REG_N_DEATHS (i));
00551 if (REG_N_CALLS_CROSSED (i) == 1)
00552 fprintf (file, "; crosses 1 call");
00553 else if (REG_N_CALLS_CROSSED (i))
00554 fprintf (file, "; crosses %d calls", REG_N_CALLS_CROSSED (i));
00555 if (regno_reg_rtx[i] != NULL
00556 && PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD)
00557 fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i));
00558
00559 class = reg_preferred_class (i);
00560 altclass = reg_alternate_class (i);
00561 if (class != GENERAL_REGS || altclass != ALL_REGS)
00562 {
00563 if (altclass == ALL_REGS || class == ALL_REGS)
00564 fprintf (file, "; pref %s", reg_class_names[(int) class]);
00565 else if (altclass == NO_REGS)
00566 fprintf (file, "; %s or none", reg_class_names[(int) class]);
00567 else
00568 fprintf (file, "; pref %s, else %s",
00569 reg_class_names[(int) class],
00570 reg_class_names[(int) altclass]);
00571 }
00572
00573 if (regno_reg_rtx[i] != NULL && REG_POINTER (regno_reg_rtx[i]))
00574 fprintf (file, "; pointer");
00575 fprintf (file, ".\n");
00576 }
00577
00578 fprintf (file, "\n%d basic blocks, %d edges.\n", n_basic_blocks, n_edges);
00579 FOR_EACH_BB (bb)
00580 {
00581 edge e;
00582 int sum;
00583 gcov_type lsum;
00584
00585 fprintf (file, "\nBasic block %d: first insn %d, last %d, ",
00586 bb->index, INSN_UID (bb->head), INSN_UID (bb->end));
00587 fprintf (file, "prev %d, next %d, ",
00588 bb->prev_bb->index, bb->next_bb->index);
00589 fprintf (file, "loop_depth %d, count ", bb->loop_depth);
00590 fprintf (file, HOST_WIDEST_INT_PRINT_DEC, bb->count);
00591 fprintf (file, ", freq %i", bb->frequency);
00592 if (maybe_hot_bb_p (bb))
00593 fprintf (file, ", maybe hot");
00594 if (probably_never_executed_bb_p (bb))
00595 fprintf (file, ", probably never executed");
00596 fprintf (file, ".\n");
00597
00598 fprintf (file, "Predecessors: ");
00599 for (e = bb->pred; e; e = e->pred_next)
00600 dump_edge_info (file, e, 0);
00601
00602 fprintf (file, "\nSuccessors: ");
00603 for (e = bb->succ; e; e = e->succ_next)
00604 dump_edge_info (file, e, 1);
00605
00606 fprintf (file, "\nRegisters live at start:");
00607 dump_regset (bb->global_live_at_start, file);
00608
00609 fprintf (file, "\nRegisters live at end:");
00610 dump_regset (bb->global_live_at_end, file);
00611
00612 putc ('\n', file);
00613
00614
00615
00616
00617
00618
00619 sum = 0;
00620 for (e = bb->succ; e; e = e->succ_next)
00621 sum += e->probability;
00622 if (bb->succ && abs (sum - REG_BR_PROB_BASE) > 100)
00623 fprintf (file, "Invalid sum of outgoing probabilities %.1f%%\n",
00624 sum * 100.0 / REG_BR_PROB_BASE);
00625 sum = 0;
00626 for (e = bb->pred; e; e = e->pred_next)
00627 sum += EDGE_FREQUENCY (e);
00628 if (abs (sum - bb->frequency) > 100)
00629 fprintf (file,
00630 "Invalid sum of incomming frequencies %i, should be %i\n",
00631 sum, bb->frequency);
00632 lsum = 0;
00633 for (e = bb->pred; e; e = e->pred_next)
00634 lsum += e->count;
00635 if (lsum - bb->count > 100 || lsum - bb->count < -100)
00636 fprintf (file, "Invalid sum of incomming counts %i, should be %i\n",
00637 (int)lsum, (int)bb->count);
00638 lsum = 0;
00639 for (e = bb->succ; e; e = e->succ_next)
00640 lsum += e->count;
00641 if (bb->succ && (lsum - bb->count > 100 || lsum - bb->count < -100))
00642 fprintf (file, "Invalid sum of incomming counts %i, should be %i\n",
00643 (int)lsum, (int)bb->count);
00644 }
00645
00646 putc ('\n', file);
00647 }
00648
00649 void
00650 debug_flow_info ()
00651 {
00652 dump_flow_info (stderr);
00653 }
00654
00655 void
00656 dump_edge_info (file, e, do_succ)
00657 FILE *file;
00658 edge e;
00659 int do_succ;
00660 {
00661 basic_block side = (do_succ ? e->dest : e->src);
00662
00663 if (side == ENTRY_BLOCK_PTR)
00664 fputs (" ENTRY", file);
00665 else if (side == EXIT_BLOCK_PTR)
00666 fputs (" EXIT", file);
00667 else
00668 fprintf (file, " %d", side->index);
00669
00670 if (e->probability)
00671 fprintf (file, " [%.1f%%] ", e->probability * 100.0 / REG_BR_PROB_BASE);
00672
00673 if (e->count)
00674 {
00675 fprintf (file, " count:");
00676 fprintf (file, HOST_WIDEST_INT_PRINT_DEC, e->count);
00677 }
00678
00679 if (e->flags)
00680 {
00681 static const char * const bitnames[]
00682 = {"fallthru", "ab", "abcall", "eh", "fake", "dfs_back", "can_fallthru"};
00683 int comma = 0;
00684 int i, flags = e->flags;
00685
00686 fputs (" (", file);
00687 for (i = 0; flags; i++)
00688 if (flags & (1 << i))
00689 {
00690 flags &= ~(1 << i);
00691
00692 if (comma)
00693 fputc (',', file);
00694 if (i < (int) ARRAY_SIZE (bitnames))
00695 fputs (bitnames[i], file);
00696 else
00697 fprintf (file, "%d", i);
00698 comma = 1;
00699 }
00700
00701 fputc (')', file);
00702 }
00703 }
00704
00705
00706
00707 static struct obstack block_aux_obstack;
00708 static void *first_block_aux_obj = 0;
00709 static struct obstack edge_aux_obstack;
00710 static void *first_edge_aux_obj = 0;
00711
00712
00713
00714
00715 #ifndef KEY
00716 inline
00717 #endif
00718 void
00719 alloc_aux_for_block (bb, size)
00720 basic_block bb;
00721 int size;
00722 {
00723
00724 if (bb->aux || !first_block_aux_obj)
00725 abort ();
00726 bb->aux = obstack_alloc (&block_aux_obstack, size);
00727 memset (bb->aux, 0, size);
00728 }
00729
00730
00731
00732
00733 void
00734 alloc_aux_for_blocks (size)
00735 int size;
00736 {
00737 static int initialized;
00738
00739 if (!initialized)
00740 {
00741 gcc_obstack_init (&block_aux_obstack);
00742 initialized = 1;
00743 }
00744
00745
00746 else if (first_block_aux_obj)
00747 abort ();
00748 first_block_aux_obj = (char *) obstack_alloc (&block_aux_obstack, 0);
00749 if (size)
00750 {
00751 basic_block bb;
00752
00753 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
00754 alloc_aux_for_block (bb, size);
00755 }
00756 }
00757
00758
00759
00760 void
00761 clear_aux_for_blocks ()
00762 {
00763 basic_block bb;
00764
00765 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
00766 bb->aux = NULL;
00767 }
00768
00769
00770
00771
00772 void
00773 free_aux_for_blocks ()
00774 {
00775 if (!first_block_aux_obj)
00776 abort ();
00777 obstack_free (&block_aux_obstack, first_block_aux_obj);
00778 first_block_aux_obj = NULL;
00779
00780 clear_aux_for_blocks ();
00781 }
00782
00783
00784
00785
00786 #ifndef KEY
00787 inline
00788 #endif
00789 void
00790 alloc_aux_for_edge (e, size)
00791 edge e;
00792 int size;
00793 {
00794
00795 if (e->aux || !first_edge_aux_obj)
00796 abort ();
00797 e->aux = obstack_alloc (&edge_aux_obstack, size);
00798 memset (e->aux, 0, size);
00799 }
00800
00801
00802
00803
00804 void
00805 alloc_aux_for_edges (size)
00806 int size;
00807 {
00808 static int initialized;
00809
00810 if (!initialized)
00811 {
00812 gcc_obstack_init (&edge_aux_obstack);
00813 initialized = 1;
00814 }
00815
00816
00817 else if (first_edge_aux_obj)
00818 abort ();
00819
00820 first_edge_aux_obj = (char *) obstack_alloc (&edge_aux_obstack, 0);
00821 if (size)
00822 {
00823 basic_block bb;
00824
00825 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00826 {
00827 edge e;
00828
00829 for (e = bb->succ; e; e = e->succ_next)
00830 alloc_aux_for_edge (e, size);
00831 }
00832 }
00833 }
00834
00835
00836
00837 void
00838 clear_aux_for_edges ()
00839 {
00840 basic_block bb;
00841 edge e;
00842
00843 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00844 {
00845 for (e = bb->succ; e; e = e->succ_next)
00846 e->aux = NULL;
00847 }
00848 }
00849
00850
00851
00852
00853 void
00854 free_aux_for_edges ()
00855 {
00856 if (!first_edge_aux_obj)
00857 abort ();
00858 obstack_free (&edge_aux_obstack, first_edge_aux_obj);
00859 first_edge_aux_obj = NULL;
00860
00861 clear_aux_for_edges ();
00862 }