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