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