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 #include "config.h"
00026 #include "system.h"
00027 #ifdef SGI_MONGOOSE
00028
00029 #include "rtl.h"
00030 #endif
00031 #include "tree.h"
00032 #ifndef SGI_MONGOOSE
00033 #include "rtl.h"
00034 #endif
00035 #include "hard-reg-set.h"
00036 #include "basic-block.h"
00037 #include "insn-config.h"
00038 #include "output.h"
00039 #include "function.h"
00040 #include "obstack.h"
00041 #include "cfglayout.h"
00042
00043
00044
00045 extern struct obstack flow_obstack;
00046
00047
00048 static rtx function_footer;
00049
00050 static rtx skip_insns_after_block PARAMS ((basic_block));
00051 static void record_effective_endpoints PARAMS ((void));
00052 static rtx label_for_bb PARAMS ((basic_block));
00053 static void fixup_reorder_chain PARAMS ((void));
00054
00055 static void set_block_levels PARAMS ((tree, int));
00056 static void change_scope PARAMS ((rtx, tree, tree));
00057
00058 void verify_insn_chain PARAMS ((void));
00059 static void cleanup_unconditional_jumps PARAMS ((void));
00060 static void fixup_fallthru_exit_predecessor PARAMS ((void));
00061 static rtx unlink_insn_chain PARAMS ((rtx, rtx));
00062 static rtx duplicate_insn_chain PARAMS ((rtx, rtx));
00063
00064 static rtx
00065 unlink_insn_chain (first, last)
00066 rtx first;
00067 rtx last;
00068 {
00069 rtx prevfirst = PREV_INSN (first);
00070 rtx nextlast = NEXT_INSN (last);
00071
00072 PREV_INSN (first) = NULL;
00073 NEXT_INSN (last) = NULL;
00074 if (prevfirst)
00075 NEXT_INSN (prevfirst) = nextlast;
00076 if (nextlast)
00077 PREV_INSN (nextlast) = prevfirst;
00078 else
00079 set_last_insn (prevfirst);
00080 if (!prevfirst)
00081 set_first_insn (nextlast);
00082 return first;
00083 }
00084
00085
00086
00087
00088
00089 static rtx
00090 skip_insns_after_block (bb)
00091 basic_block bb;
00092 {
00093 rtx insn, last_insn, next_head, prev;
00094
00095 next_head = NULL_RTX;
00096 if (bb->next_bb != EXIT_BLOCK_PTR)
00097 next_head = bb->next_bb->head;
00098
00099 for (last_insn = insn = bb->end; (insn = NEXT_INSN (insn)) != 0; )
00100 {
00101 if (insn == next_head)
00102 break;
00103
00104 switch (GET_CODE (insn))
00105 {
00106 case BARRIER:
00107 last_insn = insn;
00108 continue;
00109
00110 case NOTE:
00111 switch (NOTE_LINE_NUMBER (insn))
00112 {
00113 case NOTE_INSN_LOOP_END:
00114 case NOTE_INSN_BLOCK_END:
00115 last_insn = insn;
00116 continue;
00117 case NOTE_INSN_DELETED:
00118 case NOTE_INSN_DELETED_LABEL:
00119 continue;
00120
00121 default:
00122 continue;
00123 break;
00124 }
00125 break;
00126
00127 case CODE_LABEL:
00128 if (NEXT_INSN (insn)
00129 && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
00130 && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
00131 || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
00132 {
00133 insn = NEXT_INSN (insn);
00134 last_insn = insn;
00135 continue;
00136 }
00137 break;
00138
00139 default:
00140 break;
00141 }
00142
00143 break;
00144 }
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 for (insn = last_insn; insn != bb->end; insn = prev)
00157 {
00158 prev = PREV_INSN (insn);
00159 if (GET_CODE (insn) == NOTE)
00160 switch (NOTE_LINE_NUMBER (insn))
00161 {
00162 case NOTE_INSN_LOOP_END:
00163 case NOTE_INSN_BLOCK_END:
00164 case NOTE_INSN_DELETED:
00165 case NOTE_INSN_DELETED_LABEL:
00166 continue;
00167 default:
00168 reorder_insns (insn, insn, last_insn);
00169 }
00170 }
00171
00172 return last_insn;
00173 }
00174
00175
00176
00177 static rtx
00178 label_for_bb (bb)
00179 basic_block bb;
00180 {
00181 rtx label = bb->head;
00182
00183 if (GET_CODE (label) != CODE_LABEL)
00184 {
00185 if (rtl_dump_file)
00186 fprintf (rtl_dump_file, "Emitting label for block %d\n", bb->index);
00187
00188 label = block_label (bb);
00189 }
00190
00191 return label;
00192 }
00193
00194
00195
00196
00197 static void
00198 record_effective_endpoints ()
00199 {
00200 rtx next_insn = get_insns ();
00201 basic_block bb;
00202
00203 FOR_EACH_BB (bb)
00204 {
00205 rtx end;
00206
00207 if (PREV_INSN (bb->head) && next_insn != bb->head)
00208 RBI (bb)->header = unlink_insn_chain (next_insn,
00209 PREV_INSN (bb->head));
00210 end = skip_insns_after_block (bb);
00211 if (NEXT_INSN (bb->end) && bb->end != end)
00212 RBI (bb)->footer = unlink_insn_chain (NEXT_INSN (bb->end), end);
00213 next_insn = NEXT_INSN (bb->end);
00214 }
00215
00216 function_footer = next_insn;
00217 if (function_footer)
00218 function_footer = unlink_insn_chain (function_footer, get_last_insn ());
00219 }
00220
00221
00222
00223 void
00224 scope_to_insns_initialize ()
00225 {
00226 tree block = NULL;
00227 rtx insn, next;
00228
00229 for (insn = get_insns (); insn; insn = next)
00230 {
00231 next = NEXT_INSN (insn);
00232
00233 if (active_insn_p (insn)
00234 && GET_CODE (PATTERN (insn)) != ADDR_VEC
00235 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
00236 INSN_SCOPE (insn) = block;
00237 else if (GET_CODE (insn) == NOTE)
00238 {
00239 switch (NOTE_LINE_NUMBER (insn))
00240 {
00241 case NOTE_INSN_BLOCK_BEG:
00242 block = NOTE_BLOCK (insn);
00243 delete_insn (insn);
00244 break;
00245 case NOTE_INSN_BLOCK_END:
00246 block = BLOCK_SUPERCONTEXT (block);
00247 delete_insn (insn);
00248 break;
00249 default:
00250 break;
00251 }
00252 }
00253 }
00254
00255
00256
00257 set_block_levels (DECL_INITIAL (cfun->decl), 0);
00258 }
00259
00260
00261
00262
00263 static void
00264 set_block_levels (block, level)
00265 tree block;
00266 int level;
00267 {
00268 while (block)
00269 {
00270 BLOCK_NUMBER (block) = level;
00271 set_block_levels (BLOCK_SUBBLOCKS (block), level + 1);
00272 block = BLOCK_CHAIN (block);
00273 }
00274 }
00275
00276
00277 tree
00278 choose_inner_scope (s1, s2)
00279 tree s1, s2;
00280 {
00281 if (!s1)
00282 return s2;
00283 if (!s2)
00284 return s1;
00285 if (BLOCK_NUMBER (s1) > BLOCK_NUMBER (s2))
00286 return s1;
00287 return s2;
00288 }
00289
00290
00291
00292 static void
00293 change_scope (orig_insn, s1, s2)
00294 rtx orig_insn;
00295 tree s1, s2;
00296 {
00297 rtx insn = orig_insn;
00298 tree com = NULL_TREE;
00299 tree ts1 = s1, ts2 = s2;
00300 tree s;
00301
00302 while (ts1 != ts2)
00303 {
00304 if (ts1 == NULL || ts2 == NULL)
00305 abort ();
00306 if (BLOCK_NUMBER (ts1) > BLOCK_NUMBER (ts2))
00307 ts1 = BLOCK_SUPERCONTEXT (ts1);
00308 else if (BLOCK_NUMBER (ts1) < BLOCK_NUMBER (ts2))
00309 ts2 = BLOCK_SUPERCONTEXT (ts2);
00310 else
00311 {
00312 ts1 = BLOCK_SUPERCONTEXT (ts1);
00313 ts2 = BLOCK_SUPERCONTEXT (ts2);
00314 }
00315 }
00316 com = ts1;
00317
00318
00319 s = s1;
00320 while (s != com)
00321 {
00322 rtx note = emit_note_before (NOTE_INSN_BLOCK_END, insn);
00323 NOTE_BLOCK (note) = s;
00324 s = BLOCK_SUPERCONTEXT (s);
00325 }
00326
00327
00328 s = s2;
00329 while (s != com)
00330 {
00331 insn = emit_note_before (NOTE_INSN_BLOCK_BEG, insn);
00332 NOTE_BLOCK (insn) = s;
00333 s = BLOCK_SUPERCONTEXT (s);
00334 }
00335 }
00336
00337
00338
00339
00340 void
00341 scope_to_insns_finalize ()
00342 {
00343 tree cur_block = DECL_INITIAL (cfun->decl);
00344 rtx insn, note;
00345
00346 insn = get_insns ();
00347 if (!active_insn_p (insn))
00348 insn = next_active_insn (insn);
00349 for (; insn; insn = next_active_insn (insn))
00350 {
00351 tree this_block;
00352
00353 this_block = INSN_SCOPE (insn);
00354
00355
00356 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
00357 {
00358 int i;
00359 rtx body = PATTERN (insn);
00360
00361 this_block = NULL;
00362 for (i = 0; i < XVECLEN (body, 0); i++)
00363 this_block = choose_inner_scope (this_block,
00364 INSN_SCOPE (XVECEXP (body, 0, i)));
00365 }
00366 if (! this_block)
00367 continue;
00368
00369 if (this_block != cur_block)
00370 {
00371 change_scope (insn, cur_block, this_block);
00372 cur_block = this_block;
00373 }
00374 }
00375
00376
00377 note = emit_note (NULL, NOTE_INSN_DELETED);
00378 change_scope (note, cur_block, DECL_INITIAL (cfun->decl));
00379 delete_insn (note);
00380
00381 reorder_blocks ();
00382 }
00383
00384
00385
00386 static void
00387 fixup_reorder_chain ()
00388 {
00389 basic_block bb, prev_bb;
00390 int index;
00391 rtx insn = NULL;
00392
00393
00394
00395
00396 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
00397 bb != 0;
00398 bb = RBI (bb)->next, index++)
00399 {
00400 if (RBI (bb)->header)
00401 {
00402 if (insn)
00403 NEXT_INSN (insn) = RBI (bb)->header;
00404 else
00405 set_first_insn (RBI (bb)->header);
00406 PREV_INSN (RBI (bb)->header) = insn;
00407 insn = RBI (bb)->header;
00408 while (NEXT_INSN (insn))
00409 insn = NEXT_INSN (insn);
00410 }
00411 if (insn)
00412 NEXT_INSN (insn) = bb->head;
00413 else
00414 set_first_insn (bb->head);
00415 PREV_INSN (bb->head) = insn;
00416 insn = bb->end;
00417 if (RBI (bb)->footer)
00418 {
00419 NEXT_INSN (insn) = RBI (bb)->footer;
00420 PREV_INSN (RBI (bb)->footer) = insn;
00421 while (NEXT_INSN (insn))
00422 insn = NEXT_INSN (insn);
00423 }
00424 }
00425
00426 if (index != n_basic_blocks)
00427 abort ();
00428
00429 NEXT_INSN (insn) = function_footer;
00430 if (function_footer)
00431 PREV_INSN (function_footer) = insn;
00432
00433 while (NEXT_INSN (insn))
00434 insn = NEXT_INSN (insn);
00435
00436 set_last_insn (insn);
00437 #ifdef ENABLE_CHECKING
00438 verify_insn_chain ();
00439 #endif
00440
00441
00442
00443
00444 for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = RBI (bb)->next)
00445 {
00446 edge e_fall, e_taken, e;
00447 rtx bb_end_insn;
00448 basic_block nb;
00449
00450 if (bb->succ == NULL)
00451 continue;
00452
00453
00454
00455 e_taken = e_fall = NULL;
00456 for (e = bb->succ; e ; e = e->succ_next)
00457 if (e->flags & EDGE_FALLTHRU)
00458 e_fall = e;
00459 else if (! (e->flags & EDGE_EH))
00460 e_taken = e;
00461
00462 bb_end_insn = bb->end;
00463 if (GET_CODE (bb_end_insn) == JUMP_INSN)
00464 {
00465 if (any_condjump_p (bb_end_insn))
00466 {
00467
00468 if (RBI (bb)->next == e_fall->dest
00469 || (!RBI (bb)->next
00470 && e_fall->dest == EXIT_BLOCK_PTR))
00471 continue;
00472
00473 if (!e_taken)
00474 e_taken = e_fall;
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 if (!e_taken)
00485 {
00486 rtx note;
00487 edge e_fake;
00488
00489 e_fake = unchecked_make_edge (bb, e_fall->dest, 0);
00490
00491 note = find_reg_note (bb->end, REG_BR_PROB, NULL_RTX);
00492 if (note)
00493 {
00494 int prob = INTVAL (XEXP (note, 0));
00495
00496 e_fake->probability = prob;
00497 e_fake->count = e_fall->count * prob / REG_BR_PROB_BASE;
00498 e_fall->probability -= e_fall->probability;
00499 e_fall->count -= e_fake->count;
00500 if (e_fall->probability < 0)
00501 e_fall->probability = 0;
00502 if (e_fall->count < 0)
00503 e_fall->count = 0;
00504 }
00505 }
00506
00507
00508
00509
00510 else if (RBI (bb)->next != e_taken->dest)
00511 {
00512 rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
00513
00514 if (note
00515 && INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2
00516 && invert_jump (bb_end_insn,
00517 label_for_bb (e_fall->dest), 0))
00518 {
00519 e_fall->flags &= ~EDGE_FALLTHRU;
00520 e_taken->flags |= EDGE_FALLTHRU;
00521 update_br_prob_note (bb);
00522 e = e_fall, e_fall = e_taken, e_taken = e;
00523 }
00524 }
00525
00526
00527
00528 else if (invert_jump (bb_end_insn,
00529 label_for_bb (e_fall->dest), 0))
00530 {
00531 e_fall->flags &= ~EDGE_FALLTHRU;
00532 e_taken->flags |= EDGE_FALLTHRU;
00533 update_br_prob_note (bb);
00534 continue;
00535 }
00536 }
00537 else if (returnjump_p (bb_end_insn))
00538 continue;
00539 else
00540 {
00541
00542
00543 if (! e_fall)
00544 continue;
00545
00546 #ifdef CASE_DROPS_THROUGH
00547
00548
00549 if (RBI (bb)->next == e_fall->dest)
00550 continue;
00551 bb_end_insn = skip_insns_after_block (bb);
00552 #else
00553 abort ();
00554 #endif
00555 }
00556 }
00557 else
00558 {
00559
00560
00561
00562 if (! e_fall)
00563 continue;
00564
00565
00566 if (RBI (bb)->next == e_fall->dest)
00567 continue;
00568
00569
00570 if (!RBI (bb)->next && e_fall->dest == EXIT_BLOCK_PTR)
00571 continue;
00572 }
00573
00574
00575 nb = force_nonfallthru (e_fall);
00576 if (nb)
00577 {
00578 alloc_aux_for_block (nb, sizeof (struct reorder_block_def));
00579 RBI (nb)->visited = 1;
00580 RBI (nb)->next = RBI (bb)->next;
00581 RBI (bb)->next = nb;
00582
00583 bb = nb;
00584 }
00585 }
00586
00587
00588
00589 if (rtl_dump_file)
00590 {
00591 fprintf (rtl_dump_file, "Reordered sequence:\n");
00592 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0; bb; bb = RBI (bb)->next, index ++)
00593 {
00594 fprintf (rtl_dump_file, " %i ", index);
00595 if (RBI (bb)->original)
00596 fprintf (rtl_dump_file, "duplicate of %i ",
00597 RBI (bb)->original->index);
00598 else if (forwarder_block_p (bb) && GET_CODE (bb->head) != CODE_LABEL)
00599 fprintf (rtl_dump_file, "compensation ");
00600 else
00601 fprintf (rtl_dump_file, "bb %i ", bb->index);
00602 fprintf (rtl_dump_file, " [%i]\n", bb->frequency);
00603 }
00604 }
00605
00606 prev_bb = ENTRY_BLOCK_PTR;
00607 bb = ENTRY_BLOCK_PTR->next_bb;
00608 index = 0;
00609
00610 for (; bb; prev_bb = bb, bb = RBI (bb)->next, index ++)
00611 {
00612 bb->index = index;
00613 BASIC_BLOCK (index) = bb;
00614
00615 bb->prev_bb = prev_bb;
00616 prev_bb->next_bb = bb;
00617 }
00618 prev_bb->next_bb = EXIT_BLOCK_PTR;
00619 EXIT_BLOCK_PTR->prev_bb = prev_bb;
00620 }
00621
00622
00623
00624
00625
00626
00627
00628 void
00629 verify_insn_chain ()
00630 {
00631 rtx x, prevx, nextx;
00632 int insn_cnt1, insn_cnt2;
00633
00634 for (prevx = NULL, insn_cnt1 = 1, x = get_insns ();
00635 x != 0;
00636 prevx = x, insn_cnt1++, x = NEXT_INSN (x))
00637 if (PREV_INSN (x) != prevx)
00638 abort ();
00639
00640 if (prevx != get_last_insn ())
00641 abort ();
00642
00643 for (nextx = NULL, insn_cnt2 = 1, x = get_last_insn ();
00644 x != 0;
00645 nextx = x, insn_cnt2++, x = PREV_INSN (x))
00646 if (NEXT_INSN (x) != nextx)
00647 abort ();
00648
00649 if (insn_cnt1 != insn_cnt2)
00650 abort ();
00651 }
00652
00653
00654
00655
00656
00657
00658 static void
00659 cleanup_unconditional_jumps ()
00660 {
00661 basic_block bb;
00662
00663 FOR_EACH_BB (bb)
00664 {
00665 if (!bb->succ)
00666 continue;
00667 if (bb->succ->flags & EDGE_FALLTHRU)
00668 continue;
00669 if (!bb->succ->succ_next)
00670 {
00671 rtx insn;
00672 if (GET_CODE (bb->head) != CODE_LABEL && forwarder_block_p (bb)
00673 && bb->prev_bb != ENTRY_BLOCK_PTR)
00674 {
00675 basic_block prev = bb->prev_bb;
00676
00677 if (rtl_dump_file)
00678 fprintf (rtl_dump_file, "Removing forwarder BB %i\n",
00679 bb->index);
00680
00681 redirect_edge_succ_nodup (bb->pred, bb->succ->dest);
00682 flow_delete_block (bb);
00683 bb = prev;
00684 }
00685 else if (simplejump_p (bb->end))
00686 {
00687 rtx jump = bb->end;
00688
00689 if (rtl_dump_file)
00690 fprintf (rtl_dump_file, "Removing jump %i in BB %i\n",
00691 INSN_UID (jump), bb->index);
00692 delete_insn (jump);
00693 bb->succ->flags |= EDGE_FALLTHRU;
00694 }
00695 else
00696 continue;
00697
00698 insn = NEXT_INSN (bb->end);
00699 while (insn
00700 && (GET_CODE (insn) != NOTE
00701 || NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK))
00702 {
00703 rtx next = NEXT_INSN (insn);
00704
00705 if (GET_CODE (insn) == BARRIER)
00706 delete_barrier (insn);
00707
00708 insn = next;
00709 }
00710 }
00711 }
00712 }
00713
00714
00715
00716 static void
00717 fixup_fallthru_exit_predecessor ()
00718 {
00719 edge e;
00720 basic_block bb = NULL;
00721
00722 for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
00723 if (e->flags & EDGE_FALLTHRU)
00724 bb = e->src;
00725
00726 if (bb && RBI (bb)->next)
00727 {
00728 basic_block c = ENTRY_BLOCK_PTR->next_bb;
00729
00730 while (RBI (c)->next != bb)
00731 c = RBI (c)->next;
00732
00733 RBI (c)->next = RBI (bb)->next;
00734 while (RBI (c)->next)
00735 c = RBI (c)->next;
00736
00737 RBI (c)->next = bb;
00738 RBI (bb)->next = NULL;
00739 }
00740 }
00741
00742
00743
00744 bool
00745 cfg_layout_can_duplicate_bb_p (bb)
00746 basic_block bb;
00747 {
00748 rtx next;
00749 edge s;
00750
00751 if (bb == EXIT_BLOCK_PTR || bb == ENTRY_BLOCK_PTR)
00752 return false;
00753
00754
00755
00756 for (s = bb->succ; s; s = s->succ_next)
00757 if (s->dest == EXIT_BLOCK_PTR && s->flags & EDGE_FALLTHRU)
00758 return false;
00759
00760
00761
00762
00763 if (GET_CODE (bb->end) == JUMP_INSN && JUMP_LABEL (bb->end)
00764 && (next = next_nonnote_insn (JUMP_LABEL (bb->end)))
00765 && GET_CODE (next) == JUMP_INSN
00766 && (GET_CODE (PATTERN (next)) == ADDR_VEC
00767 || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
00768 return false;
00769 return true;
00770 }
00771
00772 static rtx
00773 duplicate_insn_chain (from, to)
00774 rtx from, to;
00775 {
00776 rtx insn, last;
00777
00778
00779
00780 last = emit_note (NULL, NOTE_INSN_DELETED);
00781
00782
00783
00784 for (insn = from; insn != NEXT_INSN (to); insn = NEXT_INSN (insn))
00785 {
00786 rtx new;
00787 switch (GET_CODE (insn))
00788 {
00789 case INSN:
00790 case CALL_INSN:
00791 case JUMP_INSN:
00792
00793
00794
00795 if (GET_CODE (PATTERN (insn)) == ADDR_VEC
00796 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
00797 break;
00798 new = emit_copy_of_insn_after (insn, get_last_insn ());
00799 break;
00800
00801 case CODE_LABEL:
00802 break;
00803
00804 case BARRIER:
00805 emit_barrier ();
00806 break;
00807
00808 case NOTE:
00809 switch (NOTE_LINE_NUMBER (insn))
00810 {
00811
00812
00813 case NOTE_INSN_PROLOGUE_END:
00814
00815 case NOTE_INSN_LOOP_VTOP:
00816 case NOTE_INSN_LOOP_CONT:
00817 case NOTE_INSN_LOOP_BEG:
00818 case NOTE_INSN_LOOP_END:
00819
00820
00821 case NOTE_INSN_DELETED:
00822 case NOTE_INSN_DELETED_LABEL:
00823
00824 case NOTE_INSN_EPILOGUE_BEG:
00825 case NOTE_INSN_FUNCTION_END:
00826
00827
00828
00829
00830 case NOTE_INSN_FUNCTION_BEG:
00831
00832 case NOTE_INSN_BASIC_BLOCK:
00833 break;
00834
00835
00836 case NOTE_INSN_BLOCK_BEG:
00837 case NOTE_INSN_BLOCK_END:
00838
00839
00840 case NOTE_INSN_EH_REGION_BEG:
00841 case NOTE_INSN_EH_REGION_END:
00842
00843 abort ();
00844 break;
00845 case NOTE_INSN_REPEATED_LINE_NUMBER:
00846 emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
00847 break;
00848
00849 default:
00850 if (NOTE_LINE_NUMBER (insn) < 0)
00851 abort ();
00852
00853
00854 emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
00855 }
00856 break;
00857 default:
00858 abort ();
00859 }
00860 }
00861 insn = NEXT_INSN (last);
00862 delete_insn (last);
00863 return insn;
00864 }
00865
00866
00867 void
00868 cfg_layout_redirect_edge (e, dest)
00869 edge e;
00870 basic_block dest;
00871 {
00872 basic_block src = e->src;
00873 basic_block old_next_bb = src->next_bb;
00874
00875
00876
00877
00878
00879 src->next_bb = NULL;
00880 if (e->flags & EDGE_FALLTHRU)
00881 {
00882
00883 if (GET_CODE (src->end) == JUMP_INSN
00884 && JUMP_LABEL (src->end) == e->dest->head)
00885 {
00886 if (!redirect_jump (src->end, block_label (dest), 0))
00887 abort ();
00888 }
00889
00890
00891 if (src->succ->succ_next
00892 && !src->succ->succ_next->succ_next)
00893 {
00894 edge s = e->succ_next ? e->succ_next : src->succ;
00895 if (s->dest == dest
00896 && any_condjump_p (src->end)
00897 && onlyjump_p (src->end))
00898 delete_insn (src->end);
00899 }
00900 redirect_edge_succ_nodup (e, dest);
00901 }
00902 else
00903 redirect_edge_and_branch (e, dest);
00904
00905
00906 if (simplejump_p (src->end))
00907 {
00908 delete_insn (src->end);
00909 delete_barrier (NEXT_INSN (src->end));
00910 src->succ->flags |= EDGE_FALLTHRU;
00911 }
00912 src->next_bb = old_next_bb;
00913 }
00914
00915
00916
00917 basic_block
00918 cfg_layout_duplicate_bb (bb, e)
00919 basic_block bb;
00920 edge e;
00921 {
00922 rtx insn;
00923 edge s, n;
00924 basic_block new_bb;
00925 gcov_type new_count = e ? e->count : 0;
00926
00927 if (bb->count < new_count)
00928 new_count = bb->count;
00929 if (!bb->pred)
00930 abort ();
00931 #ifdef ENABLE_CHECKING
00932 if (!cfg_layout_can_duplicate_bb_p (bb))
00933 abort ();
00934 #endif
00935
00936 insn = duplicate_insn_chain (bb->head, bb->end);
00937 new_bb = create_basic_block (insn,
00938 insn ? get_last_insn () : NULL,
00939 EXIT_BLOCK_PTR->prev_bb);
00940 alloc_aux_for_block (new_bb, sizeof (struct reorder_block_def));
00941
00942 if (RBI (bb)->header)
00943 {
00944 insn = RBI (bb)->header;
00945 while (NEXT_INSN (insn))
00946 insn = NEXT_INSN (insn);
00947 insn = duplicate_insn_chain (RBI (bb)->header, insn);
00948 if (insn)
00949 RBI (new_bb)->header = unlink_insn_chain (insn, get_last_insn ());
00950 }
00951
00952 if (RBI (bb)->footer)
00953 {
00954 insn = RBI (bb)->footer;
00955 while (NEXT_INSN (insn))
00956 insn = NEXT_INSN (insn);
00957 insn = duplicate_insn_chain (RBI (bb)->footer, insn);
00958 if (insn)
00959 RBI (new_bb)->footer = unlink_insn_chain (insn, get_last_insn ());
00960 }
00961
00962 if (bb->global_live_at_start)
00963 {
00964 new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
00965 new_bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
00966 COPY_REG_SET (new_bb->global_live_at_start, bb->global_live_at_start);
00967 COPY_REG_SET (new_bb->global_live_at_end, bb->global_live_at_end);
00968 }
00969
00970 new_bb->loop_depth = bb->loop_depth;
00971 new_bb->flags = bb->flags;
00972 for (s = bb->succ; s; s = s->succ_next)
00973 {
00974 n = make_edge (new_bb, s->dest, s->flags);
00975 n->probability = s->probability;
00976 if (new_count)
00977
00978 n->count = s->count * (new_count * 10000 / bb->count) / 10000;
00979 else
00980 n->count = 0;
00981 s->count -= n->count;
00982 }
00983
00984 new_bb->count = new_count;
00985 bb->count -= new_count;
00986
00987 if (e)
00988 {
00989 new_bb->frequency = EDGE_FREQUENCY (e);
00990 bb->frequency -= EDGE_FREQUENCY (e);
00991
00992 cfg_layout_redirect_edge (e, new_bb);
00993 }
00994
00995 if (bb->count < 0)
00996 bb->count = 0;
00997 if (bb->frequency < 0)
00998 bb->frequency = 0;
00999
01000 RBI (new_bb)->original = bb;
01001 return new_bb;
01002 }
01003
01004
01005
01006
01007 void
01008 cfg_layout_initialize ()
01009 {
01010
01011
01012 alloc_aux_for_blocks (sizeof (struct reorder_block_def));
01013
01014 cleanup_unconditional_jumps ();
01015
01016 record_effective_endpoints ();
01017 }
01018
01019
01020
01021
01022 void
01023 cfg_layout_finalize ()
01024 {
01025 fixup_fallthru_exit_predecessor ();
01026 fixup_reorder_chain ();
01027
01028 #ifdef ENABLE_CHECKING
01029 verify_insn_chain ();
01030 #endif
01031
01032 free_aux_for_blocks ();
01033
01034 #ifdef ENABLE_CHECKING
01035 verify_flow_info ();
01036 #endif
01037 }