00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "rtl.h"
00024 #include "tm_p.h"
00025 #include "function.h"
00026 #include "regs.h"
00027 #include "hard-reg-set.h"
00028 #include "basic-block.h"
00029 #include "df.h"
00030 #include "output.h"
00031 #include "ra.h"
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 static void push_list PARAMS ((struct dlist *, struct dlist **));
00049 static void push_list_end PARAMS ((struct dlist *, struct dlist **));
00050 static void free_dlist PARAMS ((struct dlist **));
00051 static void put_web_at_end PARAMS ((struct web *, enum node_type));
00052 static void put_move PARAMS ((struct move *, enum move_type));
00053 static void build_worklists PARAMS ((struct df *));
00054 static void enable_move PARAMS ((struct web *));
00055 static void decrement_degree PARAMS ((struct web *, int));
00056 static void simplify PARAMS ((void));
00057 static void remove_move_1 PARAMS ((struct web *, struct move *));
00058 static void remove_move PARAMS ((struct web *, struct move *));
00059 static void add_worklist PARAMS ((struct web *));
00060 static int ok PARAMS ((struct web *, struct web *));
00061 static int conservative PARAMS ((struct web *, struct web *));
00062 static inline unsigned int simplify_p PARAMS ((enum node_type));
00063 static void combine PARAMS ((struct web *, struct web *));
00064 static void coalesce PARAMS ((void));
00065 static void freeze_moves PARAMS ((struct web *));
00066 static void freeze PARAMS ((void));
00067 static void select_spill PARAMS ((void));
00068 static int color_usable_p PARAMS ((int, HARD_REG_SET, HARD_REG_SET,
00069 enum machine_mode));
00070 int get_free_reg PARAMS ((HARD_REG_SET, HARD_REG_SET, enum machine_mode));
00071 static int get_biased_reg PARAMS ((HARD_REG_SET, HARD_REG_SET, HARD_REG_SET,
00072 HARD_REG_SET, enum machine_mode));
00073 static int count_long_blocks PARAMS ((HARD_REG_SET, int));
00074 static char * hardregset_to_string PARAMS ((HARD_REG_SET));
00075 static void calculate_dont_begin PARAMS ((struct web *, HARD_REG_SET *));
00076 static void colorize_one_web PARAMS ((struct web *, int));
00077 static void assign_colors PARAMS ((void));
00078 static void try_recolor_web PARAMS ((struct web *));
00079 static void insert_coalesced_conflicts PARAMS ((void));
00080 static int comp_webs_maxcost PARAMS ((const void *, const void *));
00081 static void recolor_spills PARAMS ((void));
00082 static void check_colors PARAMS ((void));
00083 static void restore_conflicts_from_coalesce PARAMS ((struct web *));
00084 static void break_coalesced_spills PARAMS ((void));
00085 static void unalias_web PARAMS ((struct web *));
00086 static void break_aliases_to_web PARAMS ((struct web *));
00087 static void break_precolored_alias PARAMS ((struct web *));
00088 static void init_web_pairs PARAMS ((void));
00089 static void add_web_pair_cost PARAMS ((struct web *, struct web *,
00090 unsigned HOST_WIDE_INT, unsigned int));
00091 static int comp_web_pairs PARAMS ((const void *, const void *));
00092 static void sort_and_combine_web_pairs PARAMS ((int));
00093 static void aggressive_coalesce PARAMS ((void));
00094 static void extended_coalesce_2 PARAMS ((void));
00095 static void check_uncoalesced_moves PARAMS ((void));
00096
00097 static struct dlist *mv_worklist, *mv_coalesced, *mv_constrained;
00098 static struct dlist *mv_frozen, *mv_active;
00099
00100
00101
00102 static void
00103 push_list (x, list)
00104 struct dlist *x;
00105 struct dlist **list;
00106 {
00107 if (x->next || x->prev)
00108 abort ();
00109 x->next = *list;
00110 if (*list)
00111 (*list)->prev = x;
00112 *list = x;
00113 }
00114
00115 static void
00116 push_list_end (x, list)
00117 struct dlist *x;
00118 struct dlist **list;
00119 {
00120 if (x->prev || x->next)
00121 abort ();
00122 if (!*list)
00123 {
00124 *list = x;
00125 return;
00126 }
00127 while ((*list)->next)
00128 list = &((*list)->next);
00129 x->prev = *list;
00130 (*list)->next = x;
00131 }
00132
00133
00134
00135 void
00136 remove_list (x, list)
00137 struct dlist *x;
00138 struct dlist **list;
00139 {
00140 struct dlist *y = x->prev;
00141 if (y)
00142 y->next = x->next;
00143 else
00144 *list = x->next;
00145 y = x->next;
00146 if (y)
00147 y->prev = x->prev;
00148 x->next = x->prev = NULL;
00149 }
00150
00151
00152
00153 struct dlist *
00154 pop_list (list)
00155 struct dlist **list;
00156 {
00157 struct dlist *r = *list;
00158 if (r)
00159 remove_list (r, list);
00160 return r;
00161 }
00162
00163
00164
00165 static void
00166 free_dlist (list)
00167 struct dlist **list;
00168 {
00169 *list = NULL;
00170 }
00171
00172
00173
00174
00175
00176 #ifndef KEY
00177 inline
00178 #endif
00179 void
00180 put_web (web, type)
00181 struct web *web;
00182 enum node_type type;
00183 {
00184 switch (type)
00185 {
00186 case INITIAL:
00187 case FREE:
00188 case FREEZE:
00189 case SPILL:
00190 case SPILLED:
00191 case COALESCED:
00192 case COLORED:
00193 case SELECT:
00194 push_list (web->dlink, &WEBS(type));
00195 break;
00196 case PRECOLORED:
00197 push_list (web->dlink, &WEBS(INITIAL));
00198 break;
00199 case SIMPLIFY:
00200 if (web->spill_temp)
00201 push_list (web->dlink, &WEBS(type = SIMPLIFY_SPILL));
00202 else if (web->add_hardregs)
00203 push_list (web->dlink, &WEBS(type = SIMPLIFY_FAT));
00204 else
00205 push_list (web->dlink, &WEBS(SIMPLIFY));
00206 break;
00207 default:
00208 abort ();
00209 }
00210 web->type = type;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219 void
00220 reset_lists ()
00221 {
00222 struct dlist *d;
00223 unsigned int i;
00224 if (WEBS(SIMPLIFY) || WEBS(SIMPLIFY_SPILL) || WEBS(SIMPLIFY_FAT)
00225 || WEBS(FREEZE) || WEBS(SPILL) || WEBS(SELECT))
00226 abort ();
00227
00228 while ((d = pop_list (&WEBS(COALESCED))) != NULL)
00229 {
00230 struct web *web = DLIST_WEB (d);
00231 struct web *aweb = alias (web);
00232
00233
00234
00235
00236
00237
00238 if (aweb->type == SPILLED || aweb->type == FREE)
00239 put_web (web, FREE);
00240 else
00241 put_web (web, INITIAL);
00242 }
00243 while ((d = pop_list (&WEBS(SPILLED))) != NULL)
00244 put_web (DLIST_WEB (d), FREE);
00245 while ((d = pop_list (&WEBS(COLORED))) != NULL)
00246 put_web (DLIST_WEB (d), INITIAL);
00247
00248
00249 for (d = WEBS(FREE); d; d = d->next)
00250 {
00251 struct web *web = DLIST_WEB (d);
00252 BITMAP_XFREE (web->useless_conflicts);
00253 web->useless_conflicts = NULL;
00254 }
00255
00256
00257 for (i = 0; i < num_webs; i++)
00258 {
00259 struct web *web = ID2WEB (i);
00260 if (web->type != INITIAL && web->type != FREE && web->type != PRECOLORED)
00261 abort ();
00262 }
00263 free_dlist (&mv_worklist);
00264 free_dlist (&mv_coalesced);
00265 free_dlist (&mv_constrained);
00266 free_dlist (&mv_frozen);
00267 free_dlist (&mv_active);
00268 }
00269
00270
00271
00272
00273 static void
00274 put_web_at_end (web, type)
00275 struct web *web;
00276 enum node_type type;
00277 {
00278 if (type == PRECOLORED)
00279 type = INITIAL;
00280 else if (type == SIMPLIFY)
00281 abort ();
00282 push_list_end (web->dlink, &WEBS(type));
00283 web->type = type;
00284 }
00285
00286
00287
00288
00289 void
00290 remove_web_from_list (web)
00291 struct web *web;
00292 {
00293 if (web->type == PRECOLORED)
00294 remove_list (web->dlink, &WEBS(INITIAL));
00295 else
00296 remove_list (web->dlink, &WEBS(web->type));
00297 }
00298
00299
00300
00301 static inline void
00302 put_move (move, type)
00303 struct move *move;
00304 enum move_type type;
00305 {
00306 switch (type)
00307 {
00308 case WORKLIST:
00309 push_list (move->dlink, &mv_worklist);
00310 break;
00311 case MV_COALESCED:
00312 push_list (move->dlink, &mv_coalesced);
00313 break;
00314 case CONSTRAINED:
00315 push_list (move->dlink, &mv_constrained);
00316 break;
00317 case FROZEN:
00318 push_list (move->dlink, &mv_frozen);
00319 break;
00320 case ACTIVE:
00321 push_list (move->dlink, &mv_active);
00322 break;
00323 default:
00324 abort ();
00325 }
00326 move->type = type;
00327 }
00328
00329
00330
00331 static void
00332 build_worklists (df)
00333 struct df *df ATTRIBUTE_UNUSED;
00334 {
00335 struct dlist *d, *d_next;
00336 struct move_list *ml;
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 if (ra_pass > 1)
00348 {
00349 unsigned int i, num, max_num;
00350 struct web **order2web;
00351 max_num = num_webs - num_subwebs;
00352 order2web = (struct web **) xmalloc (max_num * sizeof (order2web[0]));
00353 for (i = 0, num = 0; i < max_num; i++)
00354 if (id2web[i]->regno >= max_normal_pseudo)
00355 order2web[num++] = id2web[i];
00356 if (num)
00357 {
00358 qsort (order2web, num, sizeof (order2web[0]), comp_webs_maxcost);
00359 for (i = num - 1;; i--)
00360 {
00361 struct web *web = order2web[i];
00362 struct conflict_link *wl;
00363 remove_list (web->dlink, &WEBS(INITIAL));
00364 put_web (web, SELECT);
00365 for (wl = web->conflict_list; wl; wl = wl->next)
00366 {
00367 struct web *pweb = wl->t;
00368 pweb->num_conflicts -= 1 + web->add_hardregs;
00369 }
00370 if (i == 0)
00371 break;
00372 }
00373 }
00374 free (order2web);
00375 }
00376
00377
00378 for (d = WEBS(INITIAL); d; d = d_next)
00379 {
00380 struct web *web = DLIST_WEB (d);
00381 d_next = d->next;
00382 if (web->type == PRECOLORED)
00383 continue;
00384
00385 remove_list (d, &WEBS(INITIAL));
00386 if (web->num_conflicts >= NUM_REGS (web))
00387 put_web (web, SPILL);
00388 else if (web->moves)
00389 put_web (web, FREEZE);
00390 else
00391 put_web (web, SIMPLIFY);
00392 }
00393
00394
00395
00396
00397 for (ml = wl_moves; ml; ml = ml->next)
00398 if (ml->move)
00399 {
00400 struct move *m = ml->move;
00401 d = (struct dlist *) ra_calloc (sizeof (struct dlist));
00402 DLIST_MOVE (d) = m;
00403 m->dlink = d;
00404 put_move (m, WORKLIST);
00405 }
00406 }
00407
00408
00409
00410 static void
00411 enable_move (web)
00412 struct web *web;
00413 {
00414 struct move_list *ml;
00415 for (ml = web->moves; ml; ml = ml->next)
00416 if (ml->move->type == ACTIVE)
00417 {
00418 remove_list (ml->move->dlink, &mv_active);
00419 put_move (ml->move, WORKLIST);
00420 }
00421 }
00422
00423
00424
00425
00426
00427 static void
00428 decrement_degree (web, dec)
00429 struct web *web;
00430 int dec;
00431 {
00432 int before = web->num_conflicts;
00433 web->num_conflicts -= dec;
00434 if (web->num_conflicts < NUM_REGS (web) && before >= NUM_REGS (web))
00435 {
00436 struct conflict_link *a;
00437 enable_move (web);
00438 for (a = web->conflict_list; a; a = a->next)
00439 {
00440 struct web *aweb = a->t;
00441 if (aweb->type != SELECT && aweb->type != COALESCED)
00442 enable_move (aweb);
00443 }
00444 if (web->type != FREEZE)
00445 {
00446 remove_web_from_list (web);
00447 if (web->moves)
00448 put_web (web, FREEZE);
00449 else
00450 put_web (web, SIMPLIFY);
00451 }
00452 }
00453 }
00454
00455
00456
00457 static void
00458 simplify ()
00459 {
00460 struct dlist *d;
00461 struct web *web;
00462 struct conflict_link *wl;
00463 while (1)
00464 {
00465
00466
00467
00468
00469
00470
00471
00472 d = pop_list (&WEBS(SIMPLIFY));
00473 if (!d)
00474 d = pop_list (&WEBS(SIMPLIFY_FAT));
00475 if (!d)
00476 d = pop_list (&WEBS(SIMPLIFY_SPILL));
00477 if (!d)
00478 break;
00479 web = DLIST_WEB (d);
00480 ra_debug_msg (DUMP_PROCESS, " simplifying web %3d, conflicts = %d\n",
00481 web->id, web->num_conflicts);
00482 put_web (web, SELECT);
00483 for (wl = web->conflict_list; wl; wl = wl->next)
00484 {
00485 struct web *pweb = wl->t;
00486 if (pweb->type != SELECT && pweb->type != COALESCED)
00487 {
00488 decrement_degree (pweb, 1 + web->add_hardregs);
00489 }
00490 }
00491 }
00492 }
00493
00494
00495
00496 static void
00497 remove_move_1 (web, move)
00498 struct web *web;
00499 struct move *move;
00500 {
00501 struct move_list *ml = web->moves;
00502 if (!ml)
00503 return;
00504 if (ml->move == move)
00505 {
00506 web->moves = ml->next;
00507 return;
00508 }
00509 for (; ml->next && ml->next->move != move; ml = ml->next) ;
00510 if (!ml->next)
00511 return;
00512 ml->next = ml->next->next;
00513 }
00514
00515
00516
00517
00518
00519 static void
00520 remove_move (web, move)
00521 struct web *web;
00522 struct move *move;
00523 {
00524 struct move_list *ml;
00525 remove_move_1 (web, move);
00526 for (ml = web->moves; ml; ml = ml->next)
00527 if (ml->move == move)
00528 abort ();
00529 }
00530
00531
00532
00533 void
00534 merge_moves (u, v)
00535 struct web *u, *v;
00536 {
00537 regset seen;
00538 struct move_list *ml, *ml_next;
00539
00540 seen = BITMAP_XMALLOC ();
00541 for (ml = u->moves; ml; ml = ml->next)
00542 bitmap_set_bit (seen, INSN_UID (ml->move->insn));
00543 for (ml = v->moves; ml; ml = ml_next)
00544 {
00545 ml_next = ml->next;
00546 if (! bitmap_bit_p (seen, INSN_UID (ml->move->insn)))
00547 {
00548 ml->next = u->moves;
00549 u->moves = ml;
00550 }
00551 }
00552 BITMAP_XFREE (seen);
00553 v->moves = NULL;
00554 }
00555
00556
00557
00558 static void
00559 add_worklist (web)
00560 struct web *web;
00561 {
00562 if (web->type != PRECOLORED && !web->moves
00563 && web->num_conflicts < NUM_REGS (web))
00564 {
00565 remove_list (web->dlink, &WEBS(FREEZE));
00566 put_web (web, SIMPLIFY);
00567 }
00568 }
00569
00570
00571
00572 static int
00573 ok (target, source)
00574 struct web *target, *source;
00575 {
00576 struct conflict_link *wl;
00577 int i;
00578 int color = source->color;
00579 int size;
00580
00581
00582
00583
00584
00585
00586
00587
00588 if (! HARD_REGNO_MODE_OK (source->color, GET_MODE (target->orig_x)))
00589 return 0;
00590
00591
00592 size = HARD_REGNO_NREGS (color, GET_MODE (target->orig_x));
00593 if (!size)
00594 return 0;
00595
00596
00597
00598 for (i = size; i--;)
00599 if (TEST_HARD_REG_BIT (never_use_colors, color + i)
00600 || !TEST_HARD_REG_BIT (target->usable_regs, color + i)
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 || TEST_BIT (sup_igraph,
00612 target->id * num_webs + hardreg2web[color + i]->id))
00613 return 0;
00614
00615 for (wl = target->conflict_list; wl; wl = wl->next)
00616 {
00617 struct web *pweb = wl->t;
00618 if (pweb->type == SELECT || pweb->type == COALESCED)
00619 continue;
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 if (pweb->num_conflicts < NUM_REGS (pweb)
00636 || pweb->type == PRECOLORED
00637 || TEST_BIT (igraph, igraph_index (source->id, pweb->id)) )
00638 continue;
00639
00640
00641
00642 if (wl->sub == NULL)
00643 return 0;
00644 else
00645 {
00646
00647
00648
00649
00650
00651 struct sub_conflict *sl;
00652 for (sl = wl->sub; sl; sl = sl->next)
00653 {
00654 if (!TEST_BIT (igraph, igraph_index (source->id, sl->t->id)))
00655 return 0;
00656 }
00657 }
00658 }
00659 return 1;
00660 }
00661
00662
00663
00664 static int
00665 conservative (target, source)
00666 struct web *target, *source;
00667 {
00668 unsigned int k;
00669 unsigned int loop;
00670 regset seen;
00671 struct conflict_link *wl;
00672 unsigned int num_regs = NUM_REGS (target);
00673
00674
00675
00676
00677 k = 0 * MAX (target->add_hardregs, source->add_hardregs);
00678 seen = BITMAP_XMALLOC ();
00679 for (loop = 0; loop < 2; loop++)
00680 for (wl = ((loop == 0) ? target : source)->conflict_list;
00681 wl; wl = wl->next)
00682 {
00683 struct web *pweb = wl->t;
00684 if (pweb->type != SELECT && pweb->type != COALESCED
00685 && pweb->num_conflicts >= NUM_REGS (pweb)
00686 && ! REGNO_REG_SET_P (seen, pweb->id))
00687 {
00688 SET_REGNO_REG_SET (seen, pweb->id);
00689 k += 1 + pweb->add_hardregs;
00690 }
00691 }
00692 BITMAP_XFREE (seen);
00693
00694 if (k >= num_regs)
00695 return 0;
00696 return 1;
00697 }
00698
00699
00700
00701
00702 struct web *
00703 alias (web)
00704 struct web *web;
00705 {
00706 while (web->type == COALESCED)
00707 web = web->alias;
00708 return web;
00709 }
00710
00711
00712
00713
00714 static inline unsigned int
00715 simplify_p (type)
00716 enum node_type type;
00717 {
00718 return type == SIMPLIFY || type == SIMPLIFY_SPILL || type == SIMPLIFY_FAT;
00719 }
00720
00721
00722
00723 static void
00724 combine (u, v)
00725 struct web *u, *v;
00726 {
00727 int i;
00728 struct conflict_link *wl;
00729 if (u == v || v->type == COALESCED)
00730 abort ();
00731 if ((u->regno >= max_normal_pseudo) != (v->regno >= max_normal_pseudo))
00732 abort ();
00733 remove_web_from_list (v);
00734 put_web (v, COALESCED);
00735 v->alias = u;
00736 u->is_coalesced = 1;
00737 v->is_coalesced = 1;
00738 u->num_aliased += 1 + v->num_aliased;
00739 if (flag_ra_merge_spill_costs && u->type != PRECOLORED)
00740 u->spill_cost += v->spill_cost;
00741
00742 merge_moves (u, v);
00743
00744
00745 for (wl = v->conflict_list; wl; wl = wl->next)
00746 {
00747 struct web *pweb = wl->t;
00748
00749
00750
00751
00752
00753
00754
00755 if (1)
00756 {
00757 struct web *web = u;
00758 int nregs = 1 + v->add_hardregs;
00759 if (u->type == PRECOLORED)
00760 nregs = HARD_REGNO_NREGS (u->color, GET_MODE (v->orig_x));
00761
00762
00763
00764
00765
00766
00767
00768 for (i = 0; i < nregs; i++)
00769 {
00770 if (u->type == PRECOLORED)
00771 web = hardreg2web[i + u->color];
00772 if (wl->sub == NULL)
00773 record_conflict (web, pweb);
00774 else
00775 {
00776 struct sub_conflict *sl;
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786 for (sl = wl->sub; sl; sl = sl->next)
00787 {
00788
00789
00790
00791
00792
00793
00794
00795 struct web *sweb = NULL;
00796 if (SUBWEB_P (sl->s))
00797 sweb = find_subweb (web, sl->s->orig_x);
00798 if (!sweb)
00799 sweb = web;
00800 record_conflict (sweb, sl->t);
00801 }
00802 }
00803 if (u->type != PRECOLORED)
00804 break;
00805 }
00806 if (pweb->type != SELECT && pweb->type != COALESCED)
00807 decrement_degree (pweb, 1 + v->add_hardregs);
00808 }
00809 }
00810
00811
00812
00813
00814
00815
00816
00817
00818 u->use_my_regs = 1;
00819 AND_HARD_REG_SET (u->usable_regs, v->usable_regs);
00820 u->regclass = reg_class_subunion[u->regclass][v->regclass];
00821
00822
00823
00824 u->num_freedom = hard_regs_count (u->usable_regs);
00825 u->num_freedom -= u->add_hardregs;
00826
00827
00828 if (!u->num_freedom)
00829 abort();
00830
00831 if (u->num_conflicts >= NUM_REGS (u)
00832 && (u->type == FREEZE || simplify_p (u->type)))
00833 {
00834 remove_web_from_list (u);
00835 put_web (u, SPILL);
00836 }
00837
00838
00839
00840
00841
00842 if (v->spill_temp == 0)
00843 u->spill_temp = 0;
00844 else if (v->spill_temp == 2 && u->spill_temp != 0)
00845 u->spill_temp = 2;
00846 else if (v->spill_temp == 3 && u->spill_temp == 1)
00847 u->spill_temp = 3;
00848 }
00849
00850
00851
00852
00853 static void
00854 coalesce ()
00855 {
00856 struct dlist *d = pop_list (&mv_worklist);
00857 struct move *m = DLIST_MOVE (d);
00858 struct web *source = alias (m->source_web);
00859 struct web *target = alias (m->target_web);
00860
00861 if (target->type == PRECOLORED)
00862 {
00863 struct web *h = source;
00864 source = target;
00865 target = h;
00866 }
00867 if (source == target)
00868 {
00869 remove_move (source, m);
00870 put_move (m, MV_COALESCED);
00871 add_worklist (source);
00872 }
00873 else if (target->type == PRECOLORED
00874 || TEST_BIT (sup_igraph, source->id * num_webs + target->id)
00875 || TEST_BIT (sup_igraph, target->id * num_webs + source->id))
00876 {
00877 remove_move (source, m);
00878 remove_move (target, m);
00879 put_move (m, CONSTRAINED);
00880 add_worklist (source);
00881 add_worklist (target);
00882 }
00883 else if ((source->type == PRECOLORED && ok (target, source))
00884 || (source->type != PRECOLORED
00885 && conservative (target, source)))
00886 {
00887 remove_move (source, m);
00888 remove_move (target, m);
00889 put_move (m, MV_COALESCED);
00890 combine (source, target);
00891 add_worklist (source);
00892 }
00893 else
00894 put_move (m, ACTIVE);
00895 }
00896
00897
00898
00899 static void
00900 freeze_moves (web)
00901 struct web *web;
00902 {
00903 struct move_list *ml, *ml_next;
00904 for (ml = web->moves; ml; ml = ml_next)
00905 {
00906 struct move *m = ml->move;
00907 struct web *src, *dest;
00908 ml_next = ml->next;
00909 if (m->type == ACTIVE)
00910 remove_list (m->dlink, &mv_active);
00911 else
00912 remove_list (m->dlink, &mv_worklist);
00913 put_move (m, FROZEN);
00914 remove_move (web, m);
00915 src = alias (m->source_web);
00916 dest = alias (m->target_web);
00917 src = (src == web) ? dest : src;
00918 remove_move (src, m);
00919
00920 if (!src->moves && src->num_conflicts < NUM_REGS (src))
00921 {
00922 remove_list (src->dlink, &WEBS(FREEZE));
00923 put_web (src, SIMPLIFY);
00924 }
00925 }
00926 }
00927
00928
00929
00930
00931 static void
00932 freeze ()
00933 {
00934 struct dlist *d = pop_list (&WEBS(FREEZE));
00935 put_web (DLIST_WEB (d), SIMPLIFY);
00936 freeze_moves (DLIST_WEB (d));
00937 }
00938
00939
00940
00941
00942 static unsigned HOST_WIDE_INT (*spill_heuristic) PARAMS ((struct web *));
00943
00944 static unsigned HOST_WIDE_INT default_spill_heuristic PARAMS ((struct web *));
00945
00946
00947
00948
00949
00950 static unsigned HOST_WIDE_INT
00951 default_spill_heuristic (web)
00952 struct web *web;
00953 {
00954 unsigned HOST_WIDE_INT ret;
00955 unsigned int divisor = 1;
00956
00957
00958 if (flag_ra_break_aliases)
00959 divisor += web->num_aliased;
00960 divisor += web->num_conflicts;
00961 ret = ((web->spill_cost << 8) + divisor - 1) / divisor;
00962
00963
00964
00965 if (web->span_deaths < ret)
00966 ret -= web->span_deaths;
00967 return ret;
00968 }
00969
00970
00971
00972
00973 static void
00974 select_spill ()
00975 {
00976 unsigned HOST_WIDE_INT best = (unsigned HOST_WIDE_INT) -1;
00977 struct dlist *bestd = NULL;
00978 unsigned HOST_WIDE_INT best2 = (unsigned HOST_WIDE_INT) -1;
00979 struct dlist *bestd2 = NULL;
00980 struct dlist *d;
00981 for (d = WEBS(SPILL); d; d = d->next)
00982 {
00983 struct web *w = DLIST_WEB (d);
00984 unsigned HOST_WIDE_INT cost = spill_heuristic (w);
00985 if ((!w->spill_temp) && cost < best)
00986 {
00987 best = cost;
00988 bestd = d;
00989 }
00990
00991
00992
00993 else if ((w->spill_temp == 2 || w->is_coalesced) && cost < best2)
00994 {
00995 best2 = cost;
00996 bestd2 = d;
00997 }
00998 }
00999 if (!bestd)
01000 {
01001 bestd = bestd2;
01002 best = best2;
01003 }
01004 if (!bestd)
01005 abort ();
01006
01007
01008 DLIST_WEB (bestd)->was_spilled = 1;
01009 remove_list (bestd, &WEBS(SPILL));
01010 put_web (DLIST_WEB (bestd), SIMPLIFY);
01011 freeze_moves (DLIST_WEB (bestd));
01012 ra_debug_msg (DUMP_PROCESS, " potential spill web %3d, conflicts = %d\n",
01013 DLIST_WEB (bestd)->id, DLIST_WEB (bestd)->num_conflicts);
01014 }
01015
01016
01017
01018
01019 static int
01020 color_usable_p (c, dont_begin_colors, free_colors, mode)
01021 int c;
01022 HARD_REG_SET dont_begin_colors, free_colors;
01023 enum machine_mode mode;
01024 {
01025 if (!TEST_HARD_REG_BIT (dont_begin_colors, c)
01026 && TEST_HARD_REG_BIT (free_colors, c)
01027 && HARD_REGNO_MODE_OK (c, mode))
01028 {
01029 int i, size;
01030 size = HARD_REGNO_NREGS (c, mode);
01031 for (i = 1; i < size && TEST_HARD_REG_BIT (free_colors, c + i); i++);
01032 if (i == size)
01033 return 1;
01034 }
01035 return 0;
01036 }
01037
01038
01039 #ifdef REG_ALLOC_ORDER
01040 #define INV_REG_ALLOC_ORDER(c) inv_reg_alloc_order[c]
01041 #else
01042 #define INV_REG_ALLOC_ORDER(c) c
01043 #endif
01044
01045
01046
01047
01048
01049
01050
01051 int
01052 get_free_reg (dont_begin_colors, free_colors, mode)
01053 HARD_REG_SET dont_begin_colors, free_colors;
01054 enum machine_mode mode;
01055 {
01056 int c;
01057 int last_resort_reg = -1;
01058 int pref_reg = -1;
01059 int pref_reg_order = INT_MAX;
01060 int last_resort_reg_order = INT_MAX;
01061
01062 for (c = 0; c < FIRST_PSEUDO_REGISTER; c++)
01063 if (!TEST_HARD_REG_BIT (dont_begin_colors, c)
01064 && TEST_HARD_REG_BIT (free_colors, c)
01065 && HARD_REGNO_MODE_OK (c, mode))
01066 {
01067 int i, size;
01068 size = HARD_REGNO_NREGS (c, mode);
01069 for (i = 1; i < size && TEST_HARD_REG_BIT (free_colors, c + i); i++);
01070 if (i != size)
01071 {
01072 c += i;
01073 continue;
01074 }
01075 if (i == size)
01076 {
01077 if (size < 2 || (c & 1) == 0)
01078 {
01079 if (INV_REG_ALLOC_ORDER (c) < pref_reg_order)
01080 {
01081 pref_reg = c;
01082 pref_reg_order = INV_REG_ALLOC_ORDER (c);
01083 }
01084 }
01085 else if (INV_REG_ALLOC_ORDER (c) < last_resort_reg_order)
01086 {
01087 last_resort_reg = c;
01088 last_resort_reg_order = INV_REG_ALLOC_ORDER (c);
01089 }
01090 }
01091 else
01092 c += i;
01093 }
01094 return pref_reg >= 0 ? pref_reg : last_resort_reg;
01095 }
01096
01097
01098
01099
01100
01101
01102 static int
01103 get_biased_reg (dont_begin_colors, bias, prefer_colors, free_colors, mode)
01104 HARD_REG_SET dont_begin_colors, bias, prefer_colors, free_colors;
01105 enum machine_mode mode;
01106 {
01107 int c = -1;
01108 HARD_REG_SET s;
01109 if (flag_ra_biased)
01110 {
01111 COPY_HARD_REG_SET (s, dont_begin_colors);
01112 IOR_COMPL_HARD_REG_SET (s, bias);
01113 IOR_COMPL_HARD_REG_SET (s, prefer_colors);
01114 c = get_free_reg (s, free_colors, mode);
01115 if (c >= 0)
01116 return c;
01117 COPY_HARD_REG_SET (s, dont_begin_colors);
01118 IOR_COMPL_HARD_REG_SET (s, bias);
01119 c = get_free_reg (s, free_colors, mode);
01120 if (c >= 0)
01121 return c;
01122 }
01123 COPY_HARD_REG_SET (s, dont_begin_colors);
01124 IOR_COMPL_HARD_REG_SET (s, prefer_colors);
01125 c = get_free_reg (s, free_colors, mode);
01126 if (c >= 0)
01127 return c;
01128 c = get_free_reg (dont_begin_colors, free_colors, mode);
01129 return c;
01130 }
01131
01132
01133
01134
01135 static int
01136 count_long_blocks (free_colors, len)
01137 HARD_REG_SET free_colors;
01138 int len;
01139 {
01140 int i, j;
01141 int count = 0;
01142 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01143 {
01144 if (!TEST_HARD_REG_BIT (free_colors, i))
01145 continue;
01146 for (j = 1; j < len; j++)
01147 if (!TEST_HARD_REG_BIT (free_colors, i + j))
01148 break;
01149
01150 if (j == len)
01151 count++;
01152 i += j - 1;
01153 }
01154 return count;
01155 }
01156
01157
01158
01159
01160
01161 static char *
01162 hardregset_to_string (s)
01163 HARD_REG_SET s;
01164 {
01165 static char string[1024];
01166 #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDE_INT
01167 sprintf (string, HOST_WIDE_INT_PRINT_HEX, s);
01168 #else
01169 char *c = string;
01170 int i,j;
01171 c += sprintf (c, "{ ");
01172 for (i = 0;i < HARD_REG_SET_LONGS; i++)
01173 {
01174 for (j = 0; j < HOST_BITS_PER_WIDE_INT; j++)
01175 c += sprintf (c, "%s", ( 1 << j) & s[i] ? "1" : "0");
01176 c += sprintf (c, "%s", i ? ", " : "");
01177 }
01178 c += sprintf (c, " }");
01179 #endif
01180 return string;
01181 }
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193 static void
01194 calculate_dont_begin (web, result)
01195 struct web *web;
01196 HARD_REG_SET *result;
01197 {
01198 struct conflict_link *wl;
01199 HARD_REG_SET dont_begin;
01200
01201
01202
01203
01204 CLEAR_HARD_REG_SET (dont_begin);
01205 for (wl = web->conflict_list; wl; wl = wl->next)
01206 {
01207 struct web *w;
01208 struct web *ptarget = alias (wl->t);
01209 struct sub_conflict *sl = wl->sub;
01210 w = sl ? sl->t : wl->t;
01211 while (w)
01212 {
01213 if (ptarget->type == COLORED || ptarget->type == PRECOLORED)
01214 {
01215 struct web *source = (sl) ? sl->s : web;
01216 unsigned int tsize = HARD_REGNO_NREGS (ptarget->color,
01217 GET_MODE (w->orig_x));
01218
01219 unsigned int ssize = HARD_REGNO_NREGS (ptarget->color, GET_MODE
01220 (source->orig_x));
01221 unsigned int tofs = 0;
01222 unsigned int sofs = 0;
01223
01224
01225 int c1, c2;
01226
01227 if (SUBWEB_P (w)
01228 && GET_MODE_SIZE (GET_MODE (w->orig_x)) >= UNITS_PER_WORD)
01229 tofs = (SUBREG_BYTE (w->orig_x) / UNITS_PER_WORD);
01230 if (SUBWEB_P (source)
01231 && GET_MODE_SIZE (GET_MODE (source->orig_x))
01232 >= UNITS_PER_WORD)
01233 sofs = (SUBREG_BYTE (source->orig_x) / UNITS_PER_WORD);
01234 c1 = ptarget->color + tofs - sofs - ssize + 1;
01235 c2 = ptarget->color + tofs + tsize - 1 - sofs;
01236 if (c2 >= 0)
01237 {
01238 if (c1 < 0)
01239 c1 = 0;
01240
01241
01242
01243
01244
01245 while (c1 + sofs
01246 + HARD_REGNO_NREGS (c1, GET_MODE (source->orig_x)) - 1
01247 < ptarget->color + tofs)
01248 c1++;
01249 while (c1 > 0 && c1 + sofs
01250 + HARD_REGNO_NREGS (c1, GET_MODE (source->orig_x)) - 1
01251 > ptarget->color + tofs)
01252 c1--;
01253 for (; c1 <= c2; c1++)
01254 SET_HARD_REG_BIT (dont_begin, c1);
01255 }
01256 }
01257
01258
01259
01260 if (!sl)
01261 break;
01262 sl = sl->next;
01263 w = sl ? sl->t : NULL;
01264 }
01265 }
01266 COPY_HARD_REG_SET (*result, dont_begin);
01267 }
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282 static void
01283 colorize_one_web (web, hard)
01284 struct web *web;
01285 int hard;
01286 {
01287 struct conflict_link *wl;
01288 HARD_REG_SET colors, dont_begin;
01289 int c = -1;
01290 int bestc = -1;
01291 int neighbor_needs= 0;
01292 struct web *fat_neighbor = NULL;
01293 struct web *fats_parent = NULL;
01294 int num_fat = 0;
01295 int long_blocks = 0;
01296 int best_long_blocks = -1;
01297 HARD_REG_SET fat_colors;
01298 HARD_REG_SET bias;
01299
01300 if (web->regno >= max_normal_pseudo)
01301 hard = 0;
01302
01303
01304 calculate_dont_begin (web, &dont_begin);
01305 CLEAR_HARD_REG_SET (bias);
01306
01307
01308
01309 neighbor_needs = web->add_hardregs + 1;
01310 for (wl = web->conflict_list; wl; wl = wl->next)
01311 {
01312 struct web *w;
01313 struct web *ptarget = alias (wl->t);
01314 struct sub_conflict *sl = wl->sub;
01315 IOR_HARD_REG_SET (bias, ptarget->bias_colors);
01316 w = sl ? sl->t : wl->t;
01317 if (ptarget->type != COLORED && ptarget->type != PRECOLORED
01318 && !ptarget->was_spilled)
01319 while (w)
01320 {
01321 if (find_web_for_subweb (w)->type != COALESCED
01322 && w->add_hardregs >= neighbor_needs)
01323 {
01324 neighbor_needs = w->add_hardregs;
01325 fat_neighbor = w;
01326 fats_parent = ptarget;
01327 num_fat++;
01328 }
01329 if (!sl)
01330 break;
01331 sl = sl->next;
01332 w = sl ? sl->t : NULL;
01333 }
01334 }
01335
01336 ra_debug_msg (DUMP_COLORIZE, "colorize web %d [don't begin at %s]", web->id,
01337 hardregset_to_string (dont_begin));
01338
01339
01340
01341 if (num_fat)
01342 {
01343 COPY_HARD_REG_SET (fat_colors, fats_parent->usable_regs);
01344 long_blocks = count_long_blocks (fat_colors, neighbor_needs + 1);
01345 }
01346
01347
01348
01349 while (1)
01350 {
01351 HARD_REG_SET call_clobbered;
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365 if (web->use_my_regs)
01366 {
01367 COPY_HARD_REG_SET (colors, web->usable_regs);
01368 AND_HARD_REG_SET (colors,
01369 usable_regs[reg_preferred_class (web->regno)]);
01370 }
01371 else
01372 COPY_HARD_REG_SET (colors,
01373 usable_regs[reg_preferred_class (web->regno)]);
01374 #ifdef CLASS_CANNOT_CHANGE_MODE
01375 if (web->mode_changed)
01376 AND_COMPL_HARD_REG_SET (colors, reg_class_contents[
01377 (int) CLASS_CANNOT_CHANGE_MODE]);
01378 #endif
01379 COPY_HARD_REG_SET (call_clobbered, colors);
01380 AND_HARD_REG_SET (call_clobbered, call_used_reg_set);
01381
01382
01383
01384
01385 if (web->old_color)
01386 {
01387 c = web->old_color - 1;
01388 if (!color_usable_p (c, dont_begin, colors,
01389 PSEUDO_REGNO_MODE (web->regno)))
01390 c = -1;
01391 }
01392 else
01393 c = -1;
01394 if (c < 0)
01395 c = get_biased_reg (dont_begin, bias, web->prefer_colors,
01396 call_clobbered, PSEUDO_REGNO_MODE (web->regno));
01397 if (c < 0)
01398 c = get_biased_reg (dont_begin, bias, web->prefer_colors,
01399 colors, PSEUDO_REGNO_MODE (web->regno));
01400
01401 if (c < 0)
01402 {
01403 if (web->use_my_regs)
01404 IOR_HARD_REG_SET (colors, web->usable_regs);
01405 else
01406 IOR_HARD_REG_SET (colors, usable_regs
01407 [reg_alternate_class (web->regno)]);
01408 #ifdef CLASS_CANNOT_CHANGE_MODE
01409 if (web->mode_changed)
01410 AND_COMPL_HARD_REG_SET (colors, reg_class_contents[
01411 (int) CLASS_CANNOT_CHANGE_MODE]);
01412 #endif
01413 COPY_HARD_REG_SET (call_clobbered, colors);
01414 AND_HARD_REG_SET (call_clobbered, call_used_reg_set);
01415
01416 c = get_biased_reg (dont_begin, bias, web->prefer_colors,
01417 call_clobbered, PSEUDO_REGNO_MODE (web->regno));
01418 if (c < 0)
01419 c = get_biased_reg (dont_begin, bias, web->prefer_colors,
01420 colors, PSEUDO_REGNO_MODE (web->regno));
01421 }
01422 if (c < 0)
01423 break;
01424 if (bestc < 0)
01425 bestc = c;
01426
01427
01428
01429 if (num_fat)
01430 {
01431 int i;
01432 int new_long;
01433 HARD_REG_SET colors1;
01434 COPY_HARD_REG_SET (colors1, fat_colors);
01435 for (i = 0; i < 1 + web->add_hardregs; i++)
01436 CLEAR_HARD_REG_BIT (colors1, c + i);
01437 new_long = count_long_blocks (colors1, neighbor_needs + 1);
01438
01439
01440 if (long_blocks != new_long && new_long < num_fat)
01441 {
01442 if (new_long > best_long_blocks)
01443 {
01444 best_long_blocks = new_long;
01445 bestc = c;
01446 }
01447 SET_HARD_REG_BIT (dont_begin, c);
01448 ra_debug_msg (DUMP_COLORIZE, " avoid %d", c);
01449 }
01450 else
01451
01452 break;
01453 }
01454
01455
01456 else
01457 break;
01458 }
01459 ra_debug_msg (DUMP_COLORIZE, " --> got %d", c < 0 ? bestc : c);
01460 if (bestc >= 0 && c < 0 && !web->was_spilled)
01461 {
01462
01463
01464
01465
01466 if (1 || web->spill_temp)
01467 c = bestc;
01468 ra_debug_msg (DUMP_COLORIZE, " [constrains neighbors]");
01469 }
01470 ra_debug_msg (DUMP_COLORIZE, "\n");
01471
01472 if (c < 0)
01473 {
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488 if (hard && (!web->was_spilled || web->spill_temp))
01489 {
01490 unsigned int loop;
01491 struct web *try = NULL;
01492 struct web *candidates[8];
01493
01494 ra_debug_msg (DUMP_COLORIZE, " *** %d spilled, although %s ***\n",
01495 web->id, web->spill_temp ? "spilltemp" : "non-spill");
01496
01497
01498
01499
01500
01501
01502
01503 memset (candidates, 0, sizeof candidates);
01504 #define set_cand(i, w) \
01505 do { \
01506 if (!candidates[(i)] \
01507 || (candidates[(i)]->spill_cost < (w)->spill_cost)) \
01508 candidates[(i)] = (w); \
01509 } while (0)
01510 for (wl = web->conflict_list; wl; wl = wl->next)
01511 {
01512 struct web *w = wl->t;
01513 struct web *aw = alias (w);
01514
01515
01516
01517 if (aw->type == PRECOLORED && w != aw && web->spill_temp
01518 && flag_ra_optimistic_coalescing)
01519 {
01520 if (!w->spill_temp)
01521 set_cand (4, w);
01522 else if (web->spill_temp == 2
01523 && w->spill_temp == 2
01524 && w->spill_cost < web->spill_cost)
01525 set_cand (5, w);
01526 else if (web->spill_temp != 2
01527 && (w->spill_temp == 2
01528 || w->spill_cost < web->spill_cost))
01529 set_cand (6, w);
01530 continue;
01531 }
01532 if (aw->type != COLORED)
01533 continue;
01534 if (w->type == COLORED && !w->spill_temp && !w->is_coalesced
01535 && w->was_spilled)
01536 {
01537 if (w->spill_cost < web->spill_cost)
01538 set_cand (0, w);
01539 else if (web->spill_temp)
01540 set_cand (1, w);
01541 }
01542 if (w->type == COLORED && !w->spill_temp && !w->is_coalesced
01543 && !w->was_spilled)
01544 {
01545 if (w->spill_cost < web->spill_cost)
01546 set_cand (2, w);
01547 else if (web->spill_temp && web->spill_temp != 2)
01548 set_cand (3, w);
01549 }
01550 if (web->spill_temp)
01551 {
01552 if (w->type == COLORED && w->spill_temp == 2
01553 && !w->is_coalesced
01554 && (w->spill_cost < web->spill_cost
01555 || web->spill_temp != 2))
01556 set_cand (4, w);
01557 if (!aw->spill_temp)
01558 set_cand (5, aw);
01559 if (aw->spill_temp == 2
01560 && (aw->spill_cost < web->spill_cost
01561 || web->spill_temp != 2))
01562 set_cand (6, aw);
01563
01564
01565
01566
01567
01568 if (web->spill_temp != 2 && aw->is_coalesced
01569 && flag_ra_optimistic_coalescing)
01570 set_cand (7, aw);
01571 }
01572 }
01573 for (loop = 0; try == NULL && loop < 8; loop++)
01574 if (candidates[loop])
01575 try = candidates[loop];
01576 #undef set_cand
01577 if (try)
01578 {
01579 int old_c = try->color;
01580 if (try->type == COALESCED)
01581 {
01582 if (alias (try)->type != PRECOLORED)
01583 abort ();
01584 ra_debug_msg (DUMP_COLORIZE, " breaking alias %d -> %d\n",
01585 try->id, alias (try)->id);
01586 break_precolored_alias (try);
01587 colorize_one_web (web, hard);
01588 }
01589 else
01590 {
01591 remove_list (try->dlink, &WEBS(COLORED));
01592 put_web (try, SPILLED);
01593
01594
01595
01596 ra_debug_msg (DUMP_COLORIZE, " trying to spill %d\n", try->id);
01597 colorize_one_web (web, hard);
01598 if (web->type != COLORED)
01599 {
01600
01601
01602
01603 remove_list (try->dlink, &WEBS(SPILLED));
01604 put_web (try, COLORED);
01605 try->color = old_c;
01606 ra_debug_msg (DUMP_COLORIZE,
01607 " spilling %d was useless\n", try->id);
01608 }
01609 else
01610 {
01611 ra_debug_msg (DUMP_COLORIZE,
01612 " to spill %d was a good idea\n",
01613 try->id);
01614 remove_list (try->dlink, &WEBS(SPILLED));
01615 if (try->was_spilled)
01616 colorize_one_web (try, 0);
01617 else
01618 colorize_one_web (try, hard - 1);
01619 }
01620 }
01621 }
01622 else
01623
01624
01625 put_web (web, SPILLED);
01626 }
01627 else
01628 put_web (web, SPILLED);
01629 }
01630 else
01631 {
01632 put_web (web, COLORED);
01633 web->color = c;
01634 if (flag_ra_biased)
01635 {
01636 int nregs = HARD_REGNO_NREGS (c, GET_MODE (web->orig_x));
01637 for (wl = web->conflict_list; wl; wl = wl->next)
01638 {
01639 struct web *ptarget = alias (wl->t);
01640 int i;
01641 for (i = 0; i < nregs; i++)
01642 SET_HARD_REG_BIT (ptarget->bias_colors, c + i);
01643 }
01644 }
01645 }
01646 if (web->regno >= max_normal_pseudo && web->type == SPILLED)
01647 {
01648 web->color = an_unusable_color;
01649 remove_list (web->dlink, &WEBS(SPILLED));
01650 put_web (web, COLORED);
01651 }
01652 if (web->type == SPILLED && flag_ra_optimistic_coalescing
01653 && web->is_coalesced)
01654 {
01655 ra_debug_msg (DUMP_COLORIZE, "breaking aliases to web %d:", web->id);
01656 restore_conflicts_from_coalesce (web);
01657 break_aliases_to_web (web);
01658 insert_coalesced_conflicts ();
01659 ra_debug_msg (DUMP_COLORIZE, "\n");
01660 remove_list (web->dlink, &WEBS(SPILLED));
01661 put_web (web, SELECT);
01662 web->color = -1;
01663 }
01664 }
01665
01666
01667
01668
01669 static void
01670 assign_colors ()
01671 {
01672 struct dlist *d;
01673
01674 while (WEBS(SELECT))
01675 {
01676 struct web *web;
01677 d = pop_list (&WEBS(SELECT));
01678 web = DLIST_WEB (d);
01679 colorize_one_web (DLIST_WEB (d), 1);
01680 }
01681
01682 for (d = WEBS(COALESCED); d; d = d->next)
01683 {
01684 struct web *a = alias (DLIST_WEB (d));
01685 DLIST_WEB (d)->color = a->color;
01686 }
01687 }
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700 static void
01701 try_recolor_web (web)
01702 struct web *web;
01703 {
01704 struct conflict_link *wl;
01705 unsigned HOST_WIDE_INT *cost_neighbors;
01706 unsigned int *min_color;
01707 int newcol, c;
01708 HARD_REG_SET precolored_neighbors, spill_temps;
01709 HARD_REG_SET possible_begin, wide_seen;
01710 cost_neighbors = (unsigned HOST_WIDE_INT *)
01711 xcalloc (FIRST_PSEUDO_REGISTER, sizeof (cost_neighbors[0]));
01712
01713
01714 min_color = (unsigned int *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof (int));
01715 CLEAR_HARD_REG_SET (possible_begin);
01716 for (c = 0; c < FIRST_PSEUDO_REGISTER; c++)
01717 {
01718 int i, nregs;
01719 if (!HARD_REGNO_MODE_OK (c, GET_MODE (web->orig_x)))
01720 continue;
01721 nregs = HARD_REGNO_NREGS (c, GET_MODE (web->orig_x));
01722 for (i = 0; i < nregs; i++)
01723 if (!TEST_HARD_REG_BIT (web->usable_regs, c + i))
01724 break;
01725 if (i < nregs || nregs == 0)
01726 continue;
01727 SET_HARD_REG_BIT (possible_begin, c);
01728 for (; nregs--;)
01729 if (!min_color[c + nregs])
01730 min_color[c + nregs] = 1 + c;
01731 }
01732 CLEAR_HARD_REG_SET (precolored_neighbors);
01733 CLEAR_HARD_REG_SET (spill_temps);
01734 CLEAR_HARD_REG_SET (wide_seen);
01735 for (wl = web->conflict_list; wl; wl = wl->next)
01736 {
01737 HARD_REG_SET dont_begin;
01738 struct web *web2 = alias (wl->t);
01739 struct conflict_link *nn;
01740 int c1, c2;
01741 int wide_p = 0;
01742 if (wl->t->type == COALESCED || web2->type != COLORED)
01743 {
01744 if (web2->type == PRECOLORED)
01745 {
01746 c1 = min_color[web2->color];
01747 c1 = (c1 == 0) ? web2->color : (c1 - 1);
01748 c2 = web2->color;
01749 for (; c1 <= c2; c1++)
01750 SET_HARD_REG_BIT (precolored_neighbors, c1);
01751 }
01752 continue;
01753 }
01754
01755
01756
01757
01758
01759
01760
01761 if (web2->add_hardregs)
01762 wide_p = 1;
01763 for (nn = web2->conflict_list; nn && !wide_p; nn = nn->next)
01764 if (alias (nn->t)->add_hardregs)
01765 wide_p = 1;
01766 calculate_dont_begin (web2, &dont_begin);
01767 c1 = min_color[web2->color];
01768
01769
01770 c1 = c1 == 0 ? web2->color : (c1 - 1);
01771 c2 = web2->color + HARD_REGNO_NREGS (web2->color, GET_MODE
01772 (web2->orig_x)) - 1;
01773 for (; c1 <= c2; c1++)
01774 if (TEST_HARD_REG_BIT (possible_begin, c1))
01775 {
01776 int nregs;
01777 HARD_REG_SET colors;
01778 nregs = HARD_REGNO_NREGS (c1, GET_MODE (web->orig_x));
01779 COPY_HARD_REG_SET (colors, web2->usable_regs);
01780 for (; nregs--;)
01781 CLEAR_HARD_REG_BIT (colors, c1 + nregs);
01782 if (wide_p)
01783 SET_HARD_REG_BIT (wide_seen, c1);
01784 if (get_free_reg (dont_begin, colors,
01785 GET_MODE (web2->orig_x)) < 0)
01786 {
01787 if (web2->spill_temp)
01788 SET_HARD_REG_BIT (spill_temps, c1);
01789 else
01790 cost_neighbors[c1] += web2->spill_cost;
01791 }
01792 }
01793 }
01794 newcol = -1;
01795 for (c = 0; c < FIRST_PSEUDO_REGISTER; c++)
01796 if (TEST_HARD_REG_BIT (possible_begin, c)
01797 && !TEST_HARD_REG_BIT (precolored_neighbors, c)
01798 && !TEST_HARD_REG_BIT (spill_temps, c)
01799 && (newcol == -1
01800 || cost_neighbors[c] < cost_neighbors[newcol]))
01801 newcol = c;
01802 if (newcol >= 0 && cost_neighbors[newcol] < web->spill_cost)
01803 {
01804 int nregs = HARD_REGNO_NREGS (newcol, GET_MODE (web->orig_x));
01805 unsigned HOST_WIDE_INT cost = 0;
01806 int *old_colors;
01807 struct conflict_link *wl_next;
01808 ra_debug_msg (DUMP_COLORIZE, "try to set web %d to color %d\n", web->id,
01809 newcol);
01810 remove_list (web->dlink, &WEBS(SPILLED));
01811 put_web (web, COLORED);
01812 web->color = newcol;
01813 old_colors = (int *) xcalloc (num_webs, sizeof (int));
01814 for (wl = web->conflict_list; wl; wl = wl_next)
01815 {
01816 struct web *web2 = alias (wl->t);
01817
01818
01819
01820
01821
01822
01823
01824 wl_next = wl->next;
01825 if (web2->type == COLORED)
01826 {
01827 int nregs2 = HARD_REGNO_NREGS (web2->color, GET_MODE
01828 (web2->orig_x));
01829 if (web->color >= web2->color + nregs2
01830 || web2->color >= web->color + nregs)
01831 continue;
01832 old_colors[web2->id] = web2->color + 1;
01833 web2->color = -1;
01834 remove_list (web2->dlink, &WEBS(COLORED));
01835 web2->type = SELECT;
01836
01837 if (web2->spill_temp == 0 || web2->spill_temp == 2)
01838 web2->was_spilled = 1;
01839 colorize_one_web (web2, 1);
01840 if (web2->type == SPILLED)
01841 cost += web2->spill_cost;
01842 }
01843 }
01844
01845
01846
01847
01848
01849
01850 if (cost > cost_neighbors[newcol]
01851 && nregs == 1 && !TEST_HARD_REG_BIT (wide_seen, newcol))
01852 abort ();
01853
01854
01855 if (cost > web->spill_cost)
01856 {
01857 ra_debug_msg (DUMP_COLORIZE,
01858 "reset coloring of web %d, too expensive\n", web->id);
01859 remove_list (web->dlink, &WEBS(COLORED));
01860 web->color = -1;
01861 put_web (web, SPILLED);
01862 for (wl = web->conflict_list; wl; wl = wl->next)
01863 {
01864 struct web *web2 = alias (wl->t);
01865 if (old_colors[web2->id])
01866 {
01867 if (web2->type == SPILLED)
01868 {
01869 remove_list (web2->dlink, &WEBS(SPILLED));
01870 web2->color = old_colors[web2->id] - 1;
01871 put_web (web2, COLORED);
01872 }
01873 else if (web2->type == COLORED)
01874 web2->color = old_colors[web2->id] - 1;
01875 else if (web2->type == SELECT)
01876
01877
01878
01879
01880
01881
01882
01883
01884 ;
01885 else
01886 abort ();
01887 }
01888 }
01889 }
01890 free (old_colors);
01891 }
01892 free (min_color);
01893 free (cost_neighbors);
01894 }
01895
01896
01897
01898
01899
01900
01901
01902
01903 static void
01904 insert_coalesced_conflicts ()
01905 {
01906 struct dlist *d;
01907 for (d = WEBS(COALESCED); 0 && d; d = d->next)
01908 {
01909 struct web *web = DLIST_WEB (d);
01910 struct web *aweb = alias (web);
01911 struct conflict_link *wl;
01912 for (wl = web->conflict_list; wl; wl = wl->next)
01913 {
01914 struct web *tweb = aweb;
01915 int i;
01916 int nregs = 1 + web->add_hardregs;
01917 if (aweb->type == PRECOLORED)
01918 nregs = HARD_REGNO_NREGS (aweb->color, GET_MODE (web->orig_x));
01919 for (i = 0; i < nregs; i++)
01920 {
01921 if (aweb->type == PRECOLORED)
01922 tweb = hardreg2web[i + aweb->color];
01923
01924
01925
01926
01927
01928
01929
01930 if ((!(tweb->type == PRECOLORED
01931 || TEST_BIT (sup_igraph, tweb->id * num_webs + wl->t->id))
01932 || !(wl->t->type == PRECOLORED
01933 || TEST_BIT (sup_igraph,
01934 wl->t->id * num_webs + tweb->id)))
01935 && hard_regs_intersect_p (&tweb->usable_regs,
01936 &wl->t->usable_regs))
01937 abort ();
01938
01939
01940
01941
01942
01943
01944
01945
01946 if (aweb->type != PRECOLORED)
01947 break;
01948 }
01949 }
01950 }
01951 }
01952
01953
01954
01955
01956
01957 static int
01958 comp_webs_maxcost (w1, w2)
01959 const void *w1, *w2;
01960 {
01961 struct web *web1 = *(struct web **)w1;
01962 struct web *web2 = *(struct web **)w2;
01963 if (web1->spill_cost > web2->spill_cost)
01964 return -1;
01965 else if (web1->spill_cost < web2->spill_cost)
01966 return 1;
01967 else
01968 return 0;
01969 }
01970
01971
01972
01973
01974 static void
01975 recolor_spills ()
01976 {
01977 unsigned int i, num;
01978 struct web **order2web;
01979 num = num_webs - num_subwebs;
01980 order2web = (struct web **) xmalloc (num * sizeof (order2web[0]));
01981 for (i = 0; i < num; i++)
01982 {
01983 order2web[i] = id2web[i];
01984
01985
01986 if (!flag_ra_merge_spill_costs && id2web[i]->type == COALESCED)
01987 alias (id2web[i])->spill_cost += id2web[i]->spill_cost;
01988 }
01989 qsort (order2web, num, sizeof (order2web[0]), comp_webs_maxcost);
01990 insert_coalesced_conflicts ();
01991 dump_graph_cost (DUMP_COSTS, "before spill-recolor");
01992 for (i = 0; i < num; i++)
01993 {
01994 struct web *web = order2web[i];
01995 if (web->type == SPILLED)
01996 try_recolor_web (web);
01997 }
01998
01999
02000
02001
02002
02003 assign_colors ();
02004 free (order2web);
02005 }
02006
02007
02008
02009
02010
02011 static void
02012 check_colors ()
02013 {
02014 unsigned int i;
02015 for (i = 0; i < num_webs - num_subwebs; i++)
02016 {
02017 struct web *web = id2web[i];
02018 struct web *aweb = alias (web);
02019 struct conflict_link *wl;
02020 int nregs, c;
02021 if (aweb->type == SPILLED || web->regno >= max_normal_pseudo)
02022 continue;
02023 else if (aweb->type == COLORED)
02024 nregs = HARD_REGNO_NREGS (aweb->color, GET_MODE (web->orig_x));
02025 else if (aweb->type == PRECOLORED)
02026 nregs = 1;
02027 else
02028 abort ();
02029
02030 for (c = 0; c < nregs; c++)
02031 if (!TEST_HARD_REG_BIT (web->usable_regs, aweb->color + c))
02032 abort ();
02033
02034
02035
02036
02037
02038 wl = (web->have_orig_conflicts ? web->orig_conflict_list
02039 : web->conflict_list);
02040 for (; wl; wl = wl->next)
02041 if (wl->t->regno >= max_normal_pseudo)
02042 continue;
02043 else if (!wl->sub)
02044 {
02045 struct web *web2 = alias (wl->t);
02046 int nregs2;
02047 if (web2->type == COLORED)
02048 nregs2 = HARD_REGNO_NREGS (web2->color, GET_MODE (web2->orig_x));
02049 else if (web2->type == PRECOLORED)
02050 nregs2 = 1;
02051 else
02052 continue;
02053 if (aweb->color >= web2->color + nregs2
02054 || web2->color >= aweb->color + nregs)
02055 continue;
02056 abort ();
02057 }
02058 else
02059 {
02060 struct sub_conflict *sl;
02061 int scol = aweb->color;
02062 int tcol = alias (wl->t)->color;
02063 if (alias (wl->t)->type == SPILLED)
02064 continue;
02065 for (sl = wl->sub; sl; sl = sl->next)
02066 {
02067 int ssize = HARD_REGNO_NREGS (scol, GET_MODE (sl->s->orig_x));
02068 int tsize = HARD_REGNO_NREGS (tcol, GET_MODE (sl->t->orig_x));
02069 int sofs = 0, tofs = 0;
02070 if (SUBWEB_P (sl->t)
02071 && GET_MODE_SIZE (GET_MODE (sl->t->orig_x)) >= UNITS_PER_WORD)
02072 tofs = (SUBREG_BYTE (sl->t->orig_x) / UNITS_PER_WORD);
02073 if (SUBWEB_P (sl->s)
02074 && GET_MODE_SIZE (GET_MODE (sl->s->orig_x))
02075 >= UNITS_PER_WORD)
02076 sofs = (SUBREG_BYTE (sl->s->orig_x) / UNITS_PER_WORD);
02077 if ((tcol + tofs >= scol + sofs + ssize)
02078 || (scol + sofs >= tcol + tofs + tsize))
02079 continue;
02080 abort ();
02081 }
02082 }
02083 }
02084 }
02085
02086
02087
02088
02089 static void
02090 unalias_web (web)
02091 struct web *web;
02092 {
02093 web->alias = NULL;
02094 web->is_coalesced = 0;
02095 web->color = -1;
02096
02097
02098
02099
02100
02101 web->was_spilled = 1;
02102 remove_list (web->dlink, &WEBS(COALESCED));
02103
02104
02105
02106 if (web->spill_temp && web->spill_temp != 2)
02107 put_web (web, SELECT);
02108 else
02109 put_web_at_end (web, SELECT);
02110 }
02111
02112
02113
02114
02115
02116
02117
02118 static void
02119 break_aliases_to_web (web)
02120 struct web *web;
02121 {
02122 struct dlist *d, *d_next;
02123 if (web->type != SPILLED)
02124 abort ();
02125 for (d = WEBS(COALESCED); d; d = d_next)
02126 {
02127 struct web *other = DLIST_WEB (d);
02128 d_next = d->next;
02129
02130
02131
02132 if (other->alias == web)
02133 {
02134 unalias_web (other);
02135 ra_debug_msg (DUMP_COLORIZE, " %d", other->id);
02136 }
02137 }
02138 web->spill_temp = web->orig_spill_temp;
02139 web->spill_cost = web->orig_spill_cost;
02140
02141
02142
02143
02144
02145
02146
02147 COPY_HARD_REG_SET (web->usable_regs, web->orig_usable_regs);
02148 web->is_coalesced = 0;
02149 web->num_aliased = 0;
02150 web->was_spilled = 1;
02151
02152
02153 for (d = WEBS(COALESCED); d; d = d->next)
02154 DLIST_WEB (d)->alias->is_coalesced = 1;
02155 }
02156
02157
02158
02159
02160
02161 static void
02162 break_precolored_alias (web)
02163 struct web *web;
02164 {
02165 struct web *pre = web->alias;
02166 struct conflict_link *wl;
02167 unsigned int c = pre->color;
02168 unsigned int nregs = HARD_REGNO_NREGS (c, GET_MODE (web->orig_x));
02169 if (pre->type != PRECOLORED)
02170 abort ();
02171 unalias_web (web);
02172
02173
02174
02175 for (wl = web->conflict_list; wl; wl = wl->next)
02176 {
02177 struct web *x = wl->t;
02178 struct web *y;
02179 unsigned int i;
02180 struct conflict_link *wl2;
02181 struct conflict_link **pcl;
02182 HARD_REG_SET regs;
02183 if (!x->have_orig_conflicts)
02184 continue;
02185
02186
02187 CLEAR_HARD_REG_SET (regs);
02188 for (i = 0; i < nregs; i++)
02189 SET_HARD_REG_BIT (regs, c + i);
02190 for (wl2 = x->conflict_list; wl2; wl2 = wl2->next)
02191 if (wl2->t->type == COALESCED && alias (wl2->t)->type == PRECOLORED)
02192 CLEAR_HARD_REG_BIT (regs, alias (wl2->t)->color);
02193
02194
02195 for (wl2 = x->orig_conflict_list; wl2; wl2 = wl2->next)
02196 if (wl2->t->type == PRECOLORED)
02197 CLEAR_HARD_REG_BIT (regs, wl2->t->color);
02198
02199
02200 y = NULL;
02201 for (i = 0; i < nregs; i++)
02202 if (TEST_HARD_REG_BIT (regs, c + i))
02203 {
02204 struct web *sub;
02205 y = hardreg2web[c + i];
02206 RESET_BIT (sup_igraph, x->id * num_webs + y->id);
02207 RESET_BIT (sup_igraph, y->id * num_webs + x->id);
02208 RESET_BIT (igraph, igraph_index (x->id, y->id));
02209 for (sub = x->subreg_next; sub; sub = sub->subreg_next)
02210 RESET_BIT (igraph, igraph_index (sub->id, y->id));
02211 }
02212 if (!y)
02213 continue;
02214 pcl = &(x->conflict_list);
02215 while (*pcl)
02216 {
02217 struct web *y = (*pcl)->t;
02218 if (y->type != PRECOLORED || !TEST_HARD_REG_BIT (regs, y->color))
02219 pcl = &((*pcl)->next);
02220 else
02221 *pcl = (*pcl)->next;
02222 }
02223 }
02224 }
02225
02226
02227
02228
02229
02230 static void
02231 restore_conflicts_from_coalesce (web)
02232 struct web *web;
02233 {
02234 struct conflict_link **pcl;
02235 struct conflict_link *wl;
02236 pcl = &(web->conflict_list);
02237
02238
02239
02240 if (!web->have_orig_conflicts)
02241 return;
02242 while (*pcl)
02243 {
02244 struct web *other = (*pcl)->t;
02245 for (wl = web->orig_conflict_list; wl; wl = wl->next)
02246 if (wl->t == other)
02247 break;
02248 if (wl)
02249 {
02250
02251
02252 pcl = &((*pcl)->next);
02253 }
02254 else
02255 {
02256
02257
02258 struct conflict_link **opcl;
02259 struct conflict_link *owl;
02260 struct sub_conflict *sl;
02261 wl = *pcl;
02262 *pcl = wl->next;
02263 if (!other->have_orig_conflicts && other->type != PRECOLORED)
02264 abort ();
02265 for (owl = other->orig_conflict_list; owl; owl = owl->next)
02266 if (owl->t == web)
02267 break;
02268 if (owl)
02269 abort ();
02270 opcl = &(other->conflict_list);
02271 while (*opcl)
02272 {
02273 if ((*opcl)->t == web)
02274 {
02275 owl = *opcl;
02276 *opcl = owl->next;
02277 break;
02278 }
02279 else
02280 {
02281 opcl = &((*opcl)->next);
02282 }
02283 }
02284 if (!owl && other->type != PRECOLORED)
02285 abort ();
02286
02287 RESET_BIT (sup_igraph, web->id * num_webs + other->id);
02288 RESET_BIT (sup_igraph, other->id * num_webs + web->id);
02289 RESET_BIT (igraph, igraph_index (web->id, other->id));
02290 for (sl = wl->sub; sl; sl = sl->next)
02291 RESET_BIT (igraph, igraph_index (sl->s->id, sl->t->id));
02292 if (other->type != PRECOLORED)
02293 {
02294 for (sl = owl->sub; sl; sl = sl->next)
02295 RESET_BIT (igraph, igraph_index (sl->s->id, sl->t->id));
02296 }
02297 }
02298 }
02299
02300
02301 COPY_HARD_REG_SET (web->usable_regs, web->orig_usable_regs);
02302
02303
02304
02305
02306 for (wl = web->conflict_list; wl; wl = wl->next)
02307 if (wl->t->type == COALESCED)
02308 {
02309 struct web *tweb;
02310 for (tweb = wl->t->alias; tweb; tweb = tweb->alias)
02311 {
02312 if (wl->sub == NULL)
02313 record_conflict (web, tweb);
02314 else
02315 {
02316 struct sub_conflict *sl;
02317 for (sl = wl->sub; sl; sl = sl->next)
02318 {
02319 struct web *sweb = NULL;
02320 if (SUBWEB_P (sl->t))
02321 sweb = find_subweb (tweb, sl->t->orig_x);
02322 if (!sweb)
02323 sweb = tweb;
02324 record_conflict (sl->s, sweb);
02325 }
02326 }
02327 if (tweb->type != COALESCED)
02328 break;
02329 }
02330 }
02331 }
02332
02333
02334
02335
02336
02337 static void
02338 break_coalesced_spills ()
02339 {
02340 int changed = 0;
02341 while (1)
02342 {
02343 struct dlist *d;
02344 struct web *web;
02345 for (d = WEBS(SPILLED); d; d = d->next)
02346 if (DLIST_WEB (d)->is_coalesced)
02347 break;
02348 if (!d)
02349 break;
02350 changed = 1;
02351 web = DLIST_WEB (d);
02352 ra_debug_msg (DUMP_COLORIZE, "breaking aliases to web %d:", web->id);
02353 restore_conflicts_from_coalesce (web);
02354 break_aliases_to_web (web);
02355
02356
02357
02358
02359
02360
02361 insert_coalesced_conflicts ();
02362 ra_debug_msg (DUMP_COLORIZE, "\n");
02363 remove_list (d, &WEBS(SPILLED));
02364 put_web (web, SELECT);
02365 web->color = -1;
02366 while (WEBS(SELECT))
02367 {
02368 d = pop_list (&WEBS(SELECT));
02369 colorize_one_web (DLIST_WEB (d), 1);
02370 }
02371 }
02372 if (changed)
02373 {
02374 struct dlist *d;
02375 for (d = WEBS(COALESCED); d; d = d->next)
02376 {
02377 struct web *a = alias (DLIST_WEB (d));
02378 DLIST_WEB (d)->color = a->color;
02379 }
02380 }
02381 dump_graph_cost (DUMP_COSTS, "after alias-breaking");
02382 }
02383
02384
02385
02386
02387 struct web_pair
02388 {
02389 struct web_pair *next_hash;
02390 struct web_pair *next_list;
02391 struct web *smaller;
02392 struct web *larger;
02393 unsigned int conflicts;
02394 unsigned HOST_WIDE_INT cost;
02395 };
02396
02397
02398 #define WEB_PAIR_HASH_SIZE 8192
02399 static struct web_pair *web_pair_hash[WEB_PAIR_HASH_SIZE];
02400 static struct web_pair *web_pair_list;
02401 static unsigned int num_web_pairs;
02402
02403
02404
02405 static void
02406 init_web_pairs ()
02407 {
02408 memset (web_pair_hash, 0, sizeof web_pair_hash);
02409 num_web_pairs = 0;
02410 web_pair_list = NULL;
02411 }
02412
02413
02414
02415
02416
02417 static void
02418 add_web_pair_cost (web1, web2, cost, conflicts)
02419 struct web *web1, *web2;
02420 unsigned HOST_WIDE_INT cost;
02421 unsigned int conflicts;
02422 {
02423 unsigned int hash;
02424 struct web_pair *p;
02425 if (web1->id > web2->id)
02426 {
02427 struct web *h = web1;
02428 web1 = web2;
02429 web2 = h;
02430 }
02431 hash = (web1->id * num_webs + web2->id) % WEB_PAIR_HASH_SIZE;
02432 for (p = web_pair_hash[hash]; p; p = p->next_hash)
02433 if (p->smaller == web1 && p->larger == web2)
02434 {
02435 p->cost += cost;
02436 p->conflicts += conflicts;
02437 return;
02438 }
02439 p = (struct web_pair *) ra_alloc (sizeof *p);
02440 p->next_hash = web_pair_hash[hash];
02441 p->next_list = web_pair_list;
02442 p->smaller = web1;
02443 p->larger = web2;
02444 p->conflicts = conflicts;
02445 p->cost = cost;
02446 web_pair_hash[hash] = p;
02447 web_pair_list = p;
02448 num_web_pairs++;
02449 }
02450
02451
02452
02453
02454
02455 static int
02456 comp_web_pairs (w1, w2)
02457 const void *w1, *w2;
02458 {
02459 struct web_pair *p1 = *(struct web_pair **)w1;
02460 struct web_pair *p2 = *(struct web_pair **)w2;
02461 if (p1->conflicts > p2->conflicts)
02462 return -1;
02463 else if (p1->conflicts < p2->conflicts)
02464 return 1;
02465 else if (p1->cost > p2->cost)
02466 return -1;
02467 else if (p1->cost < p2->cost)
02468 return 1;
02469 else
02470 return 0;
02471 }
02472
02473
02474
02475
02476 static void
02477 sort_and_combine_web_pairs (for_move)
02478 int for_move;
02479 {
02480 unsigned int i;
02481 struct web_pair **sorted;
02482 struct web_pair *p;
02483 if (!num_web_pairs)
02484 return;
02485 sorted = (struct web_pair **) xmalloc (num_web_pairs * sizeof (sorted[0]));
02486 for (p = web_pair_list, i = 0; p; p = p->next_list)
02487 sorted[i++] = p;
02488 if (i != num_web_pairs)
02489 abort ();
02490 qsort (sorted, num_web_pairs, sizeof (sorted[0]), comp_web_pairs);
02491
02492
02493
02494
02495 for (i = 0; i < num_web_pairs; i++)
02496 {
02497 struct web *w1, *w2;
02498 p = sorted[i];
02499 w1 = alias (p->smaller);
02500 w2 = alias (p->larger);
02501 if (!for_move && (w1->type == PRECOLORED || w2->type == PRECOLORED))
02502 continue;
02503 else if (w2->type == PRECOLORED)
02504 {
02505 struct web *h = w1;
02506 w1 = w2;
02507 w2 = h;
02508 }
02509 if (w1 != w2
02510 && !TEST_BIT (sup_igraph, w1->id * num_webs + w2->id)
02511 && !TEST_BIT (sup_igraph, w2->id * num_webs + w1->id)
02512 && w2->type != PRECOLORED
02513 && hard_regs_intersect_p (&w1->usable_regs, &w2->usable_regs))
02514 {
02515 if (w1->type != PRECOLORED
02516 || (w1->type == PRECOLORED && ok (w2, w1)))
02517 combine (w1, w2);
02518 else if (w1->type == PRECOLORED)
02519 SET_HARD_REG_BIT (w2->prefer_colors, w1->color);
02520 }
02521 }
02522 free (sorted);
02523 }
02524
02525
02526
02527
02528 static void
02529 aggressive_coalesce ()
02530 {
02531 struct dlist *d;
02532 struct move *m;
02533 init_web_pairs ();
02534 while ((d = pop_list (&mv_worklist)) != NULL)
02535 if ((m = DLIST_MOVE (d)))
02536 {
02537 struct web *s = alias (m->source_web);
02538 struct web *t = alias (m->target_web);
02539 if (t->type == PRECOLORED)
02540 {
02541 struct web *h = s;
02542 s = t;
02543 t = h;
02544 }
02545 if (s != t
02546 && t->type != PRECOLORED
02547 && !TEST_BIT (sup_igraph, s->id * num_webs + t->id)
02548 && !TEST_BIT (sup_igraph, t->id * num_webs + s->id))
02549 {
02550 if ((s->type == PRECOLORED && ok (t, s))
02551 || s->type != PRECOLORED)
02552 {
02553 put_move (m, MV_COALESCED);
02554 add_web_pair_cost (s, t, BLOCK_FOR_INSN (m->insn)->frequency,
02555 0);
02556 }
02557 else if (s->type == PRECOLORED)
02558
02559
02560
02561 {
02562 put_move (m, CONSTRAINED);
02563 SET_HARD_REG_BIT (t->prefer_colors, s->color);
02564 }
02565 }
02566 else
02567 {
02568 put_move (m, CONSTRAINED);
02569 }
02570 }
02571 sort_and_combine_web_pairs (1);
02572 }
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587 static void
02588 extended_coalesce_2 ()
02589 {
02590 rtx insn;
02591 struct ra_insn_info info;
02592 unsigned int n;
02593 init_web_pairs ();
02594 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
02595 if (INSN_P (insn) && (info = insn_df[INSN_UID (insn)]).num_defs)
02596 for (n = 0; n < info.num_defs; n++)
02597 {
02598 struct web *dest = def2web[DF_REF_ID (info.defs[n])];
02599 dest = alias (find_web_for_subweb (dest));
02600 if (dest->type != PRECOLORED && dest->regno < max_normal_pseudo)
02601 {
02602 unsigned int n2;
02603 for (n2 = 0; n2 < info.num_uses; n2++)
02604 {
02605 struct web *source = use2web[DF_REF_ID (info.uses[n2])];
02606 source = alias (find_web_for_subweb (source));
02607 if (source->type != PRECOLORED
02608 && source != dest
02609 && source->regno < max_normal_pseudo
02610
02611
02612
02613 && GET_MODE (source->orig_x) == GET_MODE (dest->orig_x)
02614 && !TEST_BIT (sup_igraph,
02615 dest->id * num_webs + source->id)
02616 && !TEST_BIT (sup_igraph,
02617 source->id * num_webs + dest->id)
02618 && hard_regs_intersect_p (&source->usable_regs,
02619 &dest->usable_regs))
02620 add_web_pair_cost (dest, source,
02621 BLOCK_FOR_INSN (insn)->frequency,
02622 dest->num_conflicts
02623 + source->num_conflicts);
02624 }
02625 }
02626 }
02627 sort_and_combine_web_pairs (0);
02628 }
02629
02630
02631
02632 static void
02633 check_uncoalesced_moves ()
02634 {
02635 struct move_list *ml;
02636 struct move *m;
02637 for (ml = wl_moves; ml; ml = ml->next)
02638 if ((m = ml->move))
02639 {
02640 struct web *s = alias (m->source_web);
02641 struct web *t = alias (m->target_web);
02642 if (t->type == PRECOLORED)
02643 {
02644 struct web *h = s;
02645 s = t;
02646 t = h;
02647 }
02648 if (s != t
02649 && m->type != CONSTRAINED
02650
02651
02652 && m->type != MV_COALESCED
02653 && t->type != PRECOLORED
02654 && ((s->type == PRECOLORED && ok (t, s))
02655 || s->type != PRECOLORED)
02656 && !TEST_BIT (sup_igraph, s->id * num_webs + t->id)
02657 && !TEST_BIT (sup_igraph, t->id * num_webs + s->id))
02658 abort ();
02659 }
02660 }
02661
02662
02663
02664
02665
02666 void
02667 ra_colorize_graph (df)
02668 struct df *df;
02669 {
02670 if (rtl_dump_file)
02671 dump_igraph (df);
02672 build_worklists (df);
02673
02674
02675 if (flag_ra_optimistic_coalescing)
02676 {
02677 aggressive_coalesce ();
02678 extended_coalesce_2 ();
02679 }
02680
02681
02682 do
02683 {
02684 simplify ();
02685 if (mv_worklist)
02686 coalesce ();
02687 else if (WEBS(FREEZE))
02688 freeze ();
02689 else if (WEBS(SPILL))
02690 select_spill ();
02691 }
02692 while (WEBS(SIMPLIFY) || WEBS(SIMPLIFY_FAT) || WEBS(SIMPLIFY_SPILL)
02693 || mv_worklist || WEBS(FREEZE) || WEBS(SPILL));
02694 if (flag_ra_optimistic_coalescing)
02695 check_uncoalesced_moves ();
02696
02697
02698 assign_colors ();
02699 check_colors ();
02700 dump_graph_cost (DUMP_COSTS, "initially");
02701 if (flag_ra_break_aliases)
02702 break_coalesced_spills ();
02703 check_colors ();
02704
02705
02706 recolor_spills ();
02707 dump_graph_cost (DUMP_COSTS, "after spill-recolor");
02708 check_colors ();
02709 }
02710
02711
02712
02713 void ra_colorize_init ()
02714 {
02715
02716 spill_heuristic = default_spill_heuristic;
02717 }
02718
02719
02720
02721
02722 void
02723 ra_colorize_free_all ()
02724 {
02725 struct dlist *d;
02726 while ((d = pop_list (&WEBS(FREE))) != NULL)
02727 put_web (DLIST_WEB (d), INITIAL);
02728 while ((d = pop_list (&WEBS(INITIAL))) != NULL)
02729 {
02730 struct web *web =DLIST_WEB (d);
02731 struct web *wnext;
02732 web->orig_conflict_list = NULL;
02733 web->conflict_list = NULL;
02734 for (web = web->subreg_next; web; web = wnext)
02735 {
02736 wnext = web->subreg_next;
02737 free (web);
02738 }
02739 free (DLIST_WEB (d));
02740 }
02741 }
02742
02743
02744
02745