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