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