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 #include "config.h"
00041 #include "system.h"
00042 #include "coretypes.h"
00043 #include "tm.h"
00044 #include "tree.h"
00045 #include "rtl.h"
00046 #include "hard-reg-set.h"
00047 #include "basic-block.h"
00048 #include "regs.h"
00049 #include "flags.h"
00050 #include "output.h"
00051 #include "function.h"
00052 #include "except.h"
00053 #include "toplev.h"
00054 #include "tm_p.h"
00055 #include "obstack.h"
00056 #include "insn-config.h"
00057 #include "cfglayout.h"
00058 #include "expr.h"
00059 #include "target.h"
00060
00061
00062
00063
00064
00065 rtx label_value_list;
00066
00067 static int can_delete_note_p (rtx);
00068 static int can_delete_label_p (rtx);
00069 static void commit_one_edge_insertion (edge, int);
00070 static rtx last_loop_beg_note (rtx);
00071 static bool back_edge_of_syntactic_loop_p (basic_block, basic_block);
00072 static basic_block rtl_split_edge (edge);
00073 static bool rtl_move_block_after (basic_block, basic_block);
00074 static int rtl_verify_flow_info (void);
00075 static basic_block cfg_layout_split_block (basic_block, void *);
00076 static edge cfg_layout_redirect_edge_and_branch (edge, basic_block);
00077 static basic_block cfg_layout_redirect_edge_and_branch_force (edge, basic_block);
00078 static void cfg_layout_delete_block (basic_block);
00079 static void rtl_delete_block (basic_block);
00080 static basic_block rtl_redirect_edge_and_branch_force (edge, basic_block);
00081 static edge rtl_redirect_edge_and_branch (edge, basic_block);
00082 static basic_block rtl_split_block (basic_block, void *);
00083 static void rtl_dump_bb (basic_block, FILE *, int);
00084 static int rtl_verify_flow_info_1 (void);
00085 static void mark_killed_regs (rtx, rtx, void *);
00086 static void rtl_make_forwarder_block (edge);
00087
00088
00089
00090
00091 static int
00092 can_delete_note_p (rtx note)
00093 {
00094 return (NOTE_LINE_NUMBER (note) == NOTE_INSN_DELETED
00095 || NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK
00096 || NOTE_LINE_NUMBER (note) == NOTE_INSN_UNLIKELY_EXECUTED_CODE);
00097 }
00098
00099
00100
00101 static int
00102 can_delete_label_p (rtx label)
00103 {
00104 return (!LABEL_PRESERVE_P (label)
00105
00106 && LABEL_NAME (label) == 0
00107 && !in_expr_list_p (forced_labels, label)
00108 && !in_expr_list_p (label_value_list, label));
00109 }
00110
00111
00112
00113 rtx
00114 delete_insn (rtx insn)
00115 {
00116 rtx next = NEXT_INSN (insn);
00117 rtx note;
00118 bool really_delete = true;
00119
00120 if (LABEL_P (insn))
00121 {
00122
00123
00124
00125 if (! can_delete_label_p (insn))
00126 {
00127 const char *name = LABEL_NAME (insn);
00128
00129 really_delete = false;
00130 PUT_CODE (insn, NOTE);
00131 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED_LABEL;
00132 NOTE_DELETED_LABEL_NAME (insn) = name;
00133 }
00134
00135 remove_node_from_expr_list (insn, &nonlocal_goto_handler_labels);
00136 }
00137
00138 if (really_delete)
00139 {
00140
00141 gcc_assert (!INSN_DELETED_P (insn));
00142 remove_insn (insn);
00143 INSN_DELETED_P (insn) = 1;
00144 }
00145
00146
00147
00148 if (JUMP_P (insn)
00149 && JUMP_LABEL (insn)
00150 && LABEL_P (JUMP_LABEL (insn)))
00151 LABEL_NUSES (JUMP_LABEL (insn))--;
00152
00153
00154 else
00155 {
00156 while ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != NULL_RTX
00157 && LABEL_P (XEXP (note, 0)))
00158 {
00159 LABEL_NUSES (XEXP (note, 0))--;
00160 remove_note (insn, note);
00161 }
00162 }
00163
00164 if (JUMP_P (insn)
00165 && (GET_CODE (PATTERN (insn)) == ADDR_VEC
00166 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
00167 {
00168 rtx pat = PATTERN (insn);
00169 int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC;
00170 int len = XVECLEN (pat, diff_vec_p);
00171 int i;
00172
00173 for (i = 0; i < len; i++)
00174 {
00175 rtx label = XEXP (XVECEXP (pat, diff_vec_p, i), 0);
00176
00177
00178
00179
00180 if (!NOTE_P (label))
00181 LABEL_NUSES (label)--;
00182 }
00183 }
00184
00185 return next;
00186 }
00187
00188
00189 rtx
00190 delete_insn_and_edges (rtx insn)
00191 {
00192 rtx x;
00193 bool purge = false;
00194
00195 if (INSN_P (insn)
00196 && BLOCK_FOR_INSN (insn)
00197 && BB_END (BLOCK_FOR_INSN (insn)) == insn)
00198 purge = true;
00199 x = delete_insn (insn);
00200 if (purge)
00201 purge_dead_edges (BLOCK_FOR_INSN (insn));
00202 return x;
00203 }
00204
00205
00206
00207
00208 void
00209 delete_insn_chain (rtx start, rtx finish)
00210 {
00211 rtx next;
00212
00213
00214
00215
00216 while (1)
00217 {
00218 next = NEXT_INSN (start);
00219 if (NOTE_P (start) && !can_delete_note_p (start))
00220 ;
00221 else
00222 next = delete_insn (start);
00223
00224 if (start == finish)
00225 break;
00226 start = next;
00227 }
00228 }
00229
00230
00231 void
00232 delete_insn_chain_and_edges (rtx first, rtx last)
00233 {
00234 bool purge = false;
00235
00236 if (INSN_P (last)
00237 && BLOCK_FOR_INSN (last)
00238 && BB_END (BLOCK_FOR_INSN (last)) == last)
00239 purge = true;
00240 delete_insn_chain (first, last);
00241 if (purge)
00242 purge_dead_edges (BLOCK_FOR_INSN (last));
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 basic_block
00254 create_basic_block_structure (rtx head, rtx end, rtx bb_note, basic_block after)
00255 {
00256 basic_block bb;
00257
00258 if (bb_note
00259 && (bb = NOTE_BASIC_BLOCK (bb_note)) != NULL
00260 && bb->aux == NULL)
00261 {
00262
00263
00264 rtx after;
00265
00266 if (LABEL_P (head))
00267 after = head;
00268 else
00269 {
00270 after = PREV_INSN (head);
00271 head = bb_note;
00272 }
00273
00274 if (after != bb_note && NEXT_INSN (after) != bb_note)
00275 reorder_insns_nobb (bb_note, bb_note, after);
00276 }
00277 else
00278 {
00279
00280
00281 bb = alloc_block ();
00282
00283 if (!head && !end)
00284 head = end = bb_note
00285 = emit_note_after (NOTE_INSN_BASIC_BLOCK, get_last_insn ());
00286 else if (LABEL_P (head) && end)
00287 {
00288 bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, head);
00289 if (head == end)
00290 end = bb_note;
00291 }
00292 else
00293 {
00294 bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, head);
00295 head = bb_note;
00296 if (!end)
00297 end = head;
00298 }
00299
00300 NOTE_BASIC_BLOCK (bb_note) = bb;
00301 }
00302
00303
00304 if (NEXT_INSN (end) == bb_note)
00305 end = bb_note;
00306
00307 BB_HEAD (bb) = head;
00308 BB_END (bb) = end;
00309 bb->index = last_basic_block++;
00310 bb->flags = BB_NEW;
00311 link_block (bb, after);
00312 BASIC_BLOCK (bb->index) = bb;
00313 update_bb_for_insn (bb);
00314 BB_SET_PARTITION (bb, BB_UNPARTITIONED);
00315
00316
00317
00318 bb->aux = bb;
00319
00320 return bb;
00321 }
00322
00323
00324
00325
00326
00327
00328 static basic_block
00329 rtl_create_basic_block (void *headp, void *endp, basic_block after)
00330 {
00331 rtx head = headp, end = endp;
00332 basic_block bb;
00333
00334
00335 if ((size_t) last_basic_block >= VARRAY_SIZE (basic_block_info))
00336 {
00337 size_t new_size = last_basic_block + (last_basic_block + 3) / 4;
00338 VARRAY_GROW (basic_block_info, new_size);
00339 }
00340
00341 n_basic_blocks++;
00342
00343 bb = create_basic_block_structure (head, end, NULL, after);
00344 bb->aux = NULL;
00345 return bb;
00346 }
00347
00348 static basic_block
00349 cfg_layout_create_basic_block (void *head, void *end, basic_block after)
00350 {
00351 basic_block newbb = rtl_create_basic_block (head, end, after);
00352
00353 initialize_bb_rbi (newbb);
00354 return newbb;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 static void
00366 rtl_delete_block (basic_block b)
00367 {
00368 rtx insn, end, tmp;
00369
00370
00371
00372
00373 insn = BB_HEAD (b);
00374 if (LABEL_P (insn))
00375 maybe_remove_eh_handler (insn);
00376
00377
00378 end = BB_END (b);
00379 if (tablejump_p (end, NULL, &tmp))
00380 end = tmp;
00381
00382
00383 tmp = next_nonnote_insn (end);
00384 while (tmp && BARRIER_P (tmp))
00385 {
00386 end = tmp;
00387 tmp = next_nonnote_insn (end);
00388 }
00389
00390
00391 BB_HEAD (b) = NULL;
00392 delete_insn_chain (insn, end);
00393 }
00394
00395
00396
00397 void
00398 compute_bb_for_insn (void)
00399 {
00400 basic_block bb;
00401
00402 FOR_EACH_BB (bb)
00403 {
00404 rtx end = BB_END (bb);
00405 rtx insn;
00406
00407 for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
00408 {
00409 BLOCK_FOR_INSN (insn) = bb;
00410 if (insn == end)
00411 break;
00412 }
00413 }
00414 }
00415
00416
00417
00418 void
00419 free_bb_for_insn (void)
00420 {
00421 rtx insn;
00422 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
00423 if (!BARRIER_P (insn))
00424 BLOCK_FOR_INSN (insn) = NULL;
00425 }
00426
00427
00428 rtx
00429 entry_of_function (void)
00430 {
00431 return (n_basic_blocks ? BB_HEAD (ENTRY_BLOCK_PTR->next_bb) : get_insns ());
00432 }
00433
00434
00435
00436 void
00437 update_bb_for_insn (basic_block bb)
00438 {
00439 rtx insn;
00440
00441 for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
00442 {
00443 if (!BARRIER_P (insn))
00444 set_block_for_insn (insn, bb);
00445 if (insn == BB_END (bb))
00446 break;
00447 }
00448 }
00449
00450
00451
00452
00453 static basic_block
00454 rtl_split_block (basic_block bb, void *insnp)
00455 {
00456 basic_block new_bb;
00457 rtx insn = insnp;
00458 edge e;
00459 edge_iterator ei;
00460
00461 if (!insn)
00462 {
00463 insn = first_insn_after_basic_block_note (bb);
00464
00465 if (insn)
00466 insn = PREV_INSN (insn);
00467 else
00468 insn = get_last_insn ();
00469 }
00470
00471
00472
00473
00474 if (insn == BB_END (bb))
00475 emit_note_after (NOTE_INSN_DELETED, insn);
00476
00477
00478 new_bb = create_basic_block (NEXT_INSN (insn), BB_END (bb), bb);
00479 BB_COPY_PARTITION (new_bb, bb);
00480 BB_END (bb) = insn;
00481
00482
00483 new_bb->succs = bb->succs;
00484 bb->succs = NULL;
00485 FOR_EACH_EDGE (e, ei, new_bb->succs)
00486 e->src = new_bb;
00487
00488 if (bb->global_live_at_start)
00489 {
00490 new_bb->global_live_at_start = ALLOC_REG_SET (®_obstack);
00491 new_bb->global_live_at_end = ALLOC_REG_SET (®_obstack);
00492 COPY_REG_SET (new_bb->global_live_at_end, bb->global_live_at_end);
00493
00494
00495
00496
00497
00498
00499 COPY_REG_SET (new_bb->global_live_at_start, bb->global_live_at_end);
00500 propagate_block (new_bb, new_bb->global_live_at_start, NULL, NULL, 0);
00501 COPY_REG_SET (bb->global_live_at_end,
00502 new_bb->global_live_at_start);
00503 #ifdef HAVE_conditional_execution
00504
00505
00506 if (reload_completed)
00507 {
00508 bb->flags |= BB_DIRTY;
00509 new_bb->flags |= BB_DIRTY;
00510 }
00511 #endif
00512 }
00513
00514 return new_bb;
00515 }
00516
00517
00518
00519
00520 static void
00521 rtl_merge_blocks (basic_block a, basic_block b)
00522 {
00523 rtx b_head = BB_HEAD (b), b_end = BB_END (b), a_end = BB_END (a);
00524 rtx del_first = NULL_RTX, del_last = NULL_RTX;
00525 int b_empty = 0;
00526
00527
00528 if (LABEL_P (b_head))
00529 {
00530
00531
00532 maybe_remove_eh_handler (b_head);
00533
00534
00535
00536 if (b_head == b_end)
00537 b_empty = 1;
00538
00539 del_first = del_last = b_head;
00540 b_head = NEXT_INSN (b_head);
00541 }
00542
00543
00544
00545 if (NOTE_INSN_BASIC_BLOCK_P (b_head))
00546 {
00547 if (b_head == b_end)
00548 b_empty = 1;
00549 if (! del_last)
00550 del_first = b_head;
00551
00552 del_last = b_head;
00553 b_head = NEXT_INSN (b_head);
00554 }
00555
00556
00557 if (JUMP_P (a_end))
00558 {
00559 rtx prev;
00560
00561 for (prev = PREV_INSN (a_end); ; prev = PREV_INSN (prev))
00562 if (!NOTE_P (prev)
00563 || NOTE_LINE_NUMBER (prev) == NOTE_INSN_BASIC_BLOCK
00564 || prev == BB_HEAD (a))
00565 break;
00566
00567 del_first = a_end;
00568
00569 #ifdef HAVE_cc0
00570
00571
00572 if (only_sets_cc0_p (prev))
00573 {
00574 rtx tmp = prev;
00575
00576 prev = prev_nonnote_insn (prev);
00577 if (!prev)
00578 prev = BB_HEAD (a);
00579 del_first = tmp;
00580 }
00581 #endif
00582
00583 a_end = PREV_INSN (del_first);
00584 }
00585 else if (BARRIER_P (NEXT_INSN (a_end)))
00586 del_first = NEXT_INSN (a_end);
00587
00588
00589
00590 BB_HEAD (b) = NULL;
00591 delete_insn_chain (del_first, del_last);
00592
00593
00594 if (!b_empty)
00595 {
00596 rtx x;
00597
00598 for (x = a_end; x != b_end; x = NEXT_INSN (x))
00599 set_block_for_insn (x, a);
00600
00601 set_block_for_insn (b_end, a);
00602
00603 a_end = b_end;
00604 }
00605
00606 BB_END (a) = a_end;
00607 }
00608
00609
00610 static bool
00611 rtl_can_merge_blocks (basic_block a,basic_block b)
00612 {
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 if (flag_reorder_blocks_and_partition
00624 && (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)
00625 || find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
00626 || BB_PARTITION (a) != BB_PARTITION (b)))
00627 return false;
00628
00629
00630 return (EDGE_COUNT (a->succs) == 1
00631 && EDGE_SUCC (a, 0)->dest == b
00632 && EDGE_COUNT (b->preds) == 1
00633 && a != b
00634
00635 && !(EDGE_SUCC (a, 0)->flags & EDGE_COMPLEX)
00636 && a->next_bb == b
00637 && a != ENTRY_BLOCK_PTR && b != EXIT_BLOCK_PTR
00638
00639
00640 && (!JUMP_P (BB_END (a))
00641 || (reload_completed
00642 ? simplejump_p (BB_END (a)) : onlyjump_p (BB_END (a)))));
00643 }
00644
00645
00646
00647
00648 rtx
00649 block_label (basic_block block)
00650 {
00651 if (block == EXIT_BLOCK_PTR)
00652 return NULL_RTX;
00653
00654 if (!LABEL_P (BB_HEAD (block)))
00655 {
00656 BB_HEAD (block) = emit_label_before (gen_label_rtx (), BB_HEAD (block));
00657 }
00658
00659 return BB_HEAD (block);
00660 }
00661
00662
00663
00664
00665
00666
00667 edge
00668 try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
00669 {
00670 basic_block src = e->src;
00671 rtx insn = BB_END (src), kill_from;
00672 rtx set;
00673 int fallthru = 0;
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685 if (flag_reorder_blocks_and_partition
00686 && (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)
00687 || BB_PARTITION (src) != BB_PARTITION (target)))
00688 return NULL;
00689
00690
00691
00692
00693 if (EDGE_COUNT (src->succs) >= 3
00694
00695
00696 || (EDGE_COUNT (src->succs) == 2
00697 && EDGE_SUCC (src, EDGE_SUCC (src, 0) == e)->dest != target))
00698 return NULL;
00699
00700 if (!onlyjump_p (insn))
00701 return NULL;
00702 if ((!optimize || reload_completed) && tablejump_p (insn, NULL, NULL))
00703 return NULL;
00704
00705
00706 set = single_set (insn);
00707 if (!set || side_effects_p (set))
00708 return NULL;
00709
00710
00711
00712 kill_from = insn;
00713 #ifdef HAVE_cc0
00714 if (reg_mentioned_p (cc0_rtx, PATTERN (insn)))
00715 kill_from = PREV_INSN (insn);
00716 #endif
00717
00718
00719 if (in_cfglayout || can_fallthru (src, target))
00720 {
00721 if (dump_file)
00722 fprintf (dump_file, "Removing jump %i.\n", INSN_UID (insn));
00723 fallthru = 1;
00724
00725
00726 if (in_cfglayout)
00727 {
00728 rtx insn = src->rbi->footer;
00729
00730 delete_insn_chain (kill_from, BB_END (src));
00731
00732
00733 while (insn)
00734 {
00735 if (BARRIER_P (insn))
00736 {
00737 if (PREV_INSN (insn))
00738 NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
00739 else
00740 src->rbi->footer = NEXT_INSN (insn);
00741 if (NEXT_INSN (insn))
00742 PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
00743 }
00744 if (LABEL_P (insn))
00745 break;
00746 insn = NEXT_INSN (insn);
00747 }
00748 }
00749 else
00750 delete_insn_chain (kill_from, PREV_INSN (BB_HEAD (target)));
00751 }
00752
00753
00754 else if (simplejump_p (insn))
00755 {
00756 if (e->dest == target)
00757 return NULL;
00758 if (dump_file)
00759 fprintf (dump_file, "Redirecting jump %i from %i to %i.\n",
00760 INSN_UID (insn), e->dest->index, target->index);
00761 if (!redirect_jump (insn, block_label (target), 0))
00762 {
00763 gcc_assert (target == EXIT_BLOCK_PTR);
00764 return NULL;
00765 }
00766 }
00767
00768
00769 else if (target == EXIT_BLOCK_PTR)
00770 return NULL;
00771
00772
00773 else
00774 {
00775 rtx target_label = block_label (target);
00776 rtx barrier, label, table;
00777
00778 emit_jump_insn_after_noloc (gen_jump (target_label), insn);
00779 JUMP_LABEL (BB_END (src)) = target_label;
00780 LABEL_NUSES (target_label)++;
00781 if (dump_file)
00782 fprintf (dump_file, "Replacing insn %i by jump %i\n",
00783 INSN_UID (insn), INSN_UID (BB_END (src)));
00784
00785
00786 delete_insn_chain (kill_from, insn);
00787
00788
00789
00790
00791 if (tablejump_p (insn, &label, &table))
00792 delete_insn_chain (label, table);
00793
00794 barrier = next_nonnote_insn (BB_END (src));
00795 if (!barrier || !BARRIER_P (barrier))
00796 emit_barrier_after (BB_END (src));
00797 else
00798 {
00799 if (barrier != NEXT_INSN (BB_END (src)))
00800 {
00801
00802
00803
00804 rtx new_insn = BB_END (src);
00805 rtx tmp;
00806
00807 for (tmp = NEXT_INSN (BB_END (src)); tmp != barrier;
00808 tmp = NEXT_INSN (tmp))
00809 set_block_for_insn (tmp, src);
00810
00811 NEXT_INSN (PREV_INSN (new_insn)) = NEXT_INSN (new_insn);
00812 PREV_INSN (NEXT_INSN (new_insn)) = PREV_INSN (new_insn);
00813
00814 NEXT_INSN (new_insn) = barrier;
00815 NEXT_INSN (PREV_INSN (barrier)) = new_insn;
00816
00817 PREV_INSN (new_insn) = PREV_INSN (barrier);
00818 PREV_INSN (barrier) = new_insn;
00819 }
00820 }
00821 }
00822
00823
00824 while (EDGE_COUNT (src->succs) > 1)
00825 remove_edge (e);
00826
00827 e = EDGE_SUCC (src, 0);
00828 if (fallthru)
00829 e->flags = EDGE_FALLTHRU;
00830 else
00831 e->flags = 0;
00832
00833 e->probability = REG_BR_PROB_BASE;
00834 e->count = src->count;
00835
00836
00837
00838 while (NOTE_P (BB_END (e->src))
00839 && NOTE_LINE_NUMBER (BB_END (e->src)) >= 0)
00840 delete_insn (BB_END (e->src));
00841
00842 if (e->dest != target)
00843 redirect_edge_succ (e, target);
00844
00845 return e;
00846 }
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856 static rtx
00857 last_loop_beg_note (rtx insn)
00858 {
00859 rtx last = insn;
00860
00861 for (insn = NEXT_INSN (insn); insn && NOTE_P (insn)
00862 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK;
00863 insn = NEXT_INSN (insn))
00864 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
00865 last = insn;
00866
00867 return last;
00868 }
00869
00870
00871
00872 static edge
00873 redirect_branch_edge (edge e, basic_block target)
00874 {
00875 rtx tmp;
00876 rtx old_label = BB_HEAD (e->dest);
00877 basic_block src = e->src;
00878 rtx insn = BB_END (src);
00879
00880
00881 if (e->flags & EDGE_FALLTHRU)
00882 return NULL;
00883 else if (!JUMP_P (insn))
00884 return NULL;
00885
00886
00887 if (tablejump_p (insn, NULL, &tmp))
00888 {
00889 rtvec vec;
00890 int j;
00891 rtx new_label = block_label (target);
00892
00893 if (target == EXIT_BLOCK_PTR)
00894 return NULL;
00895 if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
00896 vec = XVEC (PATTERN (tmp), 0);
00897 else
00898 vec = XVEC (PATTERN (tmp), 1);
00899
00900 for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
00901 if (XEXP (RTVEC_ELT (vec, j), 0) == old_label)
00902 {
00903 RTVEC_ELT (vec, j) = gen_rtx_LABEL_REF (Pmode, new_label);
00904 --LABEL_NUSES (old_label);
00905 ++LABEL_NUSES (new_label);
00906 }
00907
00908
00909 if ((tmp = single_set (insn)) != NULL
00910 && SET_DEST (tmp) == pc_rtx
00911 && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
00912 && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF
00913 && XEXP (XEXP (SET_SRC (tmp), 2), 0) == old_label)
00914 {
00915 XEXP (SET_SRC (tmp), 2) = gen_rtx_LABEL_REF (VOIDmode,
00916 new_label);
00917 --LABEL_NUSES (old_label);
00918 ++LABEL_NUSES (new_label);
00919 }
00920 }
00921 else
00922 {
00923
00924
00925
00926 if (computed_jump_p (insn)
00927
00928 || returnjump_p (insn))
00929 return NULL;
00930
00931
00932 gcc_assert (JUMP_LABEL (insn) == old_label);
00933
00934
00935
00936
00937 if (!redirect_jump (insn, block_label (target), 0))
00938 {
00939 gcc_assert (target == EXIT_BLOCK_PTR);
00940 return NULL;
00941 }
00942 }
00943
00944 if (dump_file)
00945 fprintf (dump_file, "Edge %i->%i redirected to %i\n",
00946 e->src->index, e->dest->index, target->index);
00947
00948 if (e->dest != target)
00949 e = redirect_edge_succ_nodup (e, target);
00950 return e;
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964 static edge
00965 rtl_redirect_edge_and_branch (edge e, basic_block target)
00966 {
00967 edge ret;
00968 basic_block src = e->src;
00969
00970 if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
00971 return NULL;
00972
00973 if (e->dest == target)
00974 return e;
00975
00976 if ((ret = try_redirect_by_replacing_jump (e, target, false)) != NULL)
00977 {
00978 src->flags |= BB_DIRTY;
00979 return ret;
00980 }
00981
00982 ret = redirect_branch_edge (e, target);
00983 if (!ret)
00984 return NULL;
00985
00986 src->flags |= BB_DIRTY;
00987 return ret;
00988 }
00989
00990
00991
00992
00993 static basic_block
00994 force_nonfallthru_and_redirect (edge e, basic_block target)
00995 {
00996 basic_block jump_block, new_bb = NULL, src = e->src;
00997 rtx note;
00998 edge new_edge;
00999 int abnormal_edge_flags = 0;
01000
01001
01002
01003
01004 if (e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR
01005 && any_condjump_p (BB_END (e->src))
01006
01007
01008 && e->src->next_bb == e->dest
01009 && JUMP_LABEL (BB_END (e->src)) == BB_HEAD (e->dest))
01010 {
01011 rtx note;
01012 edge b = unchecked_make_edge (e->src, target, 0);
01013 bool redirected;
01014
01015 redirected = redirect_jump (BB_END (e->src), block_label (target), 0);
01016 gcc_assert (redirected);
01017
01018 note = find_reg_note (BB_END (e->src), REG_BR_PROB, NULL_RTX);
01019 if (note)
01020 {
01021 int prob = INTVAL (XEXP (note, 0));
01022
01023 b->probability = prob;
01024 b->count = e->count * prob / REG_BR_PROB_BASE;
01025 e->probability -= e->probability;
01026 e->count -= b->count;
01027 if (e->probability < 0)
01028 e->probability = 0;
01029 if (e->count < 0)
01030 e->count = 0;
01031 }
01032 }
01033
01034 if (e->flags & EDGE_ABNORMAL)
01035 {
01036
01037
01038
01039
01040
01041 gcc_assert (e->dest == target);
01042 abnormal_edge_flags = e->flags & ~(EDGE_FALLTHRU | EDGE_CAN_FALLTHRU);
01043 e->flags &= EDGE_FALLTHRU | EDGE_CAN_FALLTHRU;
01044 }
01045 else
01046 {
01047 gcc_assert (e->flags & EDGE_FALLTHRU);
01048 if (e->src == ENTRY_BLOCK_PTR)
01049 {
01050
01051
01052
01053 edge tmp;
01054 edge_iterator ei;
01055 bool found = false;
01056
01057 basic_block bb = create_basic_block (BB_HEAD (e->dest), NULL, ENTRY_BLOCK_PTR);
01058
01059
01060
01061 e->src = bb;
01062 for (ei = ei_start (ENTRY_BLOCK_PTR->succs); (tmp = ei_safe_edge (ei)); )
01063 {
01064 if (tmp == e)
01065 {
01066 VEC_unordered_remove (edge, ENTRY_BLOCK_PTR->succs, ei.index);
01067 found = true;
01068 break;
01069 }
01070 else
01071 ei_next (&ei);
01072 }
01073
01074 gcc_assert (found);
01075
01076 VEC_safe_push (edge, bb->succs, e);
01077 make_single_succ_edge (ENTRY_BLOCK_PTR, bb, EDGE_FALLTHRU);
01078 }
01079 }
01080
01081 if (EDGE_COUNT (e->src->succs) >= 2 || abnormal_edge_flags)
01082 {
01083
01084
01085
01086
01087
01088 if (!tablejump_p (BB_END (e->src), NULL, ¬e))
01089 note = BB_END (e->src);
01090
01091
01092 note = last_loop_beg_note (note);
01093 note = NEXT_INSN (note);
01094
01095 jump_block = create_basic_block (note, NULL, e->src);
01096 jump_block->count = e->count;
01097 jump_block->frequency = EDGE_FREQUENCY (e);
01098 jump_block->loop_depth = target->loop_depth;
01099
01100 if (target->global_live_at_start)
01101 {
01102 jump_block->global_live_at_start = ALLOC_REG_SET (®_obstack);
01103 jump_block->global_live_at_end = ALLOC_REG_SET (®_obstack);
01104 COPY_REG_SET (jump_block->global_live_at_start,
01105 target->global_live_at_start);
01106 COPY_REG_SET (jump_block->global_live_at_end,
01107 target->global_live_at_start);
01108 }
01109
01110
01111
01112 BB_COPY_PARTITION (jump_block, e->src);
01113 if (flag_reorder_blocks_and_partition
01114 && targetm.have_named_sections)
01115 {
01116 if (BB_PARTITION (jump_block) == BB_COLD_PARTITION)
01117 {
01118 rtx bb_note, new_note;
01119 for (bb_note = BB_HEAD (jump_block);
01120 bb_note && bb_note != NEXT_INSN (BB_END (jump_block));
01121 bb_note = NEXT_INSN (bb_note))
01122 if (NOTE_P (bb_note)
01123 && NOTE_LINE_NUMBER (bb_note) == NOTE_INSN_BASIC_BLOCK)
01124 break;
01125 new_note = emit_note_after (NOTE_INSN_UNLIKELY_EXECUTED_CODE,
01126 bb_note);
01127 NOTE_BASIC_BLOCK (new_note) = jump_block;
01128 }
01129 if (JUMP_P (BB_END (jump_block))
01130 && !any_condjump_p (BB_END (jump_block))
01131 && (EDGE_SUCC (jump_block, 0)->flags & EDGE_CROSSING))
01132 REG_NOTES (BB_END (jump_block)) = gen_rtx_EXPR_LIST
01133 (REG_CROSSING_JUMP, NULL_RTX,
01134 REG_NOTES (BB_END (jump_block)));
01135 }
01136
01137
01138 new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU);
01139 new_edge->probability = e->probability;
01140 new_edge->count = e->count;
01141
01142
01143 redirect_edge_pred (e, jump_block);
01144 e->probability = REG_BR_PROB_BASE;
01145
01146 new_bb = jump_block;
01147 }
01148 else
01149 jump_block = e->src;
01150
01151 e->flags &= ~EDGE_FALLTHRU;
01152 if (target == EXIT_BLOCK_PTR)
01153 {
01154 #ifdef HAVE_return
01155 emit_jump_insn_after_noloc (gen_return (), BB_END (jump_block));
01156 #else
01157 gcc_unreachable ();
01158 #endif
01159 }
01160 else
01161 {
01162 rtx label = block_label (target);
01163 emit_jump_insn_after_noloc (gen_jump (label), BB_END (jump_block));
01164 JUMP_LABEL (BB_END (jump_block)) = label;
01165 LABEL_NUSES (label)++;
01166 }
01167
01168 emit_barrier_after (BB_END (jump_block));
01169 redirect_edge_succ_nodup (e, target);
01170
01171 if (abnormal_edge_flags)
01172 make_edge (src, target, abnormal_edge_flags);
01173
01174 return new_bb;
01175 }
01176
01177
01178
01179
01180
01181 basic_block
01182 force_nonfallthru (edge e)
01183 {
01184 return force_nonfallthru_and_redirect (e, e->dest);
01185 }
01186
01187
01188
01189
01190
01191 static basic_block
01192 rtl_redirect_edge_and_branch_force (edge e, basic_block target)
01193 {
01194 if (redirect_edge_and_branch (e, target)
01195 || e->dest == target)
01196 return NULL;
01197
01198
01199
01200 return force_nonfallthru_and_redirect (e, target);
01201 }
01202
01203
01204
01205
01206 static void
01207 rtl_tidy_fallthru_edge (edge e)
01208 {
01209 rtx q;
01210 basic_block b = e->src, c = b->next_bb;
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222 for (q = NEXT_INSN (BB_END (b)); q != BB_HEAD (c); q = NEXT_INSN (q))
01223 if (INSN_P (q))
01224 return;
01225
01226
01227
01228
01229 q = BB_END (b);
01230 if (JUMP_P (q)
01231 && onlyjump_p (q)
01232 && (any_uncondjump_p (q)
01233 || EDGE_COUNT (b->succs) == 1))
01234 {
01235 #ifdef HAVE_cc0
01236
01237
01238 if (any_condjump_p (q) && only_sets_cc0_p (PREV_INSN (q)))
01239 q = PREV_INSN (q);
01240 #endif
01241
01242 q = PREV_INSN (q);
01243
01244
01245
01246 while (NOTE_P (q) && NOTE_LINE_NUMBER (q) >= 0)
01247 q = PREV_INSN (q);
01248 }
01249
01250
01251 if (q != PREV_INSN (BB_HEAD (c)))
01252 delete_insn_chain (NEXT_INSN (q), PREV_INSN (BB_HEAD (c)));
01253
01254 e->flags |= EDGE_FALLTHRU;
01255 }
01256
01257
01258
01259
01260 static bool
01261 back_edge_of_syntactic_loop_p (basic_block bb1, basic_block bb2)
01262 {
01263 rtx insn;
01264 int count = 0;
01265 basic_block bb;
01266
01267 if (bb1 == bb2)
01268 return true;
01269
01270
01271
01272 for (bb = bb1; bb && bb != bb2; bb = bb->next_bb)
01273 continue;
01274
01275 if (!bb)
01276 return false;
01277
01278 for (insn = BB_END (bb1); insn != BB_HEAD (bb2) && count >= 0;
01279 insn = NEXT_INSN (insn))
01280 if (NOTE_P (insn))
01281 {
01282 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
01283 count++;
01284 else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
01285 count--;
01286 }
01287
01288 return count >= 0;
01289 }
01290
01291
01292
01293 static bool
01294 rtl_move_block_after (basic_block bb ATTRIBUTE_UNUSED,
01295 basic_block after ATTRIBUTE_UNUSED)
01296 {
01297 return false;
01298 }
01299
01300
01301
01302
01303
01304
01305
01306
01307 static basic_block
01308 rtl_split_edge (edge edge_in)
01309 {
01310 basic_block bb;
01311 rtx before;
01312
01313
01314 gcc_assert (!(edge_in->flags & EDGE_ABNORMAL));
01315
01316
01317
01318 if ((edge_in->flags & EDGE_FALLTHRU) == 0)
01319 {
01320 edge e;
01321 edge_iterator ei;
01322
01323 FOR_EACH_EDGE (e, ei, edge_in->dest->preds)
01324 if (e->flags & EDGE_FALLTHRU)
01325 break;
01326
01327 if (e)
01328 force_nonfallthru (e);
01329 }
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349 if (edge_in->dest != EXIT_BLOCK_PTR
01350 && PREV_INSN (BB_HEAD (edge_in->dest))
01351 && NOTE_P (PREV_INSN (BB_HEAD (edge_in->dest)))
01352 && (NOTE_LINE_NUMBER (PREV_INSN (BB_HEAD (edge_in->dest)))
01353 == NOTE_INSN_LOOP_BEG)
01354 && !back_edge_of_syntactic_loop_p (edge_in->dest, edge_in->src))
01355 before = PREV_INSN (BB_HEAD (edge_in->dest));
01356 else if (edge_in->dest != EXIT_BLOCK_PTR)
01357 before = BB_HEAD (edge_in->dest);
01358 else
01359 before = NULL_RTX;
01360
01361
01362
01363 if (edge_in->flags & EDGE_FALLTHRU && edge_in->dest == EXIT_BLOCK_PTR)
01364 {
01365 before = NEXT_INSN (BB_END (edge_in->src));
01366 if (before
01367 && NOTE_P (before)
01368 && NOTE_LINE_NUMBER (before) == NOTE_INSN_LOOP_END)
01369 before = NEXT_INSN (before);
01370 bb = create_basic_block (before, NULL, edge_in->src);
01371 BB_COPY_PARTITION (bb, edge_in->src);
01372 }
01373 else
01374 {
01375 bb = create_basic_block (before, NULL, edge_in->dest->prev_bb);
01376
01377 BB_COPY_PARTITION (bb, edge_in->dest);
01378 }
01379
01380
01381 if (edge_in->dest->global_live_at_start)
01382 {
01383 bb->global_live_at_start = ALLOC_REG_SET (®_obstack);
01384 bb->global_live_at_end = ALLOC_REG_SET (®_obstack);
01385 COPY_REG_SET (bb->global_live_at_start,
01386 edge_in->dest->global_live_at_start);
01387 COPY_REG_SET (bb->global_live_at_end,
01388 edge_in->dest->global_live_at_start);
01389 }
01390
01391 make_single_succ_edge (bb, edge_in->dest, EDGE_FALLTHRU);
01392
01393
01394
01395 if ((edge_in->flags & EDGE_FALLTHRU) == 0)
01396 {
01397 edge redirected = redirect_edge_and_branch (edge_in, bb);
01398 gcc_assert (redirected);
01399 }
01400 else
01401 redirect_edge_succ (edge_in, bb);
01402
01403 return bb;
01404 }
01405
01406
01407
01408
01409
01410 void
01411 insert_insn_on_edge (rtx pattern, edge e)
01412 {
01413
01414
01415 gcc_assert (!((e->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (e)));
01416
01417 if (e->insns.r == NULL_RTX)
01418 start_sequence ();
01419 else
01420 push_to_sequence (e->insns.r);
01421
01422 emit_insn (pattern);
01423
01424 e->insns.r = get_insns ();
01425 end_sequence ();
01426 }
01427
01428
01429
01430 static void
01431 mark_killed_regs (rtx reg, rtx set ATTRIBUTE_UNUSED, void *data)
01432 {
01433 regset killed = data;
01434 int regno, i;
01435
01436 if (GET_CODE (reg) == SUBREG)
01437 reg = SUBREG_REG (reg);
01438 if (!REG_P (reg))
01439 return;
01440 regno = REGNO (reg);
01441 if (regno >= FIRST_PSEUDO_REGISTER)
01442 SET_REGNO_REG_SET (killed, regno);
01443 else
01444 {
01445 for (i = 0; i < (int) hard_regno_nregs[regno][GET_MODE (reg)]; i++)
01446 SET_REGNO_REG_SET (killed, regno + i);
01447 }
01448 }
01449
01450
01451
01452
01453
01454
01455 bool
01456 safe_insert_insn_on_edge (rtx insn, edge e)
01457 {
01458 rtx x;
01459 regset killed;
01460 rtx save_regs = NULL_RTX;
01461 unsigned regno;
01462 int noccmode;
01463 enum machine_mode mode;
01464 reg_set_iterator rsi;
01465
01466 #ifdef AVOID_CCMODE_COPIES
01467 noccmode = true;
01468 #else
01469 noccmode = false;
01470 #endif
01471
01472 killed = ALLOC_REG_SET (®_obstack);
01473
01474 for (x = insn; x; x = NEXT_INSN (x))
01475 if (INSN_P (x))
01476 note_stores (PATTERN (x), mark_killed_regs, killed);
01477
01478
01479
01480
01481
01482 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01483 if (!fixed_regs[regno]
01484 && !REGNO_PTR_FRAME_P (regno))
01485 SET_REGNO_REG_SET (killed, regno);
01486
01487 bitmap_and_into (killed, e->dest->global_live_at_start);
01488
01489 EXECUTE_IF_SET_IN_REG_SET (killed, 0, regno, rsi)
01490 {
01491 mode = regno < FIRST_PSEUDO_REGISTER
01492 ? reg_raw_mode[regno]
01493 : GET_MODE (regno_reg_rtx[regno]);
01494 if (mode == VOIDmode)
01495 return false;
01496
01497 if (noccmode && mode == CCmode)
01498 return false;
01499
01500 save_regs = alloc_EXPR_LIST (0,
01501 alloc_EXPR_LIST (0,
01502 gen_reg_rtx (mode),
01503 gen_raw_REG (mode, regno)),
01504 save_regs);
01505 }
01506
01507 if (save_regs)
01508 {
01509 rtx from, to;
01510
01511 start_sequence ();
01512 for (x = save_regs; x; x = XEXP (x, 1))
01513 {
01514 from = XEXP (XEXP (x, 0), 1);
01515 to = XEXP (XEXP (x, 0), 0);
01516 emit_move_insn (to, from);
01517 }
01518 emit_insn (insn);
01519 for (x = save_regs; x; x = XEXP (x, 1))
01520 {
01521 from = XEXP (XEXP (x, 0), 0);
01522 to = XEXP (XEXP (x, 0), 1);
01523 emit_move_insn (to, from);
01524 }
01525 insn = get_insns ();
01526 end_sequence ();
01527 free_EXPR_LIST_list (&save_regs);
01528 }
01529 insert_insn_on_edge (insn, e);
01530
01531 FREE_REG_SET (killed);
01532
01533 return true;
01534 }
01535
01536
01537
01538 static void
01539 commit_one_edge_insertion (edge e, int watch_calls)
01540 {
01541 rtx before = NULL_RTX, after = NULL_RTX, insns, tmp, last;
01542 basic_block bb = NULL;
01543
01544
01545 insns = e->insns.r;
01546 e->insns.r = NULL_RTX;
01547
01548
01549
01550 if (watch_calls && (e->flags & EDGE_FALLTHRU)
01551 && EDGE_COUNT (e->dest->preds) == 1
01552 && e->src != ENTRY_BLOCK_PTR
01553 && CALL_P (BB_END (e->src)))
01554 {
01555 rtx next = next_nonnote_insn (BB_END (e->src));
01556
01557 after = BB_HEAD (e->dest);
01558
01559 while (next
01560 && keep_with_call_p (next))
01561 {
01562 after = next;
01563 next = next_nonnote_insn (next);
01564 }
01565 bb = e->dest;
01566 }
01567 if (!before && !after)
01568 {
01569
01570
01571 if (EDGE_COUNT (e->dest->preds) == 1 && e->dest != EXIT_BLOCK_PTR)
01572 {
01573 bb = e->dest;
01574
01575
01576
01577 tmp = BB_HEAD (bb);
01578 if (LABEL_P (tmp))
01579 tmp = NEXT_INSN (tmp);
01580 if (NOTE_INSN_BASIC_BLOCK_P (tmp))
01581 tmp = NEXT_INSN (tmp);
01582 if (tmp
01583 && NOTE_P (tmp)
01584 && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_UNLIKELY_EXECUTED_CODE)
01585 tmp = NEXT_INSN (tmp);
01586 if (tmp == BB_HEAD (bb))
01587 before = tmp;
01588 else if (tmp)
01589 after = PREV_INSN (tmp);
01590 else
01591 after = get_last_insn ();
01592 }
01593
01594
01595
01596 else if ((e->flags & EDGE_ABNORMAL) == 0
01597 && EDGE_COUNT (e->src->succs) == 1
01598 && e->src != ENTRY_BLOCK_PTR)
01599 {
01600 bb = e->src;
01601
01602
01603
01604
01605
01606
01607
01608 if (JUMP_P (BB_END (bb)))
01609 for (before = BB_END (bb);
01610 NOTE_P (PREV_INSN (before))
01611 && NOTE_LINE_NUMBER (PREV_INSN (before)) ==
01612 NOTE_INSN_LOOP_BEG; before = PREV_INSN (before))
01613 ;
01614 else
01615 {
01616
01617
01618 gcc_assert (e->flags & EDGE_FALLTHRU);
01619
01620 after = BB_END (bb);
01621 }
01622 }
01623
01624 else
01625 {
01626 bb = split_edge (e);
01627 after = BB_END (bb);
01628
01629 if (flag_reorder_blocks_and_partition
01630 && targetm.have_named_sections
01631 && e->src != ENTRY_BLOCK_PTR
01632 && BB_PARTITION (e->src) == BB_COLD_PARTITION
01633 && !(e->flags & EDGE_CROSSING))
01634 {
01635 rtx bb_note, new_note, cur_insn;
01636
01637 bb_note = NULL_RTX;
01638 for (cur_insn = BB_HEAD (bb); cur_insn != NEXT_INSN (BB_END (bb));
01639 cur_insn = NEXT_INSN (cur_insn))
01640 if (NOTE_P (cur_insn)
01641 && NOTE_LINE_NUMBER (cur_insn) == NOTE_INSN_BASIC_BLOCK)
01642 {
01643 bb_note = cur_insn;
01644 break;
01645 }
01646
01647 new_note = emit_note_after (NOTE_INSN_UNLIKELY_EXECUTED_CODE,
01648 bb_note);
01649 NOTE_BASIC_BLOCK (new_note) = bb;
01650 if (JUMP_P (BB_END (bb))
01651 && !any_condjump_p (BB_END (bb))
01652 && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING))
01653 REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST
01654 (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb)));
01655 if (after == bb_note)
01656 after = new_note;
01657 }
01658 }
01659 }
01660
01661
01662
01663 if (before)
01664 {
01665 emit_insn_before_noloc (insns, before);
01666 last = prev_nonnote_insn (before);
01667 }
01668 else
01669 last = emit_insn_after_noloc (insns, after);
01670
01671 if (returnjump_p (last))
01672 {
01673
01674
01675
01676
01677
01678 e = EDGE_SUCC (bb, 0);
01679 gcc_assert (e->dest == EXIT_BLOCK_PTR
01680 && EDGE_COUNT (bb->succs) == 1 && (e->flags & EDGE_FALLTHRU));
01681
01682 e->flags &= ~EDGE_FALLTHRU;
01683 emit_barrier_after (last);
01684
01685 if (before)
01686 delete_insn (before);
01687 }
01688 else
01689 gcc_assert (!JUMP_P (last));
01690
01691
01692 bb->aux = &bb->aux;
01693 }
01694
01695
01696
01697 void
01698 commit_edge_insertions (void)
01699 {
01700 basic_block bb;
01701 sbitmap blocks;
01702 bool changed = false;
01703
01704 #ifdef ENABLE_CHECKING
01705 verify_flow_info ();
01706 #endif
01707
01708 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
01709 {
01710 edge e;
01711 edge_iterator ei;
01712
01713 FOR_EACH_EDGE (e, ei, bb->succs)
01714 if (e->insns.r)
01715 {
01716 changed = true;
01717 commit_one_edge_insertion (e, false);
01718 }
01719 }
01720
01721 if (!changed)
01722 return;
01723
01724 blocks = sbitmap_alloc (last_basic_block);
01725 sbitmap_zero (blocks);
01726 FOR_EACH_BB (bb)
01727 if (bb->aux)
01728 {
01729 SET_BIT (blocks, bb->index);
01730
01731
01732 gcc_assert (bb->aux == &bb->aux);
01733 bb->aux = NULL;
01734 }
01735 find_many_sub_basic_blocks (blocks);
01736 sbitmap_free (blocks);
01737 }
01738
01739
01740
01741
01742 void
01743 commit_edge_insertions_watch_calls (void)
01744 {
01745 basic_block bb;
01746 sbitmap blocks;
01747 bool changed = false;
01748
01749 #ifdef ENABLE_CHECKING
01750 verify_flow_info ();
01751 #endif
01752
01753 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
01754 {
01755 edge e;
01756 edge_iterator ei;
01757
01758 FOR_EACH_EDGE (e, ei, bb->succs)
01759 if (e->insns.r)
01760 {
01761 changed = true;
01762 commit_one_edge_insertion (e, true);
01763 }
01764 }
01765
01766 if (!changed)
01767 return;
01768
01769 blocks = sbitmap_alloc (last_basic_block);
01770 sbitmap_zero (blocks);
01771 FOR_EACH_BB (bb)
01772 if (bb->aux)
01773 {
01774 SET_BIT (blocks, bb->index);
01775
01776
01777 gcc_assert (bb->aux == &bb->aux);
01778 bb->aux = NULL;
01779 }
01780 find_many_sub_basic_blocks (blocks);
01781 sbitmap_free (blocks);
01782 }
01783
01784
01785
01786
01787 static void
01788 rtl_dump_bb (basic_block bb, FILE *outf, int indent)
01789 {
01790 rtx insn;
01791 rtx last;
01792 char *s_indent;
01793
01794 s_indent = alloca ((size_t) indent + 1);
01795 memset (s_indent, ' ', (size_t) indent);
01796 s_indent[indent] = '\0';
01797
01798 fprintf (outf, ";;%s Registers live at start: ", s_indent);
01799 dump_regset (bb->global_live_at_start, outf);
01800 putc ('\n', outf);
01801
01802 for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb)); insn != last;
01803 insn = NEXT_INSN (insn))
01804 print_rtl_single (outf, insn);
01805
01806 fprintf (outf, ";;%s Registers live at end: ", s_indent);
01807 dump_regset (bb->global_live_at_end, outf);
01808 putc ('\n', outf);
01809 }
01810
01811
01812
01813
01814 void
01815 print_rtl_with_bb (FILE *outf, rtx rtx_first)
01816 {
01817 rtx tmp_rtx;
01818
01819 if (rtx_first == 0)
01820 fprintf (outf, "(nil)\n");
01821 else
01822 {
01823 enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
01824 int max_uid = get_max_uid ();
01825 basic_block *start = xcalloc (max_uid, sizeof (basic_block));
01826 basic_block *end = xcalloc (max_uid, sizeof (basic_block));
01827 enum bb_state *in_bb_p = xcalloc (max_uid, sizeof (enum bb_state));
01828
01829 basic_block bb;
01830
01831 FOR_EACH_BB_REVERSE (bb)
01832 {
01833 rtx x;
01834
01835 start[INSN_UID (BB_HEAD (bb))] = bb;
01836 end[INSN_UID (BB_END (bb))] = bb;
01837 for (x = BB_HEAD (bb); x != NULL_RTX; x = NEXT_INSN (x))
01838 {
01839 enum bb_state state = IN_MULTIPLE_BB;
01840
01841 if (in_bb_p[INSN_UID (x)] == NOT_IN_BB)
01842 state = IN_ONE_BB;
01843 in_bb_p[INSN_UID (x)] = state;
01844
01845 if (x == BB_END (bb))
01846 break;
01847 }
01848 }
01849
01850 for (tmp_rtx = rtx_first; NULL != tmp_rtx; tmp_rtx = NEXT_INSN (tmp_rtx))
01851 {
01852 int did_output;
01853
01854 if ((bb = start[INSN_UID (tmp_rtx)]) != NULL)
01855 {
01856 fprintf (outf, ";; Start of basic block %d, registers live:",
01857 bb->index);
01858 dump_regset (bb->global_live_at_start, outf);
01859 putc ('\n', outf);
01860 }
01861
01862 if (in_bb_p[INSN_UID (tmp_rtx)] == NOT_IN_BB
01863 && !NOTE_P (tmp_rtx)
01864 && !BARRIER_P (tmp_rtx))
01865 fprintf (outf, ";; Insn is not within a basic block\n");
01866 else if (in_bb_p[INSN_UID (tmp_rtx)] == IN_MULTIPLE_BB)
01867 fprintf (outf, ";; Insn is in multiple basic blocks\n");
01868
01869 did_output = print_rtl_single (outf, tmp_rtx);
01870
01871 if ((bb = end[INSN_UID (tmp_rtx)]) != NULL)
01872 {
01873 fprintf (outf, ";; End of basic block %d, registers live:\n",
01874 bb->index);
01875 dump_regset (bb->global_live_at_end, outf);
01876 putc ('\n', outf);
01877 }
01878
01879 if (did_output)
01880 putc ('\n', outf);
01881 }
01882
01883 free (start);
01884 free (end);
01885 free (in_bb_p);
01886 }
01887
01888 if (current_function_epilogue_delay_list != 0)
01889 {
01890 fprintf (outf, "\n;; Insns in epilogue delay list:\n\n");
01891 for (tmp_rtx = current_function_epilogue_delay_list; tmp_rtx != 0;
01892 tmp_rtx = XEXP (tmp_rtx, 1))
01893 print_rtl_single (outf, XEXP (tmp_rtx, 0));
01894 }
01895 }
01896
01897 void
01898 update_br_prob_note (basic_block bb)
01899 {
01900 rtx note;
01901 if (!JUMP_P (BB_END (bb)))
01902 return;
01903 note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX);
01904 if (!note || INTVAL (XEXP (note, 0)) == BRANCH_EDGE (bb)->probability)
01905 return;
01906 XEXP (note, 0) = GEN_INT (BRANCH_EDGE (bb)->probability);
01907 }
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925 static int
01926 rtl_verify_flow_info_1 (void)
01927 {
01928 const int max_uid = get_max_uid ();
01929 rtx last_head = get_last_insn ();
01930 basic_block *bb_info;
01931 rtx x;
01932 int err = 0;
01933 basic_block bb, last_bb_seen;
01934
01935 bb_info = xcalloc (max_uid, sizeof (basic_block));
01936
01937
01938 last_bb_seen = ENTRY_BLOCK_PTR;
01939
01940 FOR_EACH_BB_REVERSE (bb)
01941 {
01942 rtx head = BB_HEAD (bb);
01943 rtx end = BB_END (bb);
01944
01945
01946 for (x = last_head; x != NULL_RTX; x = PREV_INSN (x))
01947 if (x == end)
01948 break;
01949
01950 if (!x)
01951 {
01952 error ("end insn %d for block %d not found in the insn stream",
01953 INSN_UID (end), bb->index);
01954 err = 1;
01955 }
01956
01957
01958
01959 for (; x != NULL_RTX; x = PREV_INSN (x))
01960 {
01961
01962
01963
01964 if (bb_info[INSN_UID (x)] != NULL)
01965 {
01966 error ("insn %d is in multiple basic blocks (%d and %d)",
01967 INSN_UID (x), bb->index, bb_info[INSN_UID (x)]->index);
01968 err = 1;
01969 }
01970
01971 bb_info[INSN_UID (x)] = bb;
01972
01973 if (x == head)
01974 break;
01975 }
01976 if (!x)
01977 {
01978 error ("head insn %d for block %d not found in the insn stream",
01979 INSN_UID (head), bb->index);
01980 err = 1;
01981 }
01982
01983 last_head = x;
01984 }
01985
01986
01987 FOR_EACH_BB_REVERSE (bb)
01988 {
01989 int n_fallthru = 0, n_eh = 0, n_call = 0, n_abnormal = 0, n_branch = 0;
01990 edge e, fallthru = NULL;
01991 rtx note;
01992 edge_iterator ei;
01993
01994 if (JUMP_P (BB_END (bb))
01995 && (note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX))
01996 && EDGE_COUNT (bb->succs) >= 2
01997 && any_condjump_p (BB_END (bb)))
01998 {
01999 if (INTVAL (XEXP (note, 0)) != BRANCH_EDGE (bb)->probability
02000 && profile_status != PROFILE_ABSENT)
02001 {
02002 error ("verify_flow_info: REG_BR_PROB does not match cfg %wi %i",
02003 INTVAL (XEXP (note, 0)), BRANCH_EDGE (bb)->probability);
02004 err = 1;
02005 }
02006 }
02007 FOR_EACH_EDGE (e, ei, bb->succs)
02008 {
02009 if (e->flags & EDGE_FALLTHRU)
02010 {
02011 n_fallthru++, fallthru = e;
02012 if ((e->flags & EDGE_CROSSING)
02013 || (BB_PARTITION (e->src) != BB_PARTITION (e->dest)
02014 && e->src != ENTRY_BLOCK_PTR
02015 && e->dest != EXIT_BLOCK_PTR))
02016 {
02017 error ("Fallthru edge crosses section boundary (bb %i)",
02018 e->src->index);
02019 err = 1;
02020 }
02021 }
02022
02023 if ((e->flags & ~(EDGE_DFS_BACK
02024 | EDGE_CAN_FALLTHRU
02025 | EDGE_IRREDUCIBLE_LOOP
02026 | EDGE_LOOP_EXIT
02027 | EDGE_CROSSING)) == 0)
02028 n_branch++;
02029
02030 if (e->flags & EDGE_ABNORMAL_CALL)
02031 n_call++;
02032
02033 if (e->flags & EDGE_EH)
02034 n_eh++;
02035 else if (e->flags & EDGE_ABNORMAL)
02036 n_abnormal++;
02037 }
02038
02039 if (n_eh && GET_CODE (PATTERN (BB_END (bb))) != RESX
02040 && !find_reg_note (BB_END (bb), REG_EH_REGION, NULL_RTX))
02041 {
02042 error ("Missing REG_EH_REGION note in the end of bb %i", bb->index);
02043 err = 1;
02044 }
02045 if (n_branch
02046 && (!JUMP_P (BB_END (bb))
02047 || (n_branch > 1 && (any_uncondjump_p (BB_END (bb))
02048 || any_condjump_p (BB_END (bb))))))
02049 {
02050 error ("Too many outgoing branch edges from bb %i", bb->index);
02051 err = 1;
02052 }
02053 if (n_fallthru && any_uncondjump_p (BB_END (bb)))
02054 {
02055 error ("Fallthru edge after unconditional jump %i", bb->index);
02056 err = 1;
02057 }
02058 if (n_branch != 1 && any_uncondjump_p (BB_END (bb)))
02059 {
02060 error ("Wrong amount of branch edges after unconditional jump %i", bb->index);
02061 err = 1;
02062 }
02063 if (n_branch != 1 && any_condjump_p (BB_END (bb))
02064 && JUMP_LABEL (BB_END (bb)) != BB_HEAD (fallthru->dest))
02065 {
02066 error ("Wrong amount of branch edges after conditional jump %i", bb->index);
02067 err = 1;
02068 }
02069 if (n_call && !CALL_P (BB_END (bb)))
02070 {
02071 error ("Call edges for non-call insn in bb %i", bb->index);
02072 err = 1;
02073 }
02074 if (n_abnormal
02075 && (!CALL_P (BB_END (bb)) && n_call != n_abnormal)
02076 && (!JUMP_P (BB_END (bb))
02077 || any_condjump_p (BB_END (bb))
02078 || any_uncondjump_p (BB_END (bb))))
02079 {
02080 error ("Abnormal edges for no purpose in bb %i", bb->index);
02081 err = 1;
02082 }
02083
02084 for (x = BB_HEAD (bb); x != NEXT_INSN (BB_END (bb)); x = NEXT_INSN (x))
02085
02086
02087 if (!BARRIER_P (x) && BLOCK_FOR_INSN (x) != bb)
02088 {
02089 debug_rtx (x);
02090 if (! BLOCK_FOR_INSN (x))
02091 error
02092 ("insn %d inside basic block %d but block_for_insn is NULL",
02093 INSN_UID (x), bb->index);
02094 else
02095 error
02096 ("insn %d inside basic block %d but block_for_insn is %i",
02097 INSN_UID (x), bb->index, BLOCK_FOR_INSN (x)->index);
02098
02099 err = 1;
02100 }
02101
02102
02103
02104
02105 x = BB_HEAD (bb);
02106 if (LABEL_P (x))
02107 {
02108 if (BB_END (bb) == x)
02109 {
02110 error ("NOTE_INSN_BASIC_BLOCK is missing for block %d",
02111 bb->index);
02112 err = 1;
02113 }
02114
02115 x = NEXT_INSN (x);
02116 }
02117
02118 if (!NOTE_INSN_BASIC_BLOCK_P (x) || NOTE_BASIC_BLOCK (x) != bb)
02119 {
02120 error ("NOTE_INSN_BASIC_BLOCK is missing for block %d",
02121 bb->index);
02122 err = 1;
02123 }
02124
02125 if (BB_END (bb) == x)
02126
02127 ;
02128 else
02129 for (x = NEXT_INSN (x); x; x = NEXT_INSN (x))
02130 {
02131 if (NOTE_INSN_BASIC_BLOCK_P (x))
02132 {
02133 error ("NOTE_INSN_BASIC_BLOCK %d in middle of basic block %d",
02134 INSN_UID (x), bb->index);
02135 err = 1;
02136 }
02137
02138 if (x == BB_END (bb))
02139 break;
02140
02141 if (control_flow_insn_p (x))
02142 {
02143 error ("in basic block %d:", bb->index);
02144 fatal_insn ("flow control insn inside a basic block", x);
02145 }
02146 }
02147 }
02148
02149
02150 free (bb_info);
02151 return err;
02152 }
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163 static int
02164 rtl_verify_flow_info (void)
02165 {
02166 basic_block bb;
02167 int err = rtl_verify_flow_info_1 ();
02168 rtx x;
02169 int num_bb_notes;
02170 const rtx rtx_first = get_insns ();
02171 basic_block last_bb_seen = ENTRY_BLOCK_PTR, curr_bb = NULL;
02172
02173 FOR_EACH_BB_REVERSE (bb)
02174 {
02175 edge e;
02176 edge_iterator ei;
02177
02178 FOR_EACH_EDGE (e, ei, bb->succs)
02179 if (e->flags & EDGE_FALLTHRU)
02180 break;
02181 if (!e)
02182 {
02183 rtx insn;
02184
02185
02186 for (insn = BB_END (bb); !insn || !BARRIER_P (insn);
02187 insn = NEXT_INSN (insn))
02188 if (!insn
02189 || (NOTE_P (insn)
02190 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK))
02191 {
02192 error ("missing barrier after block %i", bb->index);
02193 err = 1;
02194 break;
02195 }
02196 }
02197 else if (e->src != ENTRY_BLOCK_PTR
02198 && e->dest != EXIT_BLOCK_PTR)
02199 {
02200 rtx insn;
02201
02202 if (e->src->next_bb != e->dest)
02203 {
02204 error
02205 ("verify_flow_info: Incorrect blocks for fallthru %i->%i",
02206 e->src->index, e->dest->index);
02207 err = 1;
02208 }
02209 else
02210 for (insn = NEXT_INSN (BB_END (e->src)); insn != BB_HEAD (e->dest);
02211 insn = NEXT_INSN (insn))
02212 if (BARRIER_P (insn) || INSN_P (insn))
02213 {
02214 error ("verify_flow_info: Incorrect fallthru %i->%i",
02215 e->src->index, e->dest->index);
02216 fatal_insn ("wrong insn in the fallthru edge", insn);
02217 err = 1;
02218 }
02219 }
02220 }
02221
02222 num_bb_notes = 0;
02223 last_bb_seen = ENTRY_BLOCK_PTR;
02224
02225 for (x = rtx_first; x; x = NEXT_INSN (x))
02226 {
02227 if (NOTE_INSN_BASIC_BLOCK_P (x))
02228 {
02229 bb = NOTE_BASIC_BLOCK (x);
02230
02231 num_bb_notes++;
02232 if (bb != last_bb_seen->next_bb)
02233 internal_error ("basic blocks not laid down consecutively");
02234
02235 curr_bb = last_bb_seen = bb;
02236 }
02237
02238 if (!curr_bb)
02239 {
02240 switch (GET_CODE (x))
02241 {
02242 case BARRIER:
02243 case NOTE:
02244 break;
02245
02246 case CODE_LABEL:
02247
02248 if (NEXT_INSN (x)
02249 && JUMP_P (NEXT_INSN (x))
02250 && (GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_DIFF_VEC
02251 || GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_VEC))
02252 x = NEXT_INSN (x);
02253
02254
02255 break;
02256
02257 default:
02258 fatal_insn ("insn outside basic block", x);
02259 }
02260 }
02261
02262 if (JUMP_P (x)
02263 && returnjump_p (x) && ! condjump_p (x)
02264 && ! (NEXT_INSN (x) && BARRIER_P (NEXT_INSN (x))))
02265 fatal_insn ("return not followed by barrier", x);
02266 if (curr_bb && x == BB_END (curr_bb))
02267 curr_bb = NULL;
02268 }
02269
02270 if (num_bb_notes != n_basic_blocks)
02271 internal_error
02272 ("number of bb notes in insn chain (%d) != n_basic_blocks (%d)",
02273 num_bb_notes, n_basic_blocks);
02274
02275 return err;
02276 }
02277
02278
02279
02280
02281
02282 bool
02283 purge_dead_edges (basic_block bb)
02284 {
02285 edge e;
02286 rtx insn = BB_END (bb), note;
02287 bool purged = false;
02288 bool found;
02289 edge_iterator ei;
02290
02291
02292 if (NONJUMP_INSN_P (insn)
02293 && (note = find_reg_note (insn, REG_EH_REGION, NULL)))
02294 {
02295 rtx eqnote;
02296
02297 if (! may_trap_p (PATTERN (insn))
02298 || ((eqnote = find_reg_equal_equiv_note (insn))
02299 && ! may_trap_p (XEXP (eqnote, 0))))
02300 remove_note (insn, note);
02301 }
02302
02303
02304 for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
02305 {
02306 if (e->flags & EDGE_EH)
02307 {
02308 if (can_throw_internal (BB_END (bb)))
02309 {
02310 ei_next (&ei);
02311 continue;
02312 }
02313 }
02314 else if (e->flags & EDGE_ABNORMAL_CALL)
02315 {
02316 if (CALL_P (BB_END (bb))
02317 && (! (note = find_reg_note (insn, REG_EH_REGION, NULL))
02318 || INTVAL (XEXP (note, 0)) >= 0))
02319 {
02320 ei_next (&ei);
02321 continue;
02322 }
02323 }
02324 else
02325 {
02326 ei_next (&ei);
02327 continue;
02328 }
02329
02330 remove_edge (e);
02331 bb->flags |= BB_DIRTY;
02332 purged = true;
02333 }
02334
02335 if (JUMP_P (insn))
02336 {
02337 rtx note;
02338 edge b,f;
02339 edge_iterator ei;
02340
02341
02342 if (!any_condjump_p (insn)
02343 && !returnjump_p (insn)
02344 && !simplejump_p (insn))
02345 return purged;
02346
02347
02348
02349 if (simplejump_p (insn))
02350 {
02351 note = find_reg_note (insn, REG_BR_PROB, NULL);
02352 if (note)
02353 remove_note (insn, note);
02354 while ((note = find_reg_note (insn, REG_BR_PRED, NULL)))
02355 remove_note (insn, note);
02356 }
02357
02358 for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
02359 {
02360
02361
02362
02363 e->flags &= ~EDGE_ABNORMAL;
02364
02365
02366 if ((e->flags & EDGE_FALLTHRU) && any_condjump_p (insn))
02367
02368
02369 {
02370 ei_next (&ei);
02371 continue;
02372 }
02373 else if (e->dest != EXIT_BLOCK_PTR
02374 && BB_HEAD (e->dest) == JUMP_LABEL (insn))
02375
02376
02377 {
02378 ei_next (&ei);
02379 continue;
02380 }
02381 else if (e->dest == EXIT_BLOCK_PTR && returnjump_p (insn))
02382
02383
02384 {
02385 ei_next (&ei);
02386 continue;
02387 }
02388 else if ((e->flags & EDGE_EH) && can_throw_internal (insn))
02389
02390
02391
02392 {
02393 e->flags |= EDGE_ABNORMAL;
02394 ei_next (&ei);
02395 continue;
02396 }
02397
02398
02399 bb->flags |= BB_DIRTY;
02400 purged = true;
02401 remove_edge (e);
02402 }
02403
02404 if (EDGE_COUNT (bb->succs) == 0 || !purged)
02405 return purged;
02406
02407 if (dump_file)
02408 fprintf (dump_file, "Purged edges from bb %i\n", bb->index);
02409
02410 if (!optimize)
02411 return purged;
02412
02413
02414 if (EDGE_COUNT (bb->succs) == 1)
02415 {
02416 EDGE_SUCC (bb, 0)->probability = REG_BR_PROB_BASE;
02417 EDGE_SUCC (bb, 0)->count = bb->count;
02418 }
02419 else
02420 {
02421 note = find_reg_note (insn, REG_BR_PROB, NULL);
02422 if (!note)
02423 return purged;
02424
02425 b = BRANCH_EDGE (bb);
02426 f = FALLTHRU_EDGE (bb);
02427 b->probability = INTVAL (XEXP (note, 0));
02428 f->probability = REG_BR_PROB_BASE - b->probability;
02429 b->count = bb->count * b->probability / REG_BR_PROB_BASE;
02430 f->count = bb->count * f->probability / REG_BR_PROB_BASE;
02431 }
02432
02433 return purged;
02434 }
02435 else if (CALL_P (insn) && SIBLING_CALL_P (insn))
02436 {
02437
02438
02439
02440
02441 gcc_assert (EDGE_COUNT (bb->succs) == 1);
02442 gcc_assert (EDGE_SUCC (bb, 0)->flags == (EDGE_SIBCALL | EDGE_ABNORMAL));
02443
02444 return 0;
02445 }
02446
02447
02448
02449
02450
02451
02452 found = false;
02453 FOR_EACH_EDGE (e, ei, bb->succs)
02454 if (! (e->flags & (EDGE_COMPLEX | EDGE_FALLTHRU)))
02455 {
02456 found = true;
02457 break;
02458 }
02459
02460 if (!found)
02461 return purged;
02462
02463 for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
02464 {
02465 if (!(e->flags & EDGE_FALLTHRU))
02466 {
02467 bb->flags |= BB_DIRTY;
02468 remove_edge (e);
02469 purged = true;
02470 }
02471 else
02472 ei_next (&ei);
02473 }
02474
02475 gcc_assert (EDGE_COUNT (bb->succs) == 1);
02476
02477 EDGE_SUCC (bb, 0)->probability = REG_BR_PROB_BASE;
02478 EDGE_SUCC (bb, 0)->count = bb->count;
02479
02480 if (dump_file)
02481 fprintf (dump_file, "Purged non-fallthru edges from bb %i\n",
02482 bb->index);
02483 return purged;
02484 }
02485
02486
02487
02488
02489 bool
02490 purge_all_dead_edges (int update_life_p)
02491 {
02492 int purged = false;
02493 sbitmap blocks = 0;
02494 basic_block bb;
02495
02496 if (update_life_p)
02497 {
02498 blocks = sbitmap_alloc (last_basic_block);
02499 sbitmap_zero (blocks);
02500 }
02501
02502 FOR_EACH_BB (bb)
02503 {
02504 bool purged_here = purge_dead_edges (bb);
02505
02506 purged |= purged_here;
02507 if (purged_here && update_life_p)
02508 SET_BIT (blocks, bb->index);
02509 }
02510
02511 if (update_life_p && purged)
02512 update_life_info (blocks, UPDATE_LIFE_GLOBAL,
02513 PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
02514 | PROP_KILL_DEAD_CODE);
02515
02516 if (update_life_p)
02517 sbitmap_free (blocks);
02518 return purged;
02519 }
02520
02521
02522
02523 static basic_block
02524 cfg_layout_split_block (basic_block bb, void *insnp)
02525 {
02526 rtx insn = insnp;
02527 basic_block new_bb = rtl_split_block (bb, insn);
02528
02529 new_bb->rbi->footer = bb->rbi->footer;
02530 bb->rbi->footer = NULL;
02531
02532 return new_bb;
02533 }
02534
02535
02536
02537 static edge
02538 cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
02539 {
02540 basic_block src = e->src;
02541 edge ret;
02542
02543 if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
02544 return NULL;
02545
02546 if (e->dest == dest)
02547 return e;
02548
02549 if (e->src != ENTRY_BLOCK_PTR
02550 && (ret = try_redirect_by_replacing_jump (e, dest, true)))
02551 {
02552 src->flags |= BB_DIRTY;
02553 return ret;
02554 }
02555
02556 if (e->src == ENTRY_BLOCK_PTR
02557 && (e->flags & EDGE_FALLTHRU) && !(e->flags & EDGE_COMPLEX))
02558 {
02559 if (dump_file)
02560 fprintf (dump_file, "Redirecting entry edge from bb %i to %i\n",
02561 e->src->index, dest->index);
02562
02563 e->src->flags |= BB_DIRTY;
02564 redirect_edge_succ (e, dest);
02565 return e;
02566 }
02567
02568
02569
02570
02571
02572 if (e->flags & EDGE_FALLTHRU)
02573 {
02574
02575 if (JUMP_P (BB_END (src))
02576 && label_is_jump_target_p (BB_HEAD (e->dest),
02577 BB_END (src)))
02578 {
02579 edge redirected;
02580
02581 if (dump_file)
02582 fprintf (dump_file, "Fallthru edge unified with branch "
02583 "%i->%i redirected to %i\n",
02584 e->src->index, e->dest->index, dest->index);
02585 e->flags &= ~EDGE_FALLTHRU;
02586 redirected = redirect_branch_edge (e, dest);
02587 gcc_assert (redirected);
02588 e->flags |= EDGE_FALLTHRU;
02589 e->src->flags |= BB_DIRTY;
02590 return e;
02591 }
02592
02593
02594 if (EDGE_COUNT (src->succs) == 2)
02595 {
02596
02597 edge s = EDGE_SUCC (src, EDGE_SUCC (src, 0) == e);
02598
02599 if (s->dest == dest
02600 && any_condjump_p (BB_END (src))
02601 && onlyjump_p (BB_END (src)))
02602 delete_insn (BB_END (src));
02603 }
02604 ret = redirect_edge_succ_nodup (e, dest);
02605 if (dump_file)
02606 fprintf (dump_file, "Fallthru edge %i->%i redirected to %i\n",
02607 e->src->index, e->dest->index, dest->index);
02608 }
02609 else
02610 ret = redirect_branch_edge (e, dest);
02611
02612
02613 gcc_assert (!simplejump_p (BB_END (src)));
02614
02615 src->flags |= BB_DIRTY;
02616 return ret;
02617 }
02618
02619
02620 static basic_block
02621 cfg_layout_redirect_edge_and_branch_force (edge e, basic_block dest)
02622 {
02623 edge redirected = cfg_layout_redirect_edge_and_branch (e, dest);
02624
02625 gcc_assert (redirected);
02626 return NULL;
02627 }
02628
02629
02630
02631 static void
02632 cfg_layout_delete_block (basic_block bb)
02633 {
02634 rtx insn, next, prev = PREV_INSN (BB_HEAD (bb)), *to, remaints;
02635
02636 if (bb->rbi->header)
02637 {
02638 next = BB_HEAD (bb);
02639 if (prev)
02640 NEXT_INSN (prev) = bb->rbi->header;
02641 else
02642 set_first_insn (bb->rbi->header);
02643 PREV_INSN (bb->rbi->header) = prev;
02644 insn = bb->rbi->header;
02645 while (NEXT_INSN (insn))
02646 insn = NEXT_INSN (insn);
02647 NEXT_INSN (insn) = next;
02648 PREV_INSN (next) = insn;
02649 }
02650 next = NEXT_INSN (BB_END (bb));
02651 if (bb->rbi->footer)
02652 {
02653 insn = bb->rbi->footer;
02654 while (insn)
02655 {
02656 if (BARRIER_P (insn))
02657 {
02658 if (PREV_INSN (insn))
02659 NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
02660 else
02661 bb->rbi->footer = NEXT_INSN (insn);
02662 if (NEXT_INSN (insn))
02663 PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
02664 }
02665 if (LABEL_P (insn))
02666 break;
02667 insn = NEXT_INSN (insn);
02668 }
02669 if (bb->rbi->footer)
02670 {
02671 insn = BB_END (bb);
02672 NEXT_INSN (insn) = bb->rbi->footer;
02673 PREV_INSN (bb->rbi->footer) = insn;
02674 while (NEXT_INSN (insn))
02675 insn = NEXT_INSN (insn);
02676 NEXT_INSN (insn) = next;
02677 if (next)
02678 PREV_INSN (next) = insn;
02679 else
02680 set_last_insn (insn);
02681 }
02682 }
02683 if (bb->next_bb != EXIT_BLOCK_PTR)
02684 to = &bb->next_bb->rbi->header;
02685 else
02686 to = &cfg_layout_function_footer;
02687 rtl_delete_block (bb);
02688
02689 if (prev)
02690 prev = NEXT_INSN (prev);
02691 else
02692 prev = get_insns ();
02693 if (next)
02694 next = PREV_INSN (next);
02695 else
02696 next = get_last_insn ();
02697
02698 if (next && NEXT_INSN (next) != prev)
02699 {
02700 remaints = unlink_insn_chain (prev, next);
02701 insn = remaints;
02702 while (NEXT_INSN (insn))
02703 insn = NEXT_INSN (insn);
02704 NEXT_INSN (insn) = *to;
02705 if (*to)
02706 PREV_INSN (*to) = insn;
02707 *to = remaints;
02708 }
02709 }
02710
02711
02712 static bool
02713 cfg_layout_can_merge_blocks_p (basic_block a, basic_block b)
02714 {
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725 if (flag_reorder_blocks_and_partition
02726 && (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)
02727 || find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
02728 || BB_PARTITION (a) != BB_PARTITION (b)))
02729 return false;
02730
02731
02732 return (EDGE_COUNT (a->succs) == 1
02733 && EDGE_SUCC (a, 0)->dest == b
02734 && EDGE_COUNT (b->preds) == 1
02735 && a != b
02736
02737 && !(EDGE_SUCC (a, 0)->flags & EDGE_COMPLEX)
02738 && a != ENTRY_BLOCK_PTR && b != EXIT_BLOCK_PTR
02739
02740
02741 && (!JUMP_P (BB_END (a))
02742 || (reload_completed
02743 ? simplejump_p (BB_END (a)) : onlyjump_p (BB_END (a)))));
02744 }
02745
02746
02747 static void
02748 cfg_layout_merge_blocks (basic_block a, basic_block b)
02749 {
02750 #ifdef ENABLE_CHECKING
02751 gcc_assert (cfg_layout_can_merge_blocks_p (a, b));
02752 #endif
02753
02754
02755 if (LABEL_P (BB_HEAD (b)))
02756 {
02757
02758
02759 maybe_remove_eh_handler (BB_HEAD (b));
02760
02761 delete_insn (BB_HEAD (b));
02762 }
02763
02764
02765
02766 if (JUMP_P (BB_END (a)))
02767 try_redirect_by_replacing_jump (EDGE_SUCC (a, 0), b, true);
02768 gcc_assert (!JUMP_P (BB_END (a)));
02769
02770
02771 if (b->rbi->header)
02772 {
02773 rtx first = BB_END (a), last;
02774
02775 last = emit_insn_after_noloc (b->rbi->header, BB_END (a));
02776 delete_insn_chain (NEXT_INSN (first), last);
02777 b->rbi->header = NULL;
02778 }
02779
02780
02781 if (NEXT_INSN (BB_END (a)) != BB_HEAD (b))
02782 {
02783 rtx first = unlink_insn_chain (BB_HEAD (b), BB_END (b));
02784
02785 emit_insn_after_noloc (first, BB_END (a));
02786
02787 if (!NOTE_INSN_BASIC_BLOCK_P (first))
02788 first = NEXT_INSN (first);
02789 gcc_assert (NOTE_INSN_BASIC_BLOCK_P (first));
02790 BB_HEAD (b) = NULL;
02791 delete_insn (first);
02792 }
02793
02794 else
02795 {
02796 rtx insn;
02797
02798 for (insn = BB_HEAD (b);
02799 insn != NEXT_INSN (BB_END (b));
02800 insn = NEXT_INSN (insn))
02801 set_block_for_insn (insn, a);
02802 insn = BB_HEAD (b);
02803
02804 if (!NOTE_INSN_BASIC_BLOCK_P (insn))
02805 insn = NEXT_INSN (insn);
02806 gcc_assert (NOTE_INSN_BASIC_BLOCK_P (insn));
02807 BB_HEAD (b) = NULL;
02808 BB_END (a) = BB_END (b);
02809 delete_insn (insn);
02810 }
02811
02812
02813 if (b->rbi->footer)
02814 {
02815 if (!a->rbi->footer)
02816 a->rbi->footer = b->rbi->footer;
02817 else
02818 {
02819 rtx last = a->rbi->footer;
02820
02821 while (NEXT_INSN (last))
02822 last = NEXT_INSN (last);
02823 NEXT_INSN (last) = b->rbi->footer;
02824 PREV_INSN (b->rbi->footer) = last;
02825 }
02826 b->rbi->footer = NULL;
02827 }
02828
02829 if (dump_file)
02830 fprintf (dump_file, "Merged blocks %d and %d.\n",
02831 a->index, b->index);
02832 }
02833
02834
02835
02836 static basic_block
02837 cfg_layout_split_edge (edge e)
02838 {
02839 edge new_e;
02840 basic_block new_bb =
02841 create_basic_block (e->src != ENTRY_BLOCK_PTR
02842 ? NEXT_INSN (BB_END (e->src)) : get_insns (),
02843 NULL_RTX, e->src);
02844
02845
02846
02847 if (e->dest->global_live_at_start)
02848 {
02849 new_bb->global_live_at_start = ALLOC_REG_SET (®_obstack);
02850 new_bb->global_live_at_end = ALLOC_REG_SET (®_obstack);
02851 COPY_REG_SET (new_bb->global_live_at_start,
02852 e->dest->global_live_at_start);
02853 COPY_REG_SET (new_bb->global_live_at_end,
02854 e->dest->global_live_at_start);
02855 }
02856
02857 new_e = make_edge (new_bb, e->dest, EDGE_FALLTHRU);
02858 redirect_edge_and_branch_force (e, new_bb);
02859
02860 return new_bb;
02861 }
02862
02863
02864
02865 static void
02866 rtl_make_forwarder_block (edge fallthru ATTRIBUTE_UNUSED)
02867 {
02868 }
02869
02870
02871
02872
02873 static bool
02874 rtl_block_ends_with_call_p (basic_block bb)
02875 {
02876 rtx insn = BB_END (bb);
02877
02878 while (!CALL_P (insn)
02879 && insn != BB_HEAD (bb)
02880 && keep_with_call_p (insn))
02881 insn = PREV_INSN (insn);
02882 return (CALL_P (insn));
02883 }
02884
02885
02886
02887 static bool
02888 rtl_block_ends_with_condjump_p (basic_block bb)
02889 {
02890 return any_condjump_p (BB_END (bb));
02891 }
02892
02893
02894
02895
02896 static bool
02897 need_fake_edge_p (rtx insn)
02898 {
02899 if (!INSN_P (insn))
02900 return false;
02901
02902 if ((CALL_P (insn)
02903 && !SIBLING_CALL_P (insn)
02904 && !find_reg_note (insn, REG_NORETURN, NULL)
02905 && !find_reg_note (insn, REG_ALWAYS_RETURN, NULL)
02906 && !CONST_OR_PURE_CALL_P (insn)))
02907 return true;
02908
02909 return ((GET_CODE (PATTERN (insn)) == ASM_OPERANDS
02910 && MEM_VOLATILE_P (PATTERN (insn)))
02911 || (GET_CODE (PATTERN (insn)) == PARALLEL
02912 && asm_noperands (insn) != -1
02913 && MEM_VOLATILE_P (XVECEXP (PATTERN (insn), 0, 0)))
02914 || GET_CODE (PATTERN (insn)) == ASM_INPUT);
02915 }
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925 static int
02926 rtl_flow_call_edges_add (sbitmap blocks)
02927 {
02928 int i;
02929 int blocks_split = 0;
02930 int last_bb = last_basic_block;
02931 bool check_last_block = false;
02932
02933 if (n_basic_blocks == 0)
02934 return 0;
02935
02936 if (! blocks)
02937 check_last_block = true;
02938 else
02939 check_last_block = TEST_BIT (blocks, EXIT_BLOCK_PTR->prev_bb->index);
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953 if (check_last_block)
02954 {
02955 basic_block bb = EXIT_BLOCK_PTR->prev_bb;
02956 rtx insn = BB_END (bb);
02957
02958
02959 while (insn != BB_HEAD (bb)
02960 && keep_with_call_p (insn))
02961 insn = PREV_INSN (insn);
02962
02963 if (need_fake_edge_p (insn))
02964 {
02965 edge e;
02966
02967 e = find_edge (bb, EXIT_BLOCK_PTR);
02968 if (e)
02969 {
02970 insert_insn_on_edge (gen_rtx_USE (VOIDmode, const0_rtx), e);
02971 commit_edge_insertions ();
02972 }
02973 }
02974 }
02975
02976
02977
02978
02979
02980 for (i = 0; i < last_bb; i++)
02981 {
02982 basic_block bb = BASIC_BLOCK (i);
02983 rtx insn;
02984 rtx prev_insn;
02985
02986 if (!bb)
02987 continue;
02988
02989 if (blocks && !TEST_BIT (blocks, i))
02990 continue;
02991
02992 for (insn = BB_END (bb); ; insn = prev_insn)
02993 {
02994 prev_insn = PREV_INSN (insn);
02995 if (need_fake_edge_p (insn))
02996 {
02997 edge e;
02998 rtx split_at_insn = insn;
02999
03000
03001
03002 if (CALL_P (insn))
03003 while (split_at_insn != BB_END (bb)
03004 && keep_with_call_p (NEXT_INSN (split_at_insn)))
03005 split_at_insn = NEXT_INSN (split_at_insn);
03006
03007
03008
03009
03010
03011
03012 #ifdef ENABLE_CHECKING
03013 if (split_at_insn == BB_END (bb))
03014 {
03015 e = find_edge (bb, EXIT_BLOCK_PTR);
03016 gcc_assert (e == NULL);
03017 }
03018 #endif
03019
03020
03021
03022 if (split_at_insn != BB_END (bb))
03023 {
03024 e = split_block (bb, split_at_insn);
03025 if (e)
03026 blocks_split++;
03027 }
03028
03029 make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
03030 }
03031
03032 if (insn == BB_HEAD (bb))
03033 break;
03034 }
03035 }
03036
03037 if (blocks_split)
03038 verify_flow_info ();
03039
03040 return blocks_split;
03041 }
03042
03043
03044 struct cfg_hooks rtl_cfg_hooks = {
03045 "rtl",
03046 rtl_verify_flow_info,
03047 rtl_dump_bb,
03048 rtl_create_basic_block,
03049 rtl_redirect_edge_and_branch,
03050 rtl_redirect_edge_and_branch_force,
03051 rtl_delete_block,
03052 rtl_split_block,
03053 rtl_move_block_after,
03054 rtl_can_merge_blocks,
03055 rtl_merge_blocks,
03056 rtl_predict_edge,
03057 rtl_predicted_by_p,
03058 NULL,
03059 NULL,
03060 rtl_split_edge,
03061 rtl_make_forwarder_block,
03062 rtl_tidy_fallthru_edge,
03063 rtl_block_ends_with_call_p,
03064 rtl_block_ends_with_condjump_p,
03065 rtl_flow_call_edges_add,
03066 NULL,
03067 NULL
03068 };
03069
03070
03071
03072
03073
03074
03075
03076
03077
03078
03079 extern bool cfg_layout_can_duplicate_bb_p (basic_block);
03080 extern basic_block cfg_layout_duplicate_bb (basic_block);
03081
03082 struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
03083 "cfglayout mode",
03084 rtl_verify_flow_info_1,
03085 rtl_dump_bb,
03086 cfg_layout_create_basic_block,
03087 cfg_layout_redirect_edge_and_branch,
03088 cfg_layout_redirect_edge_and_branch_force,
03089 cfg_layout_delete_block,
03090 cfg_layout_split_block,
03091 rtl_move_block_after,
03092 cfg_layout_can_merge_blocks_p,
03093 cfg_layout_merge_blocks,
03094 rtl_predict_edge,
03095 rtl_predicted_by_p,
03096 cfg_layout_can_duplicate_bb_p,
03097 cfg_layout_duplicate_bb,
03098 cfg_layout_split_edge,
03099 rtl_make_forwarder_block,
03100 NULL,
03101 rtl_block_ends_with_call_p,
03102 rtl_block_ends_with_condjump_p,
03103 rtl_flow_call_edges_add,
03104 NULL,
03105 NULL
03106 };
03107