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 "insn-config.h"
00026 #include "recog.h"
00027 #include "reload.h"
00028 #include "function.h"
00029 #include "regs.h"
00030 #include "hard-reg-set.h"
00031 #include "basic-block.h"
00032 #include "df.h"
00033 #include "output.h"
00034 #include "ggc.h"
00035 #include "ra.h"
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 struct curr_use;
00068
00069 static unsigned HOST_WIDE_INT rtx_to_undefined PARAMS ((rtx));
00070 static bitmap find_sub_conflicts PARAMS ((struct web_part *, unsigned int));
00071 static bitmap get_sub_conflicts PARAMS ((struct web_part *, unsigned int));
00072 static unsigned int undef_to_size_word PARAMS ((rtx, unsigned HOST_WIDE_INT *));
00073 static bitmap undef_to_bitmap PARAMS ((struct web_part *,
00074 unsigned HOST_WIDE_INT *));
00075 static struct web_part * find_web_part_1 PARAMS ((struct web_part *));
00076 static struct web_part * union_web_part_roots
00077 PARAMS ((struct web_part *, struct web_part *));
00078 static int defuse_overlap_p_1 PARAMS ((rtx, struct curr_use *));
00079 static int live_out_1 PARAMS ((struct df *, struct curr_use *, rtx));
00080 static int live_out PARAMS ((struct df *, struct curr_use *, rtx));
00081 static rtx live_in_edge PARAMS (( struct df *, struct curr_use *, edge));
00082 static void live_in PARAMS ((struct df *, struct curr_use *, rtx));
00083 static int copy_insn_p PARAMS ((rtx, rtx *, rtx *));
00084 static void remember_move PARAMS ((rtx));
00085 static void handle_asm_insn PARAMS ((struct df *, rtx));
00086 static void prune_hardregs_for_mode PARAMS ((HARD_REG_SET *,
00087 enum machine_mode));
00088 static void init_one_web_common PARAMS ((struct web *, rtx));
00089 static void init_one_web PARAMS ((struct web *, rtx));
00090 static void reinit_one_web PARAMS ((struct web *, rtx));
00091 static struct web * add_subweb PARAMS ((struct web *, rtx));
00092 static struct web * add_subweb_2 PARAMS ((struct web *, unsigned int));
00093 static void init_web_parts PARAMS ((struct df *));
00094 static void copy_conflict_list PARAMS ((struct web *));
00095 static void add_conflict_edge PARAMS ((struct web *, struct web *));
00096 static void build_inverse_webs PARAMS ((struct web *));
00097 static void copy_web PARAMS ((struct web *, struct web_link **));
00098 static void compare_and_free_webs PARAMS ((struct web_link **));
00099 static void init_webs_defs_uses PARAMS ((void));
00100 static unsigned int parts_to_webs_1 PARAMS ((struct df *, struct web_link **,
00101 struct df_link *));
00102 static void parts_to_webs PARAMS ((struct df *));
00103 static void reset_conflicts PARAMS ((void));
00104 #if 0
00105 static void check_conflict_numbers PARAMS ((void));
00106 #endif
00107 static void conflicts_between_webs PARAMS ((struct df *));
00108 static void remember_web_was_spilled PARAMS ((struct web *));
00109 static void detect_spill_temps PARAMS ((void));
00110 static int contains_pseudo PARAMS ((rtx));
00111 static int want_to_remat PARAMS ((rtx x));
00112 static void detect_remat_webs PARAMS ((void));
00113 static void determine_web_costs PARAMS ((void));
00114 static void detect_webs_set_in_cond_jump PARAMS ((void));
00115 static void make_webs PARAMS ((struct df *));
00116 static void moves_to_webs PARAMS ((struct df *));
00117 static void connect_rmw_web_parts PARAMS ((struct df *));
00118 static void update_regnos_mentioned PARAMS ((void));
00119 static void livethrough_conflicts_bb PARAMS ((basic_block));
00120 static void init_bb_info PARAMS ((void));
00121 static void free_bb_info PARAMS ((void));
00122 static void build_web_parts_and_conflicts PARAMS ((struct df *));
00123
00124
00125
00126
00127 static sbitmap live_over_abnormal;
00128
00129
00130
00131 static unsigned int visited_pass;
00132
00133
00134 static sbitmap move_handled;
00135
00136
00137
00138
00139 struct visit_trace
00140 {
00141 struct web_part *wp;
00142 unsigned HOST_WIDE_INT undefined;
00143 };
00144
00145 static struct visit_trace *visit_trace;
00146
00147
00148
00149 struct ra_bb_info
00150 {
00151
00152
00153
00154 unsigned int pass;
00155
00156
00157 unsigned HOST_WIDE_INT undefined;
00158
00159
00160
00161 bitmap regnos_mentioned;
00162
00163
00164
00165 bitmap live_throughout;
00166
00167
00168 void *old_aux;
00169 };
00170
00171
00172
00173
00174 #define BL_TO_WORD(b, l) ((((b) & 0xFFFF) << 16) | ((l) & 0xFFFF))
00175 #define BYTE_BEGIN(i) (((unsigned int)(i) >> 16) & 0xFFFF)
00176 #define BYTE_LENGTH(i) ((unsigned int)(i) & 0xFFFF)
00177
00178
00179
00180
00181 unsigned int
00182 rtx_to_bits (x)
00183 rtx x;
00184 {
00185 unsigned int len, beg;
00186 len = GET_MODE_SIZE (GET_MODE (x));
00187 beg = (GET_CODE (x) == SUBREG) ? SUBREG_BYTE (x) : 0;
00188 return BL_TO_WORD (beg, len);
00189 }
00190
00191
00192
00193 static unsigned HOST_WIDE_INT
00194 rtx_to_undefined (x)
00195 rtx x;
00196 {
00197 unsigned int len, beg;
00198 unsigned HOST_WIDE_INT ret;
00199 len = GET_MODE_SIZE (GET_MODE (x));
00200 beg = (GET_CODE (x) == SUBREG) ? SUBREG_BYTE (x) : 0;
00201 ret = ~ ((unsigned HOST_WIDE_INT) 0);
00202 ret = (~(ret << len)) << beg;
00203 return ret;
00204 }
00205
00206
00207
00208 struct copy_p_cache
00209 {
00210 int seen;
00211 rtx source;
00212 rtx target;
00213 };
00214
00215
00216
00217 static struct copy_p_cache * copy_cache;
00218
00219 int *number_seen;
00220
00221
00222
00223
00224
00225 static int
00226 copy_insn_p (insn, source, target)
00227 rtx insn;
00228 rtx *source;
00229 rtx *target;
00230 {
00231 rtx d, s;
00232 unsigned int d_regno, s_regno;
00233 int uid = INSN_UID (insn);
00234
00235 if (!INSN_P (insn))
00236 abort ();
00237
00238
00239 if (copy_cache[uid].seen)
00240 {
00241
00242 if (copy_cache[uid].seen == 1)
00243 {
00244 if (source)
00245 *source = copy_cache[uid].source;
00246 if (target)
00247 *target = copy_cache[uid].target;
00248 return 1;
00249 }
00250 return 0;
00251 }
00252
00253
00254 copy_cache[uid].seen = 2;
00255 insn = single_set (insn);
00256 if (!insn)
00257 return 0;
00258 d = SET_DEST (insn);
00259 s = SET_SRC (insn);
00260
00261
00262
00263
00264 while (GET_CODE (d) == STRICT_LOW_PART)
00265 d = XEXP (d, 0);
00266 if (GET_CODE (d) != REG
00267 && (GET_CODE (d) != SUBREG || GET_CODE (SUBREG_REG (d)) != REG))
00268 return 0;
00269 while (GET_CODE (s) == STRICT_LOW_PART)
00270 s = XEXP (s, 0);
00271 if (GET_CODE (s) != REG
00272 && (GET_CODE (s) != SUBREG || GET_CODE (SUBREG_REG (s)) != REG))
00273 return 0;
00274
00275 s_regno = (unsigned) REGNO (GET_CODE (s) == SUBREG ? SUBREG_REG (s) : s);
00276 d_regno = (unsigned) REGNO (GET_CODE (d) == SUBREG ? SUBREG_REG (d) : d);
00277
00278
00279 if ((s_regno < FIRST_PSEUDO_REGISTER
00280 && d_regno < FIRST_PSEUDO_REGISTER)
00281 || s_regno >= max_normal_pseudo
00282 || d_regno >= max_normal_pseudo)
00283 return 0;
00284
00285 if (source)
00286 *source = s;
00287 if (target)
00288 *target = d;
00289
00290
00291 copy_cache[uid].seen = 1;
00292 copy_cache[uid].source = s;
00293 copy_cache[uid].target = d;
00294 return 1;
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 static bitmap
00309 find_sub_conflicts (wp, size_word)
00310 struct web_part *wp;
00311 unsigned int size_word;
00312 {
00313 struct tagged_conflict *cl;
00314 cl = wp->sub_conflicts;
00315 for (; cl; cl = cl->next)
00316 if (cl->size_word == size_word)
00317 return cl->conflicts;
00318 return NULL;
00319 }
00320
00321
00322
00323
00324 static bitmap
00325 get_sub_conflicts (wp, size_word)
00326 struct web_part *wp;
00327 unsigned int size_word;
00328 {
00329 bitmap b = find_sub_conflicts (wp, size_word);
00330 if (!b)
00331 {
00332 struct tagged_conflict *cl =
00333 (struct tagged_conflict *) ra_alloc (sizeof *cl);
00334 cl->conflicts = BITMAP_XMALLOC ();
00335 cl->size_word = size_word;
00336 cl->next = wp->sub_conflicts;
00337 wp->sub_conflicts = cl;
00338 b = cl->conflicts;
00339 }
00340 return b;
00341 }
00342
00343
00344
00345 static struct undef_table_s {
00346 unsigned int new_undef;
00347
00348 unsigned int size_word;
00349 } const undef_table [] = {
00350 { 0, BL_TO_WORD (0, 0)},
00351 { 0, BL_TO_WORD (0, 1)},
00352 { 0, BL_TO_WORD (1, 1)},
00353 { 0, BL_TO_WORD (0, 2)},
00354 { 0, BL_TO_WORD (2, 1)},
00355 { 1, BL_TO_WORD (2, 1)},
00356 { 2, BL_TO_WORD (2, 1)},
00357 { 3, BL_TO_WORD (2, 1)},
00358 { 0, BL_TO_WORD (3, 1)},
00359 { 1, BL_TO_WORD (3, 1)},
00360 { 2, BL_TO_WORD (3, 1)},
00361 { 3, BL_TO_WORD (3, 1)},
00362 { 0, BL_TO_WORD (2, 2)},
00363 { 1, BL_TO_WORD (2, 2)},
00364 { 2, BL_TO_WORD (2, 2)},
00365 { 0, BL_TO_WORD (0, 4)}};
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 static unsigned int
00384 undef_to_size_word (reg, undefined)
00385 rtx reg;
00386 unsigned HOST_WIDE_INT *undefined;
00387 {
00388
00389
00390 if (*undefined <= 15)
00391 {
00392 struct undef_table_s u;
00393 u = undef_table[*undefined];
00394 *undefined = u.new_undef;
00395 return u.size_word;
00396 }
00397
00398
00399 switch (*undefined)
00400 {
00401 case 0x00f0 : *undefined = 0; return BL_TO_WORD (4, 4);
00402 case 0x00ff : *undefined = 0; return BL_TO_WORD (0, 8);
00403 case 0x0f00 : *undefined = 0; return BL_TO_WORD (8, 4);
00404 case 0x0ff0 : *undefined = 0xf0; return BL_TO_WORD (8, 4);
00405 case 0x0fff :
00406 if (INTEGRAL_MODE_P (GET_MODE (reg)))
00407 { *undefined = 0xff; return BL_TO_WORD (8, 4); }
00408 else
00409 { *undefined = 0; return BL_TO_WORD (0, 12); }
00410 case 0xf000 : *undefined = 0; return BL_TO_WORD (12, 4);
00411 case 0xff00 : *undefined = 0; return BL_TO_WORD (8, 8);
00412 case 0xfff0 : *undefined = 0xf0; return BL_TO_WORD (8, 8);
00413 case 0xffff : *undefined = 0; return BL_TO_WORD (0, 16);
00414
00415
00416
00417
00418
00419 default :
00420 {
00421 unsigned HOST_WIDE_INT u = *undefined;
00422 int word;
00423 struct undef_table_s tab;
00424 for (word = 0; (u & 15) == 0; word += 4)
00425 u >>= 4;
00426 u = u & 15;
00427 tab = undef_table[u];
00428 u = tab.new_undef;
00429 u = (*undefined & ~((unsigned HOST_WIDE_INT)15 << word))
00430 | (u << word);
00431 *undefined = u;
00432
00433 return tab.size_word + BL_TO_WORD (word, 0);
00434 }
00435 break;
00436 }
00437 }
00438
00439
00440
00441
00442
00443
00444 static bitmap
00445 undef_to_bitmap (wp, undefined)
00446 struct web_part *wp;
00447 unsigned HOST_WIDE_INT *undefined;
00448 {
00449 unsigned int size_word = undef_to_size_word (DF_REF_REAL_REG (wp->ref),
00450 undefined);
00451 return get_sub_conflicts (wp, size_word);
00452 }
00453
00454
00455
00456
00457 static struct web_part *
00458 find_web_part_1 (p)
00459 struct web_part *p;
00460 {
00461 struct web_part *r = p;
00462 struct web_part *p_next;
00463 while (r->uplink)
00464 r = r->uplink;
00465 for (; p != r; p = p_next)
00466 {
00467 p_next = p->uplink;
00468 p->uplink = r;
00469 }
00470 return r;
00471 }
00472
00473
00474
00475
00476 #define find_web_part(wp) ((! (wp)->uplink) ? (wp) \
00477 : (! (wp)->uplink->uplink) ? (wp)->uplink : find_web_part_1 (wp))
00478
00479
00480
00481
00482
00483
00484 static struct web_part *
00485 union_web_part_roots (r1, r2)
00486 struct web_part *r1, *r2;
00487 {
00488 if (r1 != r2)
00489 {
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 if (r1 > r2)
00501 {
00502 struct web_part *h = r1;
00503 r1 = r2;
00504 r2 = h;
00505 }
00506 r2->uplink = r1;
00507 num_webs--;
00508
00509
00510 r1->spanned_deaths += r2->spanned_deaths;
00511
00512 if (!r1->sub_conflicts)
00513 r1->sub_conflicts = r2->sub_conflicts;
00514 else if (r2->sub_conflicts)
00515
00516 {
00517 struct tagged_conflict *cl1, *cl2;
00518
00519
00520
00521 for (cl1 = r1->sub_conflicts; cl1; cl1 = cl1->next)
00522 for (cl2 = r2->sub_conflicts; cl2; cl2 = cl2->next)
00523 if (cl1->size_word == cl2->size_word)
00524 {
00525 bitmap_operation (cl1->conflicts, cl1->conflicts,
00526 cl2->conflicts, BITMAP_IOR);
00527 BITMAP_XFREE (cl2->conflicts);
00528 cl2->conflicts = NULL;
00529 }
00530
00531
00532 for (cl2 = r2->sub_conflicts; cl2;)
00533 {
00534 struct tagged_conflict *cl_next = cl2->next;
00535 if (cl2->conflicts)
00536 {
00537 cl2->next = r1->sub_conflicts;
00538 r1->sub_conflicts = cl2;
00539 }
00540 cl2 = cl_next;
00541 }
00542 }
00543 r2->sub_conflicts = NULL;
00544 r1->crosses_call |= r2->crosses_call;
00545 }
00546 return r1;
00547 }
00548
00549
00550 #define union_web_parts(p1, p2) \
00551 ((p1 == p2) ? find_web_part (p1) \
00552 : union_web_part_roots (find_web_part (p1), find_web_part (p2)))
00553
00554
00555
00556 static void
00557 remember_move (insn)
00558 rtx insn;
00559 {
00560 if (!TEST_BIT (move_handled, INSN_UID (insn)))
00561 {
00562 rtx s, d;
00563 SET_BIT (move_handled, INSN_UID (insn));
00564 if (copy_insn_p (insn, &s, &d))
00565 {
00566
00567 struct df_link *slink = DF_INSN_USES (df, insn);
00568 struct df_link *link = DF_INSN_DEFS (df, insn);
00569 if (!link || !link->ref || !slink || !slink->ref)
00570 abort ();
00571
00572
00573
00574
00575 if (link->next
00576 && DF_REF_REGNO (link->next->ref) >= FIRST_PSEUDO_REGISTER)
00577 abort ();
00578 }
00579 else
00580 abort ();
00581
00582
00583
00584
00585 if (GET_CODE (s) == REG && GET_CODE (d) == REG)
00586 {
00587 struct move *m = (struct move *) ra_calloc (sizeof (struct move));
00588 struct move_list *ml;
00589 m->insn = insn;
00590 ml = (struct move_list *) ra_alloc (sizeof (struct move_list));
00591 ml->move = m;
00592 ml->next = wl_moves;
00593 wl_moves = ml;
00594 }
00595 }
00596 }
00597
00598
00599
00600 struct curr_use {
00601 struct web_part *wp;
00602
00603 unsigned HOST_WIDE_INT undefined;
00604
00605 unsigned int regno;
00606 rtx x;
00607
00608 unsigned int live_over_abnormal;
00609 };
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 static int
00634 defuse_overlap_p_1 (def, use)
00635 rtx def;
00636 struct curr_use *use;
00637 {
00638 int mode = 0;
00639 if (def == use->x)
00640 return 1;
00641 if (!def)
00642 return 0;
00643 if (GET_CODE (def) == SUBREG)
00644 {
00645 if (REGNO (SUBREG_REG (def)) != use->regno)
00646 return 0;
00647 mode |= 1;
00648 }
00649 else if (REGNO (def) != use->regno)
00650 return 0;
00651 if (GET_CODE (use->x) == SUBREG)
00652 mode |= 2;
00653 switch (mode)
00654 {
00655 case 0:
00656 return 1;
00657 case 1:
00658 {
00659 unsigned HOST_WIDE_INT old_u = use->undefined;
00660 use->undefined &= ~ rtx_to_undefined (def);
00661 return (old_u != use->undefined) ? 2 : -1;
00662 }
00663 case 2:
00664 return 3;
00665 case 3:
00666 if (GET_MODE_SIZE (GET_MODE (def)) == GET_MODE_SIZE (GET_MODE (use->x)))
00667
00668
00669 if (SUBREG_BYTE (def) == SUBREG_BYTE (use->x))
00670 return 1;
00671
00672
00673
00674
00675
00676 {
00677 unsigned HOST_WIDE_INT old_u;
00678 int b1, e1, b2, e2;
00679 unsigned int bl1, bl2;
00680 bl1 = rtx_to_bits (def);
00681 bl2 = rtx_to_bits (use->x);
00682 b1 = BYTE_BEGIN (bl1);
00683 b2 = BYTE_BEGIN (bl2);
00684 e1 = b1 + BYTE_LENGTH (bl1) - 1;
00685 e2 = b2 + BYTE_LENGTH (bl2) - 1;
00686 if (b1 > e2 || b2 > e1)
00687 return -1;
00688 old_u = use->undefined;
00689 use->undefined &= ~ rtx_to_undefined (def);
00690 return (old_u != use->undefined) ? 4 : -1;
00691 }
00692 default:
00693 abort ();
00694 }
00695 }
00696
00697
00698
00699 #define defuse_overlap_p(def, use) \
00700 ((def) == (use)->x ? 1 : \
00701 (REGNO (GET_CODE (def) == SUBREG \
00702 ? SUBREG_REG (def) : def) != use->regno \
00703 ? 0 : defuse_overlap_p_1 (def, use)))
00704
00705
00706
00707
00708
00709
00710
00711
00712 static int
00713 live_out_1 (df, use, insn)
00714 struct df *df ATTRIBUTE_UNUSED;
00715 struct curr_use *use;
00716 rtx insn;
00717 {
00718 int defined = 0;
00719 int uid = INSN_UID (insn);
00720 struct web_part *wp = use->wp;
00721
00722
00723 visit_trace[uid].wp = wp;
00724 visit_trace[uid].undefined = use->undefined;
00725
00726 if (INSN_P (insn))
00727 {
00728 unsigned int source_regno = ~0;
00729 unsigned int regno = use->regno;
00730 unsigned HOST_WIDE_INT orig_undef = use->undefined;
00731 unsigned HOST_WIDE_INT final_undef = use->undefined;
00732 rtx s = NULL;
00733 unsigned int n, num_defs = insn_df[uid].num_defs;
00734 struct ref **defs = insn_df[uid].defs;
00735
00736
00737 wp = find_web_part (wp);
00738 if (GET_CODE (insn) == CALL_INSN)
00739 wp->crosses_call = 1;
00740 else if (copy_insn_p (insn, &s, NULL))
00741 source_regno = REGNO (GET_CODE (s) == SUBREG ? SUBREG_REG (s) : s);
00742
00743
00744 for (n = 0; n < num_defs; n++)
00745 {
00746 struct ref *ref = defs[n];
00747 int lap;
00748
00749
00750
00751
00752
00753 use->undefined = orig_undef;
00754 if ((lap = defuse_overlap_p (DF_REF_REG (ref), use)) != 0)
00755 {
00756 if (lap == -1)
00757
00758
00759
00760 {
00761 unsigned HOST_WIDE_INT undef;
00762 undef = use->undefined;
00763 while (undef)
00764 bitmap_set_bit (undef_to_bitmap (wp, &undef),
00765 DF_REF_ID (ref));
00766 continue;
00767 }
00768 if ((lap & 1) != 0)
00769
00770
00771 defined = 1;
00772 else
00773
00774 {
00775 final_undef &= use->undefined;
00776 if (final_undef == 0)
00777
00778
00779 defined = 1;
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 }
00796
00797
00798 wp = union_web_parts (wp, &web_parts[DF_REF_ID (ref)]);
00799 }
00800 else
00801 {
00802
00803
00804
00805 unsigned HOST_WIDE_INT undef = use->undefined;
00806
00807 if (regno == source_regno)
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818 {
00819 undef &= ~ rtx_to_undefined (s);
00820 }
00821 if (undef)
00822 {
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 do
00836 bitmap_set_bit (undef_to_bitmap (wp, &undef),
00837 DF_REF_ID (ref));
00838 while (undef);
00839 }
00840 }
00841 }
00842 if (defined)
00843 use->undefined = 0;
00844 else
00845 {
00846
00847
00848 if (uid >= death_insns_max_uid)
00849 abort ();
00850 if (TEST_BIT (insns_with_deaths, uid))
00851 wp->spanned_deaths++;
00852 use->undefined = final_undef;
00853 }
00854 }
00855
00856 return !defined;
00857 }
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 static inline int
00868 live_out (df, use, insn)
00869 struct df *df;
00870 struct curr_use *use;
00871 rtx insn;
00872 {
00873 unsigned int uid = INSN_UID (insn);
00874 if (visit_trace[uid].wp
00875 && DF_REF_REGNO (visit_trace[uid].wp->ref) == use->regno
00876 && (use->undefined & ~visit_trace[uid].undefined) == 0)
00877 {
00878 union_web_parts (visit_trace[uid].wp, use->wp);
00879
00880 return 0;
00881 }
00882 else
00883 return live_out_1 (df, use, insn);
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898 static rtx
00899 live_in_edge (df, use, e)
00900 struct df *df;
00901 struct curr_use *use;
00902 edge e;
00903 {
00904 struct ra_bb_info *info_pred;
00905 rtx next_insn;
00906
00907
00908
00909
00910 if ((e->flags & EDGE_EH) && use->regno < FIRST_PSEUDO_REGISTER
00911 && call_used_regs[use->regno])
00912 return NULL_RTX;
00913 if (e->flags & EDGE_ABNORMAL)
00914 use->live_over_abnormal = 1;
00915 bitmap_set_bit (live_at_end[e->src->index], DF_REF_ID (use->wp->ref));
00916 info_pred = (struct ra_bb_info *) e->src->aux;
00917 next_insn = e->src->end;
00918
00919
00920
00921 if (live_out (df, use, next_insn))
00922 {
00923
00924
00925 if (!bitmap_bit_p (info_pred->regnos_mentioned, use->regno)
00926 && (rtx_to_undefined (use->x) & ~use->undefined) == 0)
00927 {
00928
00929
00930 bitmap_set_bit (info_pred->live_throughout,
00931 DF_REF_ID (use->wp->ref));
00932 next_insn = e->src->head;
00933 }
00934 return next_insn;
00935 }
00936 else
00937 return NULL_RTX;
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947 static void
00948 live_in (df, use, insn)
00949 struct df *df;
00950 struct curr_use *use;
00951 rtx insn;
00952 {
00953 unsigned int loc_vpass = visited_pass;
00954
00955
00956
00957
00958
00959 while (1)
00960 {
00961 int uid = INSN_UID (insn);
00962 basic_block bb = BLOCK_FOR_INSN (insn);
00963 number_seen[uid]++;
00964
00965
00966
00967 for (insn = PREV_INSN (insn); insn && !INSN_P (insn);
00968 insn = PREV_INSN (insn))
00969 ;
00970 if (!insn)
00971 return;
00972 if (bb != BLOCK_FOR_INSN (insn))
00973 {
00974 edge e;
00975 unsigned HOST_WIDE_INT undef = use->undefined;
00976 struct ra_bb_info *info = (struct ra_bb_info *) bb->aux;
00977 if ((e = bb->pred) == NULL)
00978 return;
00979
00980
00981
00982
00983
00984 if (info->pass == loc_vpass && (undef & ~info->undefined) == 0)
00985 return;
00986 info->pass = loc_vpass;
00987 info->undefined = undef;
00988
00989 for (; e->pred_next; e = e->pred_next)
00990 {
00991 insn = live_in_edge (df, use, e);
00992 if (insn)
00993 live_in (df, use, insn);
00994 use->undefined = undef;
00995 }
00996 insn = live_in_edge (df, use, e);
00997 if (!insn)
00998 return;
00999 }
01000 else if (!live_out (df, use, insn))
01001 return;
01002 }
01003 }
01004
01005
01006
01007
01008
01009
01010 static void
01011 update_regnos_mentioned ()
01012 {
01013 int last_uid = last_max_uid;
01014 rtx insn;
01015 basic_block bb;
01016 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
01017 if (INSN_P (insn))
01018 {
01019
01020 if (INSN_UID (insn) < last_uid)
01021 {
01022
01023
01024 if (copy_insn_p (insn, NULL, NULL))
01025 remember_move (insn);
01026 }
01027 else if ((bb = BLOCK_FOR_INSN (insn)) != NULL)
01028 {
01029 rtx source;
01030 struct ra_bb_info *info = (struct ra_bb_info *) bb->aux;
01031 bitmap mentioned = info->regnos_mentioned;
01032 struct df_link *link;
01033 if (copy_insn_p (insn, &source, NULL))
01034 {
01035 remember_move (insn);
01036 bitmap_set_bit (mentioned,
01037 REGNO (GET_CODE (source) == SUBREG
01038 ? SUBREG_REG (source) : source));
01039 }
01040 for (link = DF_INSN_DEFS (df, insn); link; link = link->next)
01041 if (link->ref)
01042 bitmap_set_bit (mentioned, DF_REF_REGNO (link->ref));
01043 }
01044 }
01045 }
01046
01047
01048
01049
01050
01051
01052 static void
01053 livethrough_conflicts_bb (bb)
01054 basic_block bb;
01055 {
01056 struct ra_bb_info *info = (struct ra_bb_info *) bb->aux;
01057 rtx insn;
01058 bitmap all_defs;
01059 int first, use_id;
01060 unsigned int deaths = 0;
01061 unsigned int contains_call = 0;
01062
01063
01064 if ((first = bitmap_first_set_bit (info->live_throughout)) < 0)
01065 return;
01066
01067
01068
01069 all_defs = BITMAP_XMALLOC ();
01070 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
01071 {
01072 if (INSN_P (insn))
01073 {
01074 unsigned int n;
01075 struct ra_insn_info info;
01076
01077 info = insn_df[INSN_UID (insn)];
01078 for (n = 0; n < info.num_defs; n++)
01079 bitmap_set_bit (all_defs, DF_REF_ID (info.defs[n]));
01080 if (TEST_BIT (insns_with_deaths, INSN_UID (insn)))
01081 deaths++;
01082 if (GET_CODE (insn) == CALL_INSN)
01083 contains_call = 1;
01084 }
01085 if (insn == bb->end)
01086 break;
01087 }
01088
01089
01090
01091 if (deaths > 0 || bitmap_first_set_bit (all_defs) >= 0)
01092 EXECUTE_IF_SET_IN_BITMAP (info->live_throughout, first, use_id,
01093 {
01094 struct web_part *wp = &web_parts[df->def_id + use_id];
01095 unsigned int bl = rtx_to_bits (DF_REF_REG (wp->ref));
01096 bitmap conflicts;
01097 wp = find_web_part (wp);
01098 wp->spanned_deaths += deaths;
01099 wp->crosses_call |= contains_call;
01100 conflicts = get_sub_conflicts (wp, bl);
01101 bitmap_operation (conflicts, conflicts, all_defs, BITMAP_IOR);
01102 });
01103
01104 BITMAP_XFREE (all_defs);
01105 }
01106
01107
01108
01109
01110 static void
01111 init_bb_info ()
01112 {
01113 basic_block bb;
01114 FOR_ALL_BB (bb)
01115 {
01116 struct ra_bb_info *info =
01117 (struct ra_bb_info *) xcalloc (1, sizeof *info);
01118 info->regnos_mentioned = BITMAP_XMALLOC ();
01119 info->live_throughout = BITMAP_XMALLOC ();
01120 info->old_aux = bb->aux;
01121 bb->aux = (void *) info;
01122 }
01123 }
01124
01125
01126
01127 static void
01128 free_bb_info ()
01129 {
01130 basic_block bb;
01131 FOR_ALL_BB (bb)
01132 {
01133 struct ra_bb_info *info = (struct ra_bb_info *) bb->aux;
01134 BITMAP_XFREE (info->regnos_mentioned);
01135 BITMAP_XFREE (info->live_throughout);
01136 bb->aux = info->old_aux;
01137 free (info);
01138 }
01139 }
01140
01141
01142
01143
01144
01145 static void
01146 build_web_parts_and_conflicts (df)
01147 struct df *df;
01148 {
01149 struct df_link *link;
01150 struct curr_use use;
01151 basic_block bb;
01152
01153 number_seen = (int *) xcalloc (get_max_uid (), sizeof (int));
01154 visit_trace = (struct visit_trace *) xcalloc (get_max_uid (),
01155 sizeof (visit_trace[0]));
01156 update_regnos_mentioned ();
01157
01158
01159
01160
01161 visited_pass = 0;
01162 for (use.regno = 0; use.regno < (unsigned int)max_regno; use.regno++)
01163 if (use.regno >= FIRST_PSEUDO_REGISTER || !fixed_regs[use.regno])
01164 for (link = df->regs[use.regno].uses; link; link = link->next)
01165 if (link->ref)
01166 {
01167 struct ref *ref = link->ref;
01168 rtx insn = DF_REF_INSN (ref);
01169
01170 if (use.regno >= FIRST_PSEUDO_REGISTER
01171 && DF_REF_ID (ref) < last_use_id
01172 && !TEST_BIT (last_check_uses, DF_REF_ID (ref)))
01173 continue;
01174 use.wp = &web_parts[df->def_id + DF_REF_ID (ref)];
01175 use.x = DF_REF_REG (ref);
01176 use.live_over_abnormal = 0;
01177 use.undefined = rtx_to_undefined (use.x);
01178 visited_pass++;
01179 live_in (df, &use, insn);
01180 if (use.live_over_abnormal)
01181 SET_BIT (live_over_abnormal, DF_REF_ID (ref));
01182 }
01183
01184 dump_number_seen ();
01185 FOR_ALL_BB (bb)
01186 {
01187 struct ra_bb_info *info = (struct ra_bb_info *) bb->aux;
01188 livethrough_conflicts_bb (bb);
01189 bitmap_zero (info->live_throughout);
01190 info->pass = 0;
01191 }
01192 free (visit_trace);
01193 free (number_seen);
01194 }
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204 static void
01205 connect_rmw_web_parts (df)
01206 struct df *df;
01207 {
01208 unsigned int i;
01209
01210 for (i = 0; i < df->use_id; i++)
01211 {
01212 struct web_part *wp1 = &web_parts[df->def_id + i];
01213 rtx reg;
01214 struct df_link *link;
01215 if (!wp1->ref)
01216 continue;
01217
01218
01219 if (find_web_part (wp1) >= &web_parts[df->def_id])
01220 continue;
01221 reg = DF_REF_REAL_REG (wp1->ref);
01222 link = DF_INSN_DEFS (df, DF_REF_INSN (wp1->ref));
01223 for (; link; link = link->next)
01224 if (reg == DF_REF_REAL_REG (link->ref))
01225 {
01226 struct web_part *wp2 = &web_parts[DF_REF_ID (link->ref)];
01227 union_web_parts (wp1, wp2);
01228 }
01229 }
01230 }
01231
01232
01233
01234 static void
01235 prune_hardregs_for_mode (s, mode)
01236 HARD_REG_SET *s;
01237 enum machine_mode mode;
01238 {
01239 AND_HARD_REG_SET (*s, hardregs_for_mode[(int) mode]);
01240 }
01241
01242
01243
01244 static void
01245 init_one_web_common (web, reg)
01246 struct web *web;
01247 rtx reg;
01248 {
01249 if (GET_CODE (reg) != REG)
01250 abort ();
01251
01252 web->regno = REGNO (reg);
01253 web->orig_x = reg;
01254 if (!web->dlink)
01255 {
01256 web->dlink = (struct dlist *) ra_calloc (sizeof (struct dlist));
01257 DLIST_WEB (web->dlink) = web;
01258 }
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273 web->regclass = reg_class_subunion
01274 [reg_preferred_class (web->regno)] [reg_alternate_class (web->regno)];
01275 web->regclass = reg_preferred_class (web->regno);
01276 if (web->regno < FIRST_PSEUDO_REGISTER)
01277 {
01278 web->color = web->regno;
01279 put_web (web, PRECOLORED);
01280 web->num_conflicts = UINT_MAX;
01281 web->add_hardregs = 0;
01282 CLEAR_HARD_REG_SET (web->usable_regs);
01283 SET_HARD_REG_BIT (web->usable_regs, web->regno);
01284 web->num_freedom = 1;
01285 }
01286 else
01287 {
01288 HARD_REG_SET alternate;
01289 web->color = -1;
01290 put_web (web, INITIAL);
01291
01292
01293
01294
01295 web->add_hardregs =
01296 CLASS_MAX_NREGS (web->regclass, PSEUDO_REGNO_MODE (web->regno)) - 1;
01297 web->num_conflicts = 0 * web->add_hardregs;
01298 COPY_HARD_REG_SET (web->usable_regs,
01299 reg_class_contents[reg_preferred_class (web->regno)]);
01300 COPY_HARD_REG_SET (alternate,
01301 reg_class_contents[reg_alternate_class (web->regno)]);
01302 IOR_HARD_REG_SET (web->usable_regs, alternate);
01303
01304
01305
01306 AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors);
01307 prune_hardregs_for_mode (&web->usable_regs,
01308 PSEUDO_REGNO_MODE (web->regno));
01309 #ifdef CLASS_CANNOT_CHANGE_MODE
01310 if (web->mode_changed)
01311 AND_COMPL_HARD_REG_SET (web->usable_regs, reg_class_contents[
01312 (int) CLASS_CANNOT_CHANGE_MODE]);
01313 #endif
01314 web->num_freedom = hard_regs_count (web->usable_regs);
01315 web->num_freedom -= web->add_hardregs;
01316 if (!web->num_freedom)
01317 abort();
01318 }
01319 COPY_HARD_REG_SET (web->orig_usable_regs, web->usable_regs);
01320 }
01321
01322
01323
01324 static void
01325 init_one_web (web, reg)
01326 struct web *web;
01327 rtx reg;
01328 {
01329 memset (web, 0, sizeof (struct web));
01330 init_one_web_common (web, reg);
01331 web->useless_conflicts = BITMAP_XMALLOC ();
01332 }
01333
01334
01335
01336
01337
01338 static void
01339 reinit_one_web (web, reg)
01340 struct web *web;
01341 rtx reg;
01342 {
01343 web->old_color = web->color + 1;
01344 init_one_web_common (web, reg);
01345 web->span_deaths = 0;
01346 web->spill_temp = 0;
01347 web->orig_spill_temp = 0;
01348 web->use_my_regs = 0;
01349 web->spill_cost = 0;
01350 web->was_spilled = 0;
01351 web->is_coalesced = 0;
01352 web->artificial = 0;
01353 web->live_over_abnormal = 0;
01354 web->mode_changed = 0;
01355 web->move_related = 0;
01356 web->in_load = 0;
01357 web->target_of_spilled_move = 0;
01358 web->num_aliased = 0;
01359 if (web->type == PRECOLORED)
01360 {
01361 web->num_defs = 0;
01362 web->num_uses = 0;
01363 web->orig_spill_cost = 0;
01364 }
01365 CLEAR_HARD_REG_SET (web->bias_colors);
01366 CLEAR_HARD_REG_SET (web->prefer_colors);
01367 web->reg_rtx = NULL;
01368 web->stack_slot = NULL;
01369 web->pattern = NULL;
01370 web->alias = NULL;
01371 if (web->moves)
01372 abort ();
01373 if (!web->useless_conflicts)
01374 abort ();
01375 }
01376
01377
01378
01379
01380 static struct web *
01381 add_subweb (web, reg)
01382 struct web *web;
01383 rtx reg;
01384 {
01385 struct web *w;
01386 if (GET_CODE (reg) != SUBREG)
01387 abort ();
01388 w = (struct web *) xmalloc (sizeof (struct web));
01389
01390 *w = *web;
01391
01392 w->orig_x = reg;
01393 w->add_hardregs = CLASS_MAX_NREGS (web->regclass, GET_MODE (reg)) - 1;
01394 w->num_conflicts = 0 * w->add_hardregs;
01395 w->num_defs = 0;
01396 w->num_uses = 0;
01397 w->dlink = NULL;
01398 w->parent_web = web;
01399 w->subreg_next = web->subreg_next;
01400 web->subreg_next = w;
01401 return w;
01402 }
01403
01404
01405
01406
01407
01408 static struct web *
01409 add_subweb_2 (web, size_word)
01410 struct web *web;
01411 unsigned int size_word;
01412 {
01413
01414
01415
01416
01417
01418
01419
01420
01421 rtx ref_rtx = (web->subreg_next ? web->subreg_next : web)->orig_x;
01422 unsigned int size = BYTE_LENGTH (size_word) * BITS_PER_UNIT;
01423 enum machine_mode mode;
01424 mode = mode_for_size (size, GET_MODE_CLASS (GET_MODE (ref_rtx)), 0);
01425 if (mode == BLKmode)
01426 mode = mode_for_size (size, MODE_INT, 0);
01427 if (mode == BLKmode)
01428 abort ();
01429 web = add_subweb (web, gen_rtx_SUBREG (mode, web->orig_x,
01430 BYTE_BEGIN (size_word)));
01431 web->artificial = 1;
01432 return web;
01433 }
01434
01435
01436
01437 static void
01438 init_web_parts (df)
01439 struct df *df;
01440 {
01441 int regno;
01442 unsigned int no;
01443 num_webs = 0;
01444 for (no = 0; no < df->def_id; no++)
01445 {
01446 if (df->defs[no])
01447 {
01448 if (no < last_def_id && web_parts[no].ref != df->defs[no])
01449 abort ();
01450 web_parts[no].ref = df->defs[no];
01451
01452 if (!web_parts[no].uplink)
01453 num_webs++;
01454 }
01455 else
01456
01457
01458
01459
01460 web_parts[no].ref = NULL;
01461 }
01462 for (no = 0; no < df->use_id; no++)
01463 {
01464 if (df->uses[no])
01465 {
01466 if (no < last_use_id
01467 && web_parts[no + df->def_id].ref != df->uses[no])
01468 abort ();
01469 web_parts[no + df->def_id].ref = df->uses[no];
01470 if (!web_parts[no + df->def_id].uplink)
01471 num_webs++;
01472 }
01473 else
01474 web_parts[no + df->def_id].ref = NULL;
01475 }
01476
01477
01478 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01479 {
01480 struct web_part *r1 = NULL;
01481 struct df_link *link;
01482
01483
01484
01485
01486 for (link = df->regs[regno].defs; link; link = link->next)
01487 if (link->ref)
01488 {
01489 struct web_part *r2 = &web_parts[DF_REF_ID (link->ref)];
01490 if (!r1)
01491 r1 = r2;
01492 else
01493 r1 = union_web_parts (r1, r2);
01494 }
01495
01496 for (link = df->regs[regno].uses; link; link = link->next)
01497 if (link->ref)
01498 {
01499 struct web_part *r2 = &web_parts[df->def_id
01500 + DF_REF_ID (link->ref)];
01501 if (!r1)
01502 r1 = r2;
01503 else
01504 r1 = union_web_parts (r1, r2);
01505 }
01506 }
01507 }
01508
01509
01510
01511
01512 static void
01513 copy_conflict_list (web)
01514 struct web *web;
01515 {
01516 struct conflict_link *cl;
01517 if (web->orig_conflict_list || web->have_orig_conflicts)
01518 abort ();
01519 web->have_orig_conflicts = 1;
01520 for (cl = web->conflict_list; cl; cl = cl->next)
01521 {
01522 struct conflict_link *ncl;
01523 ncl = (struct conflict_link *) ra_alloc (sizeof *ncl);
01524 ncl->t = cl->t;
01525 ncl->sub = NULL;
01526 ncl->next = web->orig_conflict_list;
01527 web->orig_conflict_list = ncl;
01528 if (cl->sub)
01529 {
01530 struct sub_conflict *sl, *nsl;
01531 for (sl = cl->sub; sl; sl = sl->next)
01532 {
01533 nsl = (struct sub_conflict *) ra_alloc (sizeof *nsl);
01534 nsl->s = sl->s;
01535 nsl->t = sl->t;
01536 nsl->next = ncl->sub;
01537 ncl->sub = nsl;
01538 }
01539 }
01540 }
01541 }
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552 static void
01553 add_conflict_edge (from, to)
01554 struct web *from, *to;
01555 {
01556 if (from->type != PRECOLORED)
01557 {
01558 struct web *pfrom = find_web_for_subweb (from);
01559 struct web *pto = find_web_for_subweb (to);
01560 struct sub_conflict *sl;
01561 struct conflict_link *cl = pfrom->conflict_list;
01562 int may_delete = 1;
01563
01564
01565
01566
01567
01568
01569 if (pfrom == pto)
01570 return;
01571 if (remember_conflicts && !pfrom->have_orig_conflicts)
01572 copy_conflict_list (pfrom);
01573 if (!TEST_BIT (sup_igraph, (pfrom->id * num_webs + pto->id)))
01574 {
01575 cl = (struct conflict_link *) ra_alloc (sizeof (*cl));
01576 cl->t = pto;
01577 cl->sub = NULL;
01578 cl->next = pfrom->conflict_list;
01579 pfrom->conflict_list = cl;
01580 if (pto->type != SELECT && pto->type != COALESCED)
01581 pfrom->num_conflicts += 1 + pto->add_hardregs;
01582 SET_BIT (sup_igraph, (pfrom->id * num_webs + pto->id));
01583 may_delete = 0;
01584 }
01585 else
01586
01587
01588 while (cl->t != pto)
01589 cl = cl->next;
01590 if (pfrom != from || pto != to)
01591 {
01592
01593
01594
01595
01596
01597
01598 if (!may_delete || cl->sub != NULL)
01599 {
01600 sl = (struct sub_conflict *) ra_alloc (sizeof (*sl));
01601 sl->s = from;
01602 sl->t = to;
01603 sl->next = cl->sub;
01604 cl->sub = sl;
01605 }
01606 }
01607 else
01608
01609
01610
01611 cl->sub = NULL;
01612 }
01613 }
01614
01615
01616
01617
01618 void
01619 record_conflict (web1, web2)
01620 struct web *web1, *web2;
01621 {
01622 unsigned int id1 = web1->id, id2 = web2->id;
01623 unsigned int index = igraph_index (id1, id2);
01624
01625 if (web1 == web2 || TEST_BIT (igraph, index))
01626 return;
01627 if (id1 == id2)
01628 abort ();
01629
01630
01631 if ((web1->regno < FIRST_PSEUDO_REGISTER && fixed_regs[web1->regno])
01632 || (web2->regno < FIRST_PSEUDO_REGISTER && fixed_regs[web2->regno]))
01633 return;
01634
01635
01636 if ((web1->type == PRECOLORED
01637 && ! TEST_HARD_REG_BIT (web2->usable_regs, web1->regno))
01638 || (web2->type == PRECOLORED
01639 && ! TEST_HARD_REG_BIT (web1->usable_regs, web2->regno)))
01640 return;
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652 if (web1->type != PRECOLORED && web2->type != PRECOLORED
01653 && ! hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs))
01654 {
01655 struct web *p1 = find_web_for_subweb (web1);
01656 struct web *p2 = find_web_for_subweb (web2);
01657
01658
01659 bitmap_set_bit (p1->useless_conflicts, p2->id);
01660 bitmap_set_bit (p2->useless_conflicts, p1->id);
01661 return;
01662 }
01663 SET_BIT (igraph, index);
01664 add_conflict_edge (web1, web2);
01665 add_conflict_edge (web2, web1);
01666 }
01667
01668
01669
01670
01671 static void
01672 build_inverse_webs (web)
01673 struct web *web;
01674 {
01675 struct web *sweb = web->subreg_next;
01676 unsigned HOST_WIDE_INT undef;
01677
01678 undef = rtx_to_undefined (web->orig_x);
01679 for (; sweb; sweb = sweb->subreg_next)
01680
01681 if (!sweb->artificial)
01682 {
01683 unsigned HOST_WIDE_INT bits;
01684 bits = undef & ~ rtx_to_undefined (sweb->orig_x);
01685 while (bits)
01686 {
01687 unsigned int size_word = undef_to_size_word (web->orig_x, &bits);
01688 if (!find_subweb_2 (web, size_word))
01689 add_subweb_2 (web, size_word);
01690 }
01691 }
01692 }
01693
01694
01695
01696
01697 static void
01698 copy_web (web, wl)
01699 struct web *web;
01700 struct web_link **wl;
01701 {
01702 struct web *cweb = (struct web *) xmalloc (sizeof *cweb);
01703 struct web_link *link = (struct web_link *) ra_alloc (sizeof *link);
01704 link->next = *wl;
01705 *wl = link;
01706 link->web = cweb;
01707 *cweb = *web;
01708 }
01709
01710
01711
01712
01713 static void
01714 compare_and_free_webs (link)
01715 struct web_link **link;
01716 {
01717 struct web_link *wl;
01718 for (wl = *link; wl; wl = wl->next)
01719 {
01720 struct web *web1 = wl->web;
01721 struct web *web2 = ID2WEB (web1->id);
01722 if (web1->regno != web2->regno
01723 || web1->crosses_call != web2->crosses_call
01724 || web1->live_over_abnormal != web2->live_over_abnormal
01725 || web1->mode_changed != web2->mode_changed
01726 || !rtx_equal_p (web1->orig_x, web2->orig_x)
01727 || web1->type != web2->type
01728
01729
01730
01731 || (web1->type != PRECOLORED &&
01732 (web1->num_uses != web2->num_uses
01733 || web1->num_defs != web2->num_defs)))
01734 abort ();
01735 if (web1->type != PRECOLORED)
01736 {
01737 unsigned int i;
01738 for (i = 0; i < web1->num_defs; i++)
01739 if (web1->defs[i] != web2->defs[i])
01740 abort ();
01741 for (i = 0; i < web1->num_uses; i++)
01742 if (web1->uses[i] != web2->uses[i])
01743 abort ();
01744 }
01745 if (web1->type == PRECOLORED)
01746 {
01747 if (web1->defs)
01748 free (web1->defs);
01749 if (web1->uses)
01750 free (web1->uses);
01751 }
01752 free (web1);
01753 }
01754 *link = NULL;
01755 }
01756
01757
01758
01759 static void
01760 init_webs_defs_uses ()
01761 {
01762 struct dlist *d;
01763 for (d = WEBS(INITIAL); d; d = d->next)
01764 {
01765 struct web *web = DLIST_WEB (d);
01766 unsigned int def_i, use_i;
01767 struct df_link *link;
01768 if (web->old_web)
01769 continue;
01770 if (web->type == PRECOLORED)
01771 {
01772 web->num_defs = web->num_uses = 0;
01773 continue;
01774 }
01775 if (web->num_defs)
01776 web->defs = (struct ref **) xmalloc (web->num_defs *
01777 sizeof (web->defs[0]));
01778 if (web->num_uses)
01779 web->uses = (struct ref **) xmalloc (web->num_uses *
01780 sizeof (web->uses[0]));
01781 def_i = use_i = 0;
01782 for (link = web->temp_refs; link; link = link->next)
01783 {
01784 if (DF_REF_REG_DEF_P (link->ref))
01785 web->defs[def_i++] = link->ref;
01786 else
01787 web->uses[use_i++] = link->ref;
01788 }
01789 web->temp_refs = NULL;
01790 if (def_i != web->num_defs || use_i != web->num_uses)
01791 abort ();
01792 }
01793 }
01794
01795
01796
01797
01798
01799 static unsigned int
01800 parts_to_webs_1 (df, copy_webs, all_refs)
01801 struct df *df;
01802 struct web_link **copy_webs;
01803 struct df_link *all_refs;
01804 {
01805 unsigned int i;
01806 unsigned int webnum;
01807 unsigned int def_id = df->def_id;
01808 unsigned int use_id = df->use_id;
01809 struct web_part *wp_first_use = &web_parts[def_id];
01810
01811
01812
01813
01814
01815 webnum = 0;
01816 for (i = 0; i < def_id + use_id; i++)
01817 {
01818 struct web *subweb, *web = 0;
01819 struct web_part *wp = &web_parts[i];
01820 struct ref *ref = wp->ref;
01821 unsigned int ref_id;
01822 rtx reg;
01823 if (!ref)
01824 continue;
01825 ref_id = i;
01826 if (i >= def_id)
01827 ref_id -= def_id;
01828 all_refs[i].ref = ref;
01829 reg = DF_REF_REG (ref);
01830 if (! wp->uplink)
01831 {
01832
01833 unsigned int newid = ~(unsigned)0;
01834 unsigned int old_web = 0;
01835
01836
01837
01838 if (ra_pass == 1)
01839 {
01840 web = (struct web *) xmalloc (sizeof (struct web));
01841 newid = last_num_webs++;
01842 init_one_web (web, GET_CODE (reg) == SUBREG
01843 ? SUBREG_REG (reg) : reg);
01844 }
01845
01846 else
01847 {
01848
01849
01850
01851
01852
01853 web = def2web[i];
01854
01855 if (!web && DF_REF_REGNO (ref) < FIRST_PSEUDO_REGISTER)
01856 web = hardreg2web[DF_REF_REGNO (ref)];
01857 if (web)
01858 {
01859
01860 web = find_web_for_subweb (web);
01861 remove_list (web->dlink, &WEBS(INITIAL));
01862 old_web = 1;
01863 copy_web (web, copy_webs);
01864 }
01865 else
01866 {
01867
01868 if (WEBS(FREE))
01869 web = DLIST_WEB (pop_list (&WEBS(FREE)));
01870 else
01871 {
01872
01873 web = (struct web *) xmalloc (sizeof (struct web));
01874 newid = last_num_webs++;
01875 }
01876 }
01877
01878 if (newid == ~(unsigned)0)
01879 newid = web->id;
01880 if (old_web)
01881 reinit_one_web (web, GET_CODE (reg) == SUBREG
01882 ? SUBREG_REG (reg) : reg);
01883 else
01884 init_one_web (web, GET_CODE (reg) == SUBREG
01885 ? SUBREG_REG (reg) : reg);
01886 web->old_web = (old_web && web->type != PRECOLORED) ? 1 : 0;
01887 }
01888 web->span_deaths = wp->spanned_deaths;
01889 web->crosses_call = wp->crosses_call;
01890 web->id = newid;
01891 web->temp_refs = NULL;
01892 webnum++;
01893 if (web->regno < FIRST_PSEUDO_REGISTER && !hardreg2web[web->regno])
01894 hardreg2web[web->regno] = web;
01895 else if (web->regno < FIRST_PSEUDO_REGISTER
01896 && hardreg2web[web->regno] != web)
01897 abort ();
01898 }
01899
01900
01901
01902
01903 if (def2web[i] != NULL)
01904 {
01905 web = def2web[i];
01906 web = find_web_for_subweb (web);
01907
01908
01909 if ((DF_REF_FLAGS (ref) & DF_REF_MODE_CHANGE) != 0
01910 && web->regno >= FIRST_PSEUDO_REGISTER)
01911 web->mode_changed = 1;
01912 if (i >= def_id
01913 && TEST_BIT (live_over_abnormal, ref_id))
01914 web->live_over_abnormal = 1;
01915
01916
01917 if (!web->old_web || web->type == PRECOLORED)
01918 abort ();
01919 continue;
01920 }
01921
01922
01923 if (wp->uplink)
01924 {
01925 struct web_part *rwp = find_web_part (wp);
01926 unsigned int j = DF_REF_ID (rwp->ref);
01927 if (rwp < wp_first_use)
01928 web = def2web[j];
01929 else
01930 web = use2web[j];
01931 web = find_web_for_subweb (web);
01932 }
01933
01934
01935 all_refs[i].next = web->temp_refs;
01936 web->temp_refs = &all_refs[i];
01937
01938
01939
01940 if (web->old_web && web->type != PRECOLORED)
01941 abort ();
01942
01943
01944 if (GET_CODE (reg) == SUBREG)
01945 {
01946 subweb = find_subweb (web, reg);
01947 if (!subweb)
01948 {
01949 subweb = add_subweb (web, reg);
01950 if (web->old_web)
01951 abort ();
01952 }
01953 }
01954 else
01955 subweb = web;
01956
01957
01958 if ((DF_REF_FLAGS (ref) & DF_REF_MODE_CHANGE) != 0
01959 && web->regno >= FIRST_PSEUDO_REGISTER)
01960 web->mode_changed = 1;
01961
01962
01963 if (i < def_id)
01964 {
01965
01966 if (ra_pass > 1)
01967 {
01968 struct web *compare = def2web[i];
01969 if (i < last_def_id)
01970 {
01971 if (web->old_web && compare != subweb)
01972 abort ();
01973 }
01974 if (!web->old_web && compare)
01975 abort ();
01976 if (compare && compare != subweb)
01977 abort ();
01978 }
01979 def2web[i] = subweb;
01980 web->num_defs++;
01981 }
01982 else
01983 {
01984 if (ra_pass > 1)
01985 {
01986 struct web *compare = use2web[ref_id];
01987 if (ref_id < last_use_id)
01988 {
01989 if (web->old_web && compare != subweb)
01990 abort ();
01991 }
01992 if (!web->old_web && compare)
01993 abort ();
01994 if (compare && compare != subweb)
01995 abort ();
01996 }
01997 use2web[ref_id] = subweb;
01998 web->num_uses++;
01999 if (TEST_BIT (live_over_abnormal, ref_id))
02000 web->live_over_abnormal = 1;
02001 }
02002 }
02003
02004
02005 if (webnum != num_webs)
02006 abort ();
02007
02008 return webnum;
02009 }
02010
02011
02012
02013
02014 static void
02015 parts_to_webs (df)
02016 struct df *df;
02017 {
02018 unsigned int i;
02019 unsigned int webnum;
02020 struct web_link *copy_webs = NULL;
02021 struct dlist *d;
02022 struct df_link *all_refs;
02023 num_subwebs = 0;
02024
02025
02026 all_refs = (struct df_link *) xcalloc (df->def_id + df->use_id,
02027 sizeof (all_refs[0]));
02028 webnum = parts_to_webs_1 (df, ©_webs, all_refs);
02029
02030
02031
02032 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
02033 if (!hardreg2web[i])
02034 {
02035 struct web *web = (struct web *) xmalloc (sizeof (struct web));
02036 init_one_web (web, gen_rtx_REG (reg_raw_mode[i], i));
02037 web->id = last_num_webs++;
02038 hardreg2web[web->regno] = web;
02039 }
02040 num_webs = last_num_webs;
02041
02042
02043
02044
02045
02046
02047
02048
02049 for (i = 0; i < df->def_id + df->use_id; i++)
02050 {
02051 struct web_part *wp = &web_parts[i];
02052 struct tagged_conflict *cl;
02053 struct web *web;
02054 if (wp->uplink || !wp->ref)
02055 {
02056 if (wp->sub_conflicts)
02057 abort ();
02058 continue;
02059 }
02060 web = def2web[i];
02061 web = find_web_for_subweb (web);
02062 for (cl = wp->sub_conflicts; cl; cl = cl->next)
02063 if (!find_subweb_2 (web, cl->size_word))
02064 add_subweb_2 (web, cl->size_word);
02065 }
02066
02067
02068
02069 webnum = last_num_webs;
02070 for (d = WEBS(INITIAL); d; d = d->next)
02071 {
02072 struct web *web = DLIST_WEB (d);
02073 if (web->subreg_next)
02074 {
02075 struct web *sweb;
02076 build_inverse_webs (web);
02077 for (sweb = web->subreg_next; sweb; sweb = sweb->subreg_next)
02078 sweb->id = webnum++;
02079 }
02080 }
02081
02082
02083 id2web = (struct web **) xcalloc (webnum, sizeof (id2web[0]));
02084 for (d = WEBS(INITIAL); d; d = d->next)
02085 {
02086 struct web *web = DLIST_WEB (d);
02087 ID2WEB (web->id) = web;
02088 for (web = web->subreg_next; web; web = web->subreg_next)
02089 ID2WEB (web->id) = web;
02090 }
02091 num_subwebs = webnum - last_num_webs;
02092 num_allwebs = num_webs + num_subwebs;
02093 num_webs += num_subwebs;
02094
02095
02096 igraph = sbitmap_alloc (num_webs * num_webs / 2);
02097 sup_igraph = sbitmap_alloc (num_webs * num_webs);
02098 sbitmap_zero (igraph);
02099 sbitmap_zero (sup_igraph);
02100
02101
02102 init_webs_defs_uses ();
02103
02104
02105 compare_and_free_webs (©_webs);
02106 free (all_refs);
02107 }
02108
02109
02110
02111
02112
02113
02114 static void
02115 reset_conflicts ()
02116 {
02117 unsigned int i;
02118 bitmap newwebs = BITMAP_XMALLOC ();
02119 for (i = 0; i < num_webs - num_subwebs; i++)
02120 {
02121 struct web *web = ID2WEB (i);
02122
02123
02124 if (web->type == PRECOLORED || !web->old_web)
02125 bitmap_set_bit (newwebs, web->id);
02126 }
02127
02128 for (i = 0; i < num_webs - num_subwebs; i++)
02129 {
02130 struct web *web = ID2WEB (i);
02131 struct conflict_link *cl;
02132 struct conflict_link **pcl;
02133 pcl = &(web->conflict_list);
02134
02135
02136
02137 if (web->have_orig_conflicts)
02138 {
02139 web->conflict_list = web->orig_conflict_list;
02140 web->orig_conflict_list = NULL;
02141 }
02142 if (web->orig_conflict_list)
02143 abort ();
02144
02145
02146 if (web->type != PRECOLORED && !web->old_web)
02147 {
02148 *pcl = NULL;
02149
02150
02151
02152 if (bitmap_first_set_bit (web->useless_conflicts) >= 0)
02153 abort ();
02154 }
02155 else
02156 {
02157
02158
02159 bitmap_operation (web->useless_conflicts, web->useless_conflicts,
02160 newwebs, BITMAP_AND_COMPL);
02161
02162 for (cl = web->conflict_list; cl; cl = cl->next)
02163 {
02164 if (cl->t->old_web || cl->t->type == PRECOLORED)
02165 {
02166 *pcl = cl;
02167 pcl = &(cl->next);
02168
02169
02170 web->num_conflicts += 1 + cl->t->add_hardregs;
02171 SET_BIT (sup_igraph, (web->id * num_webs + cl->t->id));
02172
02173 if (!cl->sub)
02174 SET_BIT (igraph, igraph_index (web->id, cl->t->id));
02175 else
02176
02177
02178 {
02179 struct sub_conflict *sl;
02180 for (sl = cl->sub; sl; sl = sl->next)
02181 SET_BIT (igraph, igraph_index (sl->s->id, sl->t->id));
02182 }
02183 }
02184 }
02185 *pcl = NULL;
02186 }
02187 web->have_orig_conflicts = 0;
02188 }
02189 BITMAP_XFREE (newwebs);
02190 }
02191
02192
02193
02194
02195 #if 0
02196 static void
02197 check_conflict_numbers ()
02198 {
02199 unsigned int i;
02200 for (i = 0; i < num_webs; i++)
02201 {
02202 struct web *web = ID2WEB (i);
02203 int new_conf = 0 * web->add_hardregs;
02204 struct conflict_link *cl;
02205 for (cl = web->conflict_list; cl; cl = cl->next)
02206 if (cl->t->type != SELECT && cl->t->type != COALESCED)
02207 new_conf += 1 + cl->t->add_hardregs;
02208 if (web->type != PRECOLORED && new_conf != web->num_conflicts)
02209 abort ();
02210 }
02211 }
02212 #endif
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227 static void
02228 conflicts_between_webs (df)
02229 struct df *df;
02230 {
02231 unsigned int i;
02232 #ifdef STACK_REGS
02233 struct dlist *d;
02234 #endif
02235 bitmap ignore_defs = BITMAP_XMALLOC ();
02236 unsigned int have_ignored;
02237 unsigned int *pass_cache = (unsigned int *) xcalloc (num_webs, sizeof (int));
02238 unsigned int pass = 0;
02239
02240 if (ra_pass > 1)
02241 reset_conflicts ();
02242
02243
02244
02245
02246
02247
02248
02249
02250 for (i = 0; i < df->def_id; i++)
02251 if (web_parts[i].ref == NULL)
02252 bitmap_set_bit (ignore_defs, i);
02253 have_ignored = (bitmap_first_set_bit (ignore_defs) >= 0);
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263 for (i = 0; i < df->def_id + df->use_id; i++)
02264 {
02265 struct tagged_conflict *cl = web_parts[i].sub_conflicts;
02266 struct web *supweb1;
02267 if (!cl
02268 || (i >= df->def_id
02269 && DF_REF_REGNO (web_parts[i].ref) >= FIRST_PSEUDO_REGISTER))
02270 continue;
02271 supweb1 = def2web[i];
02272 supweb1 = find_web_for_subweb (supweb1);
02273 for (; cl; cl = cl->next)
02274 if (cl->conflicts)
02275 {
02276 int j;
02277 struct web *web1 = find_subweb_2 (supweb1, cl->size_word);
02278 if (have_ignored)
02279 bitmap_operation (cl->conflicts, cl->conflicts, ignore_defs,
02280 BITMAP_AND_COMPL);
02281
02282
02283
02284
02285
02286
02287
02288
02289 pass++;
02290
02291
02292 EXECUTE_IF_SET_IN_BITMAP (
02293 cl->conflicts, 0, j,
02294 {
02295 struct web *web2 = def2web[j];
02296 unsigned int id2 = web2->id;
02297 if (pass_cache[id2] != pass)
02298 {
02299 pass_cache[id2] = pass;
02300 record_conflict (web1, web2);
02301 }
02302 });
02303 }
02304 }
02305
02306 free (pass_cache);
02307 BITMAP_XFREE (ignore_defs);
02308
02309 #ifdef STACK_REGS
02310
02311
02312 for (d = WEBS(INITIAL); d; d = d->next)
02313 {
02314 struct web *web = DLIST_WEB (d);
02315 int j;
02316 if (web->live_over_abnormal)
02317 for (j = FIRST_STACK_REG; j <= LAST_STACK_REG; j++)
02318 record_conflict (web, hardreg2web[j]);
02319 }
02320 #endif
02321 }
02322
02323
02324
02325
02326 static void
02327 remember_web_was_spilled (web)
02328 struct web *web;
02329 {
02330 int i;
02331 unsigned int found_size = 0;
02332 int adjust;
02333 web->spill_temp = 1;
02334
02335
02336
02337
02338
02339 web->use_my_regs = 1;
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352 if (web->regno >= max_normal_pseudo)
02353 {
02354 COPY_HARD_REG_SET (web->usable_regs,
02355 reg_class_contents[reg_preferred_class (web->regno)]);
02356 IOR_HARD_REG_SET (web->usable_regs,
02357 reg_class_contents[reg_alternate_class (web->regno)]);
02358 }
02359 else
02360 COPY_HARD_REG_SET (web->usable_regs,
02361 reg_class_contents[(int) GENERAL_REGS]);
02362 AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors);
02363 prune_hardregs_for_mode (&web->usable_regs, PSEUDO_REGNO_MODE (web->regno));
02364 #ifdef CLASS_CANNOT_CHANGE_MODE
02365 if (web->mode_changed)
02366 AND_COMPL_HARD_REG_SET (web->usable_regs, reg_class_contents[
02367 (int) CLASS_CANNOT_CHANGE_MODE]);
02368 #endif
02369 web->num_freedom = hard_regs_count (web->usable_regs);
02370 if (!web->num_freedom)
02371 abort();
02372 COPY_HARD_REG_SET (web->orig_usable_regs, web->usable_regs);
02373
02374
02375 web->regclass = NO_REGS;
02376 for (i = (int) ALL_REGS - 1; i > 0; i--)
02377 {
02378 unsigned int size;
02379 HARD_REG_SET test;
02380 COPY_HARD_REG_SET (test, reg_class_contents[i]);
02381 AND_COMPL_HARD_REG_SET (test, never_use_colors);
02382 GO_IF_HARD_REG_SUBSET (test, web->usable_regs, found);
02383 continue;
02384 found:
02385
02386
02387 size = hard_regs_count (test);
02388 if (found_size < size)
02389 {
02390 web->regclass = (enum reg_class) i;
02391 found_size = size;
02392 }
02393 }
02394
02395 adjust = 0 * web->add_hardregs;
02396 web->add_hardregs =
02397 CLASS_MAX_NREGS (web->regclass, PSEUDO_REGNO_MODE (web->regno)) - 1;
02398 web->num_freedom -= web->add_hardregs;
02399 if (!web->num_freedom)
02400 abort();
02401 adjust -= 0 * web->add_hardregs;
02402 web->num_conflicts -= adjust;
02403 }
02404
02405
02406
02407
02408 static void
02409 detect_spill_temps ()
02410 {
02411 struct dlist *d;
02412 bitmap already = BITMAP_XMALLOC ();
02413
02414
02415 for (d = WEBS(INITIAL); d; d = d->next)
02416 {
02417 struct web *web = DLIST_WEB (d);
02418
02419
02420
02421
02422
02423 if (web->regno < FIRST_PSEUDO_REGISTER)
02424 continue;
02425
02426 if (web->num_defs == 0)
02427 continue;
02428
02429
02430
02431
02432 if (web->num_uses == 0)
02433 web->spill_temp = 3;
02434
02435
02436
02437 else if (web->changed)
02438 web->spill_temp = 1;
02439
02440
02441
02442
02443
02444
02445
02446
02447 else
02448 {
02449 unsigned int i;
02450 int spill_involved = 0;
02451 for (i = 0; i < web->num_uses && !spill_involved; i++)
02452 if (DF_REF_INSN_UID (web->uses[i]) >= orig_max_uid)
02453 spill_involved = 1;
02454 for (i = 0; i < web->num_defs && !spill_involved; i++)
02455 if (DF_REF_INSN_UID (web->defs[i]) >= orig_max_uid)
02456 spill_involved = 1;
02457
02458 if (spill_involved)
02459 {
02460 int num_deaths = web->span_deaths;
02461
02462
02463 remember_web_was_spilled (web);
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473 bitmap_zero (already);
02474 for (i = 0; i < web->num_defs; i++)
02475 {
02476 rtx insn = web->defs[i]->insn;
02477 if (TEST_BIT (insns_with_deaths, INSN_UID (insn))
02478 && !bitmap_bit_p (already, INSN_UID (insn)))
02479 {
02480 unsigned int j;
02481 bitmap_set_bit (already, INSN_UID (insn));
02482
02483 for (j = 0; j < web->num_uses; j++)
02484 if (web->uses[j]->insn == insn)
02485 {
02486 num_deaths--;
02487 break;
02488 }
02489 }
02490 }
02491
02492
02493
02494 if (web->crosses_call || num_deaths > 0)
02495 web->spill_temp = 1 * 2;
02496 }
02497
02498
02499
02500
02501
02502 else if (web->span_deaths == 0 && !web->crosses_call)
02503 web->spill_temp = 3;
02504 }
02505 web->orig_spill_temp = web->spill_temp;
02506 }
02507 BITMAP_XFREE (already);
02508 }
02509
02510
02511
02512 int
02513 memref_is_stack_slot (mem)
02514 rtx mem;
02515 {
02516 rtx ad = XEXP (mem, 0);
02517 rtx x;
02518 if (GET_CODE (ad) != PLUS || GET_CODE (XEXP (ad, 1)) != CONST_INT)
02519 return 0;
02520 x = XEXP (ad, 0);
02521 if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
02522 || (x == arg_pointer_rtx && fixed_regs[ARG_POINTER_REGNUM])
02523 || x == stack_pointer_rtx)
02524 return 1;
02525 return 0;
02526 }
02527
02528
02529
02530 static int
02531 contains_pseudo (x)
02532 rtx x;
02533 {
02534 const char *fmt;
02535 int i;
02536 if (GET_CODE (x) == SUBREG)
02537 x = SUBREG_REG (x);
02538 if (GET_CODE (x) == REG)
02539 {
02540 if (REGNO (x) >= FIRST_PSEUDO_REGISTER)
02541 return 1;
02542 else
02543 return 0;
02544 }
02545
02546 fmt = GET_RTX_FORMAT (GET_CODE (x));
02547 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
02548 if (fmt[i] == 'e')
02549 {
02550 if (contains_pseudo (XEXP (x, i)))
02551 return 1;
02552 }
02553 else if (fmt[i] == 'E')
02554 {
02555 int j;
02556 for (j = 0; j < XVECLEN (x, i); j++)
02557 if (contains_pseudo (XVECEXP (x, i, j)))
02558 return 1;
02559 }
02560 return 0;
02561 }
02562
02563
02564
02565
02566
02567
02568 static GTY(()) rtx remat_test_insn;
02569 static int
02570 want_to_remat (x)
02571 rtx x;
02572 {
02573 int num_clobbers = 0;
02574 int icode;
02575
02576
02577 if (general_operand (x, GET_MODE (x)))
02578 return 1;
02579
02580
02581
02582 if (remat_test_insn == 0)
02583 {
02584 remat_test_insn
02585 = make_insn_raw (gen_rtx_SET (VOIDmode,
02586 gen_rtx_REG (word_mode,
02587 FIRST_PSEUDO_REGISTER * 2),
02588 const0_rtx));
02589 NEXT_INSN (remat_test_insn) = PREV_INSN (remat_test_insn) = 0;
02590 }
02591
02592
02593
02594 PUT_MODE (SET_DEST (PATTERN (remat_test_insn)), GET_MODE (x));
02595 SET_SRC (PATTERN (remat_test_insn)) = x;
02596
02597
02598 return ((icode = recog (PATTERN (remat_test_insn), remat_test_insn,
02599 &num_clobbers)) >= 0
02600 && (num_clobbers == 0
02601 ));
02602 }
02603
02604
02605
02606
02607
02608 static void
02609 detect_remat_webs ()
02610 {
02611 struct dlist *d;
02612 for (d = WEBS(INITIAL); d; d = d->next)
02613 {
02614 struct web *web = DLIST_WEB (d);
02615 unsigned int i;
02616 rtx pat = NULL_RTX;
02617
02618
02619 if (web->regno < FIRST_PSEUDO_REGISTER || !web->num_defs
02620 || !web->num_uses)
02621 continue;
02622 for (i = 0; i < web->num_defs; i++)
02623 {
02624 rtx insn;
02625 rtx set = single_set (insn = DF_REF_INSN (web->defs[i]));
02626 rtx src;
02627 if (!set)
02628 break;
02629 src = SET_SRC (set);
02630
02631
02632 if (!rtx_equal_p (SET_DEST (set), web->orig_x))
02633 break;
02634
02635 if (pat && !rtx_equal_p (pat, src))
02636 break;
02637
02638 if (pat)
02639 continue;
02640
02641 if ((CONSTANT_P (src)
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653 || (!rtx_unstable_p (src) && !contains_pseudo (src))
02654
02655
02656
02657
02658 || (GET_CODE (src) == MEM
02659 && INSN_UID (insn) >= orig_max_uid
02660 && memref_is_stack_slot (src)))
02661
02662
02663 && want_to_remat (src))
02664 pat = src;
02665 else
02666 break;
02667 }
02668 if (pat && i == web->num_defs)
02669 web->pattern = pat;
02670 }
02671 }
02672
02673
02674
02675 static void
02676 determine_web_costs ()
02677 {
02678 struct dlist *d;
02679 for (d = WEBS(INITIAL); d; d = d->next)
02680 {
02681 unsigned int i, num_loads;
02682 int load_cost, store_cost;
02683 unsigned HOST_WIDE_INT w;
02684 struct web *web = DLIST_WEB (d);
02685 if (web->type == PRECOLORED)
02686 continue;
02687
02688
02689
02690
02691
02692 if (web->pattern)
02693 {
02694
02695
02696
02697
02698
02699
02700 load_cost = 1 + rtx_cost (web->pattern, 0);
02701 store_cost = 0;
02702 }
02703 else
02704 {
02705 load_cost = 1 + MEMORY_MOVE_COST (GET_MODE (web->orig_x),
02706 web->regclass, 1);
02707 store_cost = 1 + MEMORY_MOVE_COST (GET_MODE (web->orig_x),
02708 web->regclass, 0);
02709 }
02710
02711 num_loads = MIN (web->span_deaths, web->num_uses);
02712 for (w = 0, i = 0; i < web->num_uses; i++)
02713 w += DF_REF_BB (web->uses[i])->frequency + 1;
02714 if (num_loads < web->num_uses)
02715 w = (w * num_loads + web->num_uses - 1) / web->num_uses;
02716 web->spill_cost = w * load_cost;
02717 if (store_cost)
02718 {
02719 for (w = 0, i = 0; i < web->num_defs; i++)
02720 w += DF_REF_BB (web->defs[i])->frequency + 1;
02721 web->spill_cost += w * store_cost;
02722 }
02723 web->orig_spill_cost = web->spill_cost;
02724 }
02725 }
02726
02727
02728
02729
02730
02731
02732 static void
02733 detect_webs_set_in_cond_jump ()
02734 {
02735 basic_block bb;
02736 FOR_EACH_BB (bb)
02737 if (GET_CODE (bb->end) == JUMP_INSN)
02738 {
02739 struct df_link *link;
02740 for (link = DF_INSN_DEFS (df, bb->end); link; link = link->next)
02741 if (link->ref && DF_REF_REGNO (link->ref) >= FIRST_PSEUDO_REGISTER)
02742 {
02743 struct web *web = def2web[DF_REF_ID (link->ref)];
02744 web->orig_spill_temp = web->spill_temp = 3;
02745 }
02746 }
02747 }
02748
02749
02750
02751
02752
02753
02754
02755 static void
02756 make_webs (df)
02757 struct df *df;
02758 {
02759
02760
02761 parts_to_webs (df);
02762
02763 detect_spill_temps ();
02764 detect_webs_set_in_cond_jump ();
02765
02766
02767 conflicts_between_webs (df);
02768 detect_remat_webs ();
02769 determine_web_costs ();
02770 }
02771
02772
02773
02774 static void
02775 moves_to_webs (df)
02776 struct df *df;
02777 {
02778 struct df_link *link;
02779 struct move_list *ml;
02780
02781
02782
02783
02784 for (ml = wl_moves; ml; ml = ml->next)
02785 {
02786 struct move *m = ml->move;
02787 struct web *web;
02788 struct move_list *newml;
02789 if (!m)
02790 continue;
02791 m->type = WORKLIST;
02792 m->dlink = NULL;
02793
02794
02795
02796
02797 for (link = DF_INSN_DEFS (df, m->insn); link; link = link->next)
02798 if (link->ref)
02799 {
02800 web = def2web[DF_REF_ID (link->ref)];
02801 web = find_web_for_subweb (web);
02802 if (!m->target_web || web->regno < m->target_web->regno)
02803 m->target_web = web;
02804 }
02805 for (link = DF_INSN_USES (df, m->insn); link; link = link->next)
02806 if (link->ref)
02807 {
02808 web = use2web[DF_REF_ID (link->ref)];
02809 web = find_web_for_subweb (web);
02810 if (!m->source_web || web->regno < m->source_web->regno)
02811 m->source_web = web;
02812 }
02813 if (m->source_web && m->target_web
02814
02815
02816
02817 && hard_regs_intersect_p (&m->source_web->usable_regs,
02818 &m->target_web->usable_regs))
02819 {
02820 if (!flag_ra_optimistic_coalescing)
02821 {
02822 struct move_list *test = m->source_web->moves;
02823 for (; test && test->move != m; test = test->next);
02824 if (! test)
02825 {
02826 newml = (struct move_list*)
02827 ra_alloc (sizeof (struct move_list));
02828 newml->move = m;
02829 newml->next = m->source_web->moves;
02830 m->source_web->moves = newml;
02831 }
02832 test = m->target_web->moves;
02833 for (; test && test->move != m; test = test->next);
02834 if (! test)
02835 {
02836 newml = (struct move_list*)
02837 ra_alloc (sizeof (struct move_list));
02838 newml->move = m;
02839 newml->next = m->target_web->moves;
02840 m->target_web->moves = newml;
02841 }
02842 }
02843 }
02844 else
02845
02846 ml->move = NULL;
02847 }
02848 }
02849
02850
02851
02852
02853
02854
02855 static void
02856 handle_asm_insn (df, insn)
02857 struct df *df;
02858 rtx insn;
02859 {
02860 const char *constraints[MAX_RECOG_OPERANDS];
02861 enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
02862 int i, noperands, in_output;
02863 HARD_REG_SET clobbered, allowed, conflict;
02864 rtx pat;
02865 if (! INSN_P (insn)
02866 || (noperands = asm_noperands (PATTERN (insn))) < 0)
02867 return;
02868 pat = PATTERN (insn);
02869 CLEAR_HARD_REG_SET (clobbered);
02870
02871 if (GET_CODE (pat) == PARALLEL)
02872 for (i = 0; i < XVECLEN (pat, 0); i++)
02873 {
02874 rtx t = XVECEXP (pat, 0, i);
02875 if (GET_CODE (t) == CLOBBER && GET_CODE (XEXP (t, 0)) == REG
02876 && REGNO (XEXP (t, 0)) < FIRST_PSEUDO_REGISTER)
02877 SET_HARD_REG_BIT (clobbered, REGNO (XEXP (t, 0)));
02878 }
02879
02880 decode_asm_operands (pat, recog_data.operand, recog_data.operand_loc,
02881 constraints, operand_mode);
02882 in_output = 1;
02883 for (i = 0; i < noperands; i++)
02884 {
02885 const char *p = constraints[i];
02886 int cls = (int) NO_REGS;
02887 struct df_link *link;
02888 rtx reg;
02889 struct web *web;
02890 int nothing_allowed = 1;
02891 reg = recog_data.operand[i];
02892
02893
02894
02895 while (GET_CODE (reg) == SUBREG
02896 || GET_CODE (reg) == ZERO_EXTRACT
02897 || GET_CODE (reg) == SIGN_EXTRACT
02898 || GET_CODE (reg) == STRICT_LOW_PART)
02899 reg = XEXP (reg, 0);
02900 if (GET_CODE (reg) != REG || REGNO (reg) < FIRST_PSEUDO_REGISTER)
02901 continue;
02902
02903
02904
02905
02906 while (1)
02907 {
02908 if (in_output)
02909 link = df->insns[INSN_UID (insn)].defs;
02910 else
02911 link = df->insns[INSN_UID (insn)].uses;
02912 while (link && link->ref && DF_REF_REAL_REG (link->ref) != reg)
02913 link = link->next;
02914 if (!link || !link->ref)
02915 {
02916 if (in_output)
02917 in_output = 0;
02918 else
02919 abort ();
02920 }
02921 else
02922 break;
02923 }
02924 if (in_output)
02925 web = def2web[DF_REF_ID (link->ref)];
02926 else
02927 web = use2web[DF_REF_ID (link->ref)];
02928 reg = DF_REF_REG (link->ref);
02929
02930
02931 CLEAR_HARD_REG_SET (allowed);
02932 while (1)
02933 {
02934 char c = *p++;
02935
02936 if (c == '\0' || c == ',' || c == '#')
02937 {
02938
02939
02940
02941 IOR_HARD_REG_SET (allowed, reg_class_contents[cls]);
02942 if (cls != NO_REGS)
02943 nothing_allowed = 0;
02944 cls = NO_REGS;
02945 if (c == '#')
02946 do {
02947 c = *p++;
02948 } while (c != '\0' && c != ',');
02949 if (c == '\0')
02950 break;
02951 continue;
02952 }
02953
02954 switch (c)
02955 {
02956 case '=': case '+': case '*': case '%': case '?': case '!':
02957 case '0': case '1': case '2': case '3': case '4': case 'm':
02958 case '<': case '>': case 'V': case 'o': case '&': case 'E':
02959 case 'F': case 's': case 'i': case 'n': case 'X': case 'I':
02960 case 'J': case 'K': case 'L': case 'M': case 'N': case 'O':
02961 case 'P':
02962 break;
02963
02964 case 'p':
02965 cls = (int) reg_class_subunion[cls][(int) BASE_REG_CLASS];
02966 nothing_allowed = 0;
02967 break;
02968
02969 case 'g':
02970 case 'r':
02971 cls = (int) reg_class_subunion[cls][(int) GENERAL_REGS];
02972 nothing_allowed = 0;
02973 break;
02974
02975 default:
02976 cls =
02977 (int) reg_class_subunion[cls][(int)
02978 REG_CLASS_FROM_LETTER (c)];
02979 }
02980 }
02981
02982
02983
02984 if (nothing_allowed)
02985 {
02986
02987
02988
02989 CLEAR_HARD_REG_SET (conflict);
02990 }
02991 else
02992 {
02993 COPY_HARD_REG_SET (conflict, usable_regs
02994 [reg_preferred_class (web->regno)]);
02995 IOR_HARD_REG_SET (conflict, usable_regs
02996 [reg_alternate_class (web->regno)]);
02997 AND_COMPL_HARD_REG_SET (conflict, allowed);
02998
02999
03000
03001
03002
03003
03004
03005 #if 0
03006 for (c = 0; c < FIRST_PSEUDO_REGISTER; c++)
03007 if (TEST_HARD_REG_BIT (conflict, c))
03008 record_conflict (web, hardreg2web[c]);
03009 #endif
03010 }
03011 if (rtl_dump_file)
03012 {
03013 int c;
03014 ra_debug_msg (DUMP_ASM, " ASM constrain Web %d conflicts with:", web->id);
03015 for (c = 0; c < FIRST_PSEUDO_REGISTER; c++)
03016 if (TEST_HARD_REG_BIT (conflict, c))
03017 ra_debug_msg (DUMP_ASM, " %d", c);
03018 ra_debug_msg (DUMP_ASM, "\n");
03019 }
03020 }
03021 }
03022
03023
03024
03025
03026
03027 void
03028 build_i_graph (df)
03029 struct df *df;
03030 {
03031 rtx insn;
03032
03033 init_web_parts (df);
03034
03035 sbitmap_zero (move_handled);
03036 wl_moves = NULL;
03037
03038 build_web_parts_and_conflicts (df);
03039
03040
03041
03042 connect_rmw_web_parts (df);
03043
03044
03045
03046
03047 make_webs (df);
03048 moves_to_webs (df);
03049
03050
03051 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
03052 handle_asm_insn (df, insn);
03053 }
03054
03055
03056
03057
03058
03059
03060
03061 void
03062 ra_build_realloc (df)
03063 struct df *df;
03064 {
03065 struct web_part *last_web_parts = web_parts;
03066 struct web **last_def2web = def2web;
03067 struct web **last_use2web = use2web;
03068 sbitmap last_live_over_abnormal = live_over_abnormal;
03069 unsigned int i;
03070 struct dlist *d;
03071 move_handled = sbitmap_alloc (get_max_uid () );
03072 web_parts = (struct web_part *) xcalloc (df->def_id + df->use_id,
03073 sizeof web_parts[0]);
03074 def2web = (struct web **) xcalloc (df->def_id + df->use_id,
03075 sizeof def2web[0]);
03076 use2web = &def2web[df->def_id];
03077 live_over_abnormal = sbitmap_alloc (df->use_id);
03078 sbitmap_zero (live_over_abnormal);
03079
03080
03081 for (i = 0; i < last_def_id + last_use_id; i++)
03082 {
03083
03084
03085 struct web_part *dest = &web_parts[i < last_def_id
03086 ? i : (df->def_id + i - last_def_id)];
03087 struct web_part *up;
03088 *dest = last_web_parts[i];
03089 up = dest->uplink;
03090 dest->uplink = NULL;
03091
03092
03093 if (up && up->ref)
03094 {
03095 unsigned int id = DF_REF_ID (up->ref);
03096 if (up < &last_web_parts[last_def_id])
03097 {
03098 if (df->defs[id])
03099 dest->uplink = &web_parts[DF_REF_ID (up->ref)];
03100 }
03101 else if (df->uses[id])
03102 dest->uplink = &web_parts[df->def_id + DF_REF_ID (up->ref)];
03103 }
03104 }
03105
03106
03107
03108 for (i = 0; i < last_def_id; i++)
03109 {
03110 struct web *web = last_def2web[i];
03111 if (web)
03112 {
03113 web = find_web_for_subweb (web);
03114 if (web->type != FREE && web->type != PRECOLORED)
03115 def2web[i] = last_def2web[i];
03116 }
03117 }
03118 for (i = 0; i < last_use_id; i++)
03119 {
03120 struct web *web = last_use2web[i];
03121 if (web)
03122 {
03123 web = find_web_for_subweb (web);
03124 if (web->type != FREE && web->type != PRECOLORED)
03125 use2web[i] = last_use2web[i];
03126 }
03127 if (TEST_BIT (last_live_over_abnormal, i))
03128 SET_BIT (live_over_abnormal, i);
03129 }
03130
03131
03132
03133
03134
03135
03136
03137 for (d = WEBS(FREE); d; d = d->next)
03138 {
03139 struct web *web = DLIST_WEB (d);
03140 struct web *wnext;
03141 for (web = web->subreg_next; web; web = wnext)
03142 {
03143 wnext = web->subreg_next;
03144 free (web);
03145 }
03146 DLIST_WEB (d)->subreg_next = NULL;
03147 }
03148
03149
03150
03151
03152 if (last_check_uses)
03153 sbitmap_difference (live_over_abnormal, live_over_abnormal,
03154 last_check_uses);
03155
03156 if (last_def_id || last_use_id)
03157 {
03158 sbitmap_free (last_live_over_abnormal);
03159 free (last_web_parts);
03160 free (last_def2web);
03161 }
03162 if (!last_max_uid)
03163 {
03164
03165 copy_cache = (struct copy_p_cache *)
03166 xcalloc (get_max_uid (), sizeof (copy_cache[0]));
03167 init_bb_info ();
03168 }
03169 else
03170 {
03171 copy_cache = (struct copy_p_cache *)
03172 xrealloc (copy_cache, get_max_uid () * sizeof (copy_cache[0]));
03173 memset (©_cache[last_max_uid], 0,
03174 (get_max_uid () - last_max_uid) * sizeof (copy_cache[0]));
03175 }
03176 }
03177
03178
03179
03180 void
03181 ra_build_free ()
03182 {
03183 struct dlist *d;
03184 unsigned int i;
03185
03186
03187
03188 for (i = 0; i < num_webs; i++)
03189 {
03190 struct web *web = ID2WEB (i);
03191 if (!web)
03192 abort ();
03193 if (i >= num_webs - num_subwebs
03194 && (web->conflict_list || web->orig_conflict_list))
03195 abort ();
03196 web->moves = NULL;
03197 }
03198
03199 for (d = WEBS(FREE); d; d = d->next)
03200 {
03201 struct web *web = DLIST_WEB (d);
03202 if (web->defs)
03203 free (web->defs);
03204 web->defs = NULL;
03205 if (web->uses)
03206 free (web->uses);
03207 web->uses = NULL;
03208
03209
03210
03211 }
03212
03213
03214
03215
03216
03217
03218
03219 for (i = 0; i < df->def_id + df->use_id; i++)
03220 {
03221 struct tagged_conflict *cl;
03222 for (cl = web_parts[i].sub_conflicts; cl; cl = cl->next)
03223 {
03224 if (cl->conflicts)
03225 BITMAP_XFREE (cl->conflicts);
03226 }
03227 web_parts[i].sub_conflicts = NULL;
03228 }
03229
03230 wl_moves = NULL;
03231
03232 free (id2web);
03233 free (move_handled);
03234 sbitmap_free (sup_igraph);
03235 sbitmap_free (igraph);
03236 }
03237
03238
03239
03240 void
03241 ra_build_free_all (df)
03242 struct df *df;
03243 {
03244 unsigned int i;
03245
03246 free_bb_info ();
03247 free (copy_cache);
03248 copy_cache = NULL;
03249 for (i = 0; i < df->def_id + df->use_id; i++)
03250 {
03251 struct tagged_conflict *cl;
03252 for (cl = web_parts[i].sub_conflicts; cl; cl = cl->next)
03253 {
03254 if (cl->conflicts)
03255 BITMAP_XFREE (cl->conflicts);
03256 }
03257 web_parts[i].sub_conflicts = NULL;
03258 }
03259 sbitmap_free (live_over_abnormal);
03260 free (web_parts);
03261 web_parts = NULL;
03262 if (last_check_uses)
03263 sbitmap_free (last_check_uses);
03264 last_check_uses = NULL;
03265 free (def2web);
03266 use2web = NULL;
03267 def2web = NULL;
03268 }
03269
03270 #include "gt-ra-build.h"
03271
03272
03273
03274