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
00045
00046 static int target_n_insns;
00047
00048 static int sched_n_insns;
00049
00050
00051 static void init_ready_list (struct ready_list *);
00052 static int can_schedule_ready_p (rtx);
00053 static int new_ready (rtx);
00054 static int schedule_more_p (void);
00055 static const char *ebb_print_insn (rtx, int);
00056 static int rank (rtx, rtx);
00057 static int contributes_to_priority (rtx, rtx);
00058 static void compute_jump_reg_dependencies (rtx, regset, regset, regset);
00059 static basic_block earliest_block_with_similiar_load (basic_block, rtx);
00060 static void add_deps_for_risky_insns (rtx, rtx);
00061 static basic_block schedule_ebb (rtx, rtx);
00062 static basic_block fix_basic_block_boundaries (basic_block, basic_block, rtx,
00063 rtx);
00064 static void add_missing_bbs (rtx, basic_block, basic_block);
00065
00066
00067
00068 static int
00069 schedule_more_p (void)
00070 {
00071 return sched_n_insns < target_n_insns;
00072 }
00073
00074
00075
00076
00077 static void
00078 init_ready_list (struct ready_list *ready)
00079 {
00080 rtx prev_head = current_sched_info->prev_head;
00081 rtx next_tail = current_sched_info->next_tail;
00082 rtx insn;
00083
00084 target_n_insns = 0;
00085 sched_n_insns = 0;
00086
00087 #if 0
00088
00089 if (sched_verbose >= 5)
00090 debug_dependencies ();
00091 #endif
00092
00093
00094
00095 for (insn = NEXT_INSN (prev_head); insn != next_tail; insn = NEXT_INSN (insn))
00096 {
00097 if (INSN_DEP_COUNT (insn) == 0)
00098 ready_add (ready, insn);
00099 target_n_insns++;
00100 }
00101 }
00102
00103
00104
00105
00106 static int
00107 can_schedule_ready_p (rtx insn ATTRIBUTE_UNUSED)
00108 {
00109 sched_n_insns++;
00110 return 1;
00111 }
00112
00113
00114
00115
00116 static int
00117 new_ready (rtx next ATTRIBUTE_UNUSED)
00118 {
00119 return 1;
00120 }
00121
00122
00123
00124
00125
00126
00127 static const char *
00128 ebb_print_insn (rtx insn, int aligned ATTRIBUTE_UNUSED)
00129 {
00130 static char tmp[80];
00131
00132 sprintf (tmp, "%4d", INSN_UID (insn));
00133 return tmp;
00134 }
00135
00136
00137
00138
00139
00140 static int
00141 rank (rtx insn1, rtx insn2)
00142 {
00143 basic_block bb1 = BLOCK_FOR_INSN (insn1);
00144 basic_block bb2 = BLOCK_FOR_INSN (insn2);
00145
00146 if (bb1->count > bb2->count
00147 || bb1->frequency > bb2->frequency)
00148 return -1;
00149 if (bb1->count < bb2->count
00150 || bb1->frequency < bb2->frequency)
00151 return 1;
00152 return 0;
00153 }
00154
00155
00156
00157
00158
00159 static int
00160 contributes_to_priority (rtx next ATTRIBUTE_UNUSED,
00161 rtx insn ATTRIBUTE_UNUSED)
00162 {
00163 return 1;
00164 }
00165
00166
00167
00168
00169
00170
00171 static void
00172 compute_jump_reg_dependencies (rtx insn, regset cond_set, regset used,
00173 regset set)
00174 {
00175 basic_block b = BLOCK_FOR_INSN (insn);
00176 edge e;
00177 edge_iterator ei;
00178
00179 FOR_EACH_EDGE (e, ei, b->succs)
00180 if (e->flags & EDGE_FALLTHRU)
00181
00182
00183
00184
00185
00186 bitmap_and (set, e->dest->global_live_at_start, cond_set);
00187 else
00188 bitmap_ior_into (used, e->dest->global_live_at_start);
00189 }
00190
00191
00192
00193
00194 static struct sched_info ebb_sched_info =
00195 {
00196 init_ready_list,
00197 can_schedule_ready_p,
00198 schedule_more_p,
00199 new_ready,
00200 rank,
00201 ebb_print_insn,
00202 contributes_to_priority,
00203 compute_jump_reg_dependencies,
00204
00205 NULL, NULL,
00206 NULL, NULL,
00207 0, 1, 0
00208 };
00209
00210
00211
00212
00213 static void
00214 add_missing_bbs (rtx before, basic_block first, basic_block last)
00215 {
00216 for (; last != first->prev_bb; last = last->prev_bb)
00217 {
00218 before = emit_note_before (NOTE_INSN_BASIC_BLOCK, before);
00219 NOTE_BASIC_BLOCK (before) = last;
00220 BB_HEAD (last) = before;
00221 BB_END (last) = before;
00222 update_bb_for_insn (last);
00223 }
00224 }
00225
00226
00227
00228
00229
00230 static basic_block
00231 fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head,
00232 rtx tail)
00233 {
00234 rtx insn = head;
00235 rtx last_inside = BB_HEAD (bb);
00236 rtx aftertail = NEXT_INSN (tail);
00237
00238 head = BB_HEAD (bb);
00239
00240 for (; insn != aftertail; insn = NEXT_INSN (insn))
00241 {
00242 gcc_assert (!LABEL_P (insn));
00243
00244 if (inside_basic_block_p (insn))
00245 {
00246 if (!last_inside)
00247 {
00248 rtx note;
00249
00250
00251 if (LABEL_P (insn))
00252 {
00253 note = emit_note_after (NOTE_INSN_BASIC_BLOCK, insn);
00254 head = insn;
00255 last_inside = note;
00256 }
00257 else
00258 {
00259 note = emit_note_before (NOTE_INSN_BASIC_BLOCK, insn);
00260 head = note;
00261 last_inside = insn;
00262 }
00263 }
00264 else
00265 last_inside = insn;
00266 }
00267
00268
00269
00270
00271 if (control_flow_insn_p (insn) || (insn == tail && last_inside))
00272 {
00273 basic_block curr_bb = BLOCK_FOR_INSN (insn);
00274 rtx note;
00275
00276 if (!control_flow_insn_p (insn))
00277 curr_bb = last;
00278 if (bb == last->next_bb)
00279 {
00280 edge f;
00281 rtx h;
00282 edge_iterator ei;
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 FOR_EACH_EDGE (f, ei, bb->prev_bb->succs)
00296 if (f->flags & EDGE_FALLTHRU)
00297 break;
00298
00299 if (f)
00300 {
00301 last = curr_bb = split_edge (f);
00302 h = BB_HEAD (curr_bb);
00303 BB_HEAD (curr_bb) = head;
00304 BB_END (curr_bb) = insn;
00305
00306
00307 delete_insn (h);
00308 }
00309
00310
00311 else
00312 {
00313 rtx next = next_nonnote_insn (insn);
00314 delete_insn_chain (head, insn);
00315
00316
00317 if (BARRIER_P (next))
00318 {
00319 emit_barrier_after (prev_nonnote_insn (head));
00320 delete_insn (next);
00321 }
00322 insn = NULL;
00323 }
00324 }
00325 else
00326 {
00327 BB_HEAD (curr_bb) = head;
00328 BB_END (curr_bb) = insn;
00329 add_missing_bbs (BB_HEAD (curr_bb), bb, curr_bb->prev_bb);
00330 }
00331 note = LABEL_P (head) ? NEXT_INSN (head) : head;
00332 NOTE_BASIC_BLOCK (note) = curr_bb;
00333 update_bb_for_insn (curr_bb);
00334 bb = curr_bb->next_bb;
00335 last_inside = NULL;
00336 if (!insn)
00337 break;
00338 }
00339 }
00340 add_missing_bbs (BB_HEAD (last->next_bb), bb, last);
00341 return bb->prev_bb;
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 static basic_block
00361 earliest_block_with_similiar_load (basic_block last_block, rtx load_insn)
00362 {
00363 rtx back_link;
00364 basic_block bb, earliest_block = NULL;
00365
00366 for (back_link = LOG_LINKS (load_insn);
00367 back_link;
00368 back_link = XEXP (back_link, 1))
00369 {
00370 rtx insn1 = XEXP (back_link, 0);
00371
00372 if (GET_MODE (back_link) == VOIDmode)
00373 {
00374
00375 rtx fore_link;
00376
00377 for (fore_link = INSN_DEPEND (insn1);
00378 fore_link;
00379 fore_link = XEXP (fore_link, 1))
00380 {
00381 rtx insn2 = XEXP (fore_link, 0);
00382 basic_block insn2_block = BLOCK_FOR_INSN (insn2);
00383
00384 if (GET_MODE (fore_link) == VOIDmode)
00385 {
00386 if (earliest_block != NULL
00387 && earliest_block->index < insn2_block->index)
00388 continue;
00389
00390
00391 if (haifa_classify_insn (insn2) != PFREE_CANDIDATE)
00392
00393 continue;
00394
00395 for (bb = last_block; bb; bb = bb->aux)
00396 if (insn2_block == bb)
00397 break;
00398
00399 if (!bb)
00400
00401 earliest_block = insn2_block;
00402 }
00403 }
00404 }
00405 }
00406
00407 return earliest_block;
00408 }
00409
00410
00411
00412
00413 static void
00414 add_deps_for_risky_insns (rtx head, rtx tail)
00415 {
00416 rtx insn, prev;
00417 int class;
00418 rtx last_jump = NULL_RTX;
00419 rtx next_tail = NEXT_INSN (tail);
00420 basic_block last_block = NULL, bb;
00421
00422 for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
00423 if (JUMP_P (insn))
00424 {
00425 bb = BLOCK_FOR_INSN (insn);
00426 bb->aux = last_block;
00427 last_block = bb;
00428 last_jump = insn;
00429 }
00430 else if (INSN_P (insn) && last_jump != NULL_RTX)
00431 {
00432 class = haifa_classify_insn (insn);
00433 prev = last_jump;
00434 switch (class)
00435 {
00436 case PFREE_CANDIDATE:
00437 if (flag_schedule_speculative_load)
00438 {
00439 bb = earliest_block_with_similiar_load (last_block, insn);
00440 if (bb)
00441 {
00442 bb = bb->aux;
00443 if (!bb)
00444 break;
00445 prev = BB_END (bb);
00446 }
00447 }
00448
00449 case TRAP_RISKY:
00450 case IRISKY:
00451 case PRISKY_CANDIDATE:
00452
00453
00454
00455
00456
00457 if (add_dependence (insn, prev, REG_DEP_ANTI))
00458 add_forward_dependence (prev, insn, REG_DEP_ANTI);
00459 break;
00460
00461 default:
00462 break;
00463 }
00464 }
00465
00466 while (last_block)
00467 {
00468 bb = last_block->aux;
00469 last_block->aux = NULL;
00470 last_block = bb;
00471 }
00472 }
00473
00474
00475
00476
00477 static basic_block
00478 schedule_ebb (rtx head, rtx tail)
00479 {
00480 int n_insns;
00481 basic_block b;
00482 struct deps tmp_deps;
00483 basic_block first_bb = BLOCK_FOR_INSN (head);
00484 basic_block last_bb = BLOCK_FOR_INSN (tail);
00485
00486 if (no_real_insns_p (head, tail))
00487 return BLOCK_FOR_INSN (tail);
00488
00489 init_deps_global ();
00490
00491
00492 init_deps (&tmp_deps);
00493 sched_analyze (&tmp_deps, head, tail);
00494 free_deps (&tmp_deps);
00495
00496
00497 compute_forward_dependences (head, tail);
00498
00499 add_deps_for_risky_insns (head, tail);
00500
00501 if (targetm.sched.dependencies_evaluation_hook)
00502 targetm.sched.dependencies_evaluation_hook (head, tail);
00503
00504
00505 n_insns = set_priorities (head, tail);
00506
00507 current_sched_info->prev_head = PREV_INSN (head);
00508 current_sched_info->next_tail = NEXT_INSN (tail);
00509
00510 if (write_symbols != NO_DEBUG)
00511 {
00512 save_line_notes (first_bb->index, head, tail);
00513 rm_line_notes (head, tail);
00514 }
00515
00516
00517
00518
00519
00520
00521
00522 if (INSN_P (head))
00523 {
00524 rtx note;
00525
00526 for (note = REG_NOTES (head); note; note = XEXP (note, 1))
00527 if (REG_NOTE_KIND (note) == REG_SAVE_NOTE)
00528 remove_note (head, note);
00529 }
00530
00531
00532
00533
00534 rm_other_notes (head, tail);
00535
00536 current_sched_info->queue_must_finish_empty = 1;
00537
00538 schedule_block (-1, n_insns);
00539
00540
00541 gcc_assert (sched_n_insns == n_insns);
00542 head = current_sched_info->head;
00543 tail = current_sched_info->tail;
00544
00545 if (write_symbols != NO_DEBUG)
00546 restore_line_notes (head, tail);
00547 b = fix_basic_block_boundaries (first_bb, last_bb, head, tail);
00548
00549 finish_deps_global ();
00550 return b;
00551 }
00552
00553
00554
00555
00556 void
00557 schedule_ebbs (FILE *dump_file)
00558 {
00559 basic_block bb;
00560 int probability_cutoff;
00561
00562 if (profile_info && flag_branch_probabilities)
00563 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK);
00564 else
00565 probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY);
00566 probability_cutoff = REG_BR_PROB_BASE / 100 * probability_cutoff;
00567
00568
00569
00570 if (n_basic_blocks == 0)
00571 return;
00572
00573 sched_init (dump_file);
00574
00575 current_sched_info = &ebb_sched_info;
00576
00577 compute_bb_for_insn ();
00578
00579
00580 FOR_EACH_BB (bb)
00581 {
00582 rtx head = BB_HEAD (bb);
00583 rtx tail;
00584
00585 for (;;)
00586 {
00587 edge e;
00588 edge_iterator ei;
00589 tail = BB_END (bb);
00590 if (bb->next_bb == EXIT_BLOCK_PTR
00591 || LABEL_P (BB_HEAD (bb->next_bb)))
00592 break;
00593 FOR_EACH_EDGE (e, ei, bb->succs)
00594 if ((e->flags & EDGE_FALLTHRU) != 0)
00595 break;
00596 if (! e)
00597 break;
00598 if (e->probability <= probability_cutoff)
00599 break;
00600 bb = bb->next_bb;
00601 }
00602
00603
00604
00605 while (head != tail)
00606 {
00607 if (NOTE_P (head))
00608 head = NEXT_INSN (head);
00609 else if (NOTE_P (tail))
00610 tail = PREV_INSN (tail);
00611 else if (LABEL_P (head))
00612 head = NEXT_INSN (head);
00613 else
00614 break;
00615 }
00616
00617 bb = schedule_ebb (head, tail);
00618 }
00619
00620
00621
00622
00623
00624
00625 if (reload_completed)
00626 reposition_prologue_and_epilogue_notes (get_insns ());
00627
00628 if (write_symbols != NO_DEBUG)
00629 rm_redundant_line_notes ();
00630
00631 sched_finish ();
00632 }