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 #include "config.h"
00035 #include "system.h"
00036 #include "coretypes.h"
00037 #include "tm.h"
00038 #include "rtl.h"
00039 #include "hard-reg-set.h"
00040 #include "regs.h"
00041 #include "timevar.h"
00042 #include "output.h"
00043 #include "insn-config.h"
00044 #include "flags.h"
00045 #include "recog.h"
00046 #include "toplev.h"
00047 #include "cselib.h"
00048 #include "params.h"
00049 #include "tm_p.h"
00050 #include "target.h"
00051 #include "cfglayout.h"
00052 #include "emit-rtl.h"
00053
00054
00055
00056 enum bb_flags
00057 {
00058
00059
00060 BB_FORWARDER_BLOCK = 1,
00061 BB_NONTHREADABLE_BLOCK = 2
00062 };
00063
00064 #define BB_FLAGS(BB) (enum bb_flags) (BB)->aux
00065 #define BB_SET_FLAG(BB, FLAG) \
00066 (BB)->aux = (void *) (long) ((enum bb_flags) (BB)->aux | (FLAG))
00067 #define BB_CLEAR_FLAG(BB, FLAG) \
00068 (BB)->aux = (void *) (long) ((enum bb_flags) (BB)->aux & ~(FLAG))
00069
00070 #define FORWARDER_BLOCK_P(BB) (BB_FLAGS (BB) & BB_FORWARDER_BLOCK)
00071
00072
00073 static bool first_pass;
00074 static bool try_crossjump_to_edge (int, edge, edge);
00075 static bool try_crossjump_bb (int, basic_block);
00076 static bool outgoing_edges_match (int, basic_block, basic_block);
00077 static int flow_find_cross_jump (int, basic_block, basic_block, rtx *, rtx *);
00078 static bool insns_match_p (int, rtx, rtx);
00079
00080 static void merge_blocks_move_predecessor_nojumps (basic_block, basic_block);
00081 static void merge_blocks_move_successor_nojumps (basic_block, basic_block);
00082 static bool try_optimize_cfg (int);
00083 static bool try_simplify_condjump (basic_block);
00084 static bool try_forward_edges (int, basic_block);
00085 static edge thread_jump (int, edge, basic_block);
00086 static bool mark_effect (rtx, bitmap);
00087 static void notice_new_block (basic_block);
00088 static void update_forwarder_flag (basic_block);
00089 static int mentions_nonequal_regs (rtx *, void *);
00090 static void merge_memattrs (rtx, rtx);
00091
00092
00093
00094 static void
00095 notice_new_block (basic_block bb)
00096 {
00097 if (!bb)
00098 return;
00099
00100 if (forwarder_block_p (bb))
00101 BB_SET_FLAG (bb, BB_FORWARDER_BLOCK);
00102 }
00103
00104
00105
00106 static void
00107 update_forwarder_flag (basic_block bb)
00108 {
00109 if (forwarder_block_p (bb))
00110 BB_SET_FLAG (bb, BB_FORWARDER_BLOCK);
00111 else
00112 BB_CLEAR_FLAG (bb, BB_FORWARDER_BLOCK);
00113 }
00114
00115
00116
00117
00118 static bool
00119 try_simplify_condjump (basic_block cbranch_block)
00120 {
00121 basic_block jump_block, jump_dest_block, cbranch_dest_block;
00122 edge cbranch_jump_edge, cbranch_fallthru_edge;
00123 rtx cbranch_insn;
00124
00125
00126 if (EDGE_COUNT (cbranch_block->succs) != 2)
00127 return false;
00128
00129
00130
00131 cbranch_insn = BB_END (cbranch_block);
00132 if (!any_condjump_p (cbranch_insn))
00133 return false;
00134
00135 cbranch_fallthru_edge = FALLTHRU_EDGE (cbranch_block);
00136 cbranch_jump_edge = BRANCH_EDGE (cbranch_block);
00137
00138
00139
00140
00141 jump_block = cbranch_fallthru_edge->dest;
00142 if (EDGE_COUNT (jump_block->preds) >= 2
00143 || jump_block->next_bb == EXIT_BLOCK_PTR
00144 || !FORWARDER_BLOCK_P (jump_block))
00145 return false;
00146 jump_dest_block = EDGE_SUCC (jump_block, 0)->dest;
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 if (flag_reorder_blocks_and_partition
00159 && (BB_PARTITION (jump_block) != BB_PARTITION (jump_dest_block)
00160 || (cbranch_jump_edge->flags & EDGE_CROSSING)))
00161 return false;
00162
00163
00164
00165 cbranch_dest_block = cbranch_jump_edge->dest;
00166
00167 if (cbranch_dest_block == EXIT_BLOCK_PTR
00168 || !can_fallthru (jump_block, cbranch_dest_block))
00169 return false;
00170
00171
00172 if (!invert_jump (cbranch_insn, block_label (jump_dest_block), 0))
00173 return false;
00174
00175 if (dump_file)
00176 fprintf (dump_file, "Simplifying condjump %i around jump %i\n",
00177 INSN_UID (cbranch_insn), INSN_UID (BB_END (jump_block)));
00178
00179
00180
00181
00182 cbranch_jump_edge = redirect_edge_succ_nodup (cbranch_jump_edge,
00183 cbranch_dest_block);
00184 cbranch_fallthru_edge = redirect_edge_succ_nodup (cbranch_fallthru_edge,
00185 jump_dest_block);
00186 cbranch_jump_edge->flags |= EDGE_FALLTHRU;
00187 cbranch_fallthru_edge->flags &= ~EDGE_FALLTHRU;
00188 update_br_prob_note (cbranch_block);
00189
00190
00191 delete_basic_block (jump_block);
00192 tidy_fallthru_edge (cbranch_jump_edge);
00193 update_forwarder_flag (cbranch_block);
00194
00195 return true;
00196 }
00197
00198
00199
00200
00201 static bool
00202 mark_effect (rtx exp, regset nonequal)
00203 {
00204 int regno;
00205 rtx dest;
00206 switch (GET_CODE (exp))
00207 {
00208
00209
00210 case CLOBBER:
00211 if (REG_P (XEXP (exp, 0)))
00212 {
00213 dest = XEXP (exp, 0);
00214 regno = REGNO (dest);
00215 CLEAR_REGNO_REG_SET (nonequal, regno);
00216 if (regno < FIRST_PSEUDO_REGISTER)
00217 {
00218 int n = hard_regno_nregs[regno][GET_MODE (dest)];
00219 while (--n > 0)
00220 CLEAR_REGNO_REG_SET (nonequal, regno + n);
00221 }
00222 }
00223 return false;
00224
00225 case SET:
00226 if (rtx_equal_for_cselib_p (SET_DEST (exp), SET_SRC (exp)))
00227 return false;
00228 dest = SET_DEST (exp);
00229 if (dest == pc_rtx)
00230 return false;
00231 if (!REG_P (dest))
00232 return true;
00233 regno = REGNO (dest);
00234 SET_REGNO_REG_SET (nonequal, regno);
00235 if (regno < FIRST_PSEUDO_REGISTER)
00236 {
00237 int n = hard_regno_nregs[regno][GET_MODE (dest)];
00238 while (--n > 0)
00239 SET_REGNO_REG_SET (nonequal, regno + n);
00240 }
00241 return false;
00242
00243 default:
00244 return false;
00245 }
00246 }
00247
00248
00249
00250 static int
00251 mentions_nonequal_regs (rtx *x, void *data)
00252 {
00253 regset nonequal = (regset) data;
00254 if (REG_P (*x))
00255 {
00256 int regno;
00257
00258 regno = REGNO (*x);
00259 if (REGNO_REG_SET_P (nonequal, regno))
00260 return 1;
00261 if (regno < FIRST_PSEUDO_REGISTER)
00262 {
00263 int n = hard_regno_nregs[regno][GET_MODE (*x)];
00264 while (--n > 0)
00265 if (REGNO_REG_SET_P (nonequal, regno + n))
00266 return 1;
00267 }
00268 }
00269 return 0;
00270 }
00271
00272
00273
00274
00275 static edge
00276 thread_jump (int mode, edge e, basic_block b)
00277 {
00278 rtx set1, set2, cond1, cond2, insn;
00279 enum rtx_code code1, code2, reversed_code2;
00280 bool reverse1 = false;
00281 unsigned i;
00282 regset nonequal;
00283 bool failed = false;
00284 reg_set_iterator rsi;
00285
00286 if (BB_FLAGS (b) & BB_NONTHREADABLE_BLOCK)
00287 return NULL;
00288
00289
00290
00291 if (EDGE_COUNT (e->src->succs) != 2)
00292 return NULL;
00293 if (EDGE_COUNT (b->succs) != 2)
00294 {
00295 BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
00296 return NULL;
00297 }
00298
00299
00300 if (!any_condjump_p (BB_END (e->src)))
00301 return NULL;
00302
00303 if (!any_condjump_p (BB_END (b)) || !onlyjump_p (BB_END (b)))
00304 {
00305 BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
00306 return NULL;
00307 }
00308
00309 set1 = pc_set (BB_END (e->src));
00310 set2 = pc_set (BB_END (b));
00311 if (((e->flags & EDGE_FALLTHRU) != 0)
00312 != (XEXP (SET_SRC (set1), 1) == pc_rtx))
00313 reverse1 = true;
00314
00315 cond1 = XEXP (SET_SRC (set1), 0);
00316 cond2 = XEXP (SET_SRC (set2), 0);
00317 if (reverse1)
00318 code1 = reversed_comparison_code (cond1, BB_END (e->src));
00319 else
00320 code1 = GET_CODE (cond1);
00321
00322 code2 = GET_CODE (cond2);
00323 reversed_code2 = reversed_comparison_code (cond2, BB_END (b));
00324
00325 if (!comparison_dominates_p (code1, code2)
00326 && !comparison_dominates_p (code1, reversed_code2))
00327 return NULL;
00328
00329
00330
00331
00332
00333 if (!rtx_equal_p (XEXP (cond1, 0), XEXP (cond2, 0))
00334 || !rtx_equal_p (XEXP (cond1, 1), XEXP (cond2, 1)))
00335 return NULL;
00336
00337
00338
00339 for (insn = NEXT_INSN (BB_HEAD (b)); insn != NEXT_INSN (BB_END (b));
00340 insn = NEXT_INSN (insn))
00341 if (INSN_P (insn) && side_effects_p (PATTERN (insn)))
00342 {
00343 BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
00344 return NULL;
00345 }
00346
00347 cselib_init (false);
00348
00349
00350 for (insn = NEXT_INSN (BB_HEAD (e->src));
00351 insn != NEXT_INSN (BB_END (e->src));
00352 insn = NEXT_INSN (insn))
00353 if (INSN_P (insn))
00354 cselib_process_insn (insn);
00355
00356 nonequal = BITMAP_ALLOC (NULL);
00357 CLEAR_REG_SET (nonequal);
00358
00359
00360
00361
00362
00363 for (insn = NEXT_INSN (BB_HEAD (b));
00364 insn != NEXT_INSN (BB_END (b)) && !failed;
00365 insn = NEXT_INSN (insn))
00366 {
00367 if (INSN_P (insn))
00368 {
00369 rtx pat = PATTERN (insn);
00370
00371 if (GET_CODE (pat) == PARALLEL)
00372 {
00373 for (i = 0; i < (unsigned)XVECLEN (pat, 0); i++)
00374 failed |= mark_effect (XVECEXP (pat, 0, i), nonequal);
00375 }
00376 else
00377 failed |= mark_effect (pat, nonequal);
00378 }
00379
00380 cselib_process_insn (insn);
00381 }
00382
00383
00384
00385 if (failed)
00386 {
00387 BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
00388 goto failed_exit;
00389 }
00390
00391
00392
00393 if (for_each_rtx (&cond2, mentions_nonequal_regs, nonequal))
00394 goto failed_exit;
00395
00396
00397
00398 if (mode & CLEANUP_UPDATE_LIFE)
00399 AND_REG_SET (nonequal, b->global_live_at_end);
00400
00401 EXECUTE_IF_SET_IN_REG_SET (nonequal, 0, i, rsi)
00402 goto failed_exit;
00403
00404 BITMAP_FREE (nonequal);
00405 cselib_finish ();
00406 if ((comparison_dominates_p (code1, code2) != 0)
00407 != (XEXP (SET_SRC (set2), 1) == pc_rtx))
00408 return BRANCH_EDGE (b);
00409 else
00410 return FALLTHRU_EDGE (b);
00411
00412 failed_exit:
00413 BITMAP_FREE (nonequal);
00414 cselib_finish ();
00415 return NULL;
00416 }
00417
00418
00419
00420
00421 static bool
00422 try_forward_edges (int mode, basic_block b)
00423 {
00424 bool changed = false;
00425 edge_iterator ei;
00426 edge e, *threaded_edges = NULL;
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 if (flag_reorder_blocks_and_partition
00439 && find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX))
00440 return false;
00441
00442 for (ei = ei_start (b->succs); (e = ei_safe_edge (ei)); )
00443 {
00444 basic_block target, first;
00445 int counter;
00446 bool threaded = false;
00447 int nthreaded_edges = 0;
00448 bool may_thread = first_pass | (b->flags & BB_DIRTY);
00449
00450
00451
00452
00453
00454
00455 if (e->flags & EDGE_COMPLEX)
00456 {
00457 ei_next (&ei);
00458 continue;
00459 }
00460
00461 target = first = e->dest;
00462 counter = 0;
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 if (flag_reorder_blocks_and_partition
00475 && first != EXIT_BLOCK_PTR
00476 && find_reg_note (BB_END (first), REG_CROSSING_JUMP, NULL_RTX))
00477 return false;
00478
00479 while (counter < n_basic_blocks)
00480 {
00481 basic_block new_target = NULL;
00482 bool new_target_threaded = false;
00483 may_thread |= target->flags & BB_DIRTY;
00484
00485 if (FORWARDER_BLOCK_P (target)
00486 && !(EDGE_SUCC (target, 0)->flags & EDGE_CROSSING)
00487 && EDGE_SUCC (target, 0)->dest != EXIT_BLOCK_PTR)
00488 {
00489
00490 if (target == EDGE_SUCC (target, 0)->dest)
00491 counter = n_basic_blocks;
00492 new_target = EDGE_SUCC (target, 0)->dest;
00493 }
00494
00495
00496
00497 else if ((mode & CLEANUP_THREADING) && may_thread)
00498 {
00499 edge t = thread_jump (mode, e, target);
00500 if (t)
00501 {
00502 if (!threaded_edges)
00503 threaded_edges = xmalloc (sizeof (*threaded_edges)
00504 * n_basic_blocks);
00505 else
00506 {
00507 int i;
00508
00509
00510
00511 for (i = 0; i < nthreaded_edges; ++i)
00512 if (threaded_edges[i] == t)
00513 break;
00514 if (i < nthreaded_edges)
00515 {
00516 counter = n_basic_blocks;
00517 break;
00518 }
00519 }
00520
00521
00522 if (t->dest == b)
00523 break;
00524
00525 gcc_assert (nthreaded_edges < n_basic_blocks);
00526 threaded_edges[nthreaded_edges++] = t;
00527
00528 new_target = t->dest;
00529 new_target_threaded = true;
00530 }
00531 }
00532
00533 if (!new_target)
00534 break;
00535
00536
00537
00538
00539
00540
00541
00542 if ((mode & CLEANUP_PRE_LOOP) && optimize)
00543 {
00544 rtx insn = (EDGE_SUCC (target, 0)->flags & EDGE_FALLTHRU
00545 ? BB_HEAD (target) : prev_nonnote_insn (BB_END (target)));
00546
00547 if (!NOTE_P (insn))
00548 insn = NEXT_INSN (insn);
00549
00550 for (; insn && !LABEL_P (insn) && !INSN_P (insn);
00551 insn = NEXT_INSN (insn))
00552 if (NOTE_P (insn)
00553 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
00554 break;
00555
00556 if (insn && NOTE_P (insn))
00557 break;
00558
00559
00560
00561
00562
00563 insn = PREV_INSN (BB_HEAD (target));
00564 if (insn && NOTE_P (insn)
00565 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
00566 break;
00567 }
00568
00569 counter++;
00570 target = new_target;
00571 threaded |= new_target_threaded;
00572 }
00573
00574 if (counter >= n_basic_blocks)
00575 {
00576 if (dump_file)
00577 fprintf (dump_file, "Infinite loop in BB %i.\n",
00578 target->index);
00579 }
00580 else if (target == first)
00581 ;
00582 else
00583 {
00584
00585 gcov_type edge_count = e->count;
00586 int edge_probability = e->probability;
00587 int edge_frequency;
00588 int n = 0;
00589
00590
00591 if (threaded && target != EXIT_BLOCK_PTR)
00592 {
00593 notice_new_block (redirect_edge_and_branch_force (e, target));
00594 if (dump_file)
00595 fprintf (dump_file, "Conditionals threaded.\n");
00596 }
00597 else if (!redirect_edge_and_branch (e, target))
00598 {
00599 if (dump_file)
00600 fprintf (dump_file,
00601 "Forwarding edge %i->%i to %i failed.\n",
00602 b->index, e->dest->index, target->index);
00603 ei_next (&ei);
00604 continue;
00605 }
00606
00607
00608
00609
00610 edge_frequency = ((edge_probability * b->frequency
00611 + REG_BR_PROB_BASE / 2)
00612 / REG_BR_PROB_BASE);
00613
00614 if (!FORWARDER_BLOCK_P (b) && forwarder_block_p (b))
00615 BB_SET_FLAG (b, BB_FORWARDER_BLOCK);
00616
00617 do
00618 {
00619 edge t;
00620
00621 if (EDGE_COUNT (first->succs) > 1)
00622 {
00623 gcc_assert (n < nthreaded_edges);
00624 t = threaded_edges [n++];
00625 gcc_assert (t->src == first);
00626 update_bb_profile_for_threading (first, edge_frequency,
00627 edge_count, t);
00628 update_br_prob_note (first);
00629 }
00630 else
00631 {
00632 first->count -= edge_count;
00633 if (first->count < 0)
00634 first->count = 0;
00635 first->frequency -= edge_frequency;
00636 if (first->frequency < 0)
00637 first->frequency = 0;
00638
00639
00640
00641
00642 if (n < nthreaded_edges
00643 && first == threaded_edges [n]->src)
00644 n++;
00645 t = EDGE_SUCC (first, 0);
00646 }
00647
00648 t->count -= edge_count;
00649 if (t->count < 0)
00650 t->count = 0;
00651 first = t->dest;
00652 }
00653 while (first != target);
00654
00655 changed = true;
00656 continue;
00657 }
00658 ei_next (&ei);
00659 }
00660
00661 if (threaded_edges)
00662 free (threaded_edges);
00663 return changed;
00664 }
00665
00666
00667
00668
00669
00670
00671 static void
00672 merge_blocks_move_predecessor_nojumps (basic_block a, basic_block b)
00673 {
00674 rtx barrier;
00675 bool only_notes;
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 if (flag_reorder_blocks_and_partition
00688 && (BB_PARTITION (a) != BB_PARTITION (b)
00689 || find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)))
00690 return;
00691
00692 barrier = next_nonnote_insn (BB_END (a));
00693 gcc_assert (BARRIER_P (barrier));
00694 delete_insn (barrier);
00695
00696
00697
00698
00699
00700
00701
00702
00703 only_notes = squeeze_notes (&BB_HEAD (a), &BB_END (a));
00704 gcc_assert (!only_notes);
00705
00706
00707 if (BB_END (a) != PREV_INSN (BB_HEAD (b)))
00708 reorder_insns_nobb (BB_HEAD (a), BB_END (a), PREV_INSN (BB_HEAD (b)));
00709 a->flags |= BB_DIRTY;
00710
00711 if (dump_file)
00712 fprintf (dump_file, "Moved block %d before %d and merged.\n",
00713 a->index, b->index);
00714
00715
00716
00717 unlink_block (a);
00718 link_block (a, b->prev_bb);
00719
00720
00721 merge_blocks (a, b);
00722 }
00723
00724
00725
00726
00727
00728 static void
00729 merge_blocks_move_successor_nojumps (basic_block a, basic_block b)
00730 {
00731 rtx barrier, real_b_end;
00732 rtx label, table;
00733 bool only_notes;
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745 if (flag_reorder_blocks_and_partition
00746 && (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)
00747 || BB_PARTITION (a) != BB_PARTITION (b)))
00748 return;
00749
00750 real_b_end = BB_END (b);
00751
00752
00753
00754 if (tablejump_p (BB_END (b), &label, &table)
00755 && prev_active_insn (label) == BB_END (b))
00756 {
00757 BB_END (b) = table;
00758 }
00759
00760
00761 barrier = NEXT_INSN (BB_END (b));
00762 if (barrier && BARRIER_P (barrier))
00763 delete_insn (barrier);
00764
00765
00766
00767
00768
00769
00770
00771
00772 only_notes = squeeze_notes (&BB_HEAD (b), &BB_END (b));
00773 gcc_assert (!only_notes);
00774
00775
00776
00777 reorder_insns_nobb (BB_HEAD (b), BB_END (b), BB_END (a));
00778
00779
00780 BB_END (b) = real_b_end;
00781
00782 if (dump_file)
00783 fprintf (dump_file, "Moved block %d after %d and merged.\n",
00784 b->index, a->index);
00785
00786
00787 merge_blocks (a, b);
00788 }
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802 static basic_block
00803 merge_blocks_move (edge e, basic_block b, basic_block c, int mode)
00804 {
00805 basic_block next;
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817 if (flag_reorder_blocks_and_partition
00818 && (find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
00819 || find_reg_note (BB_END (c), REG_CROSSING_JUMP, NULL_RTX)
00820 || BB_PARTITION (b) != BB_PARTITION (c)))
00821 return NULL;
00822
00823
00824
00825
00826 if (e->flags & EDGE_FALLTHRU)
00827 {
00828 int b_index = b->index, c_index = c->index;
00829 merge_blocks (b, c);
00830 update_forwarder_flag (b);
00831
00832 if (dump_file)
00833 fprintf (dump_file, "Merged %d and %d without moving.\n",
00834 b_index, c_index);
00835
00836 return b->prev_bb == ENTRY_BLOCK_PTR ? b : b->prev_bb;
00837 }
00838
00839
00840
00841 else if (mode & CLEANUP_EXPENSIVE)
00842 {
00843 edge tmp_edge, b_fallthru_edge;
00844 bool c_has_outgoing_fallthru;
00845 bool b_has_incoming_fallthru;
00846 edge_iterator ei;
00847
00848
00849
00850
00851
00852 if (FORWARDER_BLOCK_P (b) || FORWARDER_BLOCK_P (c))
00853 return NULL;
00854
00855
00856
00857
00858
00859 FOR_EACH_EDGE (tmp_edge, ei, c->succs)
00860 if (tmp_edge->flags & EDGE_FALLTHRU)
00861 break;
00862
00863 c_has_outgoing_fallthru = (tmp_edge != NULL);
00864
00865 FOR_EACH_EDGE (tmp_edge, ei, b->preds)
00866 if (tmp_edge->flags & EDGE_FALLTHRU)
00867 break;
00868
00869 b_has_incoming_fallthru = (tmp_edge != NULL);
00870 b_fallthru_edge = tmp_edge;
00871 next = b->prev_bb;
00872 if (next == c)
00873 next = next->prev_bb;
00874
00875
00876
00877
00878 if (! c_has_outgoing_fallthru)
00879 {
00880 merge_blocks_move_successor_nojumps (b, c);
00881 return next == ENTRY_BLOCK_PTR ? next->next_bb : next;
00882 }
00883
00884
00885
00886
00887
00888
00889 if (b_has_incoming_fallthru)
00890 {
00891 basic_block bb;
00892
00893 if (b_fallthru_edge->src == ENTRY_BLOCK_PTR)
00894 return NULL;
00895 bb = force_nonfallthru (b_fallthru_edge);
00896 if (bb)
00897 notice_new_block (bb);
00898 }
00899
00900 merge_blocks_move_predecessor_nojumps (b, c);
00901 return next == ENTRY_BLOCK_PTR ? next->next_bb : next;
00902 }
00903
00904 return NULL;
00905 }
00906
00907
00908
00909
00910
00911 void
00912 merge_memattrs (rtx x, rtx y)
00913 {
00914 int i;
00915 int j;
00916 enum rtx_code code;
00917 const char *fmt;
00918
00919 if (x == y)
00920 return;
00921 if (x == 0 || y == 0)
00922 return;
00923
00924 code = GET_CODE (x);
00925
00926 if (code != GET_CODE (y))
00927 return;
00928
00929 if (GET_MODE (x) != GET_MODE (y))
00930 return;
00931
00932 if (code == MEM && MEM_ATTRS (x) != MEM_ATTRS (y))
00933 {
00934 if (! MEM_ATTRS (x))
00935 MEM_ATTRS (y) = 0;
00936 else if (! MEM_ATTRS (y))
00937 MEM_ATTRS (x) = 0;
00938 else
00939 {
00940 rtx mem_size;
00941
00942 if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y))
00943 {
00944 set_mem_alias_set (x, 0);
00945 set_mem_alias_set (y, 0);
00946 }
00947
00948 if (! mem_expr_equal_p (MEM_EXPR (x), MEM_EXPR (y)))
00949 {
00950 set_mem_expr (x, 0);
00951 set_mem_expr (y, 0);
00952 set_mem_offset (x, 0);
00953 set_mem_offset (y, 0);
00954 }
00955 else if (MEM_OFFSET (x) != MEM_OFFSET (y))
00956 {
00957 set_mem_offset (x, 0);
00958 set_mem_offset (y, 0);
00959 }
00960
00961 if (!MEM_SIZE (x))
00962 mem_size = NULL_RTX;
00963 else if (!MEM_SIZE (y))
00964 mem_size = NULL_RTX;
00965 else
00966 mem_size = GEN_INT (MAX (INTVAL (MEM_SIZE (x)),
00967 INTVAL (MEM_SIZE (y))));
00968 set_mem_size (x, mem_size);
00969 set_mem_size (y, mem_size);
00970
00971 set_mem_align (x, MIN (MEM_ALIGN (x), MEM_ALIGN (y)));
00972 set_mem_align (y, MEM_ALIGN (x));
00973 }
00974 }
00975
00976 fmt = GET_RTX_FORMAT (code);
00977 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00978 {
00979 switch (fmt[i])
00980 {
00981 case 'E':
00982
00983 if (XVECLEN (x, i) != XVECLEN (y, i))
00984 return;
00985
00986 for (j = 0; j < XVECLEN (x, i); j++)
00987 merge_memattrs (XVECEXP (x, i, j), XVECEXP (y, i, j));
00988
00989 break;
00990
00991 case 'e':
00992 merge_memattrs (XEXP (x, i), XEXP (y, i));
00993 }
00994 }
00995 return;
00996 }
00997
00998
00999
01000
01001 static bool
01002 insns_match_p (int mode ATTRIBUTE_UNUSED, rtx i1, rtx i2)
01003 {
01004 rtx p1, p2;
01005
01006
01007 if (GET_CODE (i1) != GET_CODE (i2))
01008 return false;
01009
01010 p1 = PATTERN (i1);
01011 p2 = PATTERN (i2);
01012
01013 if (GET_CODE (p1) != GET_CODE (p2))
01014 return false;
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026 if (CALL_P (i1)
01027 && (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1),
01028 CALL_INSN_FUNCTION_USAGE (i2))
01029 || SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2)))
01030 return false;
01031
01032 #ifdef STACK_REGS
01033
01034
01035
01036
01037 if ((mode & CLEANUP_POST_REGSTACK) && stack_regs_mentioned (i1))
01038 {
01039
01040
01041
01042
01043 rtx note;
01044 HARD_REG_SET i1_regset, i2_regset;
01045
01046 CLEAR_HARD_REG_SET (i1_regset);
01047 CLEAR_HARD_REG_SET (i2_regset);
01048
01049 for (note = REG_NOTES (i1); note; note = XEXP (note, 1))
01050 if (REG_NOTE_KIND (note) == REG_DEAD && STACK_REG_P (XEXP (note, 0)))
01051 SET_HARD_REG_BIT (i1_regset, REGNO (XEXP (note, 0)));
01052
01053 for (note = REG_NOTES (i2); note; note = XEXP (note, 1))
01054 if (REG_NOTE_KIND (note) == REG_DEAD && STACK_REG_P (XEXP (note, 0)))
01055 SET_HARD_REG_BIT (i2_regset, REGNO (XEXP (note, 0)));
01056
01057 GO_IF_HARD_REG_EQUAL (i1_regset, i2_regset, done);
01058
01059 return false;
01060
01061 done:
01062 ;
01063 }
01064 #endif
01065
01066 if (reload_completed
01067 ? rtx_renumbered_equal_p (p1, p2) : rtx_equal_p (p1, p2))
01068 return true;
01069
01070
01071
01072
01073
01074
01075 if (!reload_completed)
01076 {
01077
01078 rtx equiv1 = find_reg_equal_equiv_note (i1);
01079 rtx equiv2 = find_reg_equal_equiv_note (i2);
01080
01081 if (equiv1 && equiv2
01082
01083
01084
01085 && (! reload_completed
01086 || (CONSTANT_P (XEXP (equiv1, 0))
01087 && rtx_equal_p (XEXP (equiv1, 0), XEXP (equiv2, 0)))))
01088 {
01089 rtx s1 = single_set (i1);
01090 rtx s2 = single_set (i2);
01091 if (s1 != 0 && s2 != 0
01092 && rtx_renumbered_equal_p (SET_DEST (s1), SET_DEST (s2)))
01093 {
01094 validate_change (i1, &SET_SRC (s1), XEXP (equiv1, 0), 1);
01095 validate_change (i2, &SET_SRC (s2), XEXP (equiv2, 0), 1);
01096 if (! rtx_renumbered_equal_p (p1, p2))
01097 cancel_changes (0);
01098 else if (apply_change_group ())
01099 return true;
01100 }
01101 }
01102 }
01103
01104 return false;
01105 }
01106
01107
01108
01109
01110
01111
01112
01113
01114 static int
01115 flow_find_cross_jump (int mode ATTRIBUTE_UNUSED, basic_block bb1,
01116 basic_block bb2, rtx *f1, rtx *f2)
01117 {
01118 rtx i1, i2, last1, last2, afterlast1, afterlast2;
01119 int ninsns = 0;
01120
01121
01122
01123
01124 i1 = BB_END (bb1);
01125 last1 = afterlast1 = last2 = afterlast2 = NULL_RTX;
01126 if (onlyjump_p (i1)
01127 || (returnjump_p (i1) && !side_effects_p (PATTERN (i1))))
01128 {
01129 last1 = i1;
01130 i1 = PREV_INSN (i1);
01131 }
01132
01133 i2 = BB_END (bb2);
01134 if (onlyjump_p (i2)
01135 || (returnjump_p (i2) && !side_effects_p (PATTERN (i2))))
01136 {
01137 last2 = i2;
01138
01139 if (!simplejump_p (i2) && !returnjump_p (i2) && last1)
01140 ninsns++;
01141 i2 = PREV_INSN (i2);
01142 }
01143
01144 while (true)
01145 {
01146
01147 while (!INSN_P (i1) && i1 != BB_HEAD (bb1))
01148 i1 = PREV_INSN (i1);
01149
01150 while (!INSN_P (i2) && i2 != BB_HEAD (bb2))
01151 i2 = PREV_INSN (i2);
01152
01153 if (i1 == BB_HEAD (bb1) || i2 == BB_HEAD (bb2))
01154 break;
01155
01156 if (!insns_match_p (mode, i1, i2))
01157 break;
01158
01159 merge_memattrs (i1, i2);
01160
01161
01162 if (INSN_P (i1))
01163 {
01164
01165
01166 rtx equiv1 = find_reg_equal_equiv_note (i1);
01167 rtx equiv2 = find_reg_equal_equiv_note (i2);
01168
01169 if (equiv1 && !equiv2)
01170 remove_note (i1, equiv1);
01171 else if (!equiv1 && equiv2)
01172 remove_note (i2, equiv2);
01173 else if (equiv1 && equiv2
01174 && !rtx_equal_p (XEXP (equiv1, 0), XEXP (equiv2, 0)))
01175 {
01176 remove_note (i1, equiv1);
01177 remove_note (i2, equiv2);
01178 }
01179
01180 afterlast1 = last1, afterlast2 = last2;
01181 last1 = i1, last2 = i2;
01182 ninsns++;
01183 }
01184
01185 i1 = PREV_INSN (i1);
01186 i2 = PREV_INSN (i2);
01187 }
01188
01189 #ifdef HAVE_cc0
01190
01191
01192 if (ninsns && reg_mentioned_p (cc0_rtx, last1) && ! sets_cc0_p (last1))
01193 last1 = afterlast1, last2 = afterlast2, ninsns--;
01194 #endif
01195
01196
01197
01198
01199 if (ninsns)
01200 {
01201 while (last1 != BB_HEAD (bb1) && !INSN_P (PREV_INSN (last1)))
01202 last1 = PREV_INSN (last1);
01203
01204 if (last1 != BB_HEAD (bb1) && LABEL_P (PREV_INSN (last1)))
01205 last1 = PREV_INSN (last1);
01206
01207 while (last2 != BB_HEAD (bb2) && !INSN_P (PREV_INSN (last2)))
01208 last2 = PREV_INSN (last2);
01209
01210 if (last2 != BB_HEAD (bb2) && LABEL_P (PREV_INSN (last2)))
01211 last2 = PREV_INSN (last2);
01212
01213 *f1 = last1;
01214 *f2 = last2;
01215 }
01216
01217 return ninsns;
01218 }
01219
01220
01221
01222
01223
01224
01225
01226 static bool
01227 outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
01228 {
01229 int nehedges1 = 0, nehedges2 = 0;
01230 edge fallthru1 = 0, fallthru2 = 0;
01231 edge e1, e2;
01232 edge_iterator ei;
01233
01234
01235
01236 if (EDGE_COUNT (bb1->succs) == 1
01237 && (EDGE_SUCC (bb1, 0)->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
01238 && (!JUMP_P (BB_END (bb1)) || simplejump_p (BB_END (bb1))))
01239 return (EDGE_COUNT (bb2->succs) == 1
01240 && (EDGE_SUCC (bb2, 0)->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
01241 && (!JUMP_P (BB_END (bb2)) || simplejump_p (BB_END (bb2))));
01242
01243
01244
01245 if (EDGE_COUNT (bb1->succs) == 2
01246 && any_condjump_p (BB_END (bb1))
01247 && onlyjump_p (BB_END (bb1)))
01248 {
01249 edge b1, f1, b2, f2;
01250 bool reverse, match;
01251 rtx set1, set2, cond1, cond2;
01252 enum rtx_code code1, code2;
01253
01254 if (EDGE_COUNT (bb2->succs) != 2
01255 || !any_condjump_p (BB_END (bb2))
01256 || !onlyjump_p (BB_END (bb2)))
01257 return false;
01258
01259 b1 = BRANCH_EDGE (bb1);
01260 b2 = BRANCH_EDGE (bb2);
01261 f1 = FALLTHRU_EDGE (bb1);
01262 f2 = FALLTHRU_EDGE (bb2);
01263
01264
01265
01266 if (FORWARDER_BLOCK_P (f1->dest))
01267 f1 = EDGE_SUCC (f1->dest, 0);
01268
01269 if (FORWARDER_BLOCK_P (f2->dest))
01270 f2 = EDGE_SUCC (f2->dest, 0);
01271
01272
01273
01274
01275 if (FORWARDER_BLOCK_P (f1->dest)
01276 || FORWARDER_BLOCK_P (f2->dest)
01277 || FORWARDER_BLOCK_P (b1->dest)
01278 || FORWARDER_BLOCK_P (b2->dest))
01279 return false;
01280
01281 if (f1->dest == f2->dest && b1->dest == b2->dest)
01282 reverse = false;
01283 else if (f1->dest == b2->dest && b1->dest == f2->dest)
01284 reverse = true;
01285 else
01286 return false;
01287
01288 set1 = pc_set (BB_END (bb1));
01289 set2 = pc_set (BB_END (bb2));
01290 if ((XEXP (SET_SRC (set1), 1) == pc_rtx)
01291 != (XEXP (SET_SRC (set2), 1) == pc_rtx))
01292 reverse = !reverse;
01293
01294 cond1 = XEXP (SET_SRC (set1), 0);
01295 cond2 = XEXP (SET_SRC (set2), 0);
01296 code1 = GET_CODE (cond1);
01297 if (reverse)
01298 code2 = reversed_comparison_code (cond2, BB_END (bb2));
01299 else
01300 code2 = GET_CODE (cond2);
01301
01302 if (code2 == UNKNOWN)
01303 return false;
01304
01305
01306 match = ((code1 == code2
01307 && rtx_renumbered_equal_p (XEXP (cond1, 0), XEXP (cond2, 0))
01308 && rtx_renumbered_equal_p (XEXP (cond1, 1), XEXP (cond2, 1)))
01309 || (code1 == swap_condition (code2)
01310 && rtx_renumbered_equal_p (XEXP (cond1, 1),
01311 XEXP (cond2, 0))
01312 && rtx_renumbered_equal_p (XEXP (cond1, 0),
01313 XEXP (cond2, 1))));
01314
01315
01316
01317
01318
01319 if (match
01320 && !optimize_size
01321 && maybe_hot_bb_p (bb1)
01322 && maybe_hot_bb_p (bb2))
01323 {
01324 int prob2;
01325
01326 if (b1->dest == b2->dest)
01327 prob2 = b2->probability;
01328 else
01329
01330 prob2 = REG_BR_PROB_BASE - b2->probability;
01331
01332
01333
01334
01335 if (abs (b1->probability - prob2) > REG_BR_PROB_BASE / 2)
01336 {
01337 if (dump_file)
01338 fprintf (dump_file,
01339 "Outcomes of branch in bb %i and %i differ too much (%i %i)\n",
01340 bb1->index, bb2->index, b1->probability, prob2);
01341
01342 return false;
01343 }
01344 }
01345
01346 if (dump_file && match)
01347 fprintf (dump_file, "Conditionals in bb %i and %i match.\n",
01348 bb1->index, bb2->index);
01349
01350 return match;
01351 }
01352
01353
01354
01355
01356
01357
01358 {
01359 rtx label1, label2;
01360 rtx table1, table2;
01361
01362 if (tablejump_p (BB_END (bb1), &label1, &table1)
01363 && tablejump_p (BB_END (bb2), &label2, &table2)
01364 && GET_CODE (PATTERN (table1)) == GET_CODE (PATTERN (table2)))
01365 {
01366
01367
01368
01369
01370
01371
01372
01373 if (label1 != label2 && !rtx_referenced_p (label2, BB_END (bb1)))
01374 {
01375
01376 bool identical = false;
01377 rtx p1, p2;
01378
01379 p1 = PATTERN (table1);
01380 p2 = PATTERN (table2);
01381 if (GET_CODE (p1) == ADDR_VEC && rtx_equal_p (p1, p2))
01382 {
01383 identical = true;
01384 }
01385 else if (GET_CODE (p1) == ADDR_DIFF_VEC
01386 && (XVECLEN (p1, 1) == XVECLEN (p2, 1))
01387 && rtx_equal_p (XEXP (p1, 2), XEXP (p2, 2))
01388 && rtx_equal_p (XEXP (p1, 3), XEXP (p2, 3)))
01389 {
01390 int i;
01391
01392 identical = true;
01393 for (i = XVECLEN (p1, 1) - 1; i >= 0 && identical; i--)
01394 if (!rtx_equal_p (XVECEXP (p1, 1, i), XVECEXP (p2, 1, i)))
01395 identical = false;
01396 }
01397
01398 if (identical)
01399 {
01400 replace_label_data rr;
01401 bool match;
01402
01403
01404
01405 rr.r1 = label1;
01406 rr.r2 = label2;
01407 rr.update_label_nuses = false;
01408 for_each_rtx (&BB_END (bb1), replace_label, &rr);
01409
01410 match = insns_match_p (mode, BB_END (bb1), BB_END (bb2));
01411 if (dump_file && match)
01412 fprintf (dump_file,
01413 "Tablejumps in bb %i and %i match.\n",
01414 bb1->index, bb2->index);
01415
01416
01417
01418
01419 rr.r1 = label2;
01420 rr.r2 = label1;
01421 for_each_rtx (&BB_END (bb1), replace_label, &rr);
01422
01423 return match;
01424 }
01425 }
01426 return false;
01427 }
01428 }
01429
01430
01431
01432 if (!insns_match_p (mode, BB_END (bb1), BB_END (bb2)))
01433 return false;
01434
01435
01436
01437
01438 if (EDGE_COUNT (bb1->succs) != EDGE_COUNT (bb2->succs))
01439 return false;
01440
01441 FOR_EACH_EDGE (e1, ei, bb1->succs)
01442 {
01443 e2 = EDGE_SUCC (bb2, ei.index);
01444
01445 if (e1->flags & EDGE_EH)
01446 nehedges1++;
01447
01448 if (e2->flags & EDGE_EH)
01449 nehedges2++;
01450
01451 if (e1->flags & EDGE_FALLTHRU)
01452 fallthru1 = e1;
01453 if (e2->flags & EDGE_FALLTHRU)
01454 fallthru2 = e2;
01455 }
01456
01457
01458 if (nehedges1 != nehedges2
01459 || (fallthru1 != 0) != (fallthru2 != 0))
01460 return false;
01461
01462
01463 if (fallthru1)
01464 {
01465 basic_block d1 = (forwarder_block_p (fallthru1->dest)
01466 ? EDGE_SUCC (fallthru1->dest, 0)->dest: fallthru1->dest);
01467 basic_block d2 = (forwarder_block_p (fallthru2->dest)
01468 ? EDGE_SUCC (fallthru2->dest, 0)->dest: fallthru2->dest);
01469
01470 if (d1 != d2)
01471 return false;
01472 }
01473
01474
01475 {
01476 rtx n1 = find_reg_note (BB_END (bb1), REG_EH_REGION, 0);
01477 rtx n2 = find_reg_note (BB_END (bb2), REG_EH_REGION, 0);
01478
01479 if (!n1 && n2)
01480 return false;
01481
01482 if (n1 && (!n2 || XEXP (n1, 0) != XEXP (n2, 0)))
01483 return false;
01484 }
01485
01486
01487
01488 return true;
01489 }
01490
01491
01492
01493
01494
01495 static bool
01496 try_crossjump_to_edge (int mode, edge e1, edge e2)
01497 {
01498 int nmatch;
01499 basic_block src1 = e1->src, src2 = e2->src;
01500 basic_block redirect_to, redirect_from, to_remove;
01501 rtx newpos1, newpos2;
01502 edge s;
01503 edge_iterator ei;
01504
01505 newpos1 = newpos2 = NULL_RTX;
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516 if (flag_reorder_blocks_and_partition && no_new_pseudos)
01517 return false;
01518
01519
01520
01521
01522
01523 if (EDGE_COUNT (src1->preds) == 1
01524 && FORWARDER_BLOCK_P (src1))
01525 e1 = EDGE_PRED (src1, 0), src1 = e1->src;
01526
01527 if (EDGE_COUNT (src2->preds) == 1
01528 && FORWARDER_BLOCK_P (src2))
01529 e2 = EDGE_PRED (src2, 0), src2 = e2->src;
01530
01531
01532 if (src1 == ENTRY_BLOCK_PTR || src2 == ENTRY_BLOCK_PTR)
01533 return false;
01534 if (src1 == src2)
01535 return false;
01536
01537
01538 if (FORWARDER_BLOCK_P (e1->dest)
01539 && FORWARDER_BLOCK_P (EDGE_SUCC (e1->dest, 0)->dest))
01540 return false;
01541
01542 if (FORWARDER_BLOCK_P (e2->dest)
01543 && FORWARDER_BLOCK_P (EDGE_SUCC (e2->dest, 0)->dest))
01544 return false;
01545
01546
01547
01548 if (EDGE_COUNT (src1->preds) == 0 || EDGE_COUNT (src2->preds) == 0)
01549 return false;
01550
01551
01552 if (!outgoing_edges_match (mode, src1, src2))
01553 return false;
01554
01555
01556 nmatch = flow_find_cross_jump (mode, src1, src2, &newpos1, &newpos2);
01557
01558
01559
01560
01561
01562 if ((nmatch < PARAM_VALUE (PARAM_MIN_CROSSJUMP_INSNS))
01563 && (newpos1 != BB_HEAD (src1)))
01564 return false;
01565
01566
01567
01568
01569
01570
01571 {
01572 rtx label1, label2;
01573 rtx table1, table2;
01574
01575 if (tablejump_p (BB_END (src1), &label1, &table1)
01576 && tablejump_p (BB_END (src2), &label2, &table2)
01577 && label1 != label2)
01578 {
01579 replace_label_data rr;
01580 rtx insn;
01581
01582
01583 rr.r1 = label1;
01584 rr.r2 = label2;
01585 rr.update_label_nuses = true;
01586 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
01587 {
01588
01589
01590
01591 if (insn != BB_END (src1))
01592 for_each_rtx (&insn, replace_label, &rr);
01593 }
01594 }
01595 }
01596
01597
01598 if (newpos2 == BB_HEAD (src2))
01599 redirect_to = src2;
01600 else
01601 {
01602 if (dump_file)
01603 fprintf (dump_file, "Splitting bb %i before %i insns\n",
01604 src2->index, nmatch);
01605 redirect_to = split_block (src2, PREV_INSN (newpos2))->dest;
01606 }
01607
01608 if (dump_file)
01609 fprintf (dump_file,
01610 "Cross jumping from bb %i to bb %i; %i common insns\n",
01611 src1->index, src2->index, nmatch);
01612
01613 redirect_to->count += src1->count;
01614 redirect_to->frequency += src1->frequency;
01615
01616 redirect_to->flags |= BB_DIRTY;
01617
01618
01619 FOR_EACH_EDGE (s, ei, redirect_to->succs)
01620 {
01621 edge s2;
01622 edge_iterator ei;
01623 basic_block d = s->dest;
01624
01625 if (FORWARDER_BLOCK_P (d))
01626 d = EDGE_SUCC (d, 0)->dest;
01627
01628 FOR_EACH_EDGE (s2, ei, src1->succs)
01629 {
01630 basic_block d2 = s2->dest;
01631 if (FORWARDER_BLOCK_P (d2))
01632 d2 = EDGE_SUCC (d2, 0)->dest;
01633 if (d == d2)
01634 break;
01635 }
01636
01637 s->count += s2->count;
01638
01639
01640
01641
01642 if (FORWARDER_BLOCK_P (s->dest))
01643 {
01644 EDGE_SUCC (s->dest, 0)->count += s2->count;
01645 s->dest->count += s2->count;
01646 s->dest->frequency += EDGE_FREQUENCY (s);
01647 }
01648
01649 if (FORWARDER_BLOCK_P (s2->dest))
01650 {
01651 EDGE_SUCC (s2->dest, 0)->count -= s2->count;
01652 if (EDGE_SUCC (s2->dest, 0)->count < 0)
01653 EDGE_SUCC (s2->dest, 0)->count = 0;
01654 s2->dest->count -= s2->count;
01655 s2->dest->frequency -= EDGE_FREQUENCY (s);
01656 if (s2->dest->frequency < 0)
01657 s2->dest->frequency = 0;
01658 if (s2->dest->count < 0)
01659 s2->dest->count = 0;
01660 }
01661
01662 if (!redirect_to->frequency && !src1->frequency)
01663 s->probability = (s->probability + s2->probability) / 2;
01664 else
01665 s->probability
01666 = ((s->probability * redirect_to->frequency +
01667 s2->probability * src1->frequency)
01668 / (redirect_to->frequency + src1->frequency));
01669 }
01670
01671 update_br_prob_note (redirect_to);
01672
01673
01674
01675
01676 if (LABEL_P (newpos1))
01677 newpos1 = NEXT_INSN (newpos1);
01678
01679 if (NOTE_P (newpos1))
01680 newpos1 = NEXT_INSN (newpos1);
01681
01682 redirect_from = split_block (src1, PREV_INSN (newpos1))->src;
01683 to_remove = EDGE_SUCC (redirect_from, 0)->dest;
01684
01685 redirect_edge_and_branch_force (EDGE_SUCC (redirect_from, 0), redirect_to);
01686 delete_basic_block (to_remove);
01687
01688 update_forwarder_flag (redirect_from);
01689 if (redirect_to != src2)
01690 update_forwarder_flag (src2);
01691
01692 return true;
01693 }
01694
01695
01696
01697
01698
01699 static bool
01700 try_crossjump_bb (int mode, basic_block bb)
01701 {
01702 edge e, e2, fallthru;
01703 bool changed;
01704 unsigned max, ix, ix2;
01705 basic_block ev, ev2;
01706 edge_iterator ei;
01707
01708
01709 if (EDGE_COUNT (bb->preds) < 2)
01710 return false;
01711
01712
01713
01714 if (!optimize_size
01715 && bb != EXIT_BLOCK_PTR
01716 && computed_jump_p (BB_END (bb)))
01717 return false;
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729 if (flag_reorder_blocks_and_partition
01730 && (BB_PARTITION (EDGE_PRED (bb, 0)->src) != BB_PARTITION (EDGE_PRED (bb, 1)->src)
01731 || (EDGE_PRED (bb, 0)->flags & EDGE_CROSSING)))
01732 return false;
01733
01734
01735
01736
01737 fallthru = NULL;
01738 max = PARAM_VALUE (PARAM_MAX_CROSSJUMP_EDGES);
01739
01740 if (EDGE_COUNT (bb->preds) > max)
01741 return false;
01742
01743 FOR_EACH_EDGE (e, ei, bb->preds)
01744 {
01745 if (e->flags & EDGE_FALLTHRU)
01746 fallthru = e;
01747 }
01748
01749 changed = false;
01750 for (ix = 0, ev = bb; ix < EDGE_COUNT (ev->preds); )
01751 {
01752 e = EDGE_PRED (ev, ix);
01753 ix++;
01754
01755
01756 if (fallthru)
01757 {
01758
01759
01760 if (e == fallthru)
01761 continue;
01762
01763
01764 if (!first_pass
01765 && (!(e->src->flags & BB_DIRTY)
01766 && !(fallthru->src->flags & BB_DIRTY)))
01767 continue;
01768
01769 if (try_crossjump_to_edge (mode, e, fallthru))
01770 {
01771 changed = true;
01772 ix = 0;
01773 ev = bb;
01774 continue;
01775 }
01776 }
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790 if (EDGE_SUCC (e->src, 0) != e)
01791 continue;
01792
01793 for (ix2 = 0, ev2 = bb; ix2 < EDGE_COUNT (ev2->preds); )
01794 {
01795 e2 = EDGE_PRED (ev2, ix2);
01796 ix2++;
01797
01798 if (e2 == e)
01799 continue;
01800
01801
01802 if (e2 == fallthru)
01803 continue;
01804
01805
01806
01807
01808
01809 if (e->src->index > e2->src->index)
01810 continue;
01811
01812
01813
01814 if (!first_pass
01815 && (!(e->src->flags & BB_DIRTY)
01816 && !(e2->src->flags & BB_DIRTY)))
01817 continue;
01818
01819 if (try_crossjump_to_edge (mode, e, e2))
01820 {
01821 changed = true;
01822 ev2 = bb;
01823 ix = 0;
01824 break;
01825 }
01826 }
01827 }
01828
01829 return changed;
01830 }
01831
01832
01833
01834
01835 static bool
01836 try_optimize_cfg (int mode)
01837 {
01838 bool changed_overall = false;
01839 bool changed;
01840 int iterations = 0;
01841 basic_block bb, b, next;
01842
01843 if (mode & CLEANUP_CROSSJUMP)
01844 add_noreturn_fake_exit_edges ();
01845
01846 FOR_EACH_BB (bb)
01847 update_forwarder_flag (bb);
01848
01849 if (mode & (CLEANUP_UPDATE_LIFE | CLEANUP_CROSSJUMP | CLEANUP_THREADING))
01850 clear_bb_flags ();
01851
01852 if (! targetm.cannot_modify_jumps_p ())
01853 {
01854 first_pass = true;
01855
01856
01857
01858 do
01859 {
01860 changed = false;
01861 iterations++;
01862
01863 if (dump_file)
01864 fprintf (dump_file,
01865 "\n\ntry_optimize_cfg iteration %i\n\n",
01866 iterations);
01867
01868 for (b = ENTRY_BLOCK_PTR->next_bb; b != EXIT_BLOCK_PTR;)
01869 {
01870 basic_block c;
01871 edge s;
01872 bool changed_here = false;
01873
01874
01875 while (EDGE_COUNT (b->preds) == 0)
01876 {
01877 c = b->prev_bb;
01878 if (dump_file)
01879 fprintf (dump_file, "Deleting block %i.\n",
01880 b->index);
01881
01882 delete_basic_block (b);
01883 if (!(mode & CLEANUP_CFGLAYOUT))
01884 changed = true;
01885 b = c;
01886 }
01887
01888
01889 if (EDGE_COUNT (b->preds) == 1
01890 && (EDGE_PRED (b, 0)->flags & EDGE_FALLTHRU)
01891 && !(EDGE_PRED (b, 0)->flags & EDGE_COMPLEX)
01892 && LABEL_P (BB_HEAD (b))
01893
01894
01895
01896
01897
01898
01899 && (EDGE_PRED (b, 0)->src == ENTRY_BLOCK_PTR
01900 || !JUMP_P (BB_END (EDGE_PRED (b, 0)->src))
01901 || ! label_is_jump_target_p (BB_HEAD (b),
01902 BB_END (EDGE_PRED (b, 0)->src))))
01903 {
01904 rtx label = BB_HEAD (b);
01905
01906 delete_insn_chain (label, label);
01907
01908
01909 if (NOTE_LINE_NUMBER (BB_HEAD (b)) == NOTE_INSN_DELETED_LABEL)
01910 {
01911 rtx bb_note = NEXT_INSN (BB_HEAD (b));
01912
01913 reorder_insns_nobb (label, label, bb_note);
01914 BB_HEAD (b) = bb_note;
01915 }
01916 if (dump_file)
01917 fprintf (dump_file, "Deleted label in block %i.\n",
01918 b->index);
01919 }
01920
01921
01922 if (!(mode & CLEANUP_CFGLAYOUT)
01923 && EDGE_COUNT (b->preds) == 1
01924 && (EDGE_PRED (b, 0)->flags & EDGE_FALLTHRU)
01925 && !LABEL_P (BB_HEAD (b))
01926 && FORWARDER_BLOCK_P (b)
01927
01928
01929 && (EDGE_SUCC (b, 0)->flags & EDGE_FALLTHRU)
01930 && n_basic_blocks > 1)
01931 {
01932 if (dump_file)
01933 fprintf (dump_file,
01934 "Deleting fallthru block %i.\n",
01935 b->index);
01936
01937 c = b->prev_bb == ENTRY_BLOCK_PTR ? b->next_bb : b->prev_bb;
01938 redirect_edge_succ_nodup (EDGE_PRED (b, 0), EDGE_SUCC (b, 0)->dest);
01939 delete_basic_block (b);
01940 changed = true;
01941 b = c;
01942 }
01943
01944 if (EDGE_COUNT (b->succs) == 1
01945 && (s = EDGE_SUCC (b, 0))
01946 && !(s->flags & EDGE_COMPLEX)
01947 && (c = s->dest) != EXIT_BLOCK_PTR
01948 && EDGE_COUNT (c->preds) == 1
01949 && b != c)
01950 {
01951
01952
01953
01954
01955
01956
01957 if ((mode & CLEANUP_CFGLAYOUT)
01958 && can_merge_blocks_p (b, c))
01959 {
01960 merge_blocks (b, c);
01961 update_forwarder_flag (b);
01962 changed_here = true;
01963 }
01964 else if (!(mode & CLEANUP_CFGLAYOUT)
01965
01966
01967 && (!JUMP_P (BB_END (b))
01968 || (reload_completed
01969 ? simplejump_p (BB_END (b))
01970 : (onlyjump_p (BB_END (b))
01971 && !tablejump_p (BB_END (b),
01972 NULL, NULL))))
01973 && (next = merge_blocks_move (s, b, c, mode)))
01974 {
01975 b = next;
01976 changed_here = true;
01977 }
01978 }
01979
01980
01981 if ((mode & CLEANUP_EXPENSIVE)
01982 && !(mode & CLEANUP_CFGLAYOUT)
01983 && try_simplify_condjump (b))
01984 changed_here = true;
01985
01986
01987
01988
01989
01990 if (EDGE_COUNT (b->succs) == 1
01991 && EDGE_SUCC (b, 0)->dest != EXIT_BLOCK_PTR
01992 && onlyjump_p (BB_END (b))
01993 && !find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
01994 && try_redirect_by_replacing_jump (EDGE_SUCC (b, 0), EDGE_SUCC (b, 0)->dest,
01995 (mode & CLEANUP_CFGLAYOUT) != 0))
01996 {
01997 update_forwarder_flag (b);
01998 changed_here = true;
01999 }
02000
02001
02002 if (try_forward_edges (mode, b))
02003 changed_here = true;
02004
02005
02006 if ((mode & CLEANUP_CROSSJUMP)
02007 && try_crossjump_bb (mode, b))
02008 changed_here = true;
02009
02010
02011
02012 if (!changed_here)
02013 b = b->next_bb;
02014 else
02015 changed = true;
02016 }
02017
02018 if ((mode & CLEANUP_CROSSJUMP)
02019 && try_crossjump_bb (mode, EXIT_BLOCK_PTR))
02020 changed = true;
02021
02022 #ifdef ENABLE_CHECKING
02023 if (changed)
02024 verify_flow_info ();
02025 #endif
02026
02027 changed_overall |= changed;
02028 first_pass = false;
02029 }
02030 while (changed);
02031 }
02032
02033 if (mode & CLEANUP_CROSSJUMP)
02034 remove_fake_exit_edges ();
02035
02036 clear_aux_for_blocks ();
02037
02038 return changed_overall;
02039 }
02040
02041
02042
02043 bool
02044 delete_unreachable_blocks (void)
02045 {
02046 bool changed = false;
02047 basic_block b, next_bb;
02048
02049 find_unreachable_blocks ();
02050
02051
02052
02053 for (b = ENTRY_BLOCK_PTR->next_bb; b != EXIT_BLOCK_PTR; b = next_bb)
02054 {
02055 next_bb = b->next_bb;
02056
02057 if (!(b->flags & BB_REACHABLE))
02058 {
02059 delete_basic_block (b);
02060 changed = true;
02061 }
02062 }
02063
02064 if (changed)
02065 tidy_fallthru_edges ();
02066 return changed;
02067 }
02068
02069
02070
02071 bool
02072 merge_seq_blocks (void)
02073 {
02074 basic_block bb;
02075 bool changed = false;
02076
02077 for (bb = ENTRY_BLOCK_PTR->next_bb; bb != EXIT_BLOCK_PTR; )
02078 {
02079 if (EDGE_COUNT (bb->succs) == 1
02080 && can_merge_blocks_p (bb, EDGE_SUCC (bb, 0)->dest))
02081 {
02082
02083 merge_blocks (bb, EDGE_SUCC (bb, 0)->dest);
02084 changed = true;
02085 continue;
02086 }
02087
02088 bb = bb->next_bb;
02089 }
02090
02091 return changed;
02092 }
02093
02094
02095
02096 bool
02097 cleanup_cfg (int mode)
02098 {
02099 bool changed = false;
02100
02101 timevar_push (TV_CLEANUP_CFG);
02102 if (delete_unreachable_blocks ())
02103 {
02104 changed = true;
02105
02106
02107 if (!(mode & (CLEANUP_NO_INSN_DEL | CLEANUP_UPDATE_LIFE))
02108 && !reload_completed)
02109 delete_trivially_dead_insns (get_insns(), max_reg_num ());
02110 }
02111
02112 compact_blocks ();
02113
02114 while (try_optimize_cfg (mode))
02115 {
02116 delete_unreachable_blocks (), changed = true;
02117 if (mode & CLEANUP_UPDATE_LIFE)
02118 {
02119
02120
02121
02122 if (!update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
02123 PROP_DEATH_NOTES
02124 | PROP_SCAN_DEAD_CODE
02125 | PROP_KILL_DEAD_CODE
02126 | ((mode & CLEANUP_LOG_LINKS)
02127 ? PROP_LOG_LINKS : 0)))
02128 break;
02129 }
02130 else if (!(mode & CLEANUP_NO_INSN_DEL)
02131 && (mode & CLEANUP_EXPENSIVE)
02132 && !reload_completed)
02133 {
02134 if (!delete_trivially_dead_insns (get_insns(), max_reg_num ()))
02135 break;
02136 }
02137 else
02138 break;
02139 delete_dead_jumptables ();
02140 }
02141
02142
02143 free_EXPR_LIST_list (&label_value_list);
02144 timevar_pop (TV_CLEANUP_CFG);
02145
02146 return changed;
02147 }