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 "sched-int.h"
00041 #include "target.h"
00042 #include "cfglayout.h"
00043 #include "cfgloop.h"
00044 #include "cfghooks.h"
00045 #include "expr.h"
00046 #include "params.h"
00047 #include "gcov-io.h"
00048 #include "df.h"
00049 #include "ddg.h"
00050 #include "timevar.h"
00051 #include "tree-pass.h"
00052
00053 #ifdef INSN_SCHEDULING
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 typedef struct partial_schedule *partial_schedule_ptr;
00094 typedef struct ps_insn *ps_insn_ptr;
00095
00096
00097 #define PS_MIN_CYCLE(ps) (((partial_schedule_ptr)(ps))->min_cycle)
00098
00099
00100 #define PS_MAX_CYCLE(ps) (((partial_schedule_ptr)(ps))->max_cycle)
00101
00102
00103 #define SMODULO(x,y) ((x) % (y) < 0 ? ((x) % (y) + (y)) : (x) % (y))
00104
00105
00106
00107 #define PS_STAGE_COUNT(ps) ((PS_MAX_CYCLE (ps) - PS_MIN_CYCLE (ps) \
00108 + 1 + (ps)->ii - 1) / (ps)->ii)
00109
00110
00111 struct ps_insn
00112 {
00113
00114 ddg_node_ptr node;
00115
00116
00117
00118 int cycle;
00119
00120
00121 ps_insn_ptr next_in_row,
00122 prev_in_row;
00123
00124
00125 int row_rest_count;
00126 };
00127
00128
00129
00130
00131 struct partial_schedule
00132 {
00133 int ii;
00134 int history;
00135
00136
00137 ps_insn_ptr *rows;
00138
00139
00140 int min_cycle;
00141
00142
00143 int max_cycle;
00144
00145 ddg_ptr g;
00146 };
00147
00148
00149
00150 struct undo_replace_buff_elem
00151 {
00152 rtx insn;
00153 rtx orig_reg;
00154 rtx new_reg;
00155 struct undo_replace_buff_elem *next;
00156 };
00157
00158
00159
00160 static partial_schedule_ptr create_partial_schedule (int ii, ddg_ptr, int history);
00161 static void free_partial_schedule (partial_schedule_ptr);
00162 static void reset_partial_schedule (partial_schedule_ptr, int new_ii);
00163 void print_partial_schedule (partial_schedule_ptr, FILE *);
00164 static int kernel_number_of_cycles (rtx first_insn, rtx last_insn);
00165 static ps_insn_ptr ps_add_node_check_conflicts (partial_schedule_ptr,
00166 ddg_node_ptr node, int cycle,
00167 sbitmap must_precede,
00168 sbitmap must_follow);
00169 static void rotate_partial_schedule (partial_schedule_ptr, int);
00170 void set_row_column_for_ps (partial_schedule_ptr);
00171 static bool ps_unschedule_node (partial_schedule_ptr, ddg_node_ptr );
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 static int issue_rate;
00183
00184 static int sms_order_nodes (ddg_ptr, int, int * result);
00185 static void set_node_sched_params (ddg_ptr);
00186 static partial_schedule_ptr sms_schedule_by_order (ddg_ptr, int, int, int *);
00187 static void permute_partial_schedule (partial_schedule_ptr ps, rtx last);
00188 static void generate_prolog_epilog (partial_schedule_ptr ,struct loop * loop, rtx);
00189 static void duplicate_insns_of_cycles (partial_schedule_ptr ps,
00190 int from_stage, int to_stage,
00191 int is_prolog);
00192
00193 #define SCHED_ASAP(x) (((node_sched_params_ptr)(x)->aux.info)->asap)
00194 #define SCHED_TIME(x) (((node_sched_params_ptr)(x)->aux.info)->time)
00195 #define SCHED_FIRST_REG_MOVE(x) \
00196 (((node_sched_params_ptr)(x)->aux.info)->first_reg_move)
00197 #define SCHED_NREG_MOVES(x) \
00198 (((node_sched_params_ptr)(x)->aux.info)->nreg_moves)
00199 #define SCHED_ROW(x) (((node_sched_params_ptr)(x)->aux.info)->row)
00200 #define SCHED_STAGE(x) (((node_sched_params_ptr)(x)->aux.info)->stage)
00201 #define SCHED_COLUMN(x) (((node_sched_params_ptr)(x)->aux.info)->column)
00202
00203
00204 typedef struct node_sched_params
00205 {
00206 int asap;
00207 int time;
00208
00209
00210
00211
00212
00213 rtx first_reg_move;
00214
00215
00216
00217 int nreg_moves;
00218
00219 int row;
00220 int stage;
00221
00222
00223
00224 int column;
00225 } *node_sched_params_ptr;
00226
00227
00228
00229
00230
00231 static const char *
00232 sms_print_insn (rtx insn, int aligned ATTRIBUTE_UNUSED)
00233 {
00234 static char tmp[80];
00235
00236 sprintf (tmp, "i%4d", INSN_UID (insn));
00237 return tmp;
00238 }
00239
00240 static void
00241 compute_jump_reg_dependencies (rtx insn ATTRIBUTE_UNUSED,
00242 regset cond_exec ATTRIBUTE_UNUSED,
00243 regset used ATTRIBUTE_UNUSED,
00244 regset set ATTRIBUTE_UNUSED)
00245 {
00246 }
00247
00248 static struct sched_info sms_sched_info =
00249 {
00250 NULL,
00251 NULL,
00252 NULL,
00253 NULL,
00254 NULL,
00255 sms_print_insn,
00256 NULL,
00257 compute_jump_reg_dependencies,
00258 NULL, NULL,
00259 NULL, NULL,
00260 0, 0, 0,
00261
00262 NULL, NULL, NULL, NULL, NULL,
00263 #ifdef ENABLE_CHECKING
00264 NULL,
00265 #endif
00266 0
00267 };
00268
00269
00270
00271
00272
00273 static rtx
00274 doloop_register_get (rtx insn ATTRIBUTE_UNUSED)
00275 {
00276 #ifdef HAVE_doloop_end
00277 rtx pattern, reg, condition;
00278
00279 if (! JUMP_P (insn))
00280 return NULL_RTX;
00281
00282 pattern = PATTERN (insn);
00283 condition = doloop_condition_get (pattern);
00284 if (! condition)
00285 return NULL_RTX;
00286
00287 if (REG_P (XEXP (condition, 0)))
00288 reg = XEXP (condition, 0);
00289 else if (GET_CODE (XEXP (condition, 0)) == PLUS
00290 && REG_P (XEXP (XEXP (condition, 0), 0)))
00291 reg = XEXP (XEXP (condition, 0), 0);
00292 else
00293 gcc_unreachable ();
00294
00295 return reg;
00296 #else
00297 return NULL_RTX;
00298 #endif
00299 }
00300
00301
00302
00303
00304
00305 static rtx
00306 const_iteration_count (rtx count_reg, basic_block pre_header,
00307 HOST_WIDEST_INT * count)
00308 {
00309 rtx insn;
00310 rtx head, tail;
00311
00312 if (! pre_header)
00313 return NULL_RTX;
00314
00315 get_ebb_head_tail (pre_header, pre_header, &head, &tail);
00316
00317 for (insn = tail; insn != PREV_INSN (head); insn = PREV_INSN (insn))
00318 if (INSN_P (insn) && single_set (insn) &&
00319 rtx_equal_p (count_reg, SET_DEST (single_set (insn))))
00320 {
00321 rtx pat = single_set (insn);
00322
00323 if (GET_CODE (SET_SRC (pat)) == CONST_INT)
00324 {
00325 *count = INTVAL (SET_SRC (pat));
00326 return insn;
00327 }
00328
00329 return NULL_RTX;
00330 }
00331
00332 return NULL_RTX;
00333 }
00334
00335
00336
00337
00338 static int
00339 res_MII (ddg_ptr g)
00340 {
00341 return (g->num_nodes / issue_rate);
00342 }
00343
00344
00345
00346 static node_sched_params_ptr node_sched_params;
00347
00348
00349
00350
00351 static void
00352 set_node_sched_params (ddg_ptr g)
00353 {
00354 int i;
00355
00356
00357
00358 node_sched_params = (node_sched_params_ptr)
00359 xcalloc (g->num_nodes,
00360 sizeof (struct node_sched_params));
00361
00362
00363
00364 for (i = 0; i < g->num_nodes; i++)
00365 {
00366
00367 node_sched_params[i].asap = g->nodes[i].aux.count;
00368 g->nodes[i].aux.info = &node_sched_params[i];
00369 }
00370 }
00371
00372 static void
00373 print_node_sched_params (FILE * file, int num_nodes)
00374 {
00375 int i;
00376
00377 if (! file)
00378 return;
00379 for (i = 0; i < num_nodes; i++)
00380 {
00381 node_sched_params_ptr nsp = &node_sched_params[i];
00382 rtx reg_move = nsp->first_reg_move;
00383 int j;
00384
00385 fprintf (file, "Node %d:\n", i);
00386 fprintf (file, " asap = %d:\n", nsp->asap);
00387 fprintf (file, " time = %d:\n", nsp->time);
00388 fprintf (file, " nreg_moves = %d:\n", nsp->nreg_moves);
00389 for (j = 0; j < nsp->nreg_moves; j++)
00390 {
00391 fprintf (file, " reg_move = ");
00392 print_rtl_single (file, reg_move);
00393 reg_move = PREV_INSN (reg_move);
00394 }
00395 }
00396 }
00397
00398
00399
00400
00401 static int
00402 calculate_maxii (ddg_ptr g)
00403 {
00404 int i;
00405 int maxii = 0;
00406
00407 for (i = 0; i < g->num_nodes; i++)
00408 {
00409 ddg_node_ptr u = &g->nodes[i];
00410 ddg_edge_ptr e;
00411 int max_edge_latency = 0;
00412
00413 for (e = u->out; e; e = e->next_out)
00414 max_edge_latency = MAX (max_edge_latency, e->latency);
00415
00416 maxii += max_edge_latency;
00417 }
00418 return maxii;
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 static struct undo_replace_buff_elem *
00433 generate_reg_moves (partial_schedule_ptr ps)
00434 {
00435 ddg_ptr g = ps->g;
00436 int ii = ps->ii;
00437 int i;
00438 struct undo_replace_buff_elem *reg_move_replaces = NULL;
00439
00440 for (i = 0; i < g->num_nodes; i++)
00441 {
00442 ddg_node_ptr u = &g->nodes[i];
00443 ddg_edge_ptr e;
00444 int nreg_moves = 0, i_reg_move;
00445 sbitmap *uses_of_defs;
00446 rtx last_reg_move;
00447 rtx prev_reg, old_reg;
00448
00449
00450
00451 for (e = u->out; e; e = e->next_out)
00452 if (e->type == TRUE_DEP && e->dest != e->src)
00453 {
00454 int nreg_moves4e = (SCHED_TIME (e->dest) - SCHED_TIME (e->src)) / ii;
00455
00456 if (e->distance == 1)
00457 nreg_moves4e = (SCHED_TIME (e->dest) - SCHED_TIME (e->src) + ii) / ii;
00458
00459
00460
00461 if (SCHED_ROW (e->dest) == SCHED_ROW (e->src)
00462 && SCHED_COLUMN (e->dest) < SCHED_COLUMN (e->src))
00463 nreg_moves4e--;
00464
00465 nreg_moves = MAX (nreg_moves, nreg_moves4e);
00466 }
00467
00468 if (nreg_moves == 0)
00469 continue;
00470
00471
00472
00473
00474
00475 uses_of_defs = sbitmap_vector_alloc (nreg_moves, g->num_nodes);
00476 sbitmap_vector_zero (uses_of_defs, nreg_moves);
00477 for (e = u->out; e; e = e->next_out)
00478 if (e->type == TRUE_DEP && e->dest != e->src)
00479 {
00480 int dest_copy = (SCHED_TIME (e->dest) - SCHED_TIME (e->src)) / ii;
00481
00482 if (e->distance == 1)
00483 dest_copy = (SCHED_TIME (e->dest) - SCHED_TIME (e->src) + ii) / ii;
00484
00485 if (SCHED_ROW (e->dest) == SCHED_ROW (e->src)
00486 && SCHED_COLUMN (e->dest) < SCHED_COLUMN (e->src))
00487 dest_copy--;
00488
00489 if (dest_copy)
00490 SET_BIT (uses_of_defs[dest_copy - 1], e->dest->cuid);
00491 }
00492
00493
00494 SCHED_NREG_MOVES (u) = nreg_moves;
00495 old_reg = prev_reg = copy_rtx (SET_DEST (single_set (u->insn)));
00496 last_reg_move = u->insn;
00497
00498 for (i_reg_move = 0; i_reg_move < nreg_moves; i_reg_move++)
00499 {
00500 unsigned int i_use = 0;
00501 rtx new_reg = gen_reg_rtx (GET_MODE (prev_reg));
00502 rtx reg_move = gen_move_insn (new_reg, prev_reg);
00503 sbitmap_iterator sbi;
00504
00505 add_insn_before (reg_move, last_reg_move);
00506 last_reg_move = reg_move;
00507
00508 if (!SCHED_FIRST_REG_MOVE (u))
00509 SCHED_FIRST_REG_MOVE (u) = reg_move;
00510
00511 EXECUTE_IF_SET_IN_SBITMAP (uses_of_defs[i_reg_move], 0, i_use, sbi)
00512 {
00513 struct undo_replace_buff_elem *rep;
00514
00515 rep = (struct undo_replace_buff_elem *)
00516 xcalloc (1, sizeof (struct undo_replace_buff_elem));
00517 rep->insn = g->nodes[i_use].insn;
00518 rep->orig_reg = old_reg;
00519 rep->new_reg = new_reg;
00520
00521 if (! reg_move_replaces)
00522 reg_move_replaces = rep;
00523 else
00524 {
00525 rep->next = reg_move_replaces;
00526 reg_move_replaces = rep;
00527 }
00528
00529 replace_rtx (g->nodes[i_use].insn, old_reg, new_reg);
00530 }
00531
00532 prev_reg = new_reg;
00533 }
00534 sbitmap_vector_free (uses_of_defs);
00535 }
00536 return reg_move_replaces;
00537 }
00538
00539
00540
00541
00542
00543 static void
00544 undo_generate_reg_moves (partial_schedule_ptr ps,
00545 struct undo_replace_buff_elem *reg_move_replaces)
00546 {
00547 int i,j;
00548
00549 for (i = 0; i < ps->g->num_nodes; i++)
00550 {
00551 ddg_node_ptr u = &ps->g->nodes[i];
00552 rtx prev;
00553 rtx crr = SCHED_FIRST_REG_MOVE (u);
00554
00555 for (j = 0; j < SCHED_NREG_MOVES (u); j++)
00556 {
00557 prev = PREV_INSN (crr);
00558 delete_insn (crr);
00559 crr = prev;
00560 }
00561 SCHED_FIRST_REG_MOVE (u) = NULL_RTX;
00562 }
00563
00564 while (reg_move_replaces)
00565 {
00566 struct undo_replace_buff_elem *rep = reg_move_replaces;
00567
00568 reg_move_replaces = reg_move_replaces->next;
00569 replace_rtx (rep->insn, rep->new_reg, rep->orig_reg);
00570 }
00571 }
00572
00573
00574 static void
00575 free_undo_replace_buff (struct undo_replace_buff_elem *reg_move_replaces)
00576 {
00577
00578 while (reg_move_replaces)
00579 {
00580 struct undo_replace_buff_elem *rep = reg_move_replaces;
00581
00582 reg_move_replaces = reg_move_replaces->next;
00583 free (rep);
00584 }
00585 }
00586
00587
00588
00589 static void
00590 normalize_sched_times (partial_schedule_ptr ps)
00591 {
00592 int i;
00593 ddg_ptr g = ps->g;
00594 int amount = PS_MIN_CYCLE (ps);
00595 int ii = ps->ii;
00596
00597
00598 for (i = 0; i < g->num_nodes - 1; i++)
00599 {
00600 ddg_node_ptr u = &g->nodes[i];
00601 int normalized_time = SCHED_TIME (u) - amount;
00602
00603 gcc_assert (normalized_time >= 0);
00604
00605 SCHED_TIME (u) = normalized_time;
00606 SCHED_ROW (u) = normalized_time % ii;
00607 SCHED_STAGE (u) = normalized_time / ii;
00608 }
00609 }
00610
00611
00612 static void
00613 set_columns_for_ps (partial_schedule_ptr ps)
00614 {
00615 int row;
00616
00617 for (row = 0; row < ps->ii; row++)
00618 {
00619 ps_insn_ptr cur_insn = ps->rows[row];
00620 int column = 0;
00621
00622 for (; cur_insn; cur_insn = cur_insn->next_in_row)
00623 SCHED_COLUMN (cur_insn->node) = column++;
00624 }
00625 }
00626
00627
00628
00629
00630 static void
00631 permute_partial_schedule (partial_schedule_ptr ps, rtx last)
00632 {
00633 int ii = ps->ii;
00634 int row;
00635 ps_insn_ptr ps_ij;
00636
00637 for (row = 0; row < ii ; row++)
00638 for (ps_ij = ps->rows[row]; ps_ij; ps_ij = ps_ij->next_in_row)
00639 if (PREV_INSN (last) != ps_ij->node->insn)
00640 reorder_insns_nobb (ps_ij->node->first_note, ps_ij->node->insn,
00641 PREV_INSN (last));
00642 }
00643
00644
00645
00646
00647
00648
00649 static void
00650 undo_permute_partial_schedule (partial_schedule_ptr ps, rtx last)
00651 {
00652 int i;
00653
00654 for (i = 0 ; i < ps->g->num_nodes; i++)
00655 if (last == ps->g->nodes[i].insn
00656 || last == ps->g->nodes[i].first_note)
00657 break;
00658 else if (PREV_INSN (last) != ps->g->nodes[i].insn)
00659 reorder_insns_nobb (ps->g->nodes[i].first_note, ps->g->nodes[i].insn,
00660 PREV_INSN (last));
00661 }
00662
00663
00664
00665
00666 static void
00667 duplicate_insns_of_cycles (partial_schedule_ptr ps, int from_stage,
00668 int to_stage, int for_prolog)
00669 {
00670 int row;
00671 ps_insn_ptr ps_ij;
00672
00673 for (row = 0; row < ps->ii; row++)
00674 for (ps_ij = ps->rows[row]; ps_ij; ps_ij = ps_ij->next_in_row)
00675 {
00676 ddg_node_ptr u_node = ps_ij->node;
00677 int j, i_reg_moves;
00678 rtx reg_move = NULL_RTX;
00679
00680 if (for_prolog)
00681 {
00682
00683
00684
00685 i_reg_moves = to_stage - SCHED_STAGE (u_node) + 1;
00686 i_reg_moves = MAX (i_reg_moves, 0);
00687 i_reg_moves = MIN (i_reg_moves, SCHED_NREG_MOVES (u_node));
00688
00689
00690 if (i_reg_moves)
00691 {
00692 reg_move = SCHED_FIRST_REG_MOVE (u_node);
00693 for (j = 1; j < i_reg_moves; j++)
00694 reg_move = PREV_INSN (reg_move);
00695 }
00696 }
00697 else
00698 {
00699
00700
00701
00702
00703 i_reg_moves = SCHED_NREG_MOVES (u_node)
00704 - (from_stage - SCHED_STAGE (u_node) - 1);
00705 i_reg_moves = MAX (i_reg_moves, 0);
00706 i_reg_moves = MIN (i_reg_moves, SCHED_NREG_MOVES (u_node));
00707
00708
00709 if (i_reg_moves)
00710 {
00711 reg_move = SCHED_FIRST_REG_MOVE (u_node);
00712 for (j = 1; j < SCHED_NREG_MOVES (u_node); j++)
00713 reg_move = PREV_INSN (reg_move);
00714 }
00715 }
00716
00717 for (j = 0; j < i_reg_moves; j++, reg_move = NEXT_INSN (reg_move))
00718 emit_insn (copy_rtx (PATTERN (reg_move)));
00719 if (SCHED_STAGE (u_node) >= from_stage
00720 && SCHED_STAGE (u_node) <= to_stage)
00721 duplicate_insn_chain (u_node->first_note, u_node->insn);
00722 }
00723 }
00724
00725
00726
00727 static void
00728 generate_prolog_epilog (partial_schedule_ptr ps, struct loop * loop, rtx count_reg)
00729 {
00730 int i;
00731 int last_stage = PS_STAGE_COUNT (ps) - 1;
00732 edge e;
00733
00734
00735 start_sequence ();
00736
00737 if (count_reg)
00738
00739
00740 emit_insn (gen_sub2_insn (count_reg, GEN_INT (last_stage)));
00741
00742 for (i = 0; i < last_stage; i++)
00743 duplicate_insns_of_cycles (ps, 0, i, 1);
00744
00745
00746 e = loop_preheader_edge (loop);
00747 loop_split_edge_with(e , get_insns());
00748
00749 end_sequence ();
00750
00751
00752 start_sequence ();
00753
00754 for (i = 0; i < last_stage; i++)
00755 duplicate_insns_of_cycles (ps, i + 1, last_stage, 0);
00756
00757
00758 gcc_assert (loop->single_exit);
00759 e = loop->single_exit;
00760 loop_split_edge_with(e , get_insns());
00761 end_sequence ();
00762 }
00763
00764
00765
00766 static rtx
00767 find_line_note (rtx insn)
00768 {
00769 for (; insn; insn = PREV_INSN (insn))
00770 if (NOTE_P (insn)
00771 && NOTE_LINE_NUMBER (insn) >= 0)
00772 break;
00773
00774 return insn;
00775 }
00776
00777
00778
00779 static bool
00780 loop_single_full_bb_p (struct loop *loop)
00781 {
00782 unsigned i;
00783 basic_block *bbs = get_loop_body (loop);
00784
00785 for (i = 0; i < loop->num_nodes ; i++)
00786 {
00787 rtx head, tail;
00788 bool empty_bb = true;
00789
00790 if (bbs[i] == loop->header)
00791 continue;
00792
00793
00794
00795 get_ebb_head_tail (bbs[i], bbs[i], &head, &tail);
00796 for (; head != NEXT_INSN (tail); head = NEXT_INSN (head))
00797 {
00798 if (NOTE_P (head) || LABEL_P (head)
00799 || (INSN_P (head) && JUMP_P (head)))
00800 continue;
00801 empty_bb = false;
00802 break;
00803 }
00804
00805 if (! empty_bb)
00806 {
00807 free (bbs);
00808 return false;
00809 }
00810 }
00811 free (bbs);
00812 return true;
00813 }
00814
00815
00816
00817 #define SIMPLE_SMS_LOOP_P(loop) ((loop->num_nodes < 3 ) \
00818 && (EDGE_COUNT (loop->latch->preds) == 1) \
00819 && (EDGE_COUNT (loop->latch->succs) == 1))
00820
00821
00822
00823 static bool
00824 loop_canon_p (struct loop *loop)
00825 {
00826
00827 if (loop->inner || ! loop->outer)
00828 return false;
00829
00830 if (!loop->single_exit)
00831 {
00832 if (dump_file)
00833 {
00834 rtx line_note = find_line_note (BB_END (loop->header));
00835
00836 fprintf (dump_file, "SMS loop many exits ");
00837 if (line_note)
00838 {
00839 expanded_location xloc;
00840 NOTE_EXPANDED_LOCATION (xloc, line_note);
00841 fprintf (dump_file, " %s %d (file, line)\n",
00842 xloc.file, xloc.line);
00843 }
00844 }
00845 return false;
00846 }
00847
00848 if (! SIMPLE_SMS_LOOP_P (loop) && ! loop_single_full_bb_p (loop))
00849 {
00850 if (dump_file)
00851 {
00852 rtx line_note = find_line_note (BB_END (loop->header));
00853
00854 fprintf (dump_file, "SMS loop many BBs. ");
00855 if (line_note)
00856 {
00857 expanded_location xloc;
00858 NOTE_EXPANDED_LOCATION (xloc, line_note);
00859 fprintf (dump_file, " %s %d (file, line)\n",
00860 xloc.file, xloc.line);
00861 }
00862 }
00863 return false;
00864 }
00865
00866 return true;
00867 }
00868
00869
00870
00871
00872 static void
00873 canon_loop (struct loop *loop)
00874 {
00875 edge e;
00876 edge_iterator i;
00877
00878
00879
00880 FOR_EACH_EDGE (e, i, EXIT_BLOCK_PTR->preds)
00881 if ((e->flags & EDGE_FALLTHRU) && (EDGE_COUNT (e->src->succs) > 1))
00882 loop_split_edge_with (e, NULL_RTX);
00883
00884 if (loop->latch == loop->header
00885 || EDGE_COUNT (loop->latch->succs) > 1)
00886 {
00887 FOR_EACH_EDGE (e, i, loop->header->preds)
00888 if (e->src == loop->latch)
00889 break;
00890 loop_split_edge_with (e, NULL_RTX);
00891 }
00892 }
00893
00894
00895
00896 static void
00897 sms_schedule (void)
00898 {
00899 static int passes = 0;
00900 rtx insn;
00901 ddg_ptr *g_arr, g;
00902 int * node_order;
00903 int maxii;
00904 unsigned i,num_loops;
00905 partial_schedule_ptr ps;
00906 struct df *df;
00907 struct loops *loops;
00908 basic_block bb = NULL;
00909
00910 struct loop * nloop;
00911 basic_block condition_bb = NULL;
00912 edge latch_edge;
00913 gcov_type trip_count = 0;
00914
00915 loops = loop_optimizer_init (LOOPS_HAVE_PREHEADERS
00916 | LOOPS_HAVE_MARKED_SINGLE_EXITS);
00917 if (!loops)
00918 return;
00919
00920
00921 if (targetm.sched.issue_rate)
00922 {
00923 int temp = reload_completed;
00924
00925 reload_completed = 1;
00926 issue_rate = targetm.sched.issue_rate ();
00927 reload_completed = temp;
00928 }
00929 else
00930 issue_rate = 1;
00931
00932
00933 current_sched_info = &sms_sched_info;
00934 sched_init ();
00935
00936
00937 df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS);
00938 df_rd_add_problem (df, 0);
00939 df_ru_add_problem (df, 0);
00940 df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN);
00941 df_analyze (df);
00942
00943 if (dump_file)
00944 df_dump (df, dump_file);
00945
00946
00947
00948 g_arr = XCNEWVEC (ddg_ptr, loops->num);
00949
00950
00951
00952
00953 for (i = 0; i < loops->num; i++)
00954 {
00955 rtx head, tail;
00956 rtx count_reg;
00957 struct loop *loop = loops->parray[i];
00958
00959
00960 if ((passes++ > MAX_SMS_LOOP_NUMBER) && (MAX_SMS_LOOP_NUMBER != -1))
00961 {
00962 if (dump_file)
00963 fprintf (dump_file, "SMS reached MAX_PASSES... \n");
00964
00965 break;
00966 }
00967
00968 if (! loop_canon_p (loop))
00969 continue;
00970
00971 if (! loop_single_full_bb_p (loop))
00972 continue;
00973
00974 bb = loop->header;
00975
00976 get_ebb_head_tail (bb, bb, &head, &tail);
00977 latch_edge = loop_latch_edge (loop);
00978 gcc_assert (loop->single_exit);
00979 if (loop->single_exit->count)
00980 trip_count = latch_edge->count / loop->single_exit->count;
00981
00982
00983
00984 if ( latch_edge->count
00985 && (latch_edge->count < loop->single_exit->count * SMS_LOOP_AVERAGE_COUNT_THRESHOLD))
00986 {
00987 if (dump_file)
00988 {
00989 rtx line_note = find_line_note (tail);
00990
00991 if (line_note)
00992 {
00993 expanded_location xloc;
00994 NOTE_EXPANDED_LOCATION (xloc, line_note);
00995 fprintf (dump_file, "SMS bb %s %d (file, line)\n",
00996 xloc.file, xloc.line);
00997 }
00998 fprintf (dump_file, "SMS single-bb-loop\n");
00999 if (profile_info && flag_branch_probabilities)
01000 {
01001 fprintf (dump_file, "SMS loop-count ");
01002 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
01003 (HOST_WIDEST_INT) bb->count);
01004 fprintf (dump_file, "\n");
01005 fprintf (dump_file, "SMS trip-count ");
01006 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
01007 (HOST_WIDEST_INT) trip_count);
01008 fprintf (dump_file, "\n");
01009 fprintf (dump_file, "SMS profile-sum-max ");
01010 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
01011 (HOST_WIDEST_INT) profile_info->sum_max);
01012 fprintf (dump_file, "\n");
01013 }
01014 }
01015 continue;
01016 }
01017
01018
01019 if ( !(count_reg = doloop_register_get (tail)))
01020 continue;
01021
01022
01023 for (insn = head; insn != NEXT_INSN (tail); insn = NEXT_INSN (insn))
01024 if (CALL_P (insn)
01025 || BARRIER_P (insn)
01026 || (INSN_P (insn) && !JUMP_P (insn)
01027 && !single_set (insn) && GET_CODE (PATTERN (insn)) != USE))
01028 break;
01029
01030 if (insn != NEXT_INSN (tail))
01031 {
01032 if (dump_file)
01033 {
01034 if (CALL_P (insn))
01035 fprintf (dump_file, "SMS loop-with-call\n");
01036 else if (BARRIER_P (insn))
01037 fprintf (dump_file, "SMS loop-with-barrier\n");
01038 else
01039 fprintf (dump_file, "SMS loop-with-not-single-set\n");
01040 print_rtl_single (dump_file, insn);
01041 }
01042
01043 continue;
01044 }
01045
01046 if (! (g = create_ddg (bb, df, 0)))
01047 {
01048 if (dump_file)
01049 fprintf (dump_file, "SMS doloop\n");
01050 continue;
01051 }
01052
01053 g_arr[i] = g;
01054 }
01055
01056
01057 df_finish (df);
01058 df = NULL;
01059
01060
01061 num_loops = loops->num;
01062
01063 for (i = 0; i < num_loops; i++)
01064 {
01065 rtx head, tail;
01066 rtx count_reg, count_init;
01067 int mii, rec_mii;
01068 unsigned stage_count = 0;
01069 HOST_WIDEST_INT loop_count = 0;
01070 struct loop *loop = loops->parray[i];
01071
01072 if (! (g = g_arr[i]))
01073 continue;
01074
01075 if (dump_file)
01076 print_ddg (dump_file, g);
01077
01078 get_ebb_head_tail (loop->header, loop->header, &head, &tail);
01079
01080 latch_edge = loop_latch_edge (loop);
01081 gcc_assert (loop->single_exit);
01082 if (loop->single_exit->count)
01083 trip_count = latch_edge->count / loop->single_exit->count;
01084
01085 if (dump_file)
01086 {
01087 rtx line_note = find_line_note (tail);
01088
01089 if (line_note)
01090 {
01091 expanded_location xloc;
01092 NOTE_EXPANDED_LOCATION (xloc, line_note);
01093 fprintf (dump_file, "SMS bb %s %d (file, line)\n",
01094 xloc.file, xloc.line);
01095 }
01096 fprintf (dump_file, "SMS single-bb-loop\n");
01097 if (profile_info && flag_branch_probabilities)
01098 {
01099 fprintf (dump_file, "SMS loop-count ");
01100 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
01101 (HOST_WIDEST_INT) bb->count);
01102 fprintf (dump_file, "\n");
01103 fprintf (dump_file, "SMS profile-sum-max ");
01104 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
01105 (HOST_WIDEST_INT) profile_info->sum_max);
01106 fprintf (dump_file, "\n");
01107 }
01108 fprintf (dump_file, "SMS doloop\n");
01109 fprintf (dump_file, "SMS built-ddg %d\n", g->num_nodes);
01110 fprintf (dump_file, "SMS num-loads %d\n", g->num_loads);
01111 fprintf (dump_file, "SMS num-stores %d\n", g->num_stores);
01112 }
01113
01114
01115
01116
01117 count_init = NULL_RTX;
01118 if ((count_reg = doloop_register_get (tail)))
01119 {
01120 basic_block pre_header;
01121
01122 pre_header = loop_preheader_edge (loop)->src;
01123 count_init = const_iteration_count (count_reg, pre_header,
01124 &loop_count);
01125 }
01126 gcc_assert (count_reg);
01127
01128 if (dump_file && count_init)
01129 {
01130 fprintf (dump_file, "SMS const-doloop ");
01131 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
01132 loop_count);
01133 fprintf (dump_file, "\n");
01134 }
01135
01136 node_order = XNEWVEC (int, g->num_nodes);
01137
01138 mii = 1;
01139 rec_mii = sms_order_nodes (g, mii, node_order);
01140 mii = MAX (res_MII (g), rec_mii);
01141 maxii = (calculate_maxii (g) * SMS_MAX_II_FACTOR) / 100;
01142
01143 if (dump_file)
01144 fprintf (dump_file, "SMS iis %d %d %d (rec_mii, mii, maxii)\n",
01145 rec_mii, mii, maxii);
01146
01147
01148
01149 set_node_sched_params (g);
01150
01151 ps = sms_schedule_by_order (g, mii, maxii, node_order);
01152
01153 if (ps)
01154 stage_count = PS_STAGE_COUNT (ps);
01155
01156
01157
01158 if (stage_count < 1
01159 || (count_init && (loop_count <= stage_count))
01160 || (flag_branch_probabilities && (trip_count <= stage_count)))
01161 {
01162 if (dump_file)
01163 {
01164 fprintf (dump_file, "SMS failed... \n");
01165 fprintf (dump_file, "SMS sched-failed (stage-count=%d, loop-count=", stage_count);
01166 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, loop_count);
01167 fprintf (dump_file, ", trip-count=");
01168 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, trip_count);
01169 fprintf (dump_file, ")\n");
01170 }
01171 continue;
01172 }
01173 else
01174 {
01175 int orig_cycles = kernel_number_of_cycles (BB_HEAD (g->bb), BB_END (g->bb));
01176 int new_cycles;
01177 struct undo_replace_buff_elem *reg_move_replaces;
01178
01179 if (dump_file)
01180 {
01181 fprintf (dump_file,
01182 "SMS succeeded %d %d (with ii, sc)\n", ps->ii,
01183 stage_count);
01184 print_partial_schedule (ps, dump_file);
01185 fprintf (dump_file,
01186 "SMS Branch (%d) will later be scheduled at cycle %d.\n",
01187 g->closing_branch->cuid, PS_MIN_CYCLE (ps) - 1);
01188 }
01189
01190
01191
01192
01193
01194
01195 normalize_sched_times (ps);
01196 rotate_partial_schedule (ps, PS_MIN_CYCLE (ps));
01197 set_columns_for_ps (ps);
01198
01199
01200 permute_partial_schedule (ps, g->closing_branch->first_note);
01201 reg_move_replaces = generate_reg_moves (ps);
01202
01203
01204 new_cycles = kernel_number_of_cycles (BB_HEAD (g->bb), BB_END (g->bb));
01205
01206
01207 undo_permute_partial_schedule (ps, g->closing_branch->first_note);
01208 if (reg_move_replaces)
01209 undo_generate_reg_moves (ps, reg_move_replaces);
01210
01211 if ( new_cycles >= orig_cycles)
01212 {
01213
01214
01215 if (dump_file)
01216 fprintf (dump_file, "Undoing SMS because it is not profitable.\n");
01217
01218 }
01219 else
01220 {
01221 canon_loop (loop);
01222
01223
01224 if (count_reg && ! count_init)
01225 {
01226 rtx comp_rtx = gen_rtx_fmt_ee (GT, VOIDmode, count_reg,
01227 GEN_INT(stage_count));
01228
01229 nloop = loop_version (loops, loop, comp_rtx, &condition_bb,
01230 true);
01231 }
01232
01233
01234 if (count_reg && count_init)
01235 SET_SRC (single_set (count_init)) = GEN_INT (loop_count
01236 - stage_count + 1);
01237
01238
01239 permute_partial_schedule (ps, g->closing_branch->first_note);
01240
01241
01242
01243 if (! flag_resched_modulo_sched)
01244 g->bb->flags |= BB_DISABLE_SCHEDULE;
01245
01246 g->bb->flags |= BB_DIRTY;
01247
01248 reg_move_replaces = generate_reg_moves (ps);
01249 if (dump_file)
01250 print_node_sched_params (dump_file, g->num_nodes);
01251
01252 if (count_reg && !count_init)
01253 generate_prolog_epilog (ps, loop, count_reg);
01254 else
01255 generate_prolog_epilog (ps, loop, NULL_RTX);
01256 }
01257 free_undo_replace_buff (reg_move_replaces);
01258 }
01259
01260 free_partial_schedule (ps);
01261 free (node_sched_params);
01262 free (node_order);
01263 free_ddg (g);
01264 }
01265
01266 free (g_arr);
01267
01268
01269 sched_finish ();
01270 loop_optimizer_finalize (loops);
01271 }
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347 #define DFA_HISTORY SMS_DFA_HISTORY
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358 static int
01359 get_sched_window (partial_schedule_ptr ps, int *nodes_order, int i,
01360 sbitmap sched_nodes, int ii, int *start_p, int *step_p, int *end_p)
01361 {
01362 int start, step, end;
01363 ddg_edge_ptr e;
01364 int u = nodes_order [i];
01365 ddg_node_ptr u_node = &ps->g->nodes[u];
01366 sbitmap psp = sbitmap_alloc (ps->g->num_nodes);
01367 sbitmap pss = sbitmap_alloc (ps->g->num_nodes);
01368 sbitmap u_node_preds = NODE_PREDECESSORS (u_node);
01369 sbitmap u_node_succs = NODE_SUCCESSORS (u_node);
01370 int psp_not_empty;
01371 int pss_not_empty;
01372
01373
01374 sbitmap_zero (psp);
01375 sbitmap_zero (pss);
01376 psp_not_empty = sbitmap_a_and_b_cg (psp, u_node_preds, sched_nodes);
01377 pss_not_empty = sbitmap_a_and_b_cg (pss, u_node_succs, sched_nodes);
01378
01379 if (psp_not_empty && !pss_not_empty)
01380 {
01381 int early_start = INT_MIN;
01382
01383 end = INT_MAX;
01384 for (e = u_node->in; e != 0; e = e->next_in)
01385 {
01386 ddg_node_ptr v_node = e->src;
01387 if (TEST_BIT (sched_nodes, v_node->cuid))
01388 {
01389 int node_st = SCHED_TIME (v_node)
01390 + e->latency - (e->distance * ii);
01391
01392 early_start = MAX (early_start, node_st);
01393
01394 if (e->data_type == MEM_DEP)
01395 end = MIN (end, SCHED_TIME (v_node) + ii - 1);
01396 }
01397 }
01398 start = early_start;
01399 end = MIN (end, early_start + ii);
01400 step = 1;
01401 }
01402
01403 else if (!psp_not_empty && pss_not_empty)
01404 {
01405 int late_start = INT_MAX;
01406
01407 end = INT_MIN;
01408 for (e = u_node->out; e != 0; e = e->next_out)
01409 {
01410 ddg_node_ptr v_node = e->dest;
01411 if (TEST_BIT (sched_nodes, v_node->cuid))
01412 {
01413 late_start = MIN (late_start,
01414 SCHED_TIME (v_node) - e->latency
01415 + (e->distance * ii));
01416 if (e->data_type == MEM_DEP)
01417 end = MAX (end, SCHED_TIME (v_node) - ii + 1);
01418 }
01419 }
01420 start = late_start;
01421 end = MAX (end, late_start - ii);
01422 step = -1;
01423 }
01424
01425 else if (psp_not_empty && pss_not_empty)
01426 {
01427 int early_start = INT_MIN;
01428 int late_start = INT_MAX;
01429
01430 start = INT_MIN;
01431 end = INT_MAX;
01432 for (e = u_node->in; e != 0; e = e->next_in)
01433 {
01434 ddg_node_ptr v_node = e->src;
01435
01436 if (TEST_BIT (sched_nodes, v_node->cuid))
01437 {
01438 early_start = MAX (early_start,
01439 SCHED_TIME (v_node) + e->latency
01440 - (e->distance * ii));
01441 if (e->data_type == MEM_DEP)
01442 end = MIN (end, SCHED_TIME (v_node) + ii - 1);
01443 }
01444 }
01445 for (e = u_node->out; e != 0; e = e->next_out)
01446 {
01447 ddg_node_ptr v_node = e->dest;
01448
01449 if (TEST_BIT (sched_nodes, v_node->cuid))
01450 {
01451 late_start = MIN (late_start,
01452 SCHED_TIME (v_node) - e->latency
01453 + (e->distance * ii));
01454 if (e->data_type == MEM_DEP)
01455 start = MAX (start, SCHED_TIME (v_node) - ii + 1);
01456 }
01457 }
01458 start = MAX (start, early_start);
01459 end = MIN (end, MIN (early_start + ii, late_start + 1));
01460 step = 1;
01461 }
01462 else
01463 {
01464 start = SCHED_ASAP (u_node);
01465 end = start + ii;
01466 step = 1;
01467 }
01468
01469 *start_p = start;
01470 *step_p = step;
01471 *end_p = end;
01472 sbitmap_free (psp);
01473 sbitmap_free (pss);
01474
01475 if ((start >= end && step == 1) || (start <= end && step == -1))
01476 return -1;
01477 else
01478 return 0;
01479 }
01480
01481
01482
01483 static partial_schedule_ptr
01484 sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order)
01485 {
01486 int ii = mii;
01487 int i, c, success;
01488 int try_again_with_larger_ii = true;
01489 int num_nodes = g->num_nodes;
01490 ddg_edge_ptr e;
01491 int start, end, step;
01492 sbitmap sched_nodes = sbitmap_alloc (num_nodes);
01493 sbitmap must_precede = sbitmap_alloc (num_nodes);
01494 sbitmap must_follow = sbitmap_alloc (num_nodes);
01495 sbitmap tobe_scheduled = sbitmap_alloc (num_nodes);
01496
01497 partial_schedule_ptr ps = create_partial_schedule (ii, g, DFA_HISTORY);
01498
01499 sbitmap_ones (tobe_scheduled);
01500 sbitmap_zero (sched_nodes);
01501
01502 while ((! sbitmap_equal (tobe_scheduled, sched_nodes)
01503 || try_again_with_larger_ii ) && ii < maxii)
01504 {
01505 int j;
01506 bool unscheduled_nodes = false;
01507
01508 if (dump_file)
01509 fprintf(dump_file, "Starting with ii=%d\n", ii);
01510 if (try_again_with_larger_ii)
01511 {
01512 try_again_with_larger_ii = false;
01513 sbitmap_zero (sched_nodes);
01514 }
01515
01516 for (i = 0; i < num_nodes; i++)
01517 {
01518 int u = nodes_order[i];
01519 ddg_node_ptr u_node = &ps->g->nodes[u];
01520 rtx insn = u_node->insn;
01521
01522 if (!INSN_P (insn))
01523 {
01524 RESET_BIT (tobe_scheduled, u);
01525 continue;
01526 }
01527
01528 if (JUMP_P (insn))
01529 {
01530 RESET_BIT (tobe_scheduled, u);
01531 continue;
01532 }
01533
01534 if (TEST_BIT (sched_nodes, u))
01535 continue;
01536
01537
01538 j = i;
01539 while (get_sched_window (ps, nodes_order, i, sched_nodes, ii, &start, &step, &end) < 0
01540 && j > 0)
01541 {
01542 unscheduled_nodes = true;
01543 if (TEST_BIT (NODE_PREDECESSORS (u_node), nodes_order[j - 1])
01544 || TEST_BIT (NODE_SUCCESSORS (u_node), nodes_order[j - 1]))
01545 {
01546 ps_unschedule_node (ps, &ps->g->nodes[nodes_order[j - 1]]);
01547 RESET_BIT (sched_nodes, nodes_order [j - 1]);
01548 }
01549 j--;
01550 }
01551 if (j < 0)
01552 {
01553
01554 ii++;
01555 try_again_with_larger_ii = true;
01556 reset_partial_schedule (ps, ii);
01557 break;
01558 }
01559
01560 if (dump_file)
01561 fprintf(dump_file, "Trying to schedule node %d in (%d .. %d) step %d\n",
01562 u, start, end, step);
01563
01564
01565
01566 sbitmap_zero (must_precede);
01567 sbitmap_zero (must_follow);
01568 for (e = u_node->in; e != 0; e = e->next_in)
01569 if (TEST_BIT (sched_nodes, e->src->cuid)
01570 && e->latency == (ii * e->distance)
01571 && start == SCHED_TIME (e->src))
01572 SET_BIT (must_precede, e->src->cuid);
01573
01574 for (e = u_node->out; e != 0; e = e->next_out)
01575 if (TEST_BIT (sched_nodes, e->dest->cuid)
01576 && e->latency == (ii * e->distance)
01577 && end == SCHED_TIME (e->dest))
01578 SET_BIT (must_follow, e->dest->cuid);
01579
01580 success = 0;
01581 if ((step > 0 && start < end) || (step < 0 && start > end))
01582 for (c = start; c != end; c += step)
01583 {
01584 ps_insn_ptr psi;
01585
01586 psi = ps_add_node_check_conflicts (ps, u_node, c,
01587 must_precede,
01588 must_follow);
01589
01590 if (psi)
01591 {
01592 SCHED_TIME (u_node) = c;
01593 SET_BIT (sched_nodes, u);
01594 success = 1;
01595 if (dump_file)
01596 fprintf(dump_file, "Schedule in %d\n", c);
01597 break;
01598 }
01599 }
01600 if (!success)
01601 {
01602
01603 ii++;
01604 try_again_with_larger_ii = true;
01605 reset_partial_schedule (ps, ii);
01606 break;
01607 }
01608 if (unscheduled_nodes)
01609 break;
01610
01611
01612 }
01613 }
01614
01615 sbitmap_free (sched_nodes);
01616 sbitmap_free (must_precede);
01617 sbitmap_free (must_follow);
01618 sbitmap_free (tobe_scheduled);
01619
01620 if (ii >= maxii)
01621 {
01622 free_partial_schedule (ps);
01623 ps = NULL;
01624 }
01625 return ps;
01626 }
01627
01628
01629
01630
01631
01632
01633 #define ORDER_PARAMS(x) ((struct node_order_params *) (x)->aux.info)
01634 #define ASAP(x) (ORDER_PARAMS ((x))->asap)
01635 #define ALAP(x) (ORDER_PARAMS ((x))->alap)
01636 #define HEIGHT(x) (ORDER_PARAMS ((x))->height)
01637 #define MOB(x) (ALAP ((x)) - ASAP ((x)))
01638 #define DEPTH(x) (ASAP ((x)))
01639
01640 typedef struct node_order_params * nopa;
01641
01642 static void order_nodes_of_sccs (ddg_all_sccs_ptr, int * result);
01643 static int order_nodes_in_scc (ddg_ptr, sbitmap, sbitmap, int*, int);
01644 static nopa calculate_order_params (ddg_ptr, int mii);
01645 static int find_max_asap (ddg_ptr, sbitmap);
01646 static int find_max_hv_min_mob (ddg_ptr, sbitmap);
01647 static int find_max_dv_min_mob (ddg_ptr, sbitmap);
01648
01649 enum sms_direction {BOTTOMUP, TOPDOWN};
01650
01651 struct node_order_params
01652 {
01653 int asap;
01654 int alap;
01655 int height;
01656 };
01657
01658
01659 static void
01660 check_nodes_order (int *node_order, int num_nodes)
01661 {
01662 int i;
01663 sbitmap tmp = sbitmap_alloc (num_nodes);
01664
01665 sbitmap_zero (tmp);
01666
01667 for (i = 0; i < num_nodes; i++)
01668 {
01669 int u = node_order[i];
01670
01671 gcc_assert (u < num_nodes && u >= 0 && !TEST_BIT (tmp, u));
01672
01673 SET_BIT (tmp, u);
01674 }
01675
01676 sbitmap_free (tmp);
01677 }
01678
01679
01680
01681
01682 static int
01683 sms_order_nodes (ddg_ptr g, int mii, int * node_order)
01684 {
01685 int i;
01686 int rec_mii = 0;
01687 ddg_all_sccs_ptr sccs = create_ddg_all_sccs (g);
01688
01689 nopa nops = calculate_order_params (g, mii);
01690
01691 order_nodes_of_sccs (sccs, node_order);
01692
01693 if (sccs->num_sccs > 0)
01694
01695 rec_mii = sccs->sccs[0]->recurrence_length;
01696
01697
01698 for (i = 0; i < g->num_nodes; i++)
01699 {
01700 ddg_node_ptr v = &g->nodes[i];
01701 v->aux.count = ASAP (v);
01702 }
01703
01704 free (nops);
01705 free_ddg_all_sccs (sccs);
01706 check_nodes_order (node_order, g->num_nodes);
01707
01708 return rec_mii;
01709 }
01710
01711 static void
01712 order_nodes_of_sccs (ddg_all_sccs_ptr all_sccs, int * node_order)
01713 {
01714 int i, pos = 0;
01715 ddg_ptr g = all_sccs->ddg;
01716 int num_nodes = g->num_nodes;
01717 sbitmap prev_sccs = sbitmap_alloc (num_nodes);
01718 sbitmap on_path = sbitmap_alloc (num_nodes);
01719 sbitmap tmp = sbitmap_alloc (num_nodes);
01720 sbitmap ones = sbitmap_alloc (num_nodes);
01721
01722 sbitmap_zero (prev_sccs);
01723 sbitmap_ones (ones);
01724
01725
01726
01727 for (i = 0; i < all_sccs->num_sccs; i++)
01728 {
01729 ddg_scc_ptr scc = all_sccs->sccs[i];
01730
01731
01732 find_nodes_on_paths (on_path, g, prev_sccs, scc->nodes);
01733 sbitmap_a_or_b (tmp, scc->nodes, on_path);
01734
01735
01736 find_nodes_on_paths (on_path, g, scc->nodes, prev_sccs);
01737 sbitmap_a_or_b (tmp, tmp, on_path);
01738
01739
01740 sbitmap_difference (tmp, tmp, prev_sccs);
01741
01742 pos = order_nodes_in_scc (g, prev_sccs, tmp, node_order, pos);
01743
01744 }
01745
01746
01747
01748 while (pos < g->num_nodes)
01749 {
01750 sbitmap_difference (tmp, ones, prev_sccs);
01751 pos = order_nodes_in_scc (g, prev_sccs, tmp, node_order, pos);
01752 }
01753 sbitmap_free (prev_sccs);
01754 sbitmap_free (on_path);
01755 sbitmap_free (tmp);
01756 sbitmap_free (ones);
01757 }
01758
01759
01760 static struct node_order_params *
01761 calculate_order_params (ddg_ptr g, int mii ATTRIBUTE_UNUSED)
01762 {
01763 int u;
01764 int max_asap;
01765 int num_nodes = g->num_nodes;
01766 ddg_edge_ptr e;
01767
01768 nopa node_order_params_arr;
01769
01770
01771 node_order_params_arr = (nopa) xcalloc (num_nodes,
01772 sizeof (struct node_order_params));
01773
01774
01775 for (u = 0; u < num_nodes; u++)
01776 g->nodes[u].aux.info = &node_order_params_arr[u];
01777
01778
01779
01780
01781
01782
01783
01784 max_asap = 0;
01785 for (u = 0; u < num_nodes; u++)
01786 {
01787 ddg_node_ptr u_node = &g->nodes[u];
01788
01789 ASAP (u_node) = 0;
01790 for (e = u_node->in; e; e = e->next_in)
01791 if (e->distance == 0)
01792 ASAP (u_node) = MAX (ASAP (u_node),
01793 ASAP (e->src) + e->latency);
01794 max_asap = MAX (max_asap, ASAP (u_node));
01795 }
01796
01797 for (u = num_nodes - 1; u > -1; u--)
01798 {
01799 ddg_node_ptr u_node = &g->nodes[u];
01800
01801 ALAP (u_node) = max_asap;
01802 HEIGHT (u_node) = 0;
01803 for (e = u_node->out; e; e = e->next_out)
01804 if (e->distance == 0)
01805 {
01806 ALAP (u_node) = MIN (ALAP (u_node),
01807 ALAP (e->dest) - e->latency);
01808 HEIGHT (u_node) = MAX (HEIGHT (u_node),
01809 HEIGHT (e->dest) + e->latency);
01810 }
01811 }
01812
01813 return node_order_params_arr;
01814 }
01815
01816 static int
01817 find_max_asap (ddg_ptr g, sbitmap nodes)
01818 {
01819 unsigned int u = 0;
01820 int max_asap = -1;
01821 int result = -1;
01822 sbitmap_iterator sbi;
01823
01824 EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
01825 {
01826 ddg_node_ptr u_node = &g->nodes[u];
01827
01828 if (max_asap < ASAP (u_node))
01829 {
01830 max_asap = ASAP (u_node);
01831 result = u;
01832 }
01833 }
01834 return result;
01835 }
01836
01837 static int
01838 find_max_hv_min_mob (ddg_ptr g, sbitmap nodes)
01839 {
01840 unsigned int u = 0;
01841 int max_hv = -1;
01842 int min_mob = INT_MAX;
01843 int result = -1;
01844 sbitmap_iterator sbi;
01845
01846 EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
01847 {
01848 ddg_node_ptr u_node = &g->nodes[u];
01849
01850 if (max_hv < HEIGHT (u_node))
01851 {
01852 max_hv = HEIGHT (u_node);
01853 min_mob = MOB (u_node);
01854 result = u;
01855 }
01856 else if ((max_hv == HEIGHT (u_node))
01857 && (min_mob > MOB (u_node)))
01858 {
01859 min_mob = MOB (u_node);
01860 result = u;
01861 }
01862 }
01863 return result;
01864 }
01865
01866 static int
01867 find_max_dv_min_mob (ddg_ptr g, sbitmap nodes)
01868 {
01869 unsigned int u = 0;
01870 int max_dv = -1;
01871 int min_mob = INT_MAX;
01872 int result = -1;
01873 sbitmap_iterator sbi;
01874
01875 EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
01876 {
01877 ddg_node_ptr u_node = &g->nodes[u];
01878
01879 if (max_dv < DEPTH (u_node))
01880 {
01881 max_dv = DEPTH (u_node);
01882 min_mob = MOB (u_node);
01883 result = u;
01884 }
01885 else if ((max_dv == DEPTH (u_node))
01886 && (min_mob > MOB (u_node)))
01887 {
01888 min_mob = MOB (u_node);
01889 result = u;
01890 }
01891 }
01892 return result;
01893 }
01894
01895
01896
01897
01898
01899 static int
01900 order_nodes_in_scc (ddg_ptr g, sbitmap nodes_ordered, sbitmap scc,
01901 int * node_order, int pos)
01902 {
01903 enum sms_direction dir;
01904 int num_nodes = g->num_nodes;
01905 sbitmap workset = sbitmap_alloc (num_nodes);
01906 sbitmap tmp = sbitmap_alloc (num_nodes);
01907 sbitmap zero_bitmap = sbitmap_alloc (num_nodes);
01908 sbitmap predecessors = sbitmap_alloc (num_nodes);
01909 sbitmap successors = sbitmap_alloc (num_nodes);
01910
01911 sbitmap_zero (predecessors);
01912 find_predecessors (predecessors, g, nodes_ordered);
01913
01914 sbitmap_zero (successors);
01915 find_successors (successors, g, nodes_ordered);
01916
01917 sbitmap_zero (tmp);
01918 if (sbitmap_a_and_b_cg (tmp, predecessors, scc))
01919 {
01920 sbitmap_copy (workset, tmp);
01921 dir = BOTTOMUP;
01922 }
01923 else if (sbitmap_a_and_b_cg (tmp, successors, scc))
01924 {
01925 sbitmap_copy (workset, tmp);
01926 dir = TOPDOWN;
01927 }
01928 else
01929 {
01930 int u;
01931
01932 sbitmap_zero (workset);
01933 if ((u = find_max_asap (g, scc)) >= 0)
01934 SET_BIT (workset, u);
01935 dir = BOTTOMUP;
01936 }
01937
01938 sbitmap_zero (zero_bitmap);
01939 while (!sbitmap_equal (workset, zero_bitmap))
01940 {
01941 int v;
01942 ddg_node_ptr v_node;
01943 sbitmap v_node_preds;
01944 sbitmap v_node_succs;
01945
01946 if (dir == TOPDOWN)
01947 {
01948 while (!sbitmap_equal (workset, zero_bitmap))
01949 {
01950 v = find_max_hv_min_mob (g, workset);
01951 v_node = &g->nodes[v];
01952 node_order[pos++] = v;
01953 v_node_succs = NODE_SUCCESSORS (v_node);
01954 sbitmap_a_and_b (tmp, v_node_succs, scc);
01955
01956
01957 sbitmap_difference (tmp, tmp, nodes_ordered);
01958 sbitmap_a_or_b (workset, workset, tmp);
01959 RESET_BIT (workset, v);
01960 SET_BIT (nodes_ordered, v);
01961 }
01962 dir = BOTTOMUP;
01963 sbitmap_zero (predecessors);
01964 find_predecessors (predecessors, g, nodes_ordered);
01965 sbitmap_a_and_b (workset, predecessors, scc);
01966 }
01967 else
01968 {
01969 while (!sbitmap_equal (workset, zero_bitmap))
01970 {
01971 v = find_max_dv_min_mob (g, workset);
01972 v_node = &g->nodes[v];
01973 node_order[pos++] = v;
01974 v_node_preds = NODE_PREDECESSORS (v_node);
01975 sbitmap_a_and_b (tmp, v_node_preds, scc);
01976
01977
01978 sbitmap_difference (tmp, tmp, nodes_ordered);
01979 sbitmap_a_or_b (workset, workset, tmp);
01980 RESET_BIT (workset, v);
01981 SET_BIT (nodes_ordered, v);
01982 }
01983 dir = TOPDOWN;
01984 sbitmap_zero (successors);
01985 find_successors (successors, g, nodes_ordered);
01986 sbitmap_a_and_b (workset, successors, scc);
01987 }
01988 }
01989 sbitmap_free (tmp);
01990 sbitmap_free (workset);
01991 sbitmap_free (zero_bitmap);
01992 sbitmap_free (predecessors);
01993 sbitmap_free (successors);
01994 return pos;
01995 }
01996
01997
01998
01999
02000
02001
02002
02003 static partial_schedule_ptr
02004 create_partial_schedule (int ii, ddg_ptr g, int history)
02005 {
02006 partial_schedule_ptr ps = XNEW (struct partial_schedule);
02007 ps->rows = (ps_insn_ptr *) xcalloc (ii, sizeof (ps_insn_ptr));
02008 ps->ii = ii;
02009 ps->history = history;
02010 ps->min_cycle = INT_MAX;
02011 ps->max_cycle = INT_MIN;
02012 ps->g = g;
02013
02014 return ps;
02015 }
02016
02017
02018
02019 static void
02020 free_ps_insns (partial_schedule_ptr ps)
02021 {
02022 int i;
02023
02024 for (i = 0; i < ps->ii; i++)
02025 {
02026 while (ps->rows[i])
02027 {
02028 ps_insn_ptr ps_insn = ps->rows[i]->next_in_row;
02029
02030 free (ps->rows[i]);
02031 ps->rows[i] = ps_insn;
02032 }
02033 ps->rows[i] = NULL;
02034 }
02035 }
02036
02037
02038
02039 static void
02040 free_partial_schedule (partial_schedule_ptr ps)
02041 {
02042 if (!ps)
02043 return;
02044 free_ps_insns (ps);
02045 free (ps->rows);
02046 free (ps);
02047 }
02048
02049
02050
02051
02052 static void
02053 reset_partial_schedule (partial_schedule_ptr ps, int new_ii)
02054 {
02055 if (!ps)
02056 return;
02057 free_ps_insns (ps);
02058 if (new_ii == ps->ii)
02059 return;
02060 ps->rows = (ps_insn_ptr *) xrealloc (ps->rows, new_ii
02061 * sizeof (ps_insn_ptr));
02062 memset (ps->rows, 0, new_ii * sizeof (ps_insn_ptr));
02063 ps->ii = new_ii;
02064 ps->min_cycle = INT_MAX;
02065 ps->max_cycle = INT_MIN;
02066 }
02067
02068
02069
02070 void
02071 print_partial_schedule (partial_schedule_ptr ps, FILE *dump)
02072 {
02073 int i;
02074
02075 for (i = 0; i < ps->ii; i++)
02076 {
02077 ps_insn_ptr ps_i = ps->rows[i];
02078
02079 fprintf (dump, "\n[CYCLE %d ]: ", i);
02080 while (ps_i)
02081 {
02082 fprintf (dump, "%d, ",
02083 INSN_UID (ps_i->node->insn));
02084 ps_i = ps_i->next_in_row;
02085 }
02086 }
02087 }
02088
02089
02090 static ps_insn_ptr
02091 create_ps_insn (ddg_node_ptr node, int rest_count, int cycle)
02092 {
02093 ps_insn_ptr ps_i = XNEW (struct ps_insn);
02094
02095 ps_i->node = node;
02096 ps_i->next_in_row = NULL;
02097 ps_i->prev_in_row = NULL;
02098 ps_i->row_rest_count = rest_count;
02099 ps_i->cycle = cycle;
02100
02101 return ps_i;
02102 }
02103
02104
02105
02106
02107 static bool
02108 remove_node_from_ps (partial_schedule_ptr ps, ps_insn_ptr ps_i)
02109 {
02110 int row;
02111
02112 if (!ps || !ps_i)
02113 return false;
02114
02115 row = SMODULO (ps_i->cycle, ps->ii);
02116 if (! ps_i->prev_in_row)
02117 {
02118 if (ps_i != ps->rows[row])
02119 return false;
02120
02121 ps->rows[row] = ps_i->next_in_row;
02122 if (ps->rows[row])
02123 ps->rows[row]->prev_in_row = NULL;
02124 }
02125 else
02126 {
02127 ps_i->prev_in_row->next_in_row = ps_i->next_in_row;
02128 if (ps_i->next_in_row)
02129 ps_i->next_in_row->prev_in_row = ps_i->prev_in_row;
02130 }
02131 free (ps_i);
02132 return true;
02133 }
02134
02135
02136
02137
02138
02139
02140
02141 static bool
02142 ps_insn_find_column (partial_schedule_ptr ps, ps_insn_ptr ps_i,
02143 sbitmap must_precede, sbitmap must_follow)
02144 {
02145 ps_insn_ptr next_ps_i;
02146 ps_insn_ptr first_must_follow = NULL;
02147 ps_insn_ptr last_must_precede = NULL;
02148 int row;
02149
02150 if (! ps_i)
02151 return false;
02152
02153 row = SMODULO (ps_i->cycle, ps->ii);
02154
02155
02156
02157
02158 for (next_ps_i = ps->rows[row];
02159 next_ps_i;
02160 next_ps_i = next_ps_i->next_in_row)
02161 {
02162 if (TEST_BIT (must_follow, next_ps_i->node->cuid)
02163 && ! first_must_follow)
02164 first_must_follow = next_ps_i;
02165 if (TEST_BIT (must_precede, next_ps_i->node->cuid))
02166 {
02167
02168
02169 if (first_must_follow)
02170 return false;
02171 else
02172 last_must_precede = next_ps_i;
02173 }
02174 }
02175
02176
02177
02178 if (! last_must_precede)
02179 {
02180 ps_i->next_in_row = ps->rows[row];
02181 ps_i->prev_in_row = NULL;
02182 if (ps_i->next_in_row)
02183 ps_i->next_in_row->prev_in_row = ps_i;
02184 ps->rows[row] = ps_i;
02185 }
02186 else
02187 {
02188 ps_i->next_in_row = last_must_precede->next_in_row;
02189 last_must_precede->next_in_row = ps_i;
02190 ps_i->prev_in_row = last_must_precede;
02191 if (ps_i->next_in_row)
02192 ps_i->next_in_row->prev_in_row = ps_i;
02193 }
02194
02195 return true;
02196 }
02197
02198
02199
02200
02201
02202 static int
02203 ps_insn_advance_column (partial_schedule_ptr ps, ps_insn_ptr ps_i,
02204 sbitmap must_follow)
02205 {
02206 ps_insn_ptr prev, next;
02207 int row;
02208 ddg_node_ptr next_node;
02209
02210 if (!ps || !ps_i)
02211 return false;
02212
02213 row = SMODULO (ps_i->cycle, ps->ii);
02214
02215 if (! ps_i->next_in_row)
02216 return false;
02217
02218 next_node = ps_i->next_in_row->node;
02219
02220
02221
02222 if (TEST_BIT (must_follow, next_node->cuid))
02223 return false;
02224
02225
02226 prev = ps_i->prev_in_row;
02227 next = ps_i->next_in_row;
02228
02229 if (ps_i == ps->rows[row])
02230 ps->rows[row] = next;
02231
02232 ps_i->next_in_row = next->next_in_row;
02233
02234 if (next->next_in_row)
02235 next->next_in_row->prev_in_row = ps_i;
02236
02237 next->next_in_row = ps_i;
02238 ps_i->prev_in_row = next;
02239
02240 next->prev_in_row = prev;
02241 if (prev)
02242 prev->next_in_row = next;
02243
02244 return true;
02245 }
02246
02247
02248
02249
02250
02251
02252 static ps_insn_ptr
02253 add_node_to_ps (partial_schedule_ptr ps, ddg_node_ptr node, int cycle,
02254 sbitmap must_precede, sbitmap must_follow)
02255 {
02256 ps_insn_ptr ps_i;
02257 int rest_count = 1;
02258 int row = SMODULO (cycle, ps->ii);
02259
02260 if (ps->rows[row]
02261 && ps->rows[row]->row_rest_count >= issue_rate)
02262 return NULL;
02263
02264 if (ps->rows[row])
02265 rest_count += ps->rows[row]->row_rest_count;
02266
02267 ps_i = create_ps_insn (node, rest_count, cycle);
02268
02269
02270
02271 if (! ps_insn_find_column (ps, ps_i, must_precede, must_follow))
02272 {
02273 free (ps_i);
02274 return NULL;
02275 }
02276
02277 return ps_i;
02278 }
02279
02280
02281 static void
02282 advance_one_cycle (void)
02283 {
02284 if (targetm.sched.dfa_pre_cycle_insn)
02285 state_transition (curr_state,
02286 targetm.sched.dfa_pre_cycle_insn ());
02287
02288 state_transition (curr_state, NULL);
02289
02290 if (targetm.sched.dfa_post_cycle_insn)
02291 state_transition (curr_state,
02292 targetm.sched.dfa_post_cycle_insn ());
02293 }
02294
02295
02296
02297
02298
02299
02300
02301 static int
02302 kernel_number_of_cycles (rtx first_insn, rtx last_insn)
02303 {
02304 int cycles = 0;
02305 rtx insn;
02306 int can_issue_more = issue_rate;
02307
02308 state_reset (curr_state);
02309
02310 for (insn = first_insn;
02311 insn != NULL_RTX && insn != last_insn;
02312 insn = NEXT_INSN (insn))
02313 {
02314 if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
02315 continue;
02316
02317
02318 if (!can_issue_more || state_dead_lock_p (curr_state))
02319 {
02320 cycles ++;
02321 advance_one_cycle ();
02322 can_issue_more = issue_rate;
02323 }
02324
02325
02326
02327 if (state_transition (curr_state, insn) >= 0)
02328 {
02329 cycles ++;
02330 advance_one_cycle ();
02331 can_issue_more = issue_rate;
02332 }
02333
02334 if (targetm.sched.variable_issue)
02335 can_issue_more =
02336 targetm.sched.variable_issue (sched_dump, sched_verbose,
02337 insn, can_issue_more);
02338
02339
02340 else if (GET_CODE (PATTERN (insn)) != USE
02341 && GET_CODE (PATTERN (insn)) != CLOBBER)
02342 can_issue_more--;
02343 }
02344 return cycles;
02345 }
02346
02347
02348
02349
02350 static int
02351 ps_has_conflicts (partial_schedule_ptr ps, int from, int to)
02352 {
02353 int cycle;
02354
02355 state_reset (curr_state);
02356
02357 for (cycle = from; cycle <= to; cycle++)
02358 {
02359 ps_insn_ptr crr_insn;
02360
02361 int can_issue_more = issue_rate;
02362
02363
02364 for (crr_insn = ps->rows[SMODULO (cycle, ps->ii)];
02365 crr_insn;
02366 crr_insn = crr_insn->next_in_row)
02367 {
02368 rtx insn = crr_insn->node->insn;
02369
02370 if (!INSN_P (insn))
02371 continue;
02372
02373
02374 if (!can_issue_more || state_dead_lock_p (curr_state))
02375 return true;
02376
02377
02378
02379 if (state_transition (curr_state, insn) >= 0)
02380 return true;
02381
02382 if (targetm.sched.variable_issue)
02383 can_issue_more =
02384 targetm.sched.variable_issue (sched_dump, sched_verbose,
02385 insn, can_issue_more);
02386
02387
02388 else if (GET_CODE (PATTERN (insn)) != USE
02389 && GET_CODE (PATTERN (insn)) != CLOBBER)
02390 can_issue_more--;
02391 }
02392
02393
02394 advance_one_cycle ();
02395 }
02396 return false;
02397 }
02398
02399
02400
02401
02402
02403
02404 ps_insn_ptr
02405 ps_add_node_check_conflicts (partial_schedule_ptr ps, ddg_node_ptr n,
02406 int c, sbitmap must_precede,
02407 sbitmap must_follow)
02408 {
02409 int has_conflicts = 0;
02410 ps_insn_ptr ps_i;
02411
02412
02413
02414 if (! (ps_i = add_node_to_ps (ps, n, c, must_precede, must_follow)))
02415 return NULL;
02416
02417 has_conflicts = ps_has_conflicts (ps, c, c)
02418 || (ps->history > 0
02419 && ps_has_conflicts (ps,
02420 c - ps->history,
02421 c + ps->history));
02422
02423
02424
02425 while (has_conflicts)
02426 {
02427 if (! ps_insn_advance_column (ps, ps_i, must_follow))
02428 break;
02429 has_conflicts = ps_has_conflicts (ps, c, c)
02430 || (ps->history > 0
02431 && ps_has_conflicts (ps,
02432 c - ps->history,
02433 c + ps->history));
02434 }
02435
02436 if (has_conflicts)
02437 {
02438 remove_node_from_ps (ps, ps_i);
02439 return NULL;
02440 }
02441
02442 ps->min_cycle = MIN (ps->min_cycle, c);
02443 ps->max_cycle = MAX (ps->max_cycle, c);
02444 return ps_i;
02445 }
02446
02447
02448
02449 void
02450 rotate_partial_schedule (partial_schedule_ptr ps, int start_cycle)
02451 {
02452 int i, row, backward_rotates;
02453 int last_row = ps->ii - 1;
02454
02455 if (start_cycle == 0)
02456 return;
02457
02458 backward_rotates = SMODULO (start_cycle, ps->ii);
02459
02460
02461 for (i = 0; i < backward_rotates; i++)
02462 {
02463 ps_insn_ptr first_row = ps->rows[0];
02464
02465 for (row = 0; row < last_row; row++)
02466 ps->rows[row] = ps->rows[row+1];
02467
02468 ps->rows[last_row] = first_row;
02469 }
02470
02471 ps->max_cycle -= start_cycle;
02472 ps->min_cycle -= start_cycle;
02473 }
02474
02475
02476
02477
02478 static bool
02479 ps_unschedule_node (partial_schedule_ptr ps, ddg_node_ptr n)
02480 {
02481 ps_insn_ptr ps_i;
02482 int row = SMODULO (SCHED_TIME (n), ps->ii);
02483
02484 if (row < 0 || row > ps->ii)
02485 return false;
02486
02487 for (ps_i = ps->rows[row];
02488 ps_i && ps_i->node != n;
02489 ps_i = ps_i->next_in_row);
02490 if (!ps_i)
02491 return false;
02492
02493 return remove_node_from_ps (ps, ps_i);
02494 }
02495 #endif
02496
02497 static bool
02498 gate_handle_sms (void)
02499 {
02500 return (optimize > 0 && flag_modulo_sched);
02501 }
02502
02503
02504
02505
02506 static unsigned int
02507 rest_of_handle_sms (void)
02508 {
02509 #ifdef INSN_SCHEDULING
02510 basic_block bb;
02511
02512
02513 no_new_pseudos = 0;
02514
02515 cfg_layout_initialize (CLEANUP_UPDATE_LIFE);
02516 sms_schedule ();
02517
02518
02519 max_regno = max_reg_num ();
02520 allocate_reg_info (max_regno, FALSE, FALSE);
02521 update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
02522 (PROP_DEATH_NOTES
02523 | PROP_REG_INFO
02524 | PROP_KILL_DEAD_CODE
02525 | PROP_SCAN_DEAD_CODE));
02526
02527 no_new_pseudos = 1;
02528
02529
02530 FOR_EACH_BB (bb)
02531 if (bb->next_bb != EXIT_BLOCK_PTR)
02532 bb->aux = bb->next_bb;
02533 cfg_layout_finalize ();
02534 free_dominance_info (CDI_DOMINATORS);
02535 #endif
02536 return 0;
02537 }
02538
02539 struct tree_opt_pass pass_sms =
02540 {
02541 "sms",
02542 gate_handle_sms,
02543 rest_of_handle_sms,
02544 NULL,
02545 NULL,
02546 0,
02547 TV_SMS,
02548 0,
02549 0,
02550 0,
02551 TODO_dump_func,
02552 TODO_dump_func |
02553 TODO_ggc_collect,
02554 'm'
02555 };
02556