00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "toplev.h"
00029 #include "rtl.h"
00030 #include "tm_p.h"
00031 #include "hard-reg-set.h"
00032 #include "regs.h"
00033 #include "function.h"
00034 #include "flags.h"
00035 #include "insn-config.h"
00036 #include "insn-attr.h"
00037 #include "except.h"
00038 #include "toplev.h"
00039 #include "recog.h"
00040 #include "cfglayout.h"
00041 #include "params.h"
00042 #include "sched-int.h"
00043 #include "target.h"
00044 #include "output.h"
00045
00046
00047 static int sched_n_insns;
00048
00049
00050 static int n_insns;
00051
00052
00053 static bitmap_head dont_calc_deps;
00054
00055 static bitmap_head ebb_head, ebb_tail;
00056
00057
00058 static basic_block last_bb;
00059
00060
00061 static void init_ready_list (void);
00062 static void begin_schedule_ready (rtx, rtx);
00063 static int schedule_more_p (void);
00064 static const char *ebb_print_insn (rtx, int);
00065 static int rank (rtx, rtx);
00066 static int contributes_to_priority (rtx, rtx);
00067 static void compute_jump_reg_dependencies (rtx, regset, regset, regset);
00068 static basic_block earliest_block_with_similiar_load (basic_block, rtx);
00069 static void add_deps_for_risky_insns (rtx, rtx);
00070 static basic_block schedule_ebb (rtx, rtx);
00071
00072 static void add_remove_insn (rtx, int);
00073 static void add_block1 (basic_block, basic_block);
00074 static basic_block advance_target_bb (basic_block, rtx);
00075 static void fix_recovery_cfg (int, int, int);
00076
00077 #ifdef ENABLE_CHECKING
00078 static int ebb_head_or_leaf_p (basic_block, int);
00079 #endif
00080
00081
00082
00083 static int
00084 schedule_more_p (void)
00085 {
00086 return sched_n_insns < n_insns;
00087 }
00088
00089
00090
00091
00092 static void
00093 init_ready_list (void)
00094 {
00095 int n = 0;
00096 rtx prev_head = current_sched_info->prev_head;
00097 rtx next_tail = current_sched_info->next_tail;
00098 rtx insn;
00099
00100 sched_n_insns = 0;
00101
00102 #if 0
00103
00104 if (sched_verbose >= 5)
00105 debug_dependencies ();
00106 #endif
00107
00108
00109
00110 for (insn = NEXT_INSN (prev_head); insn != next_tail; insn = NEXT_INSN (insn))
00111 {
00112 try_ready (insn);
00113 n++;
00114 }
00115
00116 gcc_assert (n == n_insns);
00117 }
00118
00119
00120 static void
00121 begin_schedule_ready (rtx insn, rtx last)
00122 {
00123 sched_n_insns++;
00124
00125 if (BLOCK_FOR_INSN (insn) == last_bb
00126
00127 && control_flow_insn_p (insn)
00128
00129 && last != PREV_INSN (insn))
00130 {
00131 edge e;
00132 edge_iterator ei;
00133 basic_block bb;
00134
00135
00136
00137
00138
00139
00140 FOR_EACH_EDGE (e, ei, last_bb->succs)
00141 if (e->flags & EDGE_FALLTHRU)
00142 break;
00143
00144 #ifdef ENABLE_CHECKING
00145 gcc_assert (!e || !(e->flags & EDGE_COMPLEX));
00146
00147 gcc_assert (BLOCK_FOR_INSN (insn) == last_bb
00148 && !IS_SPECULATION_CHECK_P (insn)
00149 && BB_HEAD (last_bb) != insn
00150 && BB_END (last_bb) == insn);
00151
00152 {
00153 rtx x;
00154
00155 x = NEXT_INSN (insn);
00156 if (e)
00157 gcc_assert (NOTE_P (x) || LABEL_P (x));
00158 else
00159 gcc_assert (BARRIER_P (x));
00160 }
00161 #endif
00162
00163 if (e)
00164 {
00165 bb = split_edge (e);
00166 gcc_assert (NOTE_INSN_BASIC_BLOCK_P (BB_END (bb)));
00167 }
00168 else
00169
00170 bb = create_basic_block (NEXT_INSN (insn), NULL_RTX, last_bb);
00171
00172
00173
00174
00175
00176 current_sched_info->next_tail = NEXT_INSN (BB_END (bb));
00177 gcc_assert (current_sched_info->next_tail);
00178
00179 add_block (bb, last_bb);
00180 gcc_assert (last_bb == bb);
00181 }
00182 }
00183
00184
00185
00186
00187
00188
00189 static const char *
00190 ebb_print_insn (rtx insn, int aligned ATTRIBUTE_UNUSED)
00191 {
00192 static char tmp[80];
00193
00194 sprintf (tmp, "%4d", INSN_UID (insn));
00195 return tmp;
00196 }
00197
00198
00199
00200
00201
00202 static int
00203 rank (rtx insn1, rtx insn2)
00204 {
00205 basic_block bb1 = BLOCK_FOR_INSN (insn1);
00206 basic_block bb2 = BLOCK_FOR_INSN (insn2);
00207
00208 if (bb1->count > bb2->count
00209 || bb1->frequency > bb2->frequency)
00210 return -1;
00211 if (bb1->count < bb2->count
00212 || bb1->frequency < bb2->frequency)
00213 return 1;
00214 return 0;
00215 }
00216
00217
00218
00219
00220
00221 static int
00222 contributes_to_priority (rtx next ATTRIBUTE_UNUSED,
00223 rtx insn ATTRIBUTE_UNUSED)
00224 {
00225 return 1;
00226 }
00227
00228
00229
00230
00231
00232
00233 static void
00234 compute_jump_reg_dependencies (rtx insn, regset cond_set, regset used,
00235 regset set)
00236 {
00237 basic_block b = BLOCK_FOR_INSN (insn);
00238 edge e;
00239 edge_iterator ei;
00240
00241 FOR_EACH_EDGE (e, ei, b->succs)
00242 if (e->flags & EDGE_FALLTHRU)
00243
00244
00245
00246
00247
00248 bitmap_and (set, glat_start [e->dest->index], cond_set);
00249 else
00250 bitmap_ior_into (used, glat_start [e->dest->index]);
00251 }
00252
00253
00254
00255
00256 static struct sched_info ebb_sched_info =
00257 {
00258 init_ready_list,
00259 NULL,
00260 schedule_more_p,
00261 NULL,
00262 rank,
00263 ebb_print_insn,
00264 contributes_to_priority,
00265 compute_jump_reg_dependencies,
00266
00267 NULL, NULL,
00268 NULL, NULL,
00269 0, 1, 0,
00270
00271 add_remove_insn,
00272 begin_schedule_ready,
00273 add_block1,
00274 advance_target_bb,
00275 fix_recovery_cfg,
00276 #ifdef ENABLE_CHECKING
00277 ebb_head_or_leaf_p,
00278 #endif
00279
00280
00281 SCHED_EBB | USE_GLAT | DETACH_LIFE_INFO
00282 };
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 static basic_block
00301 earliest_block_with_similiar_load (basic_block last_block, rtx load_insn)
00302 {
00303 rtx back_link;
00304 basic_block bb, earliest_block = NULL;
00305
00306 for (back_link = LOG_LINKS (load_insn);
00307 back_link;
00308 back_link = XEXP (back_link, 1))
00309 {
00310 rtx insn1 = XEXP (back_link, 0);
00311
00312 if (GET_MODE (back_link) == VOIDmode)
00313 {
00314
00315 rtx fore_link;
00316
00317 for (fore_link = INSN_DEPEND (insn1);
00318 fore_link;
00319 fore_link = XEXP (fore_link, 1))
00320 {
00321 rtx insn2 = XEXP (fore_link, 0);
00322 basic_block insn2_block = BLOCK_FOR_INSN (insn2);
00323
00324 if (GET_MODE (fore_link) == VOIDmode)
00325 {
00326 if (earliest_block != NULL
00327 && earliest_block->index < insn2_block->index)
00328 continue;
00329
00330
00331 if (haifa_classify_insn (insn2) != PFREE_CANDIDATE)
00332
00333 continue;
00334
00335 for (bb = last_block; bb; bb = bb->aux)
00336 if (insn2_block == bb)
00337 break;
00338
00339 if (!bb)
00340
00341 earliest_block = insn2_block;
00342 }
00343 }
00344 }
00345 }
00346
00347 return earliest_block;
00348 }
00349
00350
00351
00352
00353 static void
00354 add_deps_for_risky_insns (rtx head, rtx tail)
00355 {
00356 rtx insn, prev;
00357 int class;
00358 rtx last_jump = NULL_RTX;
00359 rtx next_tail = NEXT_INSN (tail);
00360 basic_block last_block = NULL, bb;
00361
00362 for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
00363 if (control_flow_insn_p (insn))
00364 {
00365 bb = BLOCK_FOR_INSN (insn);
00366 bb->aux = last_block;
00367 last_block = bb;
00368 last_jump = insn;
00369 }
00370 else if (INSN_P (insn) && last_jump != NULL_RTX)
00371 {
00372 class = haifa_classify_insn (insn);
00373 prev = last_jump;
00374 switch (class)
00375 {
00376 case PFREE_CANDIDATE:
00377 if (flag_schedule_speculative_load)
00378 {
00379 bb = earliest_block_with_similiar_load (last_block, insn);
00380 if (bb)
00381 {
00382 bb = bb->aux;
00383 if (!bb)
00384 break;
00385 prev = BB_END (bb);
00386 }
00387 }
00388
00389 case TRAP_RISKY:
00390 case IRISKY:
00391 case PRISKY_CANDIDATE:
00392
00393
00394
00395
00396
00397 if (! sched_insns_conditions_mutex_p (insn, prev))
00398 {
00399 if (!(current_sched_info->flags & DO_SPECULATION))
00400 {
00401 enum DEPS_ADJUST_RESULT res;
00402
00403 res = add_or_update_back_dep (insn, prev,
00404 REG_DEP_ANTI, DEP_ANTI);
00405
00406 if (res == DEP_CREATED)
00407 add_forw_dep (insn, LOG_LINKS (insn));
00408 else
00409 gcc_assert (res != DEP_CHANGED);
00410 }
00411 else
00412 add_or_update_back_forw_dep (insn, prev, REG_DEP_ANTI,
00413 set_dep_weak (DEP_ANTI,
00414 BEGIN_CONTROL,
00415 MAX_DEP_WEAK));
00416 }
00417
00418 break;
00419
00420 default:
00421 break;
00422 }
00423 }
00424
00425 while (last_block)
00426 {
00427 bb = last_block->aux;
00428 last_block->aux = NULL;
00429 last_block = bb;
00430 }
00431 }
00432
00433
00434
00435
00436 static basic_block
00437 schedule_ebb (rtx head, rtx tail)
00438 {
00439 basic_block first_bb, target_bb;
00440 struct deps tmp_deps;
00441
00442 first_bb = BLOCK_FOR_INSN (head);
00443 last_bb = BLOCK_FOR_INSN (tail);
00444
00445 if (no_real_insns_p (head, tail))
00446 return BLOCK_FOR_INSN (tail);
00447
00448 gcc_assert (INSN_P (head) && INSN_P (tail));
00449
00450 if (!bitmap_bit_p (&dont_calc_deps, first_bb->index))
00451 {
00452 init_deps_global ();
00453
00454
00455 init_deps (&tmp_deps);
00456 sched_analyze (&tmp_deps, head, tail);
00457 free_deps (&tmp_deps);
00458
00459
00460 compute_forward_dependences (head, tail);
00461
00462 add_deps_for_risky_insns (head, tail);
00463
00464 if (targetm.sched.dependencies_evaluation_hook)
00465 targetm.sched.dependencies_evaluation_hook (head, tail);
00466
00467 finish_deps_global ();
00468 }
00469 else
00470
00471
00472 gcc_assert (first_bb == last_bb);
00473
00474
00475 current_sched_info->sched_max_insns_priority = 0;
00476 n_insns = set_priorities (head, tail);
00477 current_sched_info->sched_max_insns_priority++;
00478
00479 current_sched_info->prev_head = PREV_INSN (head);
00480 current_sched_info->next_tail = NEXT_INSN (tail);
00481
00482 if (write_symbols != NO_DEBUG)
00483 {
00484 save_line_notes (first_bb->index, head, tail);
00485 rm_line_notes (head, tail);
00486 }
00487
00488
00489
00490
00491
00492
00493
00494 if (INSN_P (head))
00495 {
00496 rtx note;
00497
00498 for (note = REG_NOTES (head); note; note = XEXP (note, 1))
00499 if (REG_NOTE_KIND (note) == REG_SAVE_NOTE)
00500 remove_note (head, note);
00501 }
00502
00503
00504
00505
00506 rm_other_notes (head, tail);
00507
00508 unlink_bb_notes (first_bb, last_bb);
00509
00510 current_sched_info->queue_must_finish_empty = 1;
00511
00512 target_bb = first_bb;
00513 schedule_block (&target_bb, n_insns);
00514
00515
00516
00517
00518
00519 gcc_assert (sched_n_insns == n_insns);
00520 head = current_sched_info->head;
00521 tail = current_sched_info->tail;
00522
00523 if (write_symbols != NO_DEBUG)
00524 restore_line_notes (head, tail);
00525
00526 if (EDGE_COUNT (last_bb->preds) == 0)
00527
00528 {
00529 gcc_assert (first_bb != last_bb
00530 && EDGE_COUNT (last_bb->succs) == 0);
00531 last_bb = last_bb->prev_bb;
00532 delete_basic_block (last_bb->next_bb);
00533 }
00534
00535 return last_bb;
00536 }
00537
00538
00539
00540 void
00541 schedule_ebbs (void)
00542 {
00543 basic_block bb;
00544 int probability_cutoff;
00545 rtx tail;
00546 sbitmap large_region_blocks, blocks;
00547 int any_large_regions;
00548
00549 if (profile_info && flag_branch_probabilities)
00550 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK);
00551 else
00552 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY);
00553 probability_cutoff = REG_BR_PROB_BASE / 100 * probability_cutoff;
00554
00555
00556
00557 if (n_basic_blocks == NUM_FIXED_BLOCKS)
00558 return;
00559
00560
00561
00562 current_sched_info = &ebb_sched_info;
00563
00564 sched_init ();
00565
00566 compute_bb_for_insn ();
00567
00568
00569 bitmap_initialize (&dont_calc_deps, 0);
00570 bitmap_clear (&dont_calc_deps);
00571 bitmap_initialize (&ebb_head, 0);
00572 bitmap_clear (&ebb_head);
00573 bitmap_initialize (&ebb_tail, 0);
00574 bitmap_clear (&ebb_tail);
00575
00576
00577 FOR_EACH_BB (bb)
00578 {
00579 rtx head = BB_HEAD (bb);
00580
00581 for (;;)
00582 {
00583 edge e;
00584 edge_iterator ei;
00585 tail = BB_END (bb);
00586 if (bb->next_bb == EXIT_BLOCK_PTR
00587 || LABEL_P (BB_HEAD (bb->next_bb)))
00588 break;
00589 FOR_EACH_EDGE (e, ei, bb->succs)
00590 if ((e->flags & EDGE_FALLTHRU) != 0)
00591 break;
00592 if (! e)
00593 break;
00594 if (e->probability <= probability_cutoff)
00595 break;
00596 bb = bb->next_bb;
00597 }
00598
00599
00600
00601 while (head != tail)
00602 {
00603 if (NOTE_P (head))
00604 head = NEXT_INSN (head);
00605 else if (NOTE_P (tail))
00606 tail = PREV_INSN (tail);
00607 else if (LABEL_P (head))
00608 head = NEXT_INSN (head);
00609 else
00610 break;
00611 }
00612
00613 bitmap_set_bit (&ebb_head, BLOCK_NUM (head));
00614 bb = schedule_ebb (head, tail);
00615 bitmap_set_bit (&ebb_tail, bb->index);
00616 }
00617 bitmap_clear (&dont_calc_deps);
00618
00619 gcc_assert (current_sched_info->flags & DETACH_LIFE_INFO);
00620
00621
00622
00623 attach_life_info ();
00624
00625
00626 allocate_reg_life_data ();
00627
00628 any_large_regions = 0;
00629 large_region_blocks = sbitmap_alloc (last_basic_block);
00630 sbitmap_zero (large_region_blocks);
00631 FOR_EACH_BB (bb)
00632 SET_BIT (large_region_blocks, bb->index);
00633
00634 blocks = sbitmap_alloc (last_basic_block);
00635 sbitmap_zero (blocks);
00636
00637
00638
00639
00640
00641 FOR_EACH_BB (bb)
00642 {
00643 int bbi;
00644
00645 bbi = bb->index;
00646
00647 if (!bitmap_bit_p (&ebb_head, bbi)
00648 || !bitmap_bit_p (&ebb_tail, bbi)
00649
00650
00651 || !glat_start[bbi])
00652 any_large_regions = 1;
00653 else
00654 {
00655 SET_BIT (blocks, bbi);
00656 RESET_BIT (large_region_blocks, bbi);
00657 }
00658 }
00659
00660 update_life_info (blocks, UPDATE_LIFE_LOCAL, 0);
00661 sbitmap_free (blocks);
00662
00663 if (any_large_regions)
00664 {
00665 update_life_info (large_region_blocks, UPDATE_LIFE_GLOBAL, 0);
00666
00667 #ifdef ENABLE_CHECKING
00668
00669
00670
00671
00672 #endif
00673 }
00674 sbitmap_free (large_region_blocks);
00675
00676 bitmap_clear (&ebb_head);
00677 bitmap_clear (&ebb_tail);
00678
00679
00680
00681 if (reload_completed)
00682 reposition_prologue_and_epilogue_notes (get_insns ());
00683
00684 if (write_symbols != NO_DEBUG)
00685 rm_redundant_line_notes ();
00686
00687 sched_finish ();
00688 }
00689
00690
00691 static void
00692 add_remove_insn (rtx insn ATTRIBUTE_UNUSED, int remove_p)
00693 {
00694 if (!remove_p)
00695 n_insns++;
00696 else
00697 n_insns--;
00698 }
00699
00700
00701 static void
00702 add_block1 (basic_block bb, basic_block after)
00703 {
00704
00705
00706
00707 if (after == EXIT_BLOCK_PTR)
00708 bitmap_set_bit (&dont_calc_deps, bb->index);
00709 else if (after == last_bb)
00710 last_bb = bb;
00711 }
00712
00713
00714
00715 static basic_block
00716 advance_target_bb (basic_block bb, rtx insn)
00717 {
00718 if (insn)
00719 {
00720 if (BLOCK_FOR_INSN (insn) != bb
00721 && control_flow_insn_p (insn)
00722
00723
00724
00725 && !IS_SPECULATION_BRANCHY_CHECK_P (insn)
00726 && !IS_SPECULATION_BRANCHY_CHECK_P (BB_END (bb)))
00727 {
00728
00729 gcc_assert (!control_flow_insn_p (BB_END (bb))
00730 && NOTE_INSN_BASIC_BLOCK_P (BB_HEAD (bb->next_bb)));
00731 return bb;
00732 }
00733 else
00734 return 0;
00735 }
00736 else
00737
00738 {
00739 do
00740 {
00741 gcc_assert (bb != last_bb);
00742
00743 bb = bb->next_bb;
00744 }
00745 while (bb_note (bb) == BB_END (bb));
00746
00747 return bb;
00748 }
00749 }
00750
00751
00752
00753
00754 static void
00755 fix_recovery_cfg (int bbi ATTRIBUTE_UNUSED, int jump_bbi, int jump_bb_nexti)
00756 {
00757 gcc_assert (last_bb->index != bbi);
00758
00759 if (jump_bb_nexti == last_bb->index)
00760 last_bb = BASIC_BLOCK (jump_bbi);
00761 }
00762
00763 #ifdef ENABLE_CHECKING
00764
00765
00766
00767 static int
00768 ebb_head_or_leaf_p (basic_block bb, int leaf_p)
00769 {
00770 if (!leaf_p)
00771 return bitmap_bit_p (&ebb_head, bb->index);
00772 else
00773 return bitmap_bit_p (&ebb_tail, bb->index);
00774 }
00775 #endif