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 #include "config.h"
00036 #include "system.h"
00037 #include "coretypes.h"
00038 #include "tm.h"
00039 #include "tree.h"
00040 #include "rtl.h"
00041 #include "hard-reg-set.h"
00042 #include "basic-block.h"
00043 #include "regs.h"
00044 #include "flags.h"
00045 #include "output.h"
00046 #include "function.h"
00047 #include "except.h"
00048 #include "toplev.h"
00049 #include "timevar.h"
00050
00051 static int count_basic_blocks (rtx);
00052 static void find_basic_blocks_1 (rtx);
00053 static void make_edges (basic_block, basic_block, int);
00054 static void make_label_edge (sbitmap *, basic_block, rtx, int);
00055 static void find_bb_boundaries (basic_block);
00056 static void compute_outgoing_frequencies (basic_block);
00057
00058
00059
00060
00061 bool
00062 inside_basic_block_p (rtx insn)
00063 {
00064 switch (GET_CODE (insn))
00065 {
00066 case CODE_LABEL:
00067
00068 return (NEXT_INSN (insn) == 0
00069 || !JUMP_P (NEXT_INSN (insn))
00070 || (GET_CODE (PATTERN (NEXT_INSN (insn))) != ADDR_VEC
00071 && GET_CODE (PATTERN (NEXT_INSN (insn))) != ADDR_DIFF_VEC));
00072
00073 case JUMP_INSN:
00074 return (GET_CODE (PATTERN (insn)) != ADDR_VEC
00075 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC);
00076
00077 case CALL_INSN:
00078 case INSN:
00079 return true;
00080
00081 case BARRIER:
00082 case NOTE:
00083 return false;
00084
00085 default:
00086 gcc_unreachable ();
00087 }
00088 }
00089
00090
00091
00092
00093 bool
00094 control_flow_insn_p (rtx insn)
00095 {
00096 rtx note;
00097
00098 switch (GET_CODE (insn))
00099 {
00100 case NOTE:
00101 case CODE_LABEL:
00102 return false;
00103
00104 case JUMP_INSN:
00105
00106 return (GET_CODE (PATTERN (insn)) != ADDR_VEC
00107 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC);
00108
00109 case CALL_INSN:
00110
00111
00112 if ((SIBLING_CALL_P (insn)
00113 || find_reg_note (insn, REG_NORETURN, 0))
00114 && GET_CODE (PATTERN (insn)) != COND_EXEC)
00115 return true;
00116
00117 return ((nonlocal_goto_handler_labels
00118 && (0 == (note = find_reg_note (insn, REG_EH_REGION,
00119 NULL_RTX))
00120 || INTVAL (XEXP (note, 0)) >= 0))
00121
00122 || can_throw_internal (insn));
00123
00124 case INSN:
00125 return (flag_non_call_exceptions && can_throw_internal (insn));
00126
00127 case BARRIER:
00128
00129
00130
00131 return false;
00132
00133 default:
00134 gcc_unreachable ();
00135 }
00136 }
00137
00138
00139
00140 static int
00141 count_basic_blocks (rtx f)
00142 {
00143 int count = 0;
00144 bool saw_insn = false;
00145 rtx insn;
00146
00147 for (insn = f; insn; insn = NEXT_INSN (insn))
00148 {
00149
00150
00151 if ((LABEL_P (insn) || BARRIER_P (insn))
00152 && saw_insn)
00153 count++, saw_insn = false;
00154
00155
00156 if (!saw_insn && inside_basic_block_p (insn))
00157 saw_insn = true;
00158
00159
00160 if (saw_insn && control_flow_insn_p (insn))
00161 count++, saw_insn = false;
00162 }
00163
00164 if (saw_insn)
00165 count++;
00166
00167
00168
00169 if (count == 0)
00170 {
00171 emit_insn (gen_rtx_USE (VOIDmode, const0_rtx));
00172 count = 1;
00173 }
00174
00175 return count;
00176 }
00177
00178
00179
00180
00181
00182
00183 static void
00184 make_label_edge (sbitmap *edge_cache, basic_block src, rtx label, int flags)
00185 {
00186 gcc_assert (LABEL_P (label));
00187
00188
00189
00190
00191
00192
00193 if (INSN_UID (label) == 0)
00194 return;
00195
00196 cached_make_edge (edge_cache, src, BLOCK_FOR_INSN (label), flags);
00197 }
00198
00199
00200
00201 void
00202 rtl_make_eh_edge (sbitmap *edge_cache, basic_block src, rtx insn)
00203 {
00204 int is_call = CALL_P (insn) ? EDGE_ABNORMAL_CALL : 0;
00205 rtx handlers, i;
00206
00207 handlers = reachable_handlers (insn);
00208
00209 for (i = handlers; i; i = XEXP (i, 1))
00210 make_label_edge (edge_cache, src, XEXP (i, 0),
00211 EDGE_ABNORMAL | EDGE_EH | is_call);
00212
00213 free_INSN_LIST_list (&handlers);
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 static void
00225 make_edges (basic_block min, basic_block max, int update_p)
00226 {
00227 basic_block bb;
00228 sbitmap *edge_cache = NULL;
00229
00230
00231
00232
00233 if (forced_labels || cfun->max_jumptable_ents > 100)
00234 {
00235 edge_cache = sbitmap_vector_alloc (last_basic_block, last_basic_block);
00236 sbitmap_vector_zero (edge_cache, last_basic_block);
00237
00238 if (update_p)
00239 FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
00240 {
00241 edge e;
00242 edge_iterator ei;
00243
00244 FOR_EACH_EDGE (e, ei, bb->succs)
00245 if (e->dest != EXIT_BLOCK_PTR)
00246 SET_BIT (edge_cache[bb->index], e->dest->index);
00247 }
00248 }
00249
00250
00251
00252 if (min == ENTRY_BLOCK_PTR->next_bb)
00253 cached_make_edge (edge_cache, ENTRY_BLOCK_PTR, min,
00254 EDGE_FALLTHRU);
00255
00256 FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
00257 {
00258 rtx insn, x;
00259 enum rtx_code code;
00260 edge e;
00261
00262 if (LABEL_P (BB_HEAD (bb))
00263 && LABEL_ALT_ENTRY_P (BB_HEAD (bb)))
00264 cached_make_edge (NULL, ENTRY_BLOCK_PTR, bb, 0);
00265
00266
00267
00268
00269 insn = BB_END (bb);
00270 code = GET_CODE (insn);
00271
00272
00273 if (code == JUMP_INSN)
00274 {
00275 rtx tmp;
00276
00277
00278 if (GET_CODE (PATTERN (insn)) == RESX)
00279 rtl_make_eh_edge (edge_cache, bb, insn);
00280
00281
00282
00283 else if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
00284 ;
00285
00286
00287 else if (tablejump_p (insn, NULL, &tmp))
00288 {
00289 rtvec vec;
00290 int j;
00291
00292 if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
00293 vec = XVEC (PATTERN (tmp), 0);
00294 else
00295 vec = XVEC (PATTERN (tmp), 1);
00296
00297 for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
00298 make_label_edge (edge_cache, bb,
00299 XEXP (RTVEC_ELT (vec, j), 0), 0);
00300
00301
00302
00303
00304 if ((tmp = single_set (insn)) != NULL
00305 && SET_DEST (tmp) == pc_rtx
00306 && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
00307 && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF)
00308 make_label_edge (edge_cache, bb,
00309 XEXP (XEXP (SET_SRC (tmp), 2), 0), 0);
00310 }
00311
00312
00313
00314 else if (computed_jump_p (insn))
00315 {
00316 for (x = forced_labels; x; x = XEXP (x, 1))
00317 make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL);
00318 }
00319
00320
00321 else if (returnjump_p (insn))
00322 cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, 0);
00323
00324
00325 else
00326 {
00327 gcc_assert (JUMP_LABEL (insn));
00328 make_label_edge (edge_cache, bb, JUMP_LABEL (insn), 0);
00329 }
00330 }
00331
00332
00333
00334
00335
00336 if (code == CALL_INSN && SIBLING_CALL_P (insn))
00337 cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR,
00338 EDGE_SIBCALL | EDGE_ABNORMAL);
00339
00340
00341
00342
00343
00344 else if (code == CALL_INSN || flag_non_call_exceptions)
00345 {
00346
00347 rtl_make_eh_edge (edge_cache, bb, insn);
00348
00349 if (code == CALL_INSN && nonlocal_goto_handler_labels)
00350 {
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
00361
00362 if (!note || INTVAL (XEXP (note, 0)) >= 0)
00363 for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
00364 make_label_edge (edge_cache, bb, XEXP (x, 0),
00365 EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
00366 }
00367 }
00368
00369
00370 insn = NEXT_INSN (insn);
00371 e = find_edge (bb, EXIT_BLOCK_PTR);
00372 if (e && e->flags & EDGE_FALLTHRU)
00373 insn = NULL;
00374
00375 while (insn
00376 && NOTE_P (insn)
00377 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
00378 insn = NEXT_INSN (insn);
00379
00380 if (!insn)
00381 cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
00382 else if (bb->next_bb != EXIT_BLOCK_PTR)
00383 {
00384 if (insn == BB_HEAD (bb->next_bb))
00385 cached_make_edge (edge_cache, bb, bb->next_bb, EDGE_FALLTHRU);
00386 }
00387 }
00388
00389 if (edge_cache)
00390 sbitmap_vector_free (edge_cache);
00391 }
00392
00393
00394
00395
00396
00397
00398 static void
00399 find_basic_blocks_1 (rtx f)
00400 {
00401 rtx insn, next;
00402 rtx bb_note = NULL_RTX;
00403 rtx head = NULL_RTX;
00404 rtx end = NULL_RTX;
00405 basic_block prev = ENTRY_BLOCK_PTR;
00406
00407
00408
00409
00410
00411
00412
00413 for (insn = f; insn; insn = next)
00414 {
00415 enum rtx_code code = GET_CODE (insn);
00416
00417 next = NEXT_INSN (insn);
00418
00419 if ((LABEL_P (insn) || BARRIER_P (insn))
00420 && head)
00421 {
00422 prev = create_basic_block_structure (head, end, bb_note, prev);
00423 head = end = NULL_RTX;
00424 bb_note = NULL_RTX;
00425 }
00426
00427 if (inside_basic_block_p (insn))
00428 {
00429 if (head == NULL_RTX)
00430 head = insn;
00431 end = insn;
00432 }
00433
00434 if (head && control_flow_insn_p (insn))
00435 {
00436 prev = create_basic_block_structure (head, end, bb_note, prev);
00437 head = end = NULL_RTX;
00438 bb_note = NULL_RTX;
00439 }
00440
00441 switch (code)
00442 {
00443 case NOTE:
00444 {
00445 int kind = NOTE_LINE_NUMBER (insn);
00446
00447
00448
00449
00450
00451 if (kind == NOTE_INSN_BASIC_BLOCK)
00452 {
00453 if (bb_note == NULL_RTX)
00454 bb_note = insn;
00455 else
00456 next = delete_insn (insn);
00457 }
00458 break;
00459 }
00460
00461 case CODE_LABEL:
00462 case JUMP_INSN:
00463 case CALL_INSN:
00464 case INSN:
00465 case BARRIER:
00466 break;
00467
00468 default:
00469 gcc_unreachable ();
00470 }
00471 }
00472
00473 if (head != NULL_RTX)
00474 create_basic_block_structure (head, end, bb_note, prev);
00475 else if (bb_note)
00476 delete_insn (bb_note);
00477
00478 gcc_assert (last_basic_block == n_basic_blocks);
00479
00480 clear_aux_for_blocks ();
00481 }
00482
00483
00484
00485
00486
00487 void
00488 find_basic_blocks (rtx f)
00489 {
00490 basic_block bb;
00491
00492 timevar_push (TV_CFG);
00493
00494
00495 if (basic_block_info != NULL)
00496 {
00497 clear_edges ();
00498
00499
00500
00501
00502 FOR_EACH_BB (bb)
00503 bb->aux = NULL;
00504
00505 basic_block_info = NULL;
00506 }
00507
00508 n_basic_blocks = count_basic_blocks (f);
00509 last_basic_block = 0;
00510 ENTRY_BLOCK_PTR->next_bb = EXIT_BLOCK_PTR;
00511 EXIT_BLOCK_PTR->prev_bb = ENTRY_BLOCK_PTR;
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 VARRAY_BB_INIT (basic_block_info, n_basic_blocks, "basic_block_info");
00522
00523 find_basic_blocks_1 (f);
00524
00525 profile_status = PROFILE_ABSENT;
00526
00527
00528 make_edges (ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, 0);
00529
00530
00531
00532 tidy_fallthru_edges ();
00533
00534 #ifdef ENABLE_CHECKING
00535 verify_flow_info ();
00536 #endif
00537 timevar_pop (TV_CFG);
00538 }
00539
00540
00541 enum state {BLOCK_NEW = 0, BLOCK_ORIGINAL, BLOCK_TO_SPLIT};
00542
00543 #define STATE(BB) (enum state) ((size_t) (BB)->aux)
00544 #define SET_STATE(BB, STATE) ((BB)->aux = (void *) (size_t) (STATE))
00545
00546
00547 #define BLOCK_USED_BY_TABLEJUMP 32
00548 #define FULL_STATE(BB) ((size_t) (BB)->aux)
00549
00550 static void
00551 mark_tablejump_edge (rtx label)
00552 {
00553 basic_block bb;
00554
00555 gcc_assert (LABEL_P (label));
00556
00557 if (INSN_UID (label) == 0)
00558 return;
00559 bb = BLOCK_FOR_INSN (label);
00560 SET_STATE (bb, FULL_STATE (bb) | BLOCK_USED_BY_TABLEJUMP);
00561 }
00562
00563 static void
00564 purge_dead_tablejump_edges (basic_block bb, rtx table)
00565 {
00566 rtx insn = BB_END (bb), tmp;
00567 rtvec vec;
00568 int j;
00569 edge_iterator ei;
00570 edge e;
00571
00572 if (GET_CODE (PATTERN (table)) == ADDR_VEC)
00573 vec = XVEC (PATTERN (table), 0);
00574 else
00575 vec = XVEC (PATTERN (table), 1);
00576
00577 for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
00578 mark_tablejump_edge (XEXP (RTVEC_ELT (vec, j), 0));
00579
00580
00581
00582
00583 if ((tmp = single_set (insn)) != NULL
00584 && SET_DEST (tmp) == pc_rtx
00585 && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
00586 && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF)
00587 mark_tablejump_edge (XEXP (XEXP (SET_SRC (tmp), 2), 0));
00588
00589 for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
00590 {
00591 if (FULL_STATE (e->dest) & BLOCK_USED_BY_TABLEJUMP)
00592 SET_STATE (e->dest, FULL_STATE (e->dest)
00593 & ~(size_t) BLOCK_USED_BY_TABLEJUMP);
00594 else if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH)))
00595 {
00596 remove_edge (e);
00597 continue;
00598 }
00599 ei_next (&ei);
00600 }
00601 }
00602
00603
00604
00605
00606 static void
00607 find_bb_boundaries (basic_block bb)
00608 {
00609 basic_block orig_bb = bb;
00610 rtx insn = BB_HEAD (bb);
00611 rtx end = BB_END (bb);
00612 rtx table;
00613 rtx flow_transfer_insn = NULL_RTX;
00614 edge fallthru = NULL;
00615
00616 if (insn == BB_END (bb))
00617 return;
00618
00619 if (LABEL_P (insn))
00620 insn = NEXT_INSN (insn);
00621
00622
00623 while (1)
00624 {
00625 enum rtx_code code = GET_CODE (insn);
00626
00627
00628 if (code == CODE_LABEL)
00629 {
00630 fallthru = split_block (bb, PREV_INSN (insn));
00631 if (flow_transfer_insn)
00632 BB_END (bb) = flow_transfer_insn;
00633
00634 bb = fallthru->dest;
00635 remove_edge (fallthru);
00636 flow_transfer_insn = NULL_RTX;
00637 if (LABEL_ALT_ENTRY_P (insn))
00638 make_edge (ENTRY_BLOCK_PTR, bb, 0);
00639 }
00640
00641
00642
00643 if (flow_transfer_insn && inside_basic_block_p (insn))
00644 {
00645 fallthru = split_block (bb, PREV_INSN (insn));
00646 BB_END (bb) = flow_transfer_insn;
00647 bb = fallthru->dest;
00648 remove_edge (fallthru);
00649 flow_transfer_insn = NULL_RTX;
00650 }
00651
00652 if (control_flow_insn_p (insn))
00653 flow_transfer_insn = insn;
00654 if (insn == end)
00655 break;
00656 insn = NEXT_INSN (insn);
00657 }
00658
00659
00660
00661
00662 if (flow_transfer_insn)
00663 BB_END (bb) = flow_transfer_insn;
00664
00665
00666
00667
00668 purge_dead_edges (bb);
00669
00670
00671
00672 if (bb != orig_bb && tablejump_p (BB_END (bb), NULL, &table))
00673 purge_dead_tablejump_edges (bb, table);
00674 }
00675
00676
00677
00678
00679 static void
00680 compute_outgoing_frequencies (basic_block b)
00681 {
00682 edge e, f;
00683 edge_iterator ei;
00684
00685 if (EDGE_COUNT (b->succs) == 2)
00686 {
00687 rtx note = find_reg_note (BB_END (b), REG_BR_PROB, NULL);
00688 int probability;
00689
00690 if (note)
00691 {
00692 probability = INTVAL (XEXP (note, 0));
00693 e = BRANCH_EDGE (b);
00694 e->probability = probability;
00695 e->count = ((b->count * probability + REG_BR_PROB_BASE / 2)
00696 / REG_BR_PROB_BASE);
00697 f = FALLTHRU_EDGE (b);
00698 f->probability = REG_BR_PROB_BASE - probability;
00699 f->count = b->count - e->count;
00700 return;
00701 }
00702 }
00703
00704 if (EDGE_COUNT (b->succs) == 1)
00705 {
00706 e = EDGE_SUCC (b, 0);
00707 e->probability = REG_BR_PROB_BASE;
00708 e->count = b->count;
00709 return;
00710 }
00711 guess_outgoing_edge_probabilities (b);
00712 if (b->count)
00713 FOR_EACH_EDGE (e, ei, b->succs)
00714 e->count = ((b->count * e->probability + REG_BR_PROB_BASE / 2)
00715 / REG_BR_PROB_BASE);
00716 }
00717
00718
00719
00720
00721 void
00722 find_many_sub_basic_blocks (sbitmap blocks)
00723 {
00724 basic_block bb, min, max;
00725
00726 FOR_EACH_BB (bb)
00727 SET_STATE (bb,
00728 TEST_BIT (blocks, bb->index) ? BLOCK_TO_SPLIT : BLOCK_ORIGINAL);
00729
00730 FOR_EACH_BB (bb)
00731 if (STATE (bb) == BLOCK_TO_SPLIT)
00732 find_bb_boundaries (bb);
00733
00734 FOR_EACH_BB (bb)
00735 if (STATE (bb) != BLOCK_ORIGINAL)
00736 break;
00737
00738 min = max = bb;
00739 for (; bb != EXIT_BLOCK_PTR; bb = bb->next_bb)
00740 if (STATE (bb) != BLOCK_ORIGINAL)
00741 max = bb;
00742
00743
00744
00745 make_edges (min, max, 1);
00746
00747
00748
00749 if (profile_status != PROFILE_ABSENT)
00750 FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
00751 {
00752 edge e;
00753 edge_iterator ei;
00754
00755 if (STATE (bb) == BLOCK_ORIGINAL)
00756 continue;
00757 if (STATE (bb) == BLOCK_NEW)
00758 {
00759 bb->count = 0;
00760 bb->frequency = 0;
00761 FOR_EACH_EDGE (e, ei, bb->preds)
00762 {
00763 bb->count += e->count;
00764 bb->frequency += EDGE_FREQUENCY (e);
00765 }
00766 }
00767
00768 compute_outgoing_frequencies (bb);
00769 }
00770
00771 FOR_EACH_BB (bb)
00772 SET_STATE (bb, 0);
00773 }
00774
00775
00776
00777 void
00778 find_sub_basic_blocks (basic_block bb)
00779 {
00780 basic_block min, max, b;
00781 basic_block next = bb->next_bb;
00782
00783 min = bb;
00784 find_bb_boundaries (bb);
00785 max = next->prev_bb;
00786
00787
00788
00789 make_edges (min, max, 1);
00790
00791
00792
00793 FOR_BB_BETWEEN (b, min, max->next_bb, next_bb)
00794 {
00795 edge e;
00796 edge_iterator ei;
00797
00798 if (b != min)
00799 {
00800 b->count = 0;
00801 b->frequency = 0;
00802 FOR_EACH_EDGE (e, ei, b->preds)
00803 {
00804 b->count += e->count;
00805 b->frequency += EDGE_FREQUENCY (e);
00806 }
00807 }
00808
00809 compute_outgoing_frequencies (b);
00810 }
00811 }