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