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
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "config.h"
00050 #include "system.h"
00051 #ifdef SGI_MONGOOSE
00052
00053 #include "rtl.h"
00054 #endif
00055 #include "tree.h"
00056 #ifndef SGI_MONGOOSE
00057 #include "rtl.h"
00058 #endif
00059 #include "hard-reg-set.h"
00060 #include "basic-block.h"
00061 #include "regs.h"
00062 #include "flags.h"
00063 #include "output.h"
00064 #include "function.h"
00065 #include "except.h"
00066 #include "toplev.h"
00067 #include "tm_p.h"
00068 #include "obstack.h"
00069 #include "insn-config.h"
00070
00071
00072 #ifndef HAVE_return
00073 #define HAVE_return 0
00074 #define gen_return() NULL_RTX
00075 #endif
00076
00077
00078
00079
00080 rtx label_value_list;
00081 rtx tail_recursion_label_list;
00082
00083 static int can_delete_note_p PARAMS ((rtx));
00084 static int can_delete_label_p PARAMS ((rtx));
00085 static void commit_one_edge_insertion PARAMS ((edge, int));
00086 static bool try_redirect_by_replacing_jump PARAMS ((edge, basic_block));
00087 static rtx last_loop_beg_note PARAMS ((rtx));
00088 static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block));
00089 static basic_block force_nonfallthru_and_redirect PARAMS ((edge, basic_block));
00090
00091
00092
00093
00094 static int
00095 can_delete_note_p (note)
00096 rtx note;
00097 {
00098 return (NOTE_LINE_NUMBER (note) == NOTE_INSN_DELETED
00099 || NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK
00100 || NOTE_LINE_NUMBER (note) == NOTE_INSN_PREDICTION);
00101 }
00102
00103
00104
00105 static int
00106 can_delete_label_p (label)
00107 rtx label;
00108 {
00109 return (!LABEL_PRESERVE_P (label)
00110
00111 && LABEL_NAME (label) == 0
00112 && !in_expr_list_p (forced_labels, label)
00113 && !in_expr_list_p (label_value_list, label));
00114 }
00115
00116
00117
00118 rtx
00119 delete_insn (insn)
00120 rtx insn;
00121 {
00122 rtx next = NEXT_INSN (insn);
00123 rtx note;
00124 bool really_delete = true;
00125
00126 if (GET_CODE (insn) == CODE_LABEL)
00127 {
00128
00129
00130
00131 if (! can_delete_label_p (insn))
00132 {
00133 const char *name = LABEL_NAME (insn);
00134
00135 really_delete = false;
00136 PUT_CODE (insn, NOTE);
00137 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED_LABEL;
00138 NOTE_SOURCE_FILE (insn) = name;
00139 }
00140
00141 remove_node_from_expr_list (insn, &nonlocal_goto_handler_labels);
00142 }
00143
00144 if (really_delete)
00145 {
00146
00147 if (INSN_DELETED_P (insn))
00148 abort ();
00149 remove_insn (insn);
00150 INSN_DELETED_P (insn) = 1;
00151 }
00152
00153
00154
00155 if (GET_CODE (insn) == JUMP_INSN
00156 && JUMP_LABEL (insn)
00157 && GET_CODE (JUMP_LABEL (insn)) == CODE_LABEL)
00158 LABEL_NUSES (JUMP_LABEL (insn))--;
00159
00160
00161 else if ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != NULL_RTX
00162 && GET_CODE (XEXP (note, 0)) == CODE_LABEL)
00163 LABEL_NUSES (XEXP (note, 0))--;
00164
00165 if (GET_CODE (insn) == JUMP_INSN
00166 && (GET_CODE (PATTERN (insn)) == ADDR_VEC
00167 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
00168 {
00169 rtx pat = PATTERN (insn);
00170 int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC;
00171 int len = XVECLEN (pat, diff_vec_p);
00172 int i;
00173
00174 for (i = 0; i < len; i++)
00175 {
00176 rtx label = XEXP (XVECEXP (pat, diff_vec_p, i), 0);
00177
00178
00179
00180
00181 if (GET_CODE (label) != NOTE)
00182 LABEL_NUSES (label)--;
00183 }
00184 }
00185
00186 return next;
00187 }
00188
00189
00190 rtx
00191 delete_insn_and_edges (insn)
00192 rtx insn;
00193 {
00194 rtx x;
00195 bool purge = false;
00196
00197 if (INSN_P (insn)
00198 && BLOCK_FOR_INSN (insn)
00199 && BLOCK_FOR_INSN (insn)->end == insn)
00200 purge = true;
00201 x = delete_insn (insn);
00202 if (purge)
00203 purge_dead_edges (BLOCK_FOR_INSN (insn));
00204 return x;
00205 }
00206
00207
00208
00209
00210 void
00211 delete_insn_chain (start, finish)
00212 rtx start, finish;
00213 {
00214 rtx next;
00215
00216
00217
00218
00219 while (1)
00220 {
00221 next = NEXT_INSN (start);
00222 if (GET_CODE (start) == NOTE && !can_delete_note_p (start))
00223 ;
00224 else
00225 next = delete_insn (start);
00226
00227 if (start == finish)
00228 break;
00229 start = next;
00230 }
00231 }
00232
00233
00234 void
00235 delete_insn_chain_and_edges (first, last)
00236 rtx first, last;
00237 {
00238 bool purge = false;
00239
00240 if (INSN_P (last)
00241 && BLOCK_FOR_INSN (last)
00242 && BLOCK_FOR_INSN (last)->end == last)
00243 purge = true;
00244 delete_insn_chain (first, last);
00245 if (purge)
00246 purge_dead_edges (BLOCK_FOR_INSN (last));
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 basic_block
00258 create_basic_block_structure (head, end, bb_note, after)
00259 rtx head, end, bb_note;
00260 basic_block after;
00261 {
00262 basic_block bb;
00263
00264 if (bb_note
00265 && ! RTX_INTEGRATED_P (bb_note)
00266 && (bb = NOTE_BASIC_BLOCK (bb_note)) != NULL
00267 && bb->aux == NULL)
00268 {
00269
00270
00271 rtx after;
00272
00273 if (GET_CODE (head) == CODE_LABEL)
00274 after = head;
00275 else
00276 {
00277 after = PREV_INSN (head);
00278 head = bb_note;
00279 }
00280
00281 if (after != bb_note && NEXT_INSN (after) != bb_note)
00282 reorder_insns_nobb (bb_note, bb_note, after);
00283 }
00284 else
00285 {
00286
00287
00288 bb = alloc_block ();
00289
00290 if (!head && !end)
00291 head = end = bb_note
00292 = emit_note_after (NOTE_INSN_BASIC_BLOCK, get_last_insn ());
00293 else if (GET_CODE (head) == CODE_LABEL && end)
00294 {
00295 bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, head);
00296 if (head == end)
00297 end = bb_note;
00298 }
00299 else
00300 {
00301 bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, head);
00302 head = bb_note;
00303 if (!end)
00304 end = head;
00305 }
00306
00307 NOTE_BASIC_BLOCK (bb_note) = bb;
00308 }
00309
00310
00311 if (NEXT_INSN (end) == bb_note)
00312 end = bb_note;
00313
00314 bb->head = head;
00315 bb->end = end;
00316 bb->index = last_basic_block++;
00317 bb->flags = BB_NEW;
00318 link_block (bb, after);
00319 BASIC_BLOCK (bb->index) = bb;
00320 update_bb_for_insn (bb);
00321
00322
00323
00324 bb->aux = bb;
00325
00326 return bb;
00327 }
00328
00329
00330
00331
00332
00333
00334 basic_block
00335 create_basic_block (head, end, after)
00336 rtx head, end;
00337 basic_block after;
00338 {
00339 basic_block bb;
00340
00341
00342 VARRAY_GROW (basic_block_info, last_basic_block+1);
00343
00344 n_basic_blocks++;
00345
00346 bb = create_basic_block_structure (head, end, NULL, after);
00347 bb->aux = NULL;
00348 return bb;
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 int
00360 flow_delete_block_noexpunge (b)
00361 basic_block b;
00362 {
00363 int deleted_handler = 0;
00364 rtx insn, end, tmp;
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 for (insn = PREV_INSN (b->head); insn; insn = PREV_INSN (insn))
00377 {
00378 if (GET_CODE (insn) != NOTE)
00379 break;
00380 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PREDICTION
00381 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT)
00382 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
00383 }
00384
00385 insn = b->head;
00386
00387 never_reached_warning (insn, b->end);
00388
00389 if (GET_CODE (insn) == CODE_LABEL)
00390 maybe_remove_eh_handler (insn);
00391
00392
00393 end = b->end;
00394 if (GET_CODE (end) == JUMP_INSN
00395 && (tmp = JUMP_LABEL (end)) != NULL_RTX
00396 && (tmp = NEXT_INSN (tmp)) != NULL_RTX
00397 && GET_CODE (tmp) == JUMP_INSN
00398 && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
00399 || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
00400 end = tmp;
00401
00402
00403 tmp = next_nonnote_insn (end);
00404 if (tmp && GET_CODE (tmp) == BARRIER)
00405 end = tmp;
00406
00407
00408 b->head = NULL;
00409 delete_insn_chain (insn, end);
00410
00411
00412
00413 while (b->pred != NULL)
00414 remove_edge (b->pred);
00415 while (b->succ != NULL)
00416 remove_edge (b->succ);
00417
00418 b->pred = NULL;
00419 b->succ = NULL;
00420
00421 return deleted_handler;
00422 }
00423
00424 int
00425 flow_delete_block (b)
00426 basic_block b;
00427 {
00428 int deleted_handler = flow_delete_block_noexpunge (b);
00429
00430
00431 expunge_block (b);
00432
00433 return deleted_handler;
00434 }
00435
00436
00437
00438 void
00439 compute_bb_for_insn ()
00440 {
00441 basic_block bb;
00442
00443 FOR_EACH_BB (bb)
00444 {
00445 rtx end = bb->end;
00446 rtx insn;
00447
00448 for (insn = bb->head; ; insn = NEXT_INSN (insn))
00449 {
00450 BLOCK_FOR_INSN (insn) = bb;
00451 if (insn == end)
00452 break;
00453 }
00454 }
00455 }
00456
00457
00458
00459 void
00460 free_bb_for_insn ()
00461 {
00462 rtx insn;
00463 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
00464 if (GET_CODE (insn) != BARRIER)
00465 BLOCK_FOR_INSN (insn) = NULL;
00466 }
00467
00468
00469
00470 void
00471 update_bb_for_insn (bb)
00472 basic_block bb;
00473 {
00474 rtx insn;
00475
00476 for (insn = bb->head; ; insn = NEXT_INSN (insn))
00477 {
00478 set_block_for_insn (insn, bb);
00479 if (insn == bb->end)
00480 break;
00481 }
00482 }
00483
00484
00485
00486
00487
00488
00489 edge
00490 split_block (bb, insn)
00491 basic_block bb;
00492 rtx insn;
00493 {
00494 basic_block new_bb;
00495 edge new_edge;
00496 edge e;
00497
00498
00499 if (bb->end == insn)
00500 return 0;
00501
00502
00503 new_bb = create_basic_block (NEXT_INSN (insn), bb->end, bb);
00504 new_bb->count = bb->count;
00505 new_bb->frequency = bb->frequency;
00506 new_bb->loop_depth = bb->loop_depth;
00507 bb->end = insn;
00508
00509
00510 new_bb->succ = bb->succ;
00511 bb->succ = NULL;
00512 for (e = new_bb->succ; e; e = e->succ_next)
00513 e->src = new_bb;
00514
00515 new_edge = make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
00516
00517 if (bb->global_live_at_start)
00518 {
00519 new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
00520 new_bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
00521 COPY_REG_SET (new_bb->global_live_at_end, bb->global_live_at_end);
00522
00523
00524
00525
00526
00527
00528 COPY_REG_SET (new_bb->global_live_at_start, bb->global_live_at_end);
00529 propagate_block (new_bb, new_bb->global_live_at_start, NULL, NULL, 0);
00530 COPY_REG_SET (bb->global_live_at_end,
00531 new_bb->global_live_at_start);
00532 #ifdef HAVE_conditional_execution
00533
00534
00535 if (reload_completed)
00536 {
00537 bb->flags |= BB_DIRTY;
00538 new_bb->flags |= BB_DIRTY;
00539 }
00540 #endif
00541 }
00542
00543 return new_edge;
00544 }
00545
00546
00547
00548
00549 void
00550 merge_blocks_nomove (a, b)
00551 basic_block a, b;
00552 {
00553 rtx b_head = b->head, b_end = b->end, a_end = a->end;
00554 rtx del_first = NULL_RTX, del_last = NULL_RTX;
00555 int b_empty = 0;
00556 edge e;
00557
00558
00559 if (GET_CODE (b_head) == CODE_LABEL)
00560 {
00561
00562
00563 if (b_head == b_end)
00564 b_empty = 1;
00565
00566 del_first = del_last = b_head;
00567 b_head = NEXT_INSN (b_head);
00568 }
00569
00570
00571
00572 if (NOTE_INSN_BASIC_BLOCK_P (b_head))
00573 {
00574 if (b_head == b_end)
00575 b_empty = 1;
00576 if (! del_last)
00577 del_first = b_head;
00578
00579 del_last = b_head;
00580 b_head = NEXT_INSN (b_head);
00581 }
00582
00583
00584 if (GET_CODE (a_end) == JUMP_INSN)
00585 {
00586 rtx prev;
00587
00588 for (prev = PREV_INSN (a_end); ; prev = PREV_INSN (prev))
00589 if (GET_CODE (prev) != NOTE
00590 || NOTE_LINE_NUMBER (prev) == NOTE_INSN_BASIC_BLOCK
00591 || prev == a->head)
00592 break;
00593
00594 del_first = a_end;
00595
00596 #ifdef HAVE_cc0
00597
00598
00599 if (only_sets_cc0_p (prev))
00600 {
00601 rtx tmp = prev;
00602
00603 prev = prev_nonnote_insn (prev);
00604 if (!prev)
00605 prev = a->head;
00606 del_first = tmp;
00607 }
00608 #endif
00609
00610 a_end = PREV_INSN (del_first);
00611 }
00612 else if (GET_CODE (NEXT_INSN (a_end)) == BARRIER)
00613 del_first = NEXT_INSN (a_end);
00614
00615
00616
00617
00618
00619 while (a->succ)
00620 remove_edge (a->succ);
00621
00622
00623 for (e = b->succ; e; e = e->succ_next)
00624 e->src = a;
00625 a->succ = b->succ;
00626 a->flags |= b->flags;
00627
00628
00629 b->pred = b->succ = NULL;
00630 a->global_live_at_end = b->global_live_at_end;
00631
00632 expunge_block (b);
00633
00634
00635
00636 delete_insn_chain (del_first, del_last);
00637
00638
00639 if (!b_empty)
00640 {
00641 rtx x;
00642
00643 for (x = a_end; x != b_end; x = NEXT_INSN (x))
00644 set_block_for_insn (x, a);
00645
00646 set_block_for_insn (b_end, a);
00647
00648 a_end = b_end;
00649 }
00650
00651 a->end = a_end;
00652 }
00653
00654
00655
00656
00657 rtx
00658 block_label (block)
00659 basic_block block;
00660 {
00661 if (block == EXIT_BLOCK_PTR)
00662 return NULL_RTX;
00663
00664 if (GET_CODE (block->head) != CODE_LABEL)
00665 {
00666 block->head = emit_label_before (gen_label_rtx (), block->head);
00667 }
00668
00669 return block->head;
00670 }
00671
00672
00673
00674
00675
00676
00677 static bool
00678 try_redirect_by_replacing_jump (e, target)
00679 edge e;
00680 basic_block target;
00681 {
00682 basic_block src = e->src;
00683 rtx insn = src->end, kill_from;
00684 edge tmp;
00685 rtx set, table;
00686 int fallthru = 0;
00687
00688
00689 for (tmp = src->succ; tmp; tmp = tmp->succ_next)
00690 if (tmp->dest != target && tmp != e)
00691 break;
00692
00693 if (tmp || !onlyjump_p (insn))
00694 return false;
00695 if (flow2_completed && JUMP_LABEL (insn)
00696 && (table = NEXT_INSN (JUMP_LABEL (insn))) != NULL_RTX
00697 && GET_CODE (table) == JUMP_INSN
00698 && (GET_CODE (PATTERN (table)) == ADDR_VEC
00699 || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC))
00700 return false;
00701
00702
00703 set = single_set (insn);
00704 if (!set || side_effects_p (set))
00705 return false;
00706
00707
00708
00709 kill_from = insn;
00710 #ifdef HAVE_cc0
00711 if (reg_mentioned_p (cc0_rtx, PATTERN (insn)))
00712 kill_from = PREV_INSN (insn);
00713 #endif
00714
00715
00716 if (can_fallthru (src, target))
00717 {
00718 if (rtl_dump_file)
00719 fprintf (rtl_dump_file, "Removing jump %i.\n", INSN_UID (insn));
00720 fallthru = 1;
00721
00722
00723 delete_insn_chain (kill_from, PREV_INSN (target->head));
00724 }
00725
00726
00727 else if (simplejump_p (insn))
00728 {
00729 if (e->dest == target)
00730 return false;
00731 if (rtl_dump_file)
00732 fprintf (rtl_dump_file, "Redirecting jump %i from %i to %i.\n",
00733 INSN_UID (insn), e->dest->index, target->index);
00734 if (!redirect_jump (insn, block_label (target), 0))
00735 {
00736 if (target == EXIT_BLOCK_PTR)
00737 return false;
00738 abort ();
00739 }
00740 }
00741
00742
00743 else if (target == EXIT_BLOCK_PTR)
00744 return false;
00745
00746
00747 else
00748 {
00749 rtx target_label = block_label (target);
00750 rtx barrier, tmp;
00751
00752 emit_jump_insn_after (gen_jump (target_label), insn);
00753 JUMP_LABEL (src->end) = target_label;
00754 LABEL_NUSES (target_label)++;
00755 if (rtl_dump_file)
00756 fprintf (rtl_dump_file, "Replacing insn %i by jump %i\n",
00757 INSN_UID (insn), INSN_UID (src->end));
00758
00759
00760 delete_insn_chain (kill_from, insn);
00761
00762
00763
00764
00765 if ((tmp = JUMP_LABEL (insn)) != NULL_RTX
00766 && (tmp = NEXT_INSN (tmp)) != NULL_RTX
00767 && GET_CODE (tmp) == JUMP_INSN
00768 && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
00769 || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
00770 {
00771 delete_insn_chain (JUMP_LABEL (insn), tmp);
00772 }
00773
00774 barrier = next_nonnote_insn (src->end);
00775 if (!barrier || GET_CODE (barrier) != BARRIER)
00776 emit_barrier_after (src->end);
00777 }
00778
00779
00780 while (src->succ->succ_next)
00781 remove_edge (src->succ);
00782 e = src->succ;
00783 if (fallthru)
00784 e->flags = EDGE_FALLTHRU;
00785 else
00786 e->flags = 0;
00787
00788 e->probability = REG_BR_PROB_BASE;
00789 e->count = src->count;
00790
00791
00792
00793 while (GET_CODE (e->src->end) == NOTE
00794 && NOTE_LINE_NUMBER (e->src->end) >= 0)
00795 delete_insn (e->src->end);
00796
00797 if (e->dest != target)
00798 redirect_edge_succ (e, target);
00799
00800 return true;
00801 }
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 static rtx
00812 last_loop_beg_note (insn)
00813 rtx insn;
00814 {
00815 rtx last = insn;
00816
00817 for (insn = NEXT_INSN (insn); insn && GET_CODE (insn) == NOTE
00818 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK;
00819 insn = NEXT_INSN (insn))
00820 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
00821 last = insn;
00822
00823 return last;
00824 }
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836 bool
00837 redirect_edge_and_branch (e, target)
00838 edge e;
00839 basic_block target;
00840 {
00841 rtx tmp;
00842 rtx old_label = e->dest->head;
00843 basic_block src = e->src;
00844 rtx insn = src->end;
00845
00846 if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
00847 return false;
00848
00849 if (try_redirect_by_replacing_jump (e, target))
00850 return true;
00851
00852
00853
00854
00855 else if (e->dest == target)
00856 return false;
00857
00858
00859 if (e->flags & EDGE_FALLTHRU)
00860 return false;
00861 else if (GET_CODE (insn) != JUMP_INSN)
00862 return false;
00863
00864
00865 if ((tmp = JUMP_LABEL (insn)) != NULL_RTX
00866 && (tmp = NEXT_INSN (tmp)) != NULL_RTX
00867 && GET_CODE (tmp) == JUMP_INSN
00868 && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
00869 || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
00870 {
00871 rtvec vec;
00872 int j;
00873 rtx new_label = block_label (target);
00874
00875 if (target == EXIT_BLOCK_PTR)
00876 return false;
00877 if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
00878 vec = XVEC (PATTERN (tmp), 0);
00879 else
00880 vec = XVEC (PATTERN (tmp), 1);
00881
00882 for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
00883 if (XEXP (RTVEC_ELT (vec, j), 0) == old_label)
00884 {
00885 RTVEC_ELT (vec, j) = gen_rtx_LABEL_REF (Pmode, new_label);
00886 --LABEL_NUSES (old_label);
00887 ++LABEL_NUSES (new_label);
00888 }
00889
00890
00891 if ((tmp = single_set (insn)) != NULL
00892 && SET_DEST (tmp) == pc_rtx
00893 && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
00894 && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF
00895 && XEXP (XEXP (SET_SRC (tmp), 2), 0) == old_label)
00896 {
00897 XEXP (SET_SRC (tmp), 2) = gen_rtx_LABEL_REF (VOIDmode,
00898 new_label);
00899 --LABEL_NUSES (old_label);
00900 ++LABEL_NUSES (new_label);
00901 }
00902 }
00903 else
00904 {
00905
00906
00907
00908 if (computed_jump_p (insn)
00909
00910 || returnjump_p (insn))
00911 return false;
00912
00913
00914 if (JUMP_LABEL (insn) != old_label)
00915 abort ();
00916
00917
00918
00919
00920 if (!redirect_jump (insn, block_label (target), 0))
00921 {
00922 if (target == EXIT_BLOCK_PTR)
00923 return false;
00924 abort ();
00925 }
00926 }
00927
00928 if (rtl_dump_file)
00929 fprintf (rtl_dump_file, "Edge %i->%i redirected to %i\n",
00930 e->src->index, e->dest->index, target->index);
00931
00932 if (e->dest != target)
00933 redirect_edge_succ_nodup (e, target);
00934
00935 return true;
00936 }
00937
00938
00939
00940
00941 static basic_block
00942 force_nonfallthru_and_redirect (e, target)
00943 edge e;
00944 basic_block target;
00945 {
00946 basic_block jump_block, new_bb = NULL, src = e->src;
00947 rtx note;
00948 edge new_edge;
00949 int abnormal_edge_flags = 0;
00950
00951
00952
00953
00954 if (e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR
00955 && any_condjump_p (e->src->end)
00956
00957
00958 && e->src->next_bb == e->dest
00959 && JUMP_LABEL (e->src->end) == e->dest->head)
00960 {
00961 rtx note;
00962 edge b = unchecked_make_edge (e->src, target, 0);
00963
00964 if (!redirect_jump (e->src->end, block_label (target), 0))
00965 abort ();
00966 note = find_reg_note (e->src->end, REG_BR_PROB, NULL_RTX);
00967 if (note)
00968 {
00969 int prob = INTVAL (XEXP (note, 0));
00970
00971 b->probability = prob;
00972 b->count = e->count * prob / REG_BR_PROB_BASE;
00973 e->probability -= e->probability;
00974 e->count -= b->count;
00975 if (e->probability < 0)
00976 e->probability = 0;
00977 if (e->count < 0)
00978 e->count = 0;
00979 }
00980 }
00981
00982 if (e->flags & EDGE_ABNORMAL)
00983 {
00984
00985
00986
00987
00988
00989 if (e->dest != target)
00990 abort ();
00991 abnormal_edge_flags = e->flags & ~(EDGE_FALLTHRU | EDGE_CAN_FALLTHRU);
00992 e->flags &= EDGE_FALLTHRU | EDGE_CAN_FALLTHRU;
00993 }
00994 else if (!(e->flags & EDGE_FALLTHRU))
00995 abort ();
00996 else if (e->src == ENTRY_BLOCK_PTR)
00997 {
00998
00999
01000 edge *pe1;
01001 basic_block bb = create_basic_block (e->dest->head, NULL, ENTRY_BLOCK_PTR);
01002
01003
01004
01005 e->src = bb;
01006 for (pe1 = &ENTRY_BLOCK_PTR->succ; *pe1; pe1 = &(*pe1)->succ_next)
01007 if (*pe1 == e)
01008 {
01009 *pe1 = e->succ_next;
01010 break;
01011 }
01012 e->succ_next = 0;
01013 bb->succ = e;
01014 make_single_succ_edge (ENTRY_BLOCK_PTR, bb, EDGE_FALLTHRU);
01015 }
01016
01017 if (e->src->succ->succ_next || abnormal_edge_flags)
01018 {
01019
01020
01021
01022 note = last_loop_beg_note (e->src->end);
01023 note = NEXT_INSN (note);
01024
01025
01026 if (note != NULL
01027 && GET_CODE (note) == CODE_LABEL
01028 && NEXT_INSN (note)
01029 && GET_CODE (NEXT_INSN (note)) == JUMP_INSN
01030 && (GET_CODE (PATTERN (NEXT_INSN (note))) == ADDR_DIFF_VEC
01031 || GET_CODE (PATTERN (NEXT_INSN (note))) == ADDR_VEC))
01032 note = NEXT_INSN (NEXT_INSN (note));
01033
01034 jump_block = create_basic_block (note, NULL, e->src);
01035 jump_block->count = e->count;
01036 jump_block->frequency = EDGE_FREQUENCY (e);
01037 jump_block->loop_depth = target->loop_depth;
01038
01039 if (target->global_live_at_start)
01040 {
01041 jump_block->global_live_at_start
01042 = OBSTACK_ALLOC_REG_SET (&flow_obstack);
01043 jump_block->global_live_at_end
01044 = OBSTACK_ALLOC_REG_SET (&flow_obstack);
01045 COPY_REG_SET (jump_block->global_live_at_start,
01046 target->global_live_at_start);
01047 COPY_REG_SET (jump_block->global_live_at_end,
01048 target->global_live_at_start);
01049 }
01050
01051
01052 new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU);
01053 new_edge->probability = e->probability;
01054 new_edge->count = e->count;
01055
01056
01057 redirect_edge_pred (e, jump_block);
01058 e->probability = REG_BR_PROB_BASE;
01059
01060 new_bb = jump_block;
01061 }
01062 else
01063 jump_block = e->src;
01064
01065 e->flags &= ~EDGE_FALLTHRU;
01066 if (target == EXIT_BLOCK_PTR)
01067 {
01068 if (HAVE_return)
01069 emit_jump_insn_after (gen_return (), jump_block->end);
01070 else
01071 abort ();
01072 }
01073 else
01074 {
01075 rtx label = block_label (target);
01076 emit_jump_insn_after (gen_jump (label), jump_block->end);
01077 JUMP_LABEL (jump_block->end) = label;
01078 LABEL_NUSES (label)++;
01079 }
01080
01081 emit_barrier_after (jump_block->end);
01082 redirect_edge_succ_nodup (e, target);
01083
01084 if (abnormal_edge_flags)
01085 make_edge (src, target, abnormal_edge_flags);
01086
01087 return new_bb;
01088 }
01089
01090
01091
01092
01093
01094 basic_block
01095 force_nonfallthru (e)
01096 edge e;
01097 {
01098 return force_nonfallthru_and_redirect (e, e->dest);
01099 }
01100
01101
01102
01103
01104
01105 basic_block
01106 redirect_edge_and_branch_force (e, target)
01107 edge e;
01108 basic_block target;
01109 {
01110 if (redirect_edge_and_branch (e, target)
01111 || e->dest == target)
01112 return NULL;
01113
01114
01115
01116 return force_nonfallthru_and_redirect (e, target);
01117 }
01118
01119
01120
01121
01122 void
01123 tidy_fallthru_edge (e, b, c)
01124 edge e;
01125 basic_block b, c;
01126 {
01127 rtx q;
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139 for (q = NEXT_INSN (b->end); q != c->head; q = NEXT_INSN (q))
01140 if (INSN_P (q))
01141 return;
01142
01143
01144
01145
01146 q = b->end;
01147 if (GET_CODE (q) == JUMP_INSN
01148 && onlyjump_p (q)
01149 && (any_uncondjump_p (q)
01150 || (b->succ == e && e->succ_next == NULL)))
01151 {
01152 #ifdef HAVE_cc0
01153
01154
01155 if (any_condjump_p (q) && only_sets_cc0_p (PREV_INSN (q)))
01156 q = PREV_INSN (q);
01157 #endif
01158
01159 q = PREV_INSN (q);
01160
01161
01162
01163 while (GET_CODE (q) == NOTE && NOTE_LINE_NUMBER (q) >= 0)
01164 q = PREV_INSN (q);
01165 }
01166
01167
01168 if (q != PREV_INSN (c->head))
01169 delete_insn_chain (NEXT_INSN (q), PREV_INSN (c->head));
01170
01171 e->flags |= EDGE_FALLTHRU;
01172 }
01173
01174
01175
01176
01177
01178
01179 void
01180 tidy_fallthru_edges ()
01181 {
01182 basic_block b, c;
01183
01184 if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
01185 return;
01186
01187 FOR_BB_BETWEEN (b, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, next_bb)
01188 {
01189 edge s;
01190
01191 c = b->next_bb;
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205 if ((s = b->succ) != NULL
01206 && ! (s->flags & EDGE_COMPLEX)
01207 && s->succ_next == NULL
01208 && s->dest == c
01209
01210 && (GET_CODE (b->end) != JUMP_INSN
01211 || onlyjump_p (b->end)))
01212 tidy_fallthru_edge (s, b, c);
01213 }
01214 }
01215
01216
01217
01218
01219 static bool
01220 back_edge_of_syntactic_loop_p (bb1, bb2)
01221 basic_block bb1, bb2;
01222 {
01223 rtx insn;
01224 int count = 0;
01225 basic_block bb;
01226
01227 if (bb1 == bb2)
01228 return true;
01229
01230
01231
01232 for (bb = bb1; bb && bb != bb2; bb = bb->next_bb)
01233 continue;
01234
01235 if (!bb)
01236 return false;
01237
01238 for (insn = bb1->end; insn != bb2->head && count >= 0;
01239 insn = NEXT_INSN (insn))
01240 if (GET_CODE (insn) == NOTE)
01241 {
01242 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
01243 count++;
01244 else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
01245 count--;
01246 }
01247
01248 return count >= 0;
01249 }
01250
01251
01252
01253
01254
01255
01256
01257
01258 basic_block
01259 split_edge (edge_in)
01260 edge edge_in;
01261 {
01262 basic_block bb;
01263 edge edge_out;
01264 rtx before;
01265
01266
01267 if ((edge_in->flags & EDGE_ABNORMAL) != 0)
01268 abort ();
01269
01270
01271
01272 if ((edge_in->flags & EDGE_FALLTHRU) == 0)
01273 {
01274 edge e;
01275
01276 for (e = edge_in->dest->pred; e; e = e->pred_next)
01277 if (e->flags & EDGE_FALLTHRU)
01278 break;
01279
01280 if (e)
01281 force_nonfallthru (e);
01282 }
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302 if (edge_in->dest != EXIT_BLOCK_PTR
01303 && PREV_INSN (edge_in->dest->head)
01304 && GET_CODE (PREV_INSN (edge_in->dest->head)) == NOTE
01305 && (NOTE_LINE_NUMBER (PREV_INSN (edge_in->dest->head))
01306 == NOTE_INSN_LOOP_BEG)
01307 && !back_edge_of_syntactic_loop_p (edge_in->dest, edge_in->src))
01308 before = PREV_INSN (edge_in->dest->head);
01309 else if (edge_in->dest != EXIT_BLOCK_PTR)
01310 before = edge_in->dest->head;
01311 else
01312 before = NULL_RTX;
01313
01314 bb = create_basic_block (before, NULL, edge_in->dest->prev_bb);
01315 bb->count = edge_in->count;
01316 bb->frequency = EDGE_FREQUENCY (edge_in);
01317
01318
01319 if (edge_in->dest->global_live_at_start)
01320 {
01321 bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
01322 bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
01323 COPY_REG_SET (bb->global_live_at_start,
01324 edge_in->dest->global_live_at_start);
01325 COPY_REG_SET (bb->global_live_at_end,
01326 edge_in->dest->global_live_at_start);
01327 }
01328
01329 edge_out = make_single_succ_edge (bb, edge_in->dest, EDGE_FALLTHRU);
01330
01331
01332
01333 if ((edge_in->flags & EDGE_FALLTHRU) == 0)
01334 {
01335 if (!redirect_edge_and_branch (edge_in, bb))
01336 abort ();
01337 }
01338 else
01339 redirect_edge_succ (edge_in, bb);
01340
01341 return bb;
01342 }
01343
01344
01345
01346
01347
01348 void
01349 insert_insn_on_edge (pattern, e)
01350 rtx pattern;
01351 edge e;
01352 {
01353
01354
01355 if ((e->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (e))
01356 abort ();
01357
01358 if (e->insns == NULL_RTX)
01359 start_sequence ();
01360 else
01361 push_to_sequence (e->insns);
01362
01363 emit_insn (pattern);
01364
01365 e->insns = get_insns ();
01366 end_sequence ();
01367 }
01368
01369
01370
01371 static void
01372 commit_one_edge_insertion (e, watch_calls)
01373 edge e;
01374 int watch_calls;
01375 {
01376 rtx before = NULL_RTX, after = NULL_RTX, insns, tmp, last;
01377 basic_block bb = NULL;
01378
01379
01380 insns = e->insns;
01381 e->insns = NULL_RTX;
01382
01383
01384
01385 if (watch_calls && (e->flags & EDGE_FALLTHRU) && !e->dest->pred->pred_next
01386 && e->src != ENTRY_BLOCK_PTR
01387 && GET_CODE (e->src->end) == CALL_INSN)
01388 {
01389 rtx next = next_nonnote_insn (e->src->end);
01390
01391 after = e->dest->head;
01392
01393 while (next
01394 && keep_with_call_p (next))
01395 {
01396 after = next;
01397 next = next_nonnote_insn (next);
01398 }
01399 bb = e->dest;
01400 }
01401 if (!before && !after)
01402 {
01403
01404
01405 if (e->dest->pred->pred_next == NULL && e->dest != EXIT_BLOCK_PTR)
01406 {
01407 bb = e->dest;
01408
01409
01410
01411 tmp = bb->head;
01412 if (GET_CODE (tmp) == CODE_LABEL)
01413 tmp = NEXT_INSN (tmp);
01414 if (NOTE_INSN_BASIC_BLOCK_P (tmp))
01415 tmp = NEXT_INSN (tmp);
01416 if (tmp == bb->head)
01417 before = tmp;
01418 else if (tmp)
01419 after = PREV_INSN (tmp);
01420 else
01421 after = get_last_insn ();
01422 }
01423
01424
01425
01426 else if ((e->flags & EDGE_ABNORMAL) == 0
01427 && e->src->succ->succ_next == NULL
01428 && e->src != ENTRY_BLOCK_PTR)
01429 {
01430 bb = e->src;
01431
01432
01433
01434
01435
01436
01437
01438 if (GET_CODE (bb->end) == JUMP_INSN)
01439 for (before = bb->end;
01440 GET_CODE (PREV_INSN (before)) == NOTE
01441 && NOTE_LINE_NUMBER (PREV_INSN (before)) ==
01442 NOTE_INSN_LOOP_BEG; before = PREV_INSN (before))
01443 ;
01444 else
01445 {
01446
01447 if ((e->flags & EDGE_FALLTHRU) == 0)
01448 abort ();
01449
01450 after = bb->end;
01451 }
01452 }
01453
01454 else
01455 {
01456 bb = split_edge (e);
01457 after = bb->end;
01458 }
01459 }
01460
01461
01462
01463 if (before)
01464 {
01465 emit_insn_before (insns, before);
01466 last = prev_nonnote_insn (before);
01467 }
01468 else
01469 last = emit_insn_after (insns, after);
01470
01471 if (returnjump_p (last))
01472 {
01473
01474
01475
01476
01477
01478 e = bb->succ;
01479 if (e->dest != EXIT_BLOCK_PTR
01480 || e->succ_next != NULL || (e->flags & EDGE_FALLTHRU) == 0)
01481 abort ();
01482
01483 e->flags &= ~EDGE_FALLTHRU;
01484 emit_barrier_after (last);
01485
01486 if (before)
01487 delete_insn (before);
01488 }
01489 else if (GET_CODE (last) == JUMP_INSN)
01490 abort ();
01491
01492
01493 bb->aux = &bb->aux;
01494 }
01495
01496
01497
01498 void
01499 commit_edge_insertions ()
01500 {
01501 basic_block bb;
01502 sbitmap blocks;
01503 bool changed = false;
01504
01505 #ifdef ENABLE_CHECKING
01506 verify_flow_info ();
01507 #endif
01508
01509 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
01510 {
01511 edge e, next;
01512
01513 for (e = bb->succ; e; e = next)
01514 {
01515 next = e->succ_next;
01516 if (e->insns)
01517 {
01518 changed = true;
01519 commit_one_edge_insertion (e, false);
01520 }
01521 }
01522 }
01523
01524 if (!changed)
01525 return;
01526
01527 blocks = sbitmap_alloc (last_basic_block);
01528 sbitmap_zero (blocks);
01529 FOR_EACH_BB (bb)
01530 if (bb->aux)
01531 {
01532 SET_BIT (blocks, bb->index);
01533 bb->aux = NULL;
01534 }
01535 find_many_sub_basic_blocks (blocks);
01536 sbitmap_free (blocks);
01537 }
01538
01539
01540
01541
01542 void
01543 commit_edge_insertions_watch_calls ()
01544 {
01545 basic_block bb;
01546 sbitmap blocks;
01547 bool changed = false;
01548
01549 #ifdef ENABLE_CHECKING
01550 verify_flow_info ();
01551 #endif
01552
01553 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
01554 {
01555 edge e, next;
01556
01557 for (e = bb->succ; e; e = next)
01558 {
01559 next = e->succ_next;
01560 if (e->insns)
01561 {
01562 changed = true;
01563 commit_one_edge_insertion (e, true);
01564 }
01565 }
01566 }
01567
01568 if (!changed)
01569 return;
01570
01571 blocks = sbitmap_alloc (last_basic_block);
01572 sbitmap_zero (blocks);
01573 FOR_EACH_BB (bb)
01574 if (bb->aux)
01575 {
01576 SET_BIT (blocks, bb->index);
01577 bb->aux = NULL;
01578 }
01579 find_many_sub_basic_blocks (blocks);
01580 sbitmap_free (blocks);
01581 }
01582
01583
01584
01585 void
01586 dump_bb (bb, outf)
01587 basic_block bb;
01588 FILE *outf;
01589 {
01590 rtx insn;
01591 rtx last;
01592 edge e;
01593
01594 fprintf (outf, ";; Basic block %d, loop depth %d, count ",
01595 bb->index, bb->loop_depth);
01596 fprintf (outf, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) bb->count);
01597 putc ('\n', outf);
01598
01599 fputs (";; Predecessors: ", outf);
01600 for (e = bb->pred; e; e = e->pred_next)
01601 dump_edge_info (outf, e, 0);
01602 putc ('\n', outf);
01603
01604 fputs (";; Registers live at start:", outf);
01605 dump_regset (bb->global_live_at_start, outf);
01606 putc ('\n', outf);
01607
01608 for (insn = bb->head, last = NEXT_INSN (bb->end); insn != last;
01609 insn = NEXT_INSN (insn))
01610 print_rtl_single (outf, insn);
01611
01612 fputs (";; Registers live at end:", outf);
01613 dump_regset (bb->global_live_at_end, outf);
01614 putc ('\n', outf);
01615
01616 fputs (";; Successors: ", outf);
01617 for (e = bb->succ; e; e = e->succ_next)
01618 dump_edge_info (outf, e, 1);
01619 putc ('\n', outf);
01620 }
01621
01622 void
01623 debug_bb (bb)
01624 basic_block bb;
01625 {
01626 dump_bb (bb, stderr);
01627 }
01628
01629 void
01630 debug_bb_n (n)
01631 int n;
01632 {
01633 dump_bb (BASIC_BLOCK (n), stderr);
01634 }
01635
01636
01637
01638
01639 void
01640 print_rtl_with_bb (outf, rtx_first)
01641 FILE *outf;
01642 rtx rtx_first;
01643 {
01644 rtx tmp_rtx;
01645
01646 if (rtx_first == 0)
01647 fprintf (outf, "(nil)\n");
01648 else
01649 {
01650 enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
01651 int max_uid = get_max_uid ();
01652 basic_block *start
01653 = (basic_block *) xcalloc (max_uid, sizeof (basic_block));
01654 basic_block *end
01655 = (basic_block *) xcalloc (max_uid, sizeof (basic_block));
01656 enum bb_state *in_bb_p
01657 = (enum bb_state *) xcalloc (max_uid, sizeof (enum bb_state));
01658
01659 basic_block bb;
01660
01661 FOR_EACH_BB_REVERSE (bb)
01662 {
01663 rtx x;
01664
01665 start[INSN_UID (bb->head)] = bb;
01666 end[INSN_UID (bb->end)] = bb;
01667 for (x = bb->head; x != NULL_RTX; x = NEXT_INSN (x))
01668 {
01669 enum bb_state state = IN_MULTIPLE_BB;
01670
01671 if (in_bb_p[INSN_UID (x)] == NOT_IN_BB)
01672 state = IN_ONE_BB;
01673 in_bb_p[INSN_UID (x)] = state;
01674
01675 if (x == bb->end)
01676 break;
01677 }
01678 }
01679
01680 for (tmp_rtx = rtx_first; NULL != tmp_rtx; tmp_rtx = NEXT_INSN (tmp_rtx))
01681 {
01682 int did_output;
01683
01684 if ((bb = start[INSN_UID (tmp_rtx)]) != NULL)
01685 {
01686 fprintf (outf, ";; Start of basic block %d, registers live:",
01687 bb->index);
01688 dump_regset (bb->global_live_at_start, outf);
01689 putc ('\n', outf);
01690 }
01691
01692 if (in_bb_p[INSN_UID (tmp_rtx)] == NOT_IN_BB
01693 && GET_CODE (tmp_rtx) != NOTE
01694 && GET_CODE (tmp_rtx) != BARRIER)
01695 fprintf (outf, ";; Insn is not within a basic block\n");
01696 else if (in_bb_p[INSN_UID (tmp_rtx)] == IN_MULTIPLE_BB)
01697 fprintf (outf, ";; Insn is in multiple basic blocks\n");
01698
01699 did_output = print_rtl_single (outf, tmp_rtx);
01700
01701 if ((bb = end[INSN_UID (tmp_rtx)]) != NULL)
01702 {
01703 fprintf (outf, ";; End of basic block %d, registers live:\n",
01704 bb->index);
01705 dump_regset (bb->global_live_at_end, outf);
01706 putc ('\n', outf);
01707 }
01708
01709 if (did_output)
01710 putc ('\n', outf);
01711 }
01712
01713 free (start);
01714 free (end);
01715 free (in_bb_p);
01716 }
01717
01718 if (current_function_epilogue_delay_list != 0)
01719 {
01720 fprintf (outf, "\n;; Insns in epilogue delay list:\n\n");
01721 for (tmp_rtx = current_function_epilogue_delay_list; tmp_rtx != 0;
01722 tmp_rtx = XEXP (tmp_rtx, 1))
01723 print_rtl_single (outf, XEXP (tmp_rtx, 0));
01724 }
01725 }
01726
01727 void
01728 update_br_prob_note (bb)
01729 basic_block bb;
01730 {
01731 rtx note;
01732 if (GET_CODE (bb->end) != JUMP_INSN)
01733 return;
01734 note = find_reg_note (bb->end, REG_BR_PROB, NULL_RTX);
01735 if (!note || INTVAL (XEXP (note, 0)) == BRANCH_EDGE (bb)->probability)
01736 return;
01737 XEXP (note, 0) = GEN_INT (BRANCH_EDGE (bb)->probability);
01738 }
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760 void
01761 verify_flow_info ()
01762 {
01763 const int max_uid = get_max_uid ();
01764 const rtx rtx_first = get_insns ();
01765 rtx last_head = get_last_insn ();
01766 basic_block *bb_info, *last_visited;
01767 size_t *edge_checksum;
01768 rtx x;
01769 int num_bb_notes, err = 0;
01770 basic_block bb, last_bb_seen;
01771
01772 bb_info = (basic_block *) xcalloc (max_uid, sizeof (basic_block));
01773 last_visited = (basic_block *) xcalloc (last_basic_block + 2,
01774 sizeof (basic_block));
01775 edge_checksum = (size_t *) xcalloc (last_basic_block + 2, sizeof (size_t));
01776
01777
01778 last_bb_seen = ENTRY_BLOCK_PTR;
01779 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb, NULL, next_bb)
01780 {
01781 if (bb != EXIT_BLOCK_PTR
01782 && bb != BASIC_BLOCK (bb->index))
01783 {
01784 error ("bb %d on wrong place", bb->index);
01785 err = 1;
01786 }
01787
01788 if (bb->prev_bb != last_bb_seen)
01789 {
01790 error ("prev_bb of %d should be %d, not %d",
01791 bb->index, last_bb_seen->index, bb->prev_bb->index);
01792 err = 1;
01793 }
01794
01795 last_bb_seen = bb;
01796 }
01797
01798 FOR_EACH_BB_REVERSE (bb)
01799 {
01800 rtx head = bb->head;
01801 rtx end = bb->end;
01802
01803
01804 for (x = last_head; x != NULL_RTX; x = PREV_INSN (x))
01805 if (x == end)
01806 break;
01807
01808 if (!x)
01809 {
01810 error ("end insn %d for block %d not found in the insn stream",
01811 INSN_UID (end), bb->index);
01812 err = 1;
01813 }
01814
01815
01816
01817 for (; x != NULL_RTX; x = PREV_INSN (x))
01818 {
01819
01820
01821
01822 if (bb_info[INSN_UID (x)] != NULL)
01823 {
01824 error ("insn %d is in multiple basic blocks (%d and %d)",
01825 INSN_UID (x), bb->index, bb_info[INSN_UID (x)]->index);
01826 err = 1;
01827 }
01828
01829 bb_info[INSN_UID (x)] = bb;
01830
01831 if (x == head)
01832 break;
01833 }
01834 if (!x)
01835 {
01836 error ("head insn %d for block %d not found in the insn stream",
01837 INSN_UID (head), bb->index);
01838 err = 1;
01839 }
01840
01841 last_head = x;
01842 }
01843
01844
01845 FOR_EACH_BB_REVERSE (bb)
01846 {
01847 int n_fallthru = 0, n_eh = 0, n_call = 0, n_abnormal = 0, n_branch = 0;
01848 edge e;
01849 rtx note;
01850
01851 if (INSN_P (bb->end)
01852 && (note = find_reg_note (bb->end, REG_BR_PROB, NULL_RTX))
01853 && bb->succ && bb->succ->succ_next
01854 && any_condjump_p (bb->end))
01855 {
01856 if (INTVAL (XEXP (note, 0)) != BRANCH_EDGE (bb)->probability)
01857 {
01858 error ("verify_flow_info: REG_BR_PROB does not match cfg %i %i",
01859 INTVAL (XEXP (note, 0)), BRANCH_EDGE (bb)->probability);
01860 err = 1;
01861 }
01862 }
01863 if (bb->count < 0)
01864 {
01865 error ("verify_flow_info: Wrong count of block %i %i",
01866 bb->index, (int)bb->count);
01867 err = 1;
01868 }
01869 if (bb->frequency < 0)
01870 {
01871 error ("verify_flow_info: Wrong frequency of block %i %i",
01872 bb->index, bb->frequency);
01873 err = 1;
01874 }
01875 for (e = bb->succ; e; e = e->succ_next)
01876 {
01877 if (last_visited [e->dest->index + 2] == bb)
01878 {
01879 error ("verify_flow_info: Duplicate edge %i->%i",
01880 e->src->index, e->dest->index);
01881 err = 1;
01882 }
01883 if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
01884 {
01885 error ("verify_flow_info: Wrong probability of edge %i->%i %i",
01886 e->src->index, e->dest->index, e->probability);
01887 err = 1;
01888 }
01889 if (e->count < 0)
01890 {
01891 error ("verify_flow_info: Wrong count of edge %i->%i %i",
01892 e->src->index, e->dest->index, (int)e->count);
01893 err = 1;
01894 }
01895
01896 last_visited [e->dest->index + 2] = bb;
01897
01898 if (e->flags & EDGE_FALLTHRU)
01899 n_fallthru++;
01900
01901 if ((e->flags & ~EDGE_DFS_BACK) == 0)
01902 n_branch++;
01903
01904 if (e->flags & EDGE_ABNORMAL_CALL)
01905 n_call++;
01906
01907 if (e->flags & EDGE_EH)
01908 n_eh++;
01909 else if (e->flags & EDGE_ABNORMAL)
01910 n_abnormal++;
01911
01912 if ((e->flags & EDGE_FALLTHRU)
01913 && e->src != ENTRY_BLOCK_PTR
01914 && e->dest != EXIT_BLOCK_PTR)
01915 {
01916 rtx insn;
01917
01918 if (e->src->next_bb != e->dest)
01919 {
01920 error
01921 ("verify_flow_info: Incorrect blocks for fallthru %i->%i",
01922 e->src->index, e->dest->index);
01923 err = 1;
01924 }
01925 else
01926 for (insn = NEXT_INSN (e->src->end); insn != e->dest->head;
01927 insn = NEXT_INSN (insn))
01928 if (GET_CODE (insn) == BARRIER
01929 #ifndef CASE_DROPS_THROUGH
01930 || INSN_P (insn)
01931 #else
01932 || (INSN_P (insn) && ! JUMP_TABLE_DATA_P (insn))
01933 #endif
01934 )
01935 {
01936 error ("verify_flow_info: Incorrect fallthru %i->%i",
01937 e->src->index, e->dest->index);
01938 fatal_insn ("wrong insn in the fallthru edge", insn);
01939 err = 1;
01940 }
01941 }
01942
01943 if (e->src != bb)
01944 {
01945 error ("verify_flow_info: Basic block %d succ edge is corrupted",
01946 bb->index);
01947 fprintf (stderr, "Predecessor: ");
01948 dump_edge_info (stderr, e, 0);
01949 fprintf (stderr, "\nSuccessor: ");
01950 dump_edge_info (stderr, e, 1);
01951 fprintf (stderr, "\n");
01952 err = 1;
01953 }
01954
01955 edge_checksum[e->dest->index + 2] += (size_t) e;
01956 }
01957
01958 if (n_eh && GET_CODE (PATTERN (bb->end)) != RESX
01959 && !find_reg_note (bb->end, REG_EH_REGION, NULL_RTX))
01960 {
01961 error ("Missing REG_EH_REGION note in the end of bb %i", bb->index);
01962 err = 1;
01963 }
01964 if (n_branch
01965 && (GET_CODE (bb->end) != JUMP_INSN
01966 || (n_branch > 1 && (any_uncondjump_p (bb->end)
01967 || any_condjump_p (bb->end)))))
01968 {
01969 error ("Too many outgoing branch edges from bb %i", bb->index);
01970 err = 1;
01971 }
01972 if (n_fallthru && any_uncondjump_p (bb->end))
01973 {
01974 error ("Fallthru edge after unconditional jump %i", bb->index);
01975 err = 1;
01976 }
01977 if (n_branch != 1 && any_uncondjump_p (bb->end))
01978 {
01979 error ("Wrong amount of branch edges after unconditional jump %i", bb->index);
01980 err = 1;
01981 }
01982 if (n_branch != 1 && any_condjump_p (bb->end)
01983 && JUMP_LABEL (bb->end) != bb->next_bb->head)
01984 {
01985 error ("Wrong amount of branch edges after conditional jump %i", bb->index);
01986 err = 1;
01987 }
01988 if (n_call && GET_CODE (bb->end) != CALL_INSN)
01989 {
01990 error ("Call edges for non-call insn in bb %i", bb->index);
01991 err = 1;
01992 }
01993 if (n_abnormal
01994 && (GET_CODE (bb->end) != CALL_INSN && n_call != n_abnormal)
01995 && (GET_CODE (bb->end) != JUMP_INSN
01996 || any_condjump_p (bb->end)
01997 || any_uncondjump_p (bb->end)))
01998 {
01999 error ("Abnormal edges for no purpose in bb %i", bb->index);
02000 err = 1;
02001 }
02002
02003 if (!n_fallthru)
02004 {
02005 rtx insn;
02006
02007
02008 for (insn = bb->end; !insn || GET_CODE (insn) != BARRIER;
02009 insn = NEXT_INSN (insn))
02010 if (!insn
02011 || (GET_CODE (insn) == NOTE
02012 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK))
02013 {
02014 error ("missing barrier after block %i", bb->index);
02015 err = 1;
02016 break;
02017 }
02018 }
02019
02020 for (e = bb->pred; e; e = e->pred_next)
02021 {
02022 if (e->dest != bb)
02023 {
02024 error ("basic block %d pred edge is corrupted", bb->index);
02025 fputs ("Predecessor: ", stderr);
02026 dump_edge_info (stderr, e, 0);
02027 fputs ("\nSuccessor: ", stderr);
02028 dump_edge_info (stderr, e, 1);
02029 fputc ('\n', stderr);
02030 err = 1;
02031 }
02032 edge_checksum[e->dest->index + 2] -= (size_t) e;
02033 }
02034
02035 for (x = bb->head; x != NEXT_INSN (bb->end); x = NEXT_INSN (x))
02036 if (BLOCK_FOR_INSN (x) != bb)
02037 {
02038 debug_rtx (x);
02039 if (! BLOCK_FOR_INSN (x))
02040 error
02041 ("insn %d inside basic block %d but block_for_insn is NULL",
02042 INSN_UID (x), bb->index);
02043 else
02044 error
02045 ("insn %d inside basic block %d but block_for_insn is %i",
02046 INSN_UID (x), bb->index, BLOCK_FOR_INSN (x)->index);
02047
02048 err = 1;
02049 }
02050
02051
02052
02053
02054 x = bb->head;
02055 if (GET_CODE (x) == CODE_LABEL)
02056 {
02057 if (bb->end == x)
02058 {
02059 error ("NOTE_INSN_BASIC_BLOCK is missing for block %d",
02060 bb->index);
02061 err = 1;
02062 }
02063
02064 x = NEXT_INSN (x);
02065 }
02066
02067 if (!NOTE_INSN_BASIC_BLOCK_P (x) || NOTE_BASIC_BLOCK (x) != bb)
02068 {
02069 error ("NOTE_INSN_BASIC_BLOCK is missing for block %d",
02070 bb->index);
02071 err = 1;
02072 }
02073
02074 if (bb->end == x)
02075
02076 ;
02077 else
02078 for (x = NEXT_INSN (x); x; x = NEXT_INSN (x))
02079 {
02080 if (NOTE_INSN_BASIC_BLOCK_P (x))
02081 {
02082 error ("NOTE_INSN_BASIC_BLOCK %d in middle of basic block %d",
02083 INSN_UID (x), bb->index);
02084 err = 1;
02085 }
02086
02087 if (x == bb->end)
02088 break;
02089
02090 if (GET_CODE (x) == JUMP_INSN
02091 || GET_CODE (x) == CODE_LABEL
02092 || GET_CODE (x) == BARRIER)
02093 {
02094 error ("in basic block %d:", bb->index);
02095 fatal_insn ("flow control insn inside a basic block", x);
02096 }
02097 }
02098 }
02099
02100
02101 {
02102 edge e;
02103
02104 for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next)
02105 edge_checksum[e->dest->index + 2] += (size_t) e;
02106
02107 for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
02108 edge_checksum[e->dest->index + 2] -= (size_t) e;
02109 }
02110
02111 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
02112 if (edge_checksum[bb->index + 2])
02113 {
02114 error ("basic block %i edge lists are corrupted", bb->index);
02115 err = 1;
02116 }
02117
02118 num_bb_notes = 0;
02119 last_bb_seen = ENTRY_BLOCK_PTR;
02120
02121 for (x = rtx_first; x; x = NEXT_INSN (x))
02122 {
02123 if (NOTE_INSN_BASIC_BLOCK_P (x))
02124 {
02125 bb = NOTE_BASIC_BLOCK (x);
02126
02127 num_bb_notes++;
02128 if (bb != last_bb_seen->next_bb)
02129 internal_error ("basic blocks not numbered consecutively");
02130
02131 last_bb_seen = bb;
02132 }
02133
02134 if (!bb_info[INSN_UID (x)])
02135 {
02136 switch (GET_CODE (x))
02137 {
02138 case BARRIER:
02139 case NOTE:
02140 break;
02141
02142 case CODE_LABEL:
02143
02144 if (NEXT_INSN (x)
02145 && GET_CODE (NEXT_INSN (x)) == JUMP_INSN
02146 && (GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_DIFF_VEC
02147 || GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_VEC))
02148 x = NEXT_INSN (x);
02149
02150
02151 break;
02152
02153 default:
02154 fatal_insn ("insn outside basic block", x);
02155 }
02156 }
02157
02158 if (INSN_P (x)
02159 && GET_CODE (x) == JUMP_INSN
02160 && returnjump_p (x) && ! condjump_p (x)
02161 && ! (NEXT_INSN (x) && GET_CODE (NEXT_INSN (x)) == BARRIER))
02162 fatal_insn ("return not followed by barrier", x);
02163 }
02164
02165 if (num_bb_notes != n_basic_blocks)
02166 internal_error
02167 ("number of bb notes in insn chain (%d) != n_basic_blocks (%d)",
02168 num_bb_notes, n_basic_blocks);
02169
02170 if (err)
02171 internal_error ("verify_flow_info failed");
02172
02173
02174 free (bb_info);
02175 free (last_visited);
02176 free (edge_checksum);
02177 }
02178
02179
02180
02181
02182
02183 bool
02184 purge_dead_edges (bb)
02185 basic_block bb;
02186 {
02187 edge e, next;
02188 rtx insn = bb->end, note;
02189 bool purged = false;
02190
02191
02192 if (GET_CODE (insn) == INSN
02193 && (note = find_reg_note (insn, REG_EH_REGION, NULL)))
02194 {
02195 rtx eqnote;
02196
02197 if (! may_trap_p (PATTERN (insn))
02198 || ((eqnote = find_reg_equal_equiv_note (insn))
02199 && ! may_trap_p (XEXP (eqnote, 0))))
02200 remove_note (insn, note);
02201 }
02202
02203
02204 for (e = bb->succ; e; e = next)
02205 {
02206 next = e->succ_next;
02207 if (e->flags & EDGE_EH)
02208 {
02209 if (can_throw_internal (bb->end))
02210 continue;
02211 }
02212 else if (e->flags & EDGE_ABNORMAL_CALL)
02213 {
02214 if (GET_CODE (bb->end) == CALL_INSN
02215 && (! (note = find_reg_note (insn, REG_EH_REGION, NULL))
02216 || INTVAL (XEXP (note, 0)) >= 0))
02217 continue;
02218 }
02219 else
02220 continue;
02221
02222 remove_edge (e);
02223 bb->flags |= BB_DIRTY;
02224 purged = true;
02225 }
02226
02227 if (GET_CODE (insn) == JUMP_INSN)
02228 {
02229 rtx note;
02230 edge b,f;
02231
02232
02233 if (!any_condjump_p (insn)
02234 && !returnjump_p (insn)
02235 && !simplejump_p (insn))
02236 return purged;
02237
02238
02239
02240 if (simplejump_p (insn))
02241 {
02242 note = find_reg_note (insn, REG_BR_PROB, NULL);
02243 if (note)
02244 remove_note (insn, note);
02245 while ((note = find_reg_note (insn, REG_BR_PRED, NULL)))
02246 remove_note (insn, note);
02247 }
02248
02249 for (e = bb->succ; e; e = next)
02250 {
02251 next = e->succ_next;
02252
02253
02254
02255
02256 e->flags &= ~EDGE_ABNORMAL;
02257
02258
02259 if ((e->flags & EDGE_FALLTHRU) && any_condjump_p (insn))
02260
02261
02262 continue;
02263 else if (e->dest != EXIT_BLOCK_PTR
02264 && e->dest->head == JUMP_LABEL (insn))
02265
02266
02267 continue;
02268 else if (e->dest == EXIT_BLOCK_PTR && returnjump_p (insn))
02269
02270
02271 continue;
02272 else if ((e->flags & EDGE_EH) && can_throw_internal (insn))
02273
02274
02275 continue;
02276
02277
02278 bb->flags |= BB_DIRTY;
02279 purged = true;
02280 remove_edge (e);
02281 }
02282
02283 if (!bb->succ || !purged)
02284 return purged;
02285
02286 if (rtl_dump_file)
02287 fprintf (rtl_dump_file, "Purged edges from bb %i\n", bb->index);
02288
02289 if (!optimize)
02290 return purged;
02291
02292
02293 if (!bb->succ->succ_next)
02294 {
02295 bb->succ->probability = REG_BR_PROB_BASE;
02296 bb->succ->count = bb->count;
02297 }
02298 else
02299 {
02300 note = find_reg_note (insn, REG_BR_PROB, NULL);
02301 if (!note)
02302 return purged;
02303
02304 b = BRANCH_EDGE (bb);
02305 f = FALLTHRU_EDGE (bb);
02306 b->probability = INTVAL (XEXP (note, 0));
02307 f->probability = REG_BR_PROB_BASE - b->probability;
02308 b->count = bb->count * b->probability / REG_BR_PROB_BASE;
02309 f->count = bb->count * f->probability / REG_BR_PROB_BASE;
02310 }
02311
02312 return purged;
02313 }
02314
02315
02316
02317
02318
02319
02320 for (e = bb->succ; e && (e->flags & (EDGE_COMPLEX | EDGE_FALLTHRU));
02321 e = e->succ_next)
02322 ;
02323
02324 if (!e)
02325 return purged;
02326
02327 for (e = bb->succ; e; e = next)
02328 {
02329 next = e->succ_next;
02330 if (!(e->flags & EDGE_FALLTHRU))
02331 {
02332 bb->flags |= BB_DIRTY;
02333 remove_edge (e);
02334 purged = true;
02335 }
02336 }
02337
02338 if (!bb->succ || bb->succ->succ_next)
02339 abort ();
02340
02341 bb->succ->probability = REG_BR_PROB_BASE;
02342 bb->succ->count = bb->count;
02343
02344 if (rtl_dump_file)
02345 fprintf (rtl_dump_file, "Purged non-fallthru edges from bb %i\n",
02346 bb->index);
02347 return purged;
02348 }
02349
02350
02351
02352
02353 bool
02354 purge_all_dead_edges (update_life_p)
02355 int update_life_p;
02356 {
02357 int purged = false;
02358 sbitmap blocks = 0;
02359 basic_block bb;
02360
02361 if (update_life_p)
02362 {
02363 blocks = sbitmap_alloc (last_basic_block);
02364 sbitmap_zero (blocks);
02365 }
02366
02367 FOR_EACH_BB (bb)
02368 {
02369 bool purged_here = purge_dead_edges (bb);
02370
02371 purged |= purged_here;
02372 if (purged_here && update_life_p)
02373 SET_BIT (blocks, bb->index);
02374 }
02375
02376 if (update_life_p && purged)
02377 update_life_info (blocks, UPDATE_LIFE_GLOBAL,
02378 PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
02379 | PROP_KILL_DEAD_CODE);
02380
02381 if (update_life_p)
02382 sbitmap_free (blocks);
02383 return purged;
02384 }