00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "tree.h"
00026 #include "rtl.h"
00027 #include "hard-reg-set.h"
00028 #include "obstack.h"
00029 #include "basic-block.h"
00030 #include "insn-config.h"
00031 #include "output.h"
00032 #include "function.h"
00033 #include "cfglayout.h"
00034 #include "cfgloop.h"
00035 #include "target.h"
00036 #include "ggc.h"
00037 #include "alloc-pool.h"
00038 #include "flags.h"
00039
00040
00041 rtx cfg_layout_function_footer, cfg_layout_function_header;
00042
00043 static rtx skip_insns_after_block (basic_block);
00044 static void record_effective_endpoints (void);
00045 static rtx label_for_bb (basic_block);
00046 static void fixup_reorder_chain (void);
00047
00048 static void set_block_levels (tree, int);
00049 static void change_scope (rtx, tree, tree);
00050
00051 void verify_insn_chain (void);
00052 static void fixup_fallthru_exit_predecessor (void);
00053 static tree insn_scope (rtx);
00054 static void update_unlikely_executed_notes (basic_block);
00055
00056 rtx
00057 unlink_insn_chain (rtx first, rtx last)
00058 {
00059 rtx prevfirst = PREV_INSN (first);
00060 rtx nextlast = NEXT_INSN (last);
00061
00062 PREV_INSN (first) = NULL;
00063 NEXT_INSN (last) = NULL;
00064 if (prevfirst)
00065 NEXT_INSN (prevfirst) = nextlast;
00066 if (nextlast)
00067 PREV_INSN (nextlast) = prevfirst;
00068 else
00069 set_last_insn (prevfirst);
00070 if (!prevfirst)
00071 set_first_insn (nextlast);
00072 return first;
00073 }
00074
00075
00076
00077
00078
00079 static rtx
00080 skip_insns_after_block (basic_block bb)
00081 {
00082 rtx insn, last_insn, next_head, prev;
00083
00084 next_head = NULL_RTX;
00085 if (bb->next_bb != EXIT_BLOCK_PTR)
00086 next_head = BB_HEAD (bb->next_bb);
00087
00088 for (last_insn = insn = BB_END (bb); (insn = NEXT_INSN (insn)) != 0; )
00089 {
00090 if (insn == next_head)
00091 break;
00092
00093 switch (GET_CODE (insn))
00094 {
00095 case BARRIER:
00096 last_insn = insn;
00097 continue;
00098
00099 case NOTE:
00100 switch (NOTE_LINE_NUMBER (insn))
00101 {
00102 case NOTE_INSN_LOOP_END:
00103 case NOTE_INSN_BLOCK_END:
00104 last_insn = insn;
00105 continue;
00106 case NOTE_INSN_DELETED:
00107 case NOTE_INSN_DELETED_LABEL:
00108 continue;
00109
00110 default:
00111 continue;
00112 break;
00113 }
00114 break;
00115
00116 case CODE_LABEL:
00117 if (NEXT_INSN (insn)
00118 && JUMP_P (NEXT_INSN (insn))
00119 && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
00120 || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
00121 {
00122 insn = NEXT_INSN (insn);
00123 last_insn = insn;
00124 continue;
00125 }
00126 break;
00127
00128 default:
00129 break;
00130 }
00131
00132 break;
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 for (insn = last_insn; insn != BB_END (bb); insn = prev)
00146 {
00147 prev = PREV_INSN (insn);
00148 if (NOTE_P (insn))
00149 switch (NOTE_LINE_NUMBER (insn))
00150 {
00151 case NOTE_INSN_LOOP_END:
00152 case NOTE_INSN_BLOCK_END:
00153 case NOTE_INSN_DELETED:
00154 case NOTE_INSN_DELETED_LABEL:
00155 continue;
00156 default:
00157 reorder_insns (insn, insn, last_insn);
00158 }
00159 }
00160
00161 return last_insn;
00162 }
00163
00164
00165
00166 static rtx
00167 label_for_bb (basic_block bb)
00168 {
00169 rtx label = BB_HEAD (bb);
00170
00171 if (!LABEL_P (label))
00172 {
00173 if (dump_file)
00174 fprintf (dump_file, "Emitting label for block %d\n", bb->index);
00175
00176 label = block_label (bb);
00177 }
00178
00179 return label;
00180 }
00181
00182
00183
00184
00185 static void
00186 record_effective_endpoints (void)
00187 {
00188 rtx next_insn;
00189 basic_block bb;
00190 rtx insn;
00191
00192 for (insn = get_insns ();
00193 insn
00194 && NOTE_P (insn)
00195 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK;
00196 insn = NEXT_INSN (insn))
00197 continue;
00198
00199 gcc_assert (insn);
00200
00201 if (PREV_INSN (insn))
00202 cfg_layout_function_header =
00203 unlink_insn_chain (get_insns (), PREV_INSN (insn));
00204 else
00205 cfg_layout_function_header = NULL_RTX;
00206
00207 next_insn = get_insns ();
00208 FOR_EACH_BB (bb)
00209 {
00210 rtx end;
00211
00212 if (PREV_INSN (BB_HEAD (bb)) && next_insn != BB_HEAD (bb))
00213 bb->rbi->header = unlink_insn_chain (next_insn,
00214 PREV_INSN (BB_HEAD (bb)));
00215 end = skip_insns_after_block (bb);
00216 if (NEXT_INSN (BB_END (bb)) && BB_END (bb) != end)
00217 bb->rbi->footer = unlink_insn_chain (NEXT_INSN (BB_END (bb)), end);
00218 next_insn = NEXT_INSN (BB_END (bb));
00219 }
00220
00221 cfg_layout_function_footer = next_insn;
00222 if (cfg_layout_function_footer)
00223 cfg_layout_function_footer = unlink_insn_chain (cfg_layout_function_footer, get_last_insn ());
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233 static GTY(()) varray_type block_locators_locs;
00234 static GTY(()) varray_type block_locators_blocks;
00235 static GTY(()) varray_type line_locators_locs;
00236 static GTY(()) varray_type line_locators_lines;
00237 static GTY(()) varray_type file_locators_locs;
00238 static GTY(()) varray_type file_locators_files;
00239 int prologue_locator;
00240 int epilogue_locator;
00241
00242
00243
00244
00245
00246 void
00247 insn_locators_initialize (void)
00248 {
00249 tree block = NULL;
00250 tree last_block = NULL;
00251 rtx insn, next;
00252 int loc = 0;
00253 int line_number = 0, last_line_number = 0;
00254 const char *file_name = NULL, *last_file_name = NULL;
00255
00256 prologue_locator = epilogue_locator = 0;
00257
00258 VARRAY_INT_INIT (block_locators_locs, 32, "block_locators_locs");
00259 VARRAY_TREE_INIT (block_locators_blocks, 32, "block_locators_blocks");
00260 VARRAY_INT_INIT (line_locators_locs, 32, "line_locators_locs");
00261 VARRAY_INT_INIT (line_locators_lines, 32, "line_locators_lines");
00262 VARRAY_INT_INIT (file_locators_locs, 32, "file_locators_locs");
00263 VARRAY_CHAR_PTR_INIT (file_locators_files, 32, "file_locators_files");
00264
00265 for (insn = get_insns (); insn; insn = next)
00266 {
00267 int active = 0;
00268
00269 next = NEXT_INSN (insn);
00270
00271 if (NOTE_P (insn))
00272 {
00273 gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_BEG
00274 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END);
00275 if (NOTE_LINE_NUMBER (insn) > 0)
00276 {
00277 expanded_location xloc;
00278 NOTE_EXPANDED_LOCATION (xloc, insn);
00279 line_number = xloc.line;
00280 file_name = xloc.file;
00281 }
00282 }
00283 else
00284 active = (active_insn_p (insn)
00285 && GET_CODE (PATTERN (insn)) != ADDR_VEC
00286 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC);
00287
00288 check_block_change (insn, &block);
00289
00290 if (active
00291 || !next
00292 || (!prologue_locator && file_name))
00293 {
00294 if (last_block != block)
00295 {
00296 loc++;
00297 VARRAY_PUSH_INT (block_locators_locs, loc);
00298 VARRAY_PUSH_TREE (block_locators_blocks, block);
00299 last_block = block;
00300 }
00301 if (last_line_number != line_number)
00302 {
00303 loc++;
00304 VARRAY_PUSH_INT (line_locators_locs, loc);
00305 VARRAY_PUSH_INT (line_locators_lines, line_number);
00306 last_line_number = line_number;
00307 }
00308 if (last_file_name != file_name)
00309 {
00310 loc++;
00311 VARRAY_PUSH_INT (file_locators_locs, loc);
00312 VARRAY_PUSH_CHAR_PTR (file_locators_files, (char *) file_name);
00313 last_file_name = file_name;
00314 }
00315 if (!prologue_locator && file_name)
00316 prologue_locator = loc;
00317 if (!next)
00318 epilogue_locator = loc;
00319 if (active)
00320 INSN_LOCATOR (insn) = loc;
00321 }
00322 }
00323
00324
00325
00326 set_block_levels (DECL_INITIAL (cfun->decl), 0);
00327
00328 free_block_changes ();
00329 }
00330
00331
00332
00333
00334 static void
00335 set_block_levels (tree block, int level)
00336 {
00337 while (block)
00338 {
00339 BLOCK_NUMBER (block) = level;
00340 set_block_levels (BLOCK_SUBBLOCKS (block), level + 1);
00341 block = BLOCK_CHAIN (block);
00342 }
00343 }
00344
00345
00346 static tree
00347 choose_inner_scope (tree s1, tree s2)
00348 {
00349 if (!s1)
00350 return s2;
00351 if (!s2)
00352 return s1;
00353 if (BLOCK_NUMBER (s1) > BLOCK_NUMBER (s2))
00354 return s1;
00355 return s2;
00356 }
00357
00358
00359
00360 static void
00361 change_scope (rtx orig_insn, tree s1, tree s2)
00362 {
00363 rtx insn = orig_insn;
00364 tree com = NULL_TREE;
00365 tree ts1 = s1, ts2 = s2;
00366 tree s;
00367
00368 while (ts1 != ts2)
00369 {
00370 gcc_assert (ts1 && ts2);
00371 if (BLOCK_NUMBER (ts1) > BLOCK_NUMBER (ts2))
00372 ts1 = BLOCK_SUPERCONTEXT (ts1);
00373 else if (BLOCK_NUMBER (ts1) < BLOCK_NUMBER (ts2))
00374 ts2 = BLOCK_SUPERCONTEXT (ts2);
00375 else
00376 {
00377 ts1 = BLOCK_SUPERCONTEXT (ts1);
00378 ts2 = BLOCK_SUPERCONTEXT (ts2);
00379 }
00380 }
00381 com = ts1;
00382
00383
00384 s = s1;
00385 while (s != com)
00386 {
00387 rtx note = emit_note_before (NOTE_INSN_BLOCK_END, insn);
00388 NOTE_BLOCK (note) = s;
00389 s = BLOCK_SUPERCONTEXT (s);
00390 }
00391
00392
00393 s = s2;
00394 while (s != com)
00395 {
00396 insn = emit_note_before (NOTE_INSN_BLOCK_BEG, insn);
00397 NOTE_BLOCK (insn) = s;
00398 s = BLOCK_SUPERCONTEXT (s);
00399 }
00400 }
00401
00402
00403 static tree
00404 insn_scope (rtx insn)
00405 {
00406 int max = VARRAY_ACTIVE_SIZE (block_locators_locs);
00407 int min = 0;
00408 int loc = INSN_LOCATOR (insn);
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 if (loc == prologue_locator || loc == epilogue_locator)
00420 return DECL_INITIAL (cfun->decl);
00421
00422 if (!max || !loc)
00423 return NULL;
00424 while (1)
00425 {
00426 int pos = (min + max) / 2;
00427 int tmp = VARRAY_INT (block_locators_locs, pos);
00428
00429 if (tmp <= loc && min != pos)
00430 min = pos;
00431 else if (tmp > loc && max != pos)
00432 max = pos;
00433 else
00434 {
00435 min = pos;
00436 break;
00437 }
00438 }
00439 return VARRAY_TREE (block_locators_blocks, min);
00440 }
00441
00442
00443 int
00444 locator_line (int loc)
00445 {
00446 int max = VARRAY_ACTIVE_SIZE (line_locators_locs);
00447 int min = 0;
00448
00449 if (!max || !loc)
00450 return 0;
00451 while (1)
00452 {
00453 int pos = (min + max) / 2;
00454 int tmp = VARRAY_INT (line_locators_locs, pos);
00455
00456 if (tmp <= loc && min != pos)
00457 min = pos;
00458 else if (tmp > loc && max != pos)
00459 max = pos;
00460 else
00461 {
00462 min = pos;
00463 break;
00464 }
00465 }
00466 return VARRAY_INT (line_locators_lines, min);
00467 }
00468
00469
00470 int
00471 insn_line (rtx insn)
00472 {
00473 return locator_line (INSN_LOCATOR (insn));
00474 }
00475
00476
00477 const char *
00478 locator_file (int loc)
00479 {
00480 int max = VARRAY_ACTIVE_SIZE (file_locators_locs);
00481 int min = 0;
00482
00483 if (!max || !loc)
00484 return NULL;
00485 while (1)
00486 {
00487 int pos = (min + max) / 2;
00488 int tmp = VARRAY_INT (file_locators_locs, pos);
00489
00490 if (tmp <= loc && min != pos)
00491 min = pos;
00492 else if (tmp > loc && max != pos)
00493 max = pos;
00494 else
00495 {
00496 min = pos;
00497 break;
00498 }
00499 }
00500 return VARRAY_CHAR_PTR (file_locators_files, min);
00501 }
00502
00503
00504 const char *
00505 insn_file (rtx insn)
00506 {
00507 return locator_file (INSN_LOCATOR (insn));
00508 }
00509
00510
00511
00512
00513 void
00514 reemit_insn_block_notes (void)
00515 {
00516 tree cur_block = DECL_INITIAL (cfun->decl);
00517 rtx insn, note;
00518
00519 insn = get_insns ();
00520 if (!active_insn_p (insn))
00521 insn = next_active_insn (insn);
00522 for (; insn; insn = next_active_insn (insn))
00523 {
00524 tree this_block;
00525
00526
00527 if (JUMP_P (insn)
00528 && (GET_CODE (PATTERN (insn)) == ADDR_VEC
00529 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
00530 continue;
00531
00532 this_block = insn_scope (insn);
00533
00534
00535 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
00536 {
00537 int i;
00538 rtx body = PATTERN (insn);
00539
00540 this_block = NULL;
00541 for (i = 0; i < XVECLEN (body, 0); i++)
00542 this_block = choose_inner_scope (this_block,
00543 insn_scope (XVECEXP (body, 0, i)));
00544 }
00545 if (! this_block)
00546 continue;
00547
00548 if (this_block != cur_block)
00549 {
00550 change_scope (insn, cur_block, this_block);
00551 cur_block = this_block;
00552 }
00553 }
00554
00555
00556 note = emit_note (NOTE_INSN_DELETED);
00557 change_scope (note, cur_block, DECL_INITIAL (cfun->decl));
00558 delete_insn (note);
00559
00560 reorder_blocks ();
00561 }
00562
00563
00564
00565 static void
00566 fixup_reorder_chain (void)
00567 {
00568 basic_block bb, prev_bb;
00569 int index;
00570 rtx insn = NULL;
00571
00572 if (cfg_layout_function_header)
00573 {
00574 set_first_insn (cfg_layout_function_header);
00575 insn = cfg_layout_function_header;
00576 while (NEXT_INSN (insn))
00577 insn = NEXT_INSN (insn);
00578 }
00579
00580
00581
00582
00583 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
00584 bb != 0;
00585 bb = bb->rbi->next, index++)
00586 {
00587 if (bb->rbi->header)
00588 {
00589 if (insn)
00590 NEXT_INSN (insn) = bb->rbi->header;
00591 else
00592 set_first_insn (bb->rbi->header);
00593 PREV_INSN (bb->rbi->header) = insn;
00594 insn = bb->rbi->header;
00595 while (NEXT_INSN (insn))
00596 insn = NEXT_INSN (insn);
00597 }
00598 if (insn)
00599 NEXT_INSN (insn) = BB_HEAD (bb);
00600 else
00601 set_first_insn (BB_HEAD (bb));
00602 PREV_INSN (BB_HEAD (bb)) = insn;
00603 insn = BB_END (bb);
00604 if (bb->rbi->footer)
00605 {
00606 NEXT_INSN (insn) = bb->rbi->footer;
00607 PREV_INSN (bb->rbi->footer) = insn;
00608 while (NEXT_INSN (insn))
00609 insn = NEXT_INSN (insn);
00610 }
00611 }
00612
00613 gcc_assert (index == n_basic_blocks);
00614
00615 NEXT_INSN (insn) = cfg_layout_function_footer;
00616 if (cfg_layout_function_footer)
00617 PREV_INSN (cfg_layout_function_footer) = insn;
00618
00619 while (NEXT_INSN (insn))
00620 insn = NEXT_INSN (insn);
00621
00622 set_last_insn (insn);
00623 #ifdef ENABLE_CHECKING
00624 verify_insn_chain ();
00625 #endif
00626 delete_dead_jumptables ();
00627
00628
00629
00630
00631 for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = bb->rbi->next)
00632 {
00633 edge e_fall, e_taken, e;
00634 rtx bb_end_insn;
00635 basic_block nb;
00636 basic_block old_bb;
00637 edge_iterator ei;
00638
00639 if (EDGE_COUNT (bb->succs) == 0)
00640 continue;
00641
00642
00643
00644 e_taken = e_fall = NULL;
00645
00646 FOR_EACH_EDGE (e, ei, bb->succs)
00647 if (e->flags & EDGE_FALLTHRU)
00648 e_fall = e;
00649 else if (! (e->flags & EDGE_EH))
00650 e_taken = e;
00651
00652 bb_end_insn = BB_END (bb);
00653 if (JUMP_P (bb_end_insn))
00654 {
00655 if (any_condjump_p (bb_end_insn))
00656 {
00657
00658 if (bb->rbi->next == e_fall->dest
00659 || e_fall->dest == EXIT_BLOCK_PTR)
00660 continue;
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 if (!e_taken)
00671 {
00672 rtx note;
00673 edge e_fake;
00674 bool redirected;
00675
00676 e_fake = unchecked_make_edge (bb, e_fall->dest, 0);
00677
00678 redirected = redirect_jump (BB_END (bb),
00679 block_label (bb), 0);
00680 gcc_assert (redirected);
00681
00682 note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX);
00683 if (note)
00684 {
00685 int prob = INTVAL (XEXP (note, 0));
00686
00687 e_fake->probability = prob;
00688 e_fake->count = e_fall->count * prob / REG_BR_PROB_BASE;
00689 e_fall->probability -= e_fall->probability;
00690 e_fall->count -= e_fake->count;
00691 if (e_fall->probability < 0)
00692 e_fall->probability = 0;
00693 if (e_fall->count < 0)
00694 e_fall->count = 0;
00695 }
00696 }
00697
00698
00699
00700
00701 else if (bb->rbi->next != e_taken->dest)
00702 {
00703 rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
00704
00705 if (note
00706 && INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2
00707 && invert_jump (bb_end_insn,
00708 (e_fall->dest == EXIT_BLOCK_PTR
00709 ? NULL_RTX
00710 : label_for_bb (e_fall->dest)), 0))
00711 {
00712 e_fall->flags &= ~EDGE_FALLTHRU;
00713 #ifdef ENABLE_CHECKING
00714 gcc_assert (could_fall_through
00715 (e_taken->src, e_taken->dest));
00716 #endif
00717 e_taken->flags |= EDGE_FALLTHRU;
00718 update_br_prob_note (bb);
00719 e = e_fall, e_fall = e_taken, e_taken = e;
00720 }
00721 }
00722
00723
00724
00725 else if ((e_taken->flags & EDGE_CROSSING)
00726 && !(e_fall->flags & EDGE_CROSSING))
00727 continue;
00728
00729
00730
00731 else if (invert_jump (bb_end_insn,
00732 (e_fall->dest == EXIT_BLOCK_PTR
00733 ? NULL_RTX
00734 : label_for_bb (e_fall->dest)), 0))
00735 {
00736 e_fall->flags &= ~EDGE_FALLTHRU;
00737 #ifdef ENABLE_CHECKING
00738 gcc_assert (could_fall_through
00739 (e_taken->src, e_taken->dest));
00740 #endif
00741 e_taken->flags |= EDGE_FALLTHRU;
00742 update_br_prob_note (bb);
00743 continue;
00744 }
00745 }
00746 else
00747 {
00748
00749
00750
00751 gcc_assert (returnjump_p (bb_end_insn) || !e_fall);
00752 continue;
00753 }
00754 }
00755 else
00756 {
00757
00758
00759
00760 if (! e_fall)
00761 continue;
00762
00763
00764 if (bb->rbi->next == e_fall->dest)
00765 continue;
00766
00767
00768 if (e_fall->dest == EXIT_BLOCK_PTR)
00769 continue;
00770 }
00771
00772
00773 nb = force_nonfallthru (e_fall);
00774 if (nb)
00775 {
00776 initialize_bb_rbi (nb);
00777 nb->rbi->visited = 1;
00778 nb->rbi->next = bb->rbi->next;
00779 bb->rbi->next = nb;
00780
00781 old_bb = bb;
00782 bb = nb;
00783
00784
00785
00786
00787 BB_COPY_PARTITION (e_fall->src, EDGE_PRED (bb, 0)->src);
00788 if (flag_reorder_blocks_and_partition
00789 && targetm.have_named_sections)
00790 {
00791 if (BB_PARTITION (EDGE_PRED (bb, 0)->src) == BB_COLD_PARTITION)
00792 {
00793 rtx new_note;
00794 rtx note = BB_HEAD (e_fall->src);
00795
00796 while (!INSN_P (note)
00797 && note != BB_END (e_fall->src))
00798 note = NEXT_INSN (note);
00799
00800 new_note = emit_note_before
00801 (NOTE_INSN_UNLIKELY_EXECUTED_CODE,
00802 note);
00803 NOTE_BASIC_BLOCK (new_note) = bb;
00804 }
00805 if (JUMP_P (BB_END (bb))
00806 && !any_condjump_p (BB_END (bb))
00807 && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING))
00808 REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST
00809 (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb)));
00810 }
00811 }
00812 }
00813
00814
00815
00816 if (dump_file)
00817 {
00818 fprintf (dump_file, "Reordered sequence:\n");
00819 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
00820 bb;
00821 bb = bb->rbi->next, index++)
00822 {
00823 fprintf (dump_file, " %i ", index);
00824 if (bb->rbi->original)
00825 fprintf (dump_file, "duplicate of %i ",
00826 bb->rbi->original->index);
00827 else if (forwarder_block_p (bb)
00828 && !LABEL_P (BB_HEAD (bb)))
00829 fprintf (dump_file, "compensation ");
00830 else
00831 fprintf (dump_file, "bb %i ", bb->index);
00832 fprintf (dump_file, " [%i]\n", bb->frequency);
00833 }
00834 }
00835
00836 prev_bb = ENTRY_BLOCK_PTR;
00837 bb = ENTRY_BLOCK_PTR->next_bb;
00838 index = 0;
00839
00840 for (; bb; prev_bb = bb, bb = bb->rbi->next, index ++)
00841 {
00842 bb->index = index;
00843 BASIC_BLOCK (index) = bb;
00844
00845 update_unlikely_executed_notes (bb);
00846
00847 bb->prev_bb = prev_bb;
00848 prev_bb->next_bb = bb;
00849 }
00850 prev_bb->next_bb = EXIT_BLOCK_PTR;
00851 EXIT_BLOCK_PTR->prev_bb = prev_bb;
00852
00853
00854 FOR_EACH_BB (bb)
00855 {
00856 edge e;
00857 edge_iterator ei;
00858
00859 FOR_EACH_EDGE (e, ei, bb->succs)
00860 if (e->flags & EDGE_FALLTHRU)
00861 break;
00862
00863 if (e && !can_fallthru (e->src, e->dest))
00864 force_nonfallthru (e);
00865 }
00866 }
00867
00868
00869
00870
00871 static void
00872 update_unlikely_executed_notes (basic_block bb)
00873 {
00874 rtx cur_insn;
00875
00876 for (cur_insn = BB_HEAD (bb); cur_insn != BB_END (bb);
00877 cur_insn = NEXT_INSN (cur_insn))
00878 if (NOTE_P (cur_insn)
00879 && NOTE_LINE_NUMBER (cur_insn) == NOTE_INSN_UNLIKELY_EXECUTED_CODE)
00880 NOTE_BASIC_BLOCK (cur_insn) = bb;
00881 }
00882
00883
00884
00885
00886
00887
00888
00889 void
00890 verify_insn_chain (void)
00891 {
00892 rtx x, prevx, nextx;
00893 int insn_cnt1, insn_cnt2;
00894
00895 for (prevx = NULL, insn_cnt1 = 1, x = get_insns ();
00896 x != 0;
00897 prevx = x, insn_cnt1++, x = NEXT_INSN (x))
00898 gcc_assert (PREV_INSN (x) == prevx);
00899
00900 gcc_assert (prevx == get_last_insn ());
00901
00902 for (nextx = NULL, insn_cnt2 = 1, x = get_last_insn ();
00903 x != 0;
00904 nextx = x, insn_cnt2++, x = PREV_INSN (x))
00905 gcc_assert (NEXT_INSN (x) == nextx);
00906
00907 gcc_assert (insn_cnt1 == insn_cnt2);
00908 }
00909
00910
00911
00912
00913 static void
00914 fixup_fallthru_exit_predecessor (void)
00915 {
00916 edge e;
00917 edge_iterator ei;
00918 basic_block bb = NULL;
00919
00920
00921
00922
00923 gcc_assert (reload_completed);
00924
00925 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
00926 if (e->flags & EDGE_FALLTHRU)
00927 bb = e->src;
00928
00929 if (bb && bb->rbi->next)
00930 {
00931 basic_block c = ENTRY_BLOCK_PTR->next_bb;
00932
00933
00934
00935 if (c == bb)
00936 {
00937 bb = split_block (bb, NULL)->dest;
00938 initialize_bb_rbi (bb);
00939 bb->rbi->next = c->rbi->next;
00940 c->rbi->next = bb;
00941 bb->rbi->footer = c->rbi->footer;
00942 c->rbi->footer = NULL;
00943 }
00944
00945 while (c->rbi->next != bb)
00946 c = c->rbi->next;
00947
00948 c->rbi->next = bb->rbi->next;
00949 while (c->rbi->next)
00950 c = c->rbi->next;
00951
00952 c->rbi->next = bb;
00953 bb->rbi->next = NULL;
00954 }
00955 }
00956
00957
00958
00959
00960
00961
00962
00963 extern bool cfg_layout_can_duplicate_bb_p (basic_block);
00964
00965 bool
00966 cfg_layout_can_duplicate_bb_p (basic_block bb)
00967 {
00968
00969
00970
00971 if (tablejump_p (BB_END (bb), NULL, NULL))
00972 return false;
00973
00974
00975 if (targetm.cannot_copy_insn_p)
00976 {
00977 rtx insn = BB_HEAD (bb);
00978 while (1)
00979 {
00980 if (INSN_P (insn) && targetm.cannot_copy_insn_p (insn))
00981 return false;
00982 if (insn == BB_END (bb))
00983 break;
00984 insn = NEXT_INSN (insn);
00985 }
00986 }
00987
00988 return true;
00989 }
00990
00991 rtx
00992 duplicate_insn_chain (rtx from, rtx to)
00993 {
00994 rtx insn, last;
00995
00996
00997
00998 last = emit_note (NOTE_INSN_DELETED);
00999
01000
01001
01002 for (insn = from; insn != NEXT_INSN (to); insn = NEXT_INSN (insn))
01003 {
01004 switch (GET_CODE (insn))
01005 {
01006 case INSN:
01007 case CALL_INSN:
01008 case JUMP_INSN:
01009
01010
01011
01012 if (GET_CODE (PATTERN (insn)) == ADDR_VEC
01013 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
01014 break;
01015 emit_copy_of_insn_after (insn, get_last_insn ());
01016 break;
01017
01018 case CODE_LABEL:
01019 break;
01020
01021 case BARRIER:
01022 emit_barrier ();
01023 break;
01024
01025 case NOTE:
01026 switch (NOTE_LINE_NUMBER (insn))
01027 {
01028
01029
01030 case NOTE_INSN_PROLOGUE_END:
01031
01032 case NOTE_INSN_LOOP_BEG:
01033 case NOTE_INSN_LOOP_END:
01034
01035
01036 case NOTE_INSN_DELETED:
01037 case NOTE_INSN_DELETED_LABEL:
01038
01039 case NOTE_INSN_EPILOGUE_BEG:
01040 case NOTE_INSN_FUNCTION_END:
01041
01042
01043
01044
01045 case NOTE_INSN_FUNCTION_BEG:
01046
01047 case NOTE_INSN_BASIC_BLOCK:
01048 break;
01049
01050 case NOTE_INSN_REPEATED_LINE_NUMBER:
01051 case NOTE_INSN_UNLIKELY_EXECUTED_CODE:
01052 emit_note_copy (insn);
01053 break;
01054
01055 default:
01056
01057
01058 gcc_assert (NOTE_LINE_NUMBER (insn) >= 0);
01059
01060
01061
01062 emit_note_copy (insn);
01063 }
01064 break;
01065 default:
01066 gcc_unreachable ();
01067 }
01068 }
01069 insn = NEXT_INSN (last);
01070 delete_insn (last);
01071 return insn;
01072 }
01073
01074
01075
01076
01077
01078
01079 extern basic_block cfg_layout_duplicate_bb (basic_block);
01080
01081 basic_block
01082 cfg_layout_duplicate_bb (basic_block bb)
01083 {
01084 rtx insn;
01085 basic_block new_bb;
01086
01087 insn = duplicate_insn_chain (BB_HEAD (bb), BB_END (bb));
01088 new_bb = create_basic_block (insn,
01089 insn ? get_last_insn () : NULL,
01090 EXIT_BLOCK_PTR->prev_bb);
01091
01092 BB_COPY_PARTITION (new_bb, bb);
01093 if (bb->rbi->header)
01094 {
01095 insn = bb->rbi->header;
01096 while (NEXT_INSN (insn))
01097 insn = NEXT_INSN (insn);
01098 insn = duplicate_insn_chain (bb->rbi->header, insn);
01099 if (insn)
01100 new_bb->rbi->header = unlink_insn_chain (insn, get_last_insn ());
01101 }
01102
01103 if (bb->rbi->footer)
01104 {
01105 insn = bb->rbi->footer;
01106 while (NEXT_INSN (insn))
01107 insn = NEXT_INSN (insn);
01108 insn = duplicate_insn_chain (bb->rbi->footer, insn);
01109 if (insn)
01110 new_bb->rbi->footer = unlink_insn_chain (insn, get_last_insn ());
01111 }
01112
01113 if (bb->global_live_at_start)
01114 {
01115 new_bb->global_live_at_start = ALLOC_REG_SET (®_obstack);
01116 new_bb->global_live_at_end = ALLOC_REG_SET (®_obstack);
01117 COPY_REG_SET (new_bb->global_live_at_start, bb->global_live_at_start);
01118 COPY_REG_SET (new_bb->global_live_at_end, bb->global_live_at_end);
01119 }
01120
01121 return new_bb;
01122 }
01123
01124
01125
01126
01127
01128
01129
01130
01131 void
01132 cfg_layout_initialize (unsigned int flags)
01133 {
01134 basic_block bb;
01135
01136
01137
01138 alloc_rbi_pool ();
01139
01140 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
01141 initialize_bb_rbi (bb);
01142
01143 cfg_layout_rtl_register_cfg_hooks ();
01144
01145 record_effective_endpoints ();
01146
01147 cleanup_cfg (CLEANUP_CFGLAYOUT | flags);
01148 }
01149
01150
01151 void
01152 break_superblocks (void)
01153 {
01154 sbitmap superblocks;
01155 bool need = false;
01156 basic_block bb;
01157
01158 superblocks = sbitmap_alloc (last_basic_block);
01159 sbitmap_zero (superblocks);
01160
01161 FOR_EACH_BB (bb)
01162 if (bb->flags & BB_SUPERBLOCK)
01163 {
01164 bb->flags &= ~BB_SUPERBLOCK;
01165 SET_BIT (superblocks, bb->index);
01166 need = true;
01167 }
01168
01169 if (need)
01170 {
01171 rebuild_jump_labels (get_insns ());
01172 find_many_sub_basic_blocks (superblocks);
01173 }
01174
01175 free (superblocks);
01176 }
01177
01178
01179
01180
01181 void
01182 cfg_layout_finalize (void)
01183 {
01184 basic_block bb;
01185
01186 #ifdef ENABLE_CHECKING
01187 verify_flow_info ();
01188 #endif
01189 rtl_register_cfg_hooks ();
01190 if (reload_completed
01191 #ifdef HAVE_epilogue
01192 && !HAVE_epilogue
01193 #endif
01194 )
01195 fixup_fallthru_exit_predecessor ();
01196 fixup_reorder_chain ();
01197
01198 #ifdef ENABLE_CHECKING
01199 verify_insn_chain ();
01200 #endif
01201
01202 free_rbi_pool ();
01203 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
01204 bb->rbi = NULL;
01205
01206 break_superblocks ();
01207
01208 #ifdef ENABLE_CHECKING
01209 verify_flow_info ();
01210 #endif
01211 }
01212
01213
01214 bool
01215 can_copy_bbs_p (basic_block *bbs, unsigned n)
01216 {
01217 unsigned i;
01218 edge e;
01219 int ret = true;
01220
01221 for (i = 0; i < n; i++)
01222 bbs[i]->rbi->duplicated = 1;
01223
01224 for (i = 0; i < n; i++)
01225 {
01226
01227 edge_iterator ei;
01228 FOR_EACH_EDGE (e, ei, bbs[i]->succs)
01229 if ((e->flags & EDGE_ABNORMAL)
01230 && e->dest->rbi->duplicated)
01231 {
01232 ret = false;
01233 goto end;
01234 }
01235
01236 if (!can_duplicate_block_p (bbs[i]))
01237 {
01238 ret = false;
01239 break;
01240 }
01241 }
01242
01243 end:
01244 for (i = 0; i < n; i++)
01245 bbs[i]->rbi->duplicated = 0;
01246
01247 return ret;
01248 }
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265 void
01266 copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs,
01267 edge *edges, unsigned n_edges, edge *new_edges,
01268 struct loop *base)
01269 {
01270 unsigned i, j;
01271 basic_block bb, new_bb, dom_bb;
01272 edge e;
01273
01274
01275 for (i = 0; i < n; i++)
01276 {
01277
01278 bb = bbs[i];
01279 new_bb = new_bbs[i] = duplicate_block (bb, NULL);
01280 bb->rbi->duplicated = 1;
01281
01282 add_bb_to_loop (new_bb, bb->loop_father->copy);
01283
01284 if (bb->loop_father->header == bb && bb->loop_father != base)
01285 new_bb->loop_father->header = new_bb;
01286
01287 if (bb->loop_father->latch == bb && bb->loop_father != base)
01288 new_bb->loop_father->latch = new_bb;
01289 }
01290
01291
01292 for (i = 0; i < n; i++)
01293 {
01294 bb = bbs[i];
01295 new_bb = new_bbs[i];
01296
01297 dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb);
01298 if (dom_bb->rbi->duplicated)
01299 {
01300 dom_bb = dom_bb->rbi->copy;
01301 set_immediate_dominator (CDI_DOMINATORS, new_bb, dom_bb);
01302 }
01303 }
01304
01305
01306 for (j = 0; j < n_edges; j++)
01307 new_edges[j] = NULL;
01308 for (i = 0; i < n; i++)
01309 {
01310 edge_iterator ei;
01311 new_bb = new_bbs[i];
01312 bb = bbs[i];
01313
01314 FOR_EACH_EDGE (e, ei, new_bb->succs)
01315 {
01316 for (j = 0; j < n_edges; j++)
01317 if (edges[j] && edges[j]->src == bb && edges[j]->dest == e->dest)
01318 new_edges[j] = e;
01319
01320 if (!e->dest->rbi->duplicated)
01321 continue;
01322 redirect_edge_and_branch_force (e, e->dest->rbi->copy);
01323 }
01324 }
01325
01326
01327 for (i = 0; i < n; i++)
01328 bbs[i]->rbi->duplicated = 0;
01329 }
01330
01331 #include "gt-cfglayout.h"