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 "toplev.h"
00027 #include "rtl.h"
00028 #include "tm_p.h"
00029 #include "hard-reg-set.h"
00030 #include "basic-block.h"
00031 #include "regs.h"
00032 #include "function.h"
00033 #include "flags.h"
00034 #include "insn-config.h"
00035 #include "insn-attr.h"
00036 #include "except.h"
00037 #include "toplev.h"
00038 #include "recog.h"
00039 #include "cfglayout.h"
00040 #include "sched-int.h"
00041
00042
00043 static int target_n_insns;
00044
00045 static int sched_n_insns;
00046
00047
00048 static void init_ready_list PARAMS ((struct ready_list *));
00049 static int can_schedule_ready_p PARAMS ((rtx));
00050 static int new_ready PARAMS ((rtx));
00051 static int schedule_more_p PARAMS ((void));
00052 static const char *ebb_print_insn PARAMS ((rtx, int));
00053 static int rank PARAMS ((rtx, rtx));
00054 static int contributes_to_priority PARAMS ((rtx, rtx));
00055 static void compute_jump_reg_dependencies PARAMS ((rtx, regset, regset,
00056 regset));
00057 static basic_block earliest_block_with_similiar_load PARAMS ((basic_block,
00058 rtx));
00059 static void add_deps_for_risky_insns PARAMS ((rtx, rtx));
00060 static void schedule_ebb PARAMS ((rtx, rtx));
00061
00062
00063
00064 static int
00065 schedule_more_p ()
00066 {
00067 return sched_n_insns < target_n_insns;
00068 }
00069
00070
00071
00072
00073 static void
00074 init_ready_list (ready)
00075 struct ready_list *ready;
00076 {
00077 rtx prev_head = current_sched_info->prev_head;
00078 rtx next_tail = current_sched_info->next_tail;
00079 rtx insn;
00080
00081 target_n_insns = 0;
00082 sched_n_insns = 0;
00083
00084 #if 0
00085
00086 if (sched_verbose >= 5)
00087 debug_dependencies ();
00088 #endif
00089
00090
00091
00092 for (insn = NEXT_INSN (prev_head); insn != next_tail; insn = NEXT_INSN (insn))
00093 {
00094 rtx next;
00095
00096 if (! INSN_P (insn))
00097 continue;
00098 next = NEXT_INSN (insn);
00099
00100 if (INSN_DEP_COUNT (insn) == 0
00101 && (! INSN_P (next) || SCHED_GROUP_P (next) == 0))
00102 ready_add (ready, insn);
00103 if (!(SCHED_GROUP_P (insn)))
00104 target_n_insns++;
00105 }
00106 }
00107
00108
00109
00110
00111 static int
00112 can_schedule_ready_p (insn)
00113 rtx insn ATTRIBUTE_UNUSED;
00114 {
00115 sched_n_insns++;
00116 return 1;
00117 }
00118
00119
00120
00121
00122 static int
00123 new_ready (next)
00124 rtx next ATTRIBUTE_UNUSED;
00125 {
00126 return 1;
00127 }
00128
00129
00130
00131
00132
00133
00134 static const char *
00135 ebb_print_insn (insn, aligned)
00136 rtx insn;
00137 int aligned ATTRIBUTE_UNUSED;
00138 {
00139 static char tmp[80];
00140
00141 sprintf (tmp, "%4d", INSN_UID (insn));
00142 return tmp;
00143 }
00144
00145
00146
00147
00148
00149 static int
00150 rank (insn1, insn2)
00151 rtx insn1 ATTRIBUTE_UNUSED, insn2 ATTRIBUTE_UNUSED;
00152 {
00153 return 0;
00154 }
00155
00156
00157
00158
00159
00160 static int
00161 contributes_to_priority (next, insn)
00162 rtx next ATTRIBUTE_UNUSED, insn ATTRIBUTE_UNUSED;
00163 {
00164 return 1;
00165 }
00166
00167
00168
00169
00170
00171
00172 static void
00173 compute_jump_reg_dependencies (insn, cond_set, used, set)
00174 rtx insn;
00175 regset cond_set, used, set;
00176 {
00177 basic_block b = BLOCK_FOR_INSN (insn);
00178 edge e;
00179 for (e = b->succ; e; e = e->succ_next)
00180 if (e->flags & EDGE_FALLTHRU)
00181
00182
00183
00184
00185
00186 bitmap_operation (set, e->dest->global_live_at_start, cond_set,
00187 BITMAP_AND);
00188 else
00189 bitmap_operation (used, used, e->dest->global_live_at_start,
00190 BITMAP_IOR);
00191 }
00192
00193
00194
00195
00196 static struct sched_info ebb_sched_info =
00197 {
00198 init_ready_list,
00199 can_schedule_ready_p,
00200 schedule_more_p,
00201 new_ready,
00202 rank,
00203 ebb_print_insn,
00204 contributes_to_priority,
00205 compute_jump_reg_dependencies,
00206
00207 NULL, NULL,
00208 NULL, NULL,
00209 0, 1
00210 };
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 static basic_block
00229 earliest_block_with_similiar_load (last_block, load_insn)
00230 basic_block last_block;
00231 rtx load_insn;
00232 {
00233 rtx back_link;
00234 basic_block bb, earliest_block = NULL;
00235
00236 for (back_link = LOG_LINKS (load_insn);
00237 back_link;
00238 back_link = XEXP (back_link, 1))
00239 {
00240 rtx insn1 = XEXP (back_link, 0);
00241
00242 if (GET_MODE (back_link) == VOIDmode)
00243 {
00244
00245 rtx fore_link;
00246
00247 for (fore_link = INSN_DEPEND (insn1);
00248 fore_link;
00249 fore_link = XEXP (fore_link, 1))
00250 {
00251 rtx insn2 = XEXP (fore_link, 0);
00252 basic_block insn2_block = BLOCK_FOR_INSN (insn2);
00253
00254 if (GET_MODE (fore_link) == VOIDmode)
00255 {
00256 if (earliest_block != NULL
00257 && earliest_block->index < insn2_block->index)
00258 continue;
00259
00260
00261 if (haifa_classify_insn (insn2) != PFREE_CANDIDATE)
00262
00263 continue;
00264
00265 for (bb = last_block; bb; bb = bb->aux)
00266 if (insn2_block == bb)
00267 break;
00268
00269 if (!bb)
00270
00271 earliest_block = insn2_block;
00272 }
00273 }
00274 }
00275 }
00276
00277 return earliest_block;
00278 }
00279
00280
00281
00282
00283 static void
00284 add_deps_for_risky_insns (head, tail)
00285 rtx head, tail;
00286 {
00287 rtx insn, prev;
00288 int class;
00289 rtx last_jump = NULL_RTX;
00290 rtx next_tail = NEXT_INSN (tail);
00291 basic_block last_block = NULL, bb;
00292
00293 for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
00294 if (GET_CODE (insn) == JUMP_INSN)
00295 {
00296 bb = BLOCK_FOR_INSN (insn);
00297 bb->aux = last_block;
00298 last_block = bb;
00299 last_jump = insn;
00300 }
00301 else if (INSN_P (insn) && last_jump != NULL_RTX)
00302 {
00303 class = haifa_classify_insn (insn);
00304 prev = last_jump;
00305 switch (class)
00306 {
00307 case PFREE_CANDIDATE:
00308 if (flag_schedule_speculative_load)
00309 {
00310 bb = earliest_block_with_similiar_load (last_block, insn);
00311 if (bb)
00312 {
00313 bb = bb->aux;
00314 if (!bb)
00315 break;
00316 prev = bb->end;
00317 }
00318 }
00319
00320 case TRAP_RISKY:
00321 case IRISKY:
00322 case PRISKY_CANDIDATE:
00323
00324
00325
00326
00327
00328 if (add_dependence (insn, prev, REG_DEP_ANTI))
00329 add_forward_dependence (prev, insn, REG_DEP_ANTI);
00330 break;
00331
00332 default:
00333 break;
00334 }
00335 }
00336
00337 while (last_block)
00338 {
00339 bb = last_block->aux;
00340 last_block->aux = NULL;
00341 last_block = bb;
00342 }
00343 }
00344
00345
00346
00347
00348 static void
00349 schedule_ebb (head, tail)
00350 rtx head, tail;
00351 {
00352 int n_insns;
00353 struct deps tmp_deps;
00354
00355 if (no_real_insns_p (head, tail))
00356 return;
00357
00358 init_deps_global ();
00359
00360
00361 init_deps (&tmp_deps);
00362 sched_analyze (&tmp_deps, head, tail);
00363 free_deps (&tmp_deps);
00364
00365
00366 compute_forward_dependences (head, tail);
00367
00368 add_deps_for_risky_insns (head, tail);
00369
00370
00371 n_insns = set_priorities (head, tail);
00372
00373 current_sched_info->prev_head = PREV_INSN (head);
00374 current_sched_info->next_tail = NEXT_INSN (tail);
00375
00376 if (write_symbols != NO_DEBUG)
00377 {
00378 save_line_notes (0, head, tail);
00379 rm_line_notes (head, tail);
00380 }
00381
00382
00383
00384
00385
00386
00387
00388 if (INSN_P (head))
00389 {
00390 rtx note;
00391
00392 for (note = REG_NOTES (head); note; note = XEXP (note, 1))
00393 if (REG_NOTE_KIND (note) == REG_SAVE_NOTE)
00394 {
00395 remove_note (head, note);
00396 note = XEXP (note, 1);
00397 remove_note (head, note);
00398 }
00399 }
00400
00401
00402
00403
00404 rm_other_notes (head, tail);
00405
00406 current_sched_info->queue_must_finish_empty = 1;
00407
00408 schedule_block (-1, n_insns);
00409
00410
00411 if (sched_n_insns != n_insns)
00412 abort ();
00413 head = current_sched_info->head;
00414 tail = current_sched_info->tail;
00415
00416 if (write_symbols != NO_DEBUG)
00417 restore_line_notes (head, tail);
00418
00419 finish_deps_global ();
00420 }
00421
00422
00423
00424
00425 void
00426 schedule_ebbs (dump_file)
00427 FILE *dump_file;
00428 {
00429 basic_block bb;
00430
00431
00432
00433 if (n_basic_blocks == 0)
00434 return;
00435
00436 sched_init (dump_file);
00437
00438 current_sched_info = &ebb_sched_info;
00439
00440 allocate_reg_life_data ();
00441 compute_bb_for_insn ();
00442
00443
00444 FOR_EACH_BB (bb)
00445 {
00446 rtx head = bb->head;
00447 rtx tail;
00448
00449 for (;;)
00450 {
00451 edge e;
00452 tail = bb->end;
00453 if (bb->next_bb == EXIT_BLOCK_PTR
00454 || GET_CODE (bb->next_bb->head) == CODE_LABEL)
00455 break;
00456 for (e = bb->succ; e; e = e->succ_next)
00457 if ((e->flags & EDGE_FALLTHRU) != 0)
00458 break;
00459 if (! e)
00460 break;
00461 if (GET_CODE (tail) == JUMP_INSN)
00462 {
00463 rtx x = find_reg_note (tail, REG_BR_PROB, 0);
00464 if (x)
00465 {
00466 int pred_val = INTVAL (XEXP (x, 0));
00467 if (pred_val > REG_BR_PROB_BASE / 2)
00468 break;
00469 }
00470 }
00471
00472 bb = bb->next_bb;
00473 }
00474
00475
00476
00477 while (head != tail)
00478 {
00479 if (GET_CODE (head) == NOTE)
00480 head = NEXT_INSN (head);
00481 else if (GET_CODE (tail) == NOTE)
00482 tail = PREV_INSN (tail);
00483 else if (GET_CODE (head) == CODE_LABEL)
00484 head = NEXT_INSN (head);
00485 else
00486 break;
00487 }
00488
00489 schedule_ebb (head, tail);
00490 }
00491
00492
00493
00494
00495
00496
00497 if (reload_completed)
00498 reposition_prologue_and_epilogue_notes (get_insns ());
00499
00500 if (write_symbols != NO_DEBUG)
00501 rm_redundant_line_notes ();
00502
00503 sched_finish ();
00504 }