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
00049 #include "config.h"
00050 #include "system.h"
00051 #include "coretypes.h"
00052 #include "tm.h"
00053 #include "tree.h"
00054 #include "rtl.h"
00055 #include "hard-reg-set.h"
00056 #include "regs.h"
00057 #include "flags.h"
00058 #include "output.h"
00059 #include "function.h"
00060 #include "except.h"
00061 #include "toplev.h"
00062 #include "tm_p.h"
00063 #include "obstack.h"
00064 #include "timevar.h"
00065 #include "tree-pass.h"
00066 #include "ggc.h"
00067 #include "hashtab.h"
00068 #include "alloc-pool.h"
00069
00070
00071
00072 struct bitmap_obstack reg_obstack;
00073
00074 void debug_flow_info (void);
00075 static void free_edge (edge);
00076
00077 #define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
00078
00079
00080
00081 void
00082 init_flow (void)
00083 {
00084 if (!cfun->cfg)
00085 cfun->cfg = ggc_alloc_cleared (sizeof (struct control_flow_graph));
00086 n_edges = 0;
00087 ENTRY_BLOCK_PTR = ggc_alloc_cleared (sizeof (struct basic_block_def));
00088 ENTRY_BLOCK_PTR->index = ENTRY_BLOCK;
00089 EXIT_BLOCK_PTR = ggc_alloc_cleared (sizeof (struct basic_block_def));
00090 EXIT_BLOCK_PTR->index = EXIT_BLOCK;
00091 ENTRY_BLOCK_PTR->next_bb = EXIT_BLOCK_PTR;
00092 EXIT_BLOCK_PTR->prev_bb = ENTRY_BLOCK_PTR;
00093 }
00094
00095
00096
00097
00098 static void
00099 free_edge (edge e ATTRIBUTE_UNUSED)
00100 {
00101 n_edges--;
00102 ggc_free (e);
00103 }
00104
00105
00106
00107 void
00108 clear_edges (void)
00109 {
00110 basic_block bb;
00111 edge e;
00112 edge_iterator ei;
00113
00114 FOR_EACH_BB (bb)
00115 {
00116 FOR_EACH_EDGE (e, ei, bb->succs)
00117 free_edge (e);
00118 VEC_truncate (edge, bb->succs, 0);
00119 VEC_truncate (edge, bb->preds, 0);
00120 }
00121
00122 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
00123 free_edge (e);
00124 VEC_truncate (edge, EXIT_BLOCK_PTR->preds, 0);
00125 VEC_truncate (edge, ENTRY_BLOCK_PTR->succs, 0);
00126
00127 gcc_assert (!n_edges);
00128 }
00129
00130
00131
00132 basic_block
00133 alloc_block (void)
00134 {
00135 basic_block bb;
00136 bb = ggc_alloc_cleared (sizeof (*bb));
00137 return bb;
00138 }
00139
00140
00141 void
00142 link_block (basic_block b, basic_block after)
00143 {
00144 b->next_bb = after->next_bb;
00145 b->prev_bb = after;
00146 after->next_bb = b;
00147 b->next_bb->prev_bb = b;
00148 }
00149
00150
00151 void
00152 unlink_block (basic_block b)
00153 {
00154 b->next_bb->prev_bb = b->prev_bb;
00155 b->prev_bb->next_bb = b->next_bb;
00156 b->prev_bb = NULL;
00157 b->next_bb = NULL;
00158 }
00159
00160
00161 void
00162 compact_blocks (void)
00163 {
00164 int i;
00165 basic_block bb;
00166
00167 SET_BASIC_BLOCK (ENTRY_BLOCK, ENTRY_BLOCK_PTR);
00168 SET_BASIC_BLOCK (EXIT_BLOCK, EXIT_BLOCK_PTR);
00169
00170 i = NUM_FIXED_BLOCKS;
00171 FOR_EACH_BB (bb)
00172 {
00173 SET_BASIC_BLOCK (i, bb);
00174 bb->index = i;
00175 i++;
00176 }
00177
00178 gcc_assert (i == n_basic_blocks);
00179
00180 for (; i < last_basic_block; i++)
00181 SET_BASIC_BLOCK (i, NULL);
00182
00183 last_basic_block = n_basic_blocks;
00184 }
00185
00186
00187
00188 void
00189 expunge_block (basic_block b)
00190 {
00191 unlink_block (b);
00192 SET_BASIC_BLOCK (b->index, NULL);
00193 n_basic_blocks--;
00194
00195
00196
00197
00198
00199 }
00200
00201
00202
00203 static inline void
00204 connect_src (edge e)
00205 {
00206 VEC_safe_push (edge, gc, e->src->succs, e);
00207 }
00208
00209
00210
00211 static inline void
00212 connect_dest (edge e)
00213 {
00214 basic_block dest = e->dest;
00215 VEC_safe_push (edge, gc, dest->preds, e);
00216 e->dest_idx = EDGE_COUNT (dest->preds) - 1;
00217 }
00218
00219
00220
00221 static inline void
00222 disconnect_src (edge e)
00223 {
00224 basic_block src = e->src;
00225 edge_iterator ei;
00226 edge tmp;
00227
00228 for (ei = ei_start (src->succs); (tmp = ei_safe_edge (ei)); )
00229 {
00230 if (tmp == e)
00231 {
00232 VEC_unordered_remove (edge, src->succs, ei.index);
00233 return;
00234 }
00235 else
00236 ei_next (&ei);
00237 }
00238
00239 gcc_unreachable ();
00240 }
00241
00242
00243
00244 static inline void
00245 disconnect_dest (edge e)
00246 {
00247 basic_block dest = e->dest;
00248 unsigned int dest_idx = e->dest_idx;
00249
00250 VEC_unordered_remove (edge, dest->preds, dest_idx);
00251
00252
00253
00254 if (dest_idx < EDGE_COUNT (dest->preds))
00255 EDGE_PRED (dest, dest_idx)->dest_idx = dest_idx;
00256 }
00257
00258
00259
00260
00261
00262 edge
00263 unchecked_make_edge (basic_block src, basic_block dst, int flags)
00264 {
00265 edge e;
00266 e = ggc_alloc_cleared (sizeof (*e));
00267 n_edges++;
00268
00269 e->src = src;
00270 e->dest = dst;
00271 e->flags = flags;
00272
00273 connect_src (e);
00274 connect_dest (e);
00275
00276 execute_on_growing_pred (e);
00277
00278 return e;
00279 }
00280
00281
00282
00283
00284 edge
00285 cached_make_edge (sbitmap edge_cache, basic_block src, basic_block dst, int flags)
00286 {
00287 if (edge_cache == NULL
00288 || src == ENTRY_BLOCK_PTR
00289 || dst == EXIT_BLOCK_PTR)
00290 return make_edge (src, dst, flags);
00291
00292
00293 if (! TEST_BIT (edge_cache, dst->index))
00294 {
00295
00296
00297 SET_BIT (edge_cache, dst->index);
00298 return unchecked_make_edge (src, dst, flags);
00299 }
00300
00301
00302
00303 if (flags)
00304 {
00305 edge e = find_edge (src, dst);
00306 e->flags |= flags;
00307 }
00308
00309 return NULL;
00310 }
00311
00312
00313
00314
00315 edge
00316 make_edge (basic_block src, basic_block dest, int flags)
00317 {
00318 edge e = find_edge (src, dest);
00319
00320
00321 if (e)
00322 {
00323 e->flags |= flags;
00324 return NULL;
00325 }
00326
00327 return unchecked_make_edge (src, dest, flags);
00328 }
00329
00330
00331
00332
00333 edge
00334 make_single_succ_edge (basic_block src, basic_block dest, int flags)
00335 {
00336 edge e = make_edge (src, dest, flags);
00337
00338 e->probability = REG_BR_PROB_BASE;
00339 e->count = src->count;
00340 return e;
00341 }
00342
00343
00344
00345 void
00346 remove_edge (edge e)
00347 {
00348 remove_predictions_associated_with_edge (e);
00349 execute_on_shrinking_pred (e);
00350
00351 disconnect_src (e);
00352 disconnect_dest (e);
00353
00354 free_edge (e);
00355 }
00356
00357
00358
00359 void
00360 redirect_edge_succ (edge e, basic_block new_succ)
00361 {
00362 execute_on_shrinking_pred (e);
00363
00364 disconnect_dest (e);
00365
00366 e->dest = new_succ;
00367
00368
00369 connect_dest (e);
00370
00371 execute_on_growing_pred (e);
00372 }
00373
00374
00375
00376 edge
00377 redirect_edge_succ_nodup (edge e, basic_block new_succ)
00378 {
00379 edge s;
00380
00381 s = find_edge (e->src, new_succ);
00382 if (s && s != e)
00383 {
00384 s->flags |= e->flags;
00385 s->probability += e->probability;
00386 if (s->probability > REG_BR_PROB_BASE)
00387 s->probability = REG_BR_PROB_BASE;
00388 s->count += e->count;
00389 remove_edge (e);
00390 e = s;
00391 }
00392 else
00393 redirect_edge_succ (e, new_succ);
00394
00395 return e;
00396 }
00397
00398
00399
00400 void
00401 redirect_edge_pred (edge e, basic_block new_pred)
00402 {
00403 disconnect_src (e);
00404
00405 e->src = new_pred;
00406
00407
00408 connect_src (e);
00409 }
00410
00411
00412 void
00413 clear_bb_flags (void)
00414 {
00415 basic_block bb;
00416
00417 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
00418 bb->flags = (BB_PARTITION (bb) | (bb->flags & BB_DISABLE_SCHEDULE)
00419 | (bb->flags & BB_RTL));
00420 }
00421
00422
00423
00424
00425
00426
00427 void
00428 check_bb_profile (basic_block bb, FILE * file)
00429 {
00430 edge e;
00431 int sum = 0;
00432 gcov_type lsum;
00433 edge_iterator ei;
00434
00435 if (profile_status == PROFILE_ABSENT)
00436 return;
00437
00438 if (bb != EXIT_BLOCK_PTR)
00439 {
00440 FOR_EACH_EDGE (e, ei, bb->succs)
00441 sum += e->probability;
00442 if (EDGE_COUNT (bb->succs) && abs (sum - REG_BR_PROB_BASE) > 100)
00443 fprintf (file, "Invalid sum of outgoing probabilities %.1f%%\n",
00444 sum * 100.0 / REG_BR_PROB_BASE);
00445 lsum = 0;
00446 FOR_EACH_EDGE (e, ei, bb->succs)
00447 lsum += e->count;
00448 if (EDGE_COUNT (bb->succs)
00449 && (lsum - bb->count > 100 || lsum - bb->count < -100))
00450 fprintf (file, "Invalid sum of outgoing counts %i, should be %i\n",
00451 (int) lsum, (int) bb->count);
00452 }
00453 if (bb != ENTRY_BLOCK_PTR)
00454 {
00455 sum = 0;
00456 FOR_EACH_EDGE (e, ei, bb->preds)
00457 sum += EDGE_FREQUENCY (e);
00458 if (abs (sum - bb->frequency) > 100)
00459 fprintf (file,
00460 "Invalid sum of incoming frequencies %i, should be %i\n",
00461 sum, bb->frequency);
00462 lsum = 0;
00463 FOR_EACH_EDGE (e, ei, bb->preds)
00464 lsum += e->count;
00465 if (lsum - bb->count > 100 || lsum - bb->count < -100)
00466 fprintf (file, "Invalid sum of incoming counts %i, should be %i\n",
00467 (int) lsum, (int) bb->count);
00468 }
00469 }
00470
00471
00472
00473
00474
00475
00476 void
00477 dump_bb_info (basic_block bb, bool header, bool footer, int flags,
00478 const char *prefix, FILE *file)
00479 {
00480 edge e;
00481 edge_iterator ei;
00482
00483 if (header)
00484 {
00485 fprintf (file, "\n%sBasic block %d ", prefix, bb->index);
00486 if (bb->prev_bb)
00487 fprintf (file, ", prev %d", bb->prev_bb->index);
00488 if (bb->next_bb)
00489 fprintf (file, ", next %d", bb->next_bb->index);
00490 fprintf (file, ", loop_depth %d, count ", bb->loop_depth);
00491 fprintf (file, HOST_WIDEST_INT_PRINT_DEC, bb->count);
00492 fprintf (file, ", freq %i", bb->frequency);
00493 if (maybe_hot_bb_p (bb))
00494 fprintf (file, ", maybe hot");
00495 if (probably_never_executed_bb_p (bb))
00496 fprintf (file, ", probably never executed");
00497 fprintf (file, ".\n");
00498
00499 fprintf (file, "%sPredecessors: ", prefix);
00500 FOR_EACH_EDGE (e, ei, bb->preds)
00501 dump_edge_info (file, e, 0);
00502 }
00503
00504 if (footer)
00505 {
00506 fprintf (file, "\n%sSuccessors: ", prefix);
00507 FOR_EACH_EDGE (e, ei, bb->succs)
00508 dump_edge_info (file, e, 1);
00509 }
00510
00511 if ((flags & TDF_DETAILS)
00512 && (bb->flags & BB_RTL))
00513 {
00514 if (bb->il.rtl->global_live_at_start && header)
00515 {
00516 fprintf (file, "\n%sRegisters live at start:", prefix);
00517 dump_regset (bb->il.rtl->global_live_at_start, file);
00518 }
00519
00520 if (bb->il.rtl->global_live_at_end && footer)
00521 {
00522 fprintf (file, "\n%sRegisters live at end:", prefix);
00523 dump_regset (bb->il.rtl->global_live_at_end, file);
00524 }
00525 }
00526
00527 putc ('\n', file);
00528 }
00529
00530 void
00531 dump_flow_info (FILE *file, int flags)
00532 {
00533 basic_block bb;
00534
00535
00536 if (reg_n_info && !reload_completed
00537 && (flags & TDF_DETAILS) != 0)
00538 {
00539 unsigned int i, max = max_reg_num ();
00540 fprintf (file, "%d registers.\n", max);
00541 for (i = FIRST_PSEUDO_REGISTER; i < max; i++)
00542 if (REG_N_REFS (i))
00543 {
00544 enum reg_class class, altclass;
00545
00546 fprintf (file, "\nRegister %d used %d times across %d insns",
00547 i, REG_N_REFS (i), REG_LIVE_LENGTH (i));
00548 if (REG_BASIC_BLOCK (i) >= 0)
00549 fprintf (file, " in block %d", REG_BASIC_BLOCK (i));
00550 if (REG_N_SETS (i))
00551 fprintf (file, "; set %d time%s", REG_N_SETS (i),
00552 (REG_N_SETS (i) == 1) ? "" : "s");
00553 if (regno_reg_rtx[i] != NULL && REG_USERVAR_P (regno_reg_rtx[i]))
00554 fprintf (file, "; user var");
00555 if (REG_N_DEATHS (i) != 1)
00556 fprintf (file, "; dies in %d places", REG_N_DEATHS (i));
00557 if (REG_N_CALLS_CROSSED (i) == 1)
00558 fprintf (file, "; crosses 1 call");
00559 else if (REG_N_CALLS_CROSSED (i))
00560 fprintf (file, "; crosses %d calls", REG_N_CALLS_CROSSED (i));
00561 if (regno_reg_rtx[i] != NULL
00562 && PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD)
00563 fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i));
00564
00565 class = reg_preferred_class (i);
00566 altclass = reg_alternate_class (i);
00567 if (class != GENERAL_REGS || altclass != ALL_REGS)
00568 {
00569 if (altclass == ALL_REGS || class == ALL_REGS)
00570 fprintf (file, "; pref %s", reg_class_names[(int) class]);
00571 else if (altclass == NO_REGS)
00572 fprintf (file, "; %s or none", reg_class_names[(int) class]);
00573 else
00574 fprintf (file, "; pref %s, else %s",
00575 reg_class_names[(int) class],
00576 reg_class_names[(int) altclass]);
00577 }
00578
00579 if (regno_reg_rtx[i] != NULL && REG_POINTER (regno_reg_rtx[i]))
00580 fprintf (file, "; pointer");
00581 fprintf (file, ".\n");
00582 }
00583 }
00584
00585 fprintf (file, "\n%d basic blocks, %d edges.\n", n_basic_blocks, n_edges);
00586 FOR_EACH_BB (bb)
00587 {
00588 dump_bb_info (bb, true, true, flags, "", file);
00589 check_bb_profile (bb, file);
00590 }
00591
00592 putc ('\n', file);
00593 }
00594
00595 void
00596 debug_flow_info (void)
00597 {
00598 dump_flow_info (stderr, TDF_DETAILS);
00599 }
00600
00601 void
00602 dump_edge_info (FILE *file, edge e, int do_succ)
00603 {
00604 basic_block side = (do_succ ? e->dest : e->src);
00605
00606 if (side == ENTRY_BLOCK_PTR)
00607 fputs (" ENTRY", file);
00608 else if (side == EXIT_BLOCK_PTR)
00609 fputs (" EXIT", file);
00610 else
00611 fprintf (file, " %d", side->index);
00612
00613 if (e->probability)
00614 fprintf (file, " [%.1f%%] ", e->probability * 100.0 / REG_BR_PROB_BASE);
00615
00616 if (e->count)
00617 {
00618 fprintf (file, " count:");
00619 fprintf (file, HOST_WIDEST_INT_PRINT_DEC, e->count);
00620 }
00621
00622 if (e->flags)
00623 {
00624 static const char * const bitnames[] = {
00625 "fallthru", "ab", "abcall", "eh", "fake", "dfs_back",
00626 "can_fallthru", "irreducible", "sibcall", "loop_exit",
00627 "true", "false", "exec"
00628 };
00629 int comma = 0;
00630 int i, flags = e->flags;
00631
00632 fputs (" (", file);
00633 for (i = 0; flags; i++)
00634 if (flags & (1 << i))
00635 {
00636 flags &= ~(1 << i);
00637
00638 if (comma)
00639 fputc (',', file);
00640 if (i < (int) ARRAY_SIZE (bitnames))
00641 fputs (bitnames[i], file);
00642 else
00643 fprintf (file, "%d", i);
00644 comma = 1;
00645 }
00646
00647 fputc (')', file);
00648 }
00649 }
00650
00651
00652
00653 static struct obstack block_aux_obstack;
00654 static void *first_block_aux_obj = 0;
00655 static struct obstack edge_aux_obstack;
00656 static void *first_edge_aux_obj = 0;
00657
00658
00659
00660
00661 inline void
00662 alloc_aux_for_block (basic_block bb, int size)
00663 {
00664
00665 gcc_assert (!bb->aux && first_block_aux_obj);
00666 bb->aux = obstack_alloc (&block_aux_obstack, size);
00667 memset (bb->aux, 0, size);
00668 }
00669
00670
00671
00672
00673 void
00674 alloc_aux_for_blocks (int size)
00675 {
00676 static int initialized;
00677
00678 if (!initialized)
00679 {
00680 gcc_obstack_init (&block_aux_obstack);
00681 initialized = 1;
00682 }
00683 else
00684
00685 gcc_assert (!first_block_aux_obj);
00686
00687 first_block_aux_obj = obstack_alloc (&block_aux_obstack, 0);
00688 if (size)
00689 {
00690 basic_block bb;
00691
00692 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
00693 alloc_aux_for_block (bb, size);
00694 }
00695 }
00696
00697
00698
00699 void
00700 clear_aux_for_blocks (void)
00701 {
00702 basic_block bb;
00703
00704 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
00705 bb->aux = NULL;
00706 }
00707
00708
00709
00710
00711 void
00712 free_aux_for_blocks (void)
00713 {
00714 gcc_assert (first_block_aux_obj);
00715 obstack_free (&block_aux_obstack, first_block_aux_obj);
00716 first_block_aux_obj = NULL;
00717
00718 clear_aux_for_blocks ();
00719 }
00720
00721
00722
00723
00724 inline void
00725 alloc_aux_for_edge (edge e, int size)
00726 {
00727
00728 gcc_assert (!e->aux && first_edge_aux_obj);
00729 e->aux = obstack_alloc (&edge_aux_obstack, size);
00730 memset (e->aux, 0, size);
00731 }
00732
00733
00734
00735
00736 void
00737 alloc_aux_for_edges (int size)
00738 {
00739 static int initialized;
00740
00741 if (!initialized)
00742 {
00743 gcc_obstack_init (&edge_aux_obstack);
00744 initialized = 1;
00745 }
00746 else
00747
00748 gcc_assert (!first_edge_aux_obj);
00749
00750 first_edge_aux_obj = obstack_alloc (&edge_aux_obstack, 0);
00751 if (size)
00752 {
00753 basic_block bb;
00754
00755 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00756 {
00757 edge e;
00758 edge_iterator ei;
00759
00760 FOR_EACH_EDGE (e, ei, bb->succs)
00761 alloc_aux_for_edge (e, size);
00762 }
00763 }
00764 }
00765
00766
00767
00768 void
00769 clear_aux_for_edges (void)
00770 {
00771 basic_block bb;
00772 edge e;
00773
00774 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00775 {
00776 edge_iterator ei;
00777 FOR_EACH_EDGE (e, ei, bb->succs)
00778 e->aux = NULL;
00779 }
00780 }
00781
00782
00783
00784
00785 void
00786 free_aux_for_edges (void)
00787 {
00788 gcc_assert (first_edge_aux_obj);
00789 obstack_free (&edge_aux_obstack, first_edge_aux_obj);
00790 first_edge_aux_obj = NULL;
00791
00792 clear_aux_for_edges ();
00793 }
00794
00795 void
00796 debug_bb (basic_block bb)
00797 {
00798 dump_bb (bb, stderr, 0);
00799 }
00800
00801 basic_block
00802 debug_bb_n (int n)
00803 {
00804 basic_block bb = BASIC_BLOCK (n);
00805 dump_bb (bb, stderr, 0);
00806 return bb;
00807 }
00808
00809
00810
00811 static void
00812 dump_cfg_bb_info (FILE *file, basic_block bb)
00813 {
00814 unsigned i;
00815 edge_iterator ei;
00816 bool first = true;
00817 static const char * const bb_bitnames[] =
00818 {
00819 "dirty", "new", "reachable", "visited", "irreducible_loop", "superblock"
00820 };
00821 const unsigned n_bitnames = sizeof (bb_bitnames) / sizeof (char *);
00822 edge e;
00823
00824 fprintf (file, "Basic block %d", bb->index);
00825 for (i = 0; i < n_bitnames; i++)
00826 if (bb->flags & (1 << i))
00827 {
00828 if (first)
00829 fprintf (file, " (");
00830 else
00831 fprintf (file, ", ");
00832 first = false;
00833 fprintf (file, bb_bitnames[i]);
00834 }
00835 if (!first)
00836 fprintf (file, ")");
00837 fprintf (file, "\n");
00838
00839 fprintf (file, "Predecessors: ");
00840 FOR_EACH_EDGE (e, ei, bb->preds)
00841 dump_edge_info (file, e, 0);
00842
00843 fprintf (file, "\nSuccessors: ");
00844 FOR_EACH_EDGE (e, ei, bb->succs)
00845 dump_edge_info (file, e, 1);
00846 fprintf (file, "\n\n");
00847 }
00848
00849
00850
00851 void
00852 brief_dump_cfg (FILE *file)
00853 {
00854 basic_block bb;
00855
00856 FOR_EACH_BB (bb)
00857 {
00858 dump_cfg_bb_info (file, bb);
00859 }
00860 }
00861
00862
00863
00864
00865
00866
00867
00868
00869 void
00870 update_bb_profile_for_threading (basic_block bb, int edge_frequency,
00871 gcov_type count, edge taken_edge)
00872 {
00873 edge c;
00874 int prob;
00875 edge_iterator ei;
00876
00877 bb->count -= count;
00878 if (bb->count < 0)
00879 {
00880 if (dump_file)
00881 fprintf (dump_file, "bb %i count became negative after threading",
00882 bb->index);
00883 bb->count = 0;
00884 }
00885
00886
00887
00888 if (bb->frequency)
00889 prob = edge_frequency * REG_BR_PROB_BASE / bb->frequency;
00890 else
00891 prob = 0;
00892 if (prob > taken_edge->probability)
00893 {
00894 if (dump_file)
00895 fprintf (dump_file, "Jump threading proved probability of edge "
00896 "%i->%i too small (it is %i, should be %i).\n",
00897 taken_edge->src->index, taken_edge->dest->index,
00898 taken_edge->probability, prob);
00899 prob = taken_edge->probability;
00900 }
00901
00902
00903 taken_edge->probability -= prob;
00904 prob = REG_BR_PROB_BASE - prob;
00905 bb->frequency -= edge_frequency;
00906 if (bb->frequency < 0)
00907 bb->frequency = 0;
00908 if (prob <= 0)
00909 {
00910 if (dump_file)
00911 fprintf (dump_file, "Edge frequencies of bb %i has been reset, "
00912 "frequency of block should end up being 0, it is %i\n",
00913 bb->index, bb->frequency);
00914 EDGE_SUCC (bb, 0)->probability = REG_BR_PROB_BASE;
00915 ei = ei_start (bb->succs);
00916 ei_next (&ei);
00917 for (; (c = ei_safe_edge (ei)); ei_next (&ei))
00918 c->probability = 0;
00919 }
00920 else if (prob != REG_BR_PROB_BASE)
00921 {
00922 int scale = RDIV (65536 * REG_BR_PROB_BASE, prob);
00923
00924 FOR_EACH_EDGE (c, ei, bb->succs)
00925 {
00926 c->probability = RDIV (c->probability * scale, 65536);
00927 if (c->probability > REG_BR_PROB_BASE)
00928 c->probability = REG_BR_PROB_BASE;
00929 }
00930 }
00931
00932 gcc_assert (bb == taken_edge->src);
00933 taken_edge->count -= count;
00934 if (taken_edge->count < 0)
00935 {
00936 if (dump_file)
00937 fprintf (dump_file, "edge %i->%i count became negative after threading",
00938 taken_edge->src->index, taken_edge->dest->index);
00939 taken_edge->count = 0;
00940 }
00941 }
00942
00943
00944
00945 void
00946 scale_bbs_frequencies_int (basic_block *bbs, int nbbs, int num, int den)
00947 {
00948 int i;
00949 edge e;
00950 if (num < 0)
00951 num = 0;
00952 if (num > den)
00953 return;
00954
00955
00956 gcc_assert (num < 65536);
00957 for (i = 0; i < nbbs; i++)
00958 {
00959 edge_iterator ei;
00960 bbs[i]->frequency = RDIV (bbs[i]->frequency * num, den);
00961 bbs[i]->count = RDIV (bbs[i]->count * num, den);
00962 FOR_EACH_EDGE (e, ei, bbs[i]->succs)
00963 e->count = RDIV (e->count * num, den);
00964 }
00965 }
00966
00967
00968
00969 #define MAX_SAFE_MULTIPLIER (1 << (sizeof (HOST_WIDEST_INT) * 4 - 1))
00970
00971
00972
00973
00974 void
00975 scale_bbs_frequencies_gcov_type (basic_block *bbs, int nbbs, gcov_type num,
00976 gcov_type den)
00977 {
00978 int i;
00979 edge e;
00980 gcov_type fraction = RDIV (num * 65536, den);
00981
00982 gcc_assert (fraction >= 0);
00983
00984 if (num < MAX_SAFE_MULTIPLIER)
00985 for (i = 0; i < nbbs; i++)
00986 {
00987 edge_iterator ei;
00988 bbs[i]->frequency = RDIV (bbs[i]->frequency * num, den);
00989 if (bbs[i]->count <= MAX_SAFE_MULTIPLIER)
00990 bbs[i]->count = RDIV (bbs[i]->count * num, den);
00991 else
00992 bbs[i]->count = RDIV (bbs[i]->count * fraction, 65536);
00993 FOR_EACH_EDGE (e, ei, bbs[i]->succs)
00994 if (bbs[i]->count <= MAX_SAFE_MULTIPLIER)
00995 e->count = RDIV (e->count * num, den);
00996 else
00997 e->count = RDIV (e->count * fraction, 65536);
00998 }
00999 else
01000 for (i = 0; i < nbbs; i++)
01001 {
01002 edge_iterator ei;
01003 if (sizeof (gcov_type) > sizeof (int))
01004 bbs[i]->frequency = RDIV (bbs[i]->frequency * num, den);
01005 else
01006 bbs[i]->frequency = RDIV (bbs[i]->frequency * fraction, 65536);
01007 bbs[i]->count = RDIV (bbs[i]->count * fraction, 65536);
01008 FOR_EACH_EDGE (e, ei, bbs[i]->succs)
01009 e->count = RDIV (e->count * fraction, 65536);
01010 }
01011 }
01012
01013
01014
01015 static htab_t bb_original;
01016 static htab_t bb_copy;
01017 static alloc_pool original_copy_bb_pool;
01018
01019 struct htab_bb_copy_original_entry
01020 {
01021
01022 int index1;
01023
01024 int index2;
01025 };
01026
01027 static hashval_t
01028 bb_copy_original_hash (const void *p)
01029 {
01030 struct htab_bb_copy_original_entry *data
01031 = ((struct htab_bb_copy_original_entry *)p);
01032
01033 return data->index1;
01034 }
01035 static int
01036 bb_copy_original_eq (const void *p, const void *q)
01037 {
01038 struct htab_bb_copy_original_entry *data
01039 = ((struct htab_bb_copy_original_entry *)p);
01040 struct htab_bb_copy_original_entry *data2
01041 = ((struct htab_bb_copy_original_entry *)q);
01042
01043 return data->index1 == data2->index1;
01044 }
01045
01046
01047
01048 void
01049 initialize_original_copy_tables (void)
01050 {
01051 gcc_assert (!original_copy_bb_pool);
01052 original_copy_bb_pool
01053 = create_alloc_pool ("original_copy",
01054 sizeof (struct htab_bb_copy_original_entry), 10);
01055 bb_original = htab_create (10, bb_copy_original_hash,
01056 bb_copy_original_eq, NULL);
01057 bb_copy = htab_create (10, bb_copy_original_hash, bb_copy_original_eq, NULL);
01058 }
01059
01060
01061
01062 void
01063 free_original_copy_tables (void)
01064 {
01065 gcc_assert (original_copy_bb_pool);
01066 htab_delete (bb_copy);
01067 htab_delete (bb_original);
01068 free_alloc_pool (original_copy_bb_pool);
01069 bb_copy = NULL;
01070 bb_original = NULL;
01071 original_copy_bb_pool = NULL;
01072 }
01073
01074
01075
01076 void
01077 set_bb_original (basic_block bb, basic_block original)
01078 {
01079 if (original_copy_bb_pool)
01080 {
01081 struct htab_bb_copy_original_entry **slot;
01082 struct htab_bb_copy_original_entry key;
01083
01084 key.index1 = bb->index;
01085 slot =
01086 (struct htab_bb_copy_original_entry **) htab_find_slot (bb_original,
01087 &key, INSERT);
01088 if (*slot)
01089 (*slot)->index2 = original->index;
01090 else
01091 {
01092 *slot = pool_alloc (original_copy_bb_pool);
01093 (*slot)->index1 = bb->index;
01094 (*slot)->index2 = original->index;
01095 }
01096 }
01097 }
01098
01099
01100 basic_block
01101 get_bb_original (basic_block bb)
01102 {
01103 struct htab_bb_copy_original_entry *entry;
01104 struct htab_bb_copy_original_entry key;
01105
01106 gcc_assert (original_copy_bb_pool);
01107
01108 key.index1 = bb->index;
01109 entry = (struct htab_bb_copy_original_entry *) htab_find (bb_original, &key);
01110 if (entry)
01111 return BASIC_BLOCK (entry->index2);
01112 else
01113 return NULL;
01114 }
01115
01116
01117
01118 void
01119 set_bb_copy (basic_block bb, basic_block copy)
01120 {
01121 if (original_copy_bb_pool)
01122 {
01123 struct htab_bb_copy_original_entry **slot;
01124 struct htab_bb_copy_original_entry key;
01125
01126 key.index1 = bb->index;
01127 slot =
01128 (struct htab_bb_copy_original_entry **) htab_find_slot (bb_copy,
01129 &key, INSERT);
01130 if (*slot)
01131 (*slot)->index2 = copy->index;
01132 else
01133 {
01134 *slot = pool_alloc (original_copy_bb_pool);
01135 (*slot)->index1 = bb->index;
01136 (*slot)->index2 = copy->index;
01137 }
01138 }
01139 }
01140
01141
01142 basic_block
01143 get_bb_copy (basic_block bb)
01144 {
01145 struct htab_bb_copy_original_entry *entry;
01146 struct htab_bb_copy_original_entry key;
01147
01148 gcc_assert (original_copy_bb_pool);
01149
01150 key.index1 = bb->index;
01151 entry = (struct htab_bb_copy_original_entry *) htab_find (bb_copy, &key);
01152 if (entry)
01153 return BASIC_BLOCK (entry->index2);
01154 else
01155 return NULL;
01156 }