00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025
00026 #include "machmode.h"
00027 #include "hard-reg-set.h"
00028 #include "rtl.h"
00029 #include "tm_p.h"
00030 #include "flags.h"
00031 #include "basic-block.h"
00032 #include "regs.h"
00033 #include "function.h"
00034 #include "insn-config.h"
00035 #include "reload.h"
00036 #include "output.h"
00037 #include "toplev.h"
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
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 static int max_allocno;
00081
00082
00083
00084
00085 static int *reg_allocno;
00086
00087 struct allocno
00088 {
00089 int reg;
00090
00091
00092 int size;
00093
00094
00095 int calls_crossed;
00096
00097
00098 int n_refs;
00099
00100
00101 int freq;
00102
00103
00104
00105 int live_length;
00106
00107
00108
00109 HARD_REG_SET hard_reg_conflicts;
00110
00111
00112
00113
00114
00115 HARD_REG_SET hard_reg_preferences;
00116
00117
00118
00119
00120
00121
00122 HARD_REG_SET hard_reg_copy_preferences;
00123
00124
00125
00126
00127
00128 HARD_REG_SET hard_reg_full_preferences;
00129
00130
00131
00132 HARD_REG_SET regs_someone_prefers;
00133
00134 #ifdef STACK_REGS
00135
00136 bool no_stack_reg;
00137 #endif
00138 };
00139
00140 static struct allocno *allocno;
00141
00142
00143
00144
00145 static int *allocno_order;
00146
00147
00148
00149
00150
00151 static int *reg_may_share;
00152
00153
00154
00155
00156
00157 #define INT_BITS HOST_BITS_PER_WIDE_INT
00158 #define INT_TYPE HOST_WIDE_INT
00159
00160
00161
00162
00163
00164
00165
00166 static INT_TYPE *conflicts;
00167
00168
00169
00170
00171 static int allocno_row_words;
00172
00173
00174
00175 #define CONFLICTP(I, J) \
00176 (conflicts[(I) * allocno_row_words + (unsigned) (J) / INT_BITS] \
00177 & ((INT_TYPE) 1 << ((unsigned) (J) % INT_BITS)))
00178
00179
00180
00181 #define EXECUTE_IF_SET_IN_ALLOCNO_SET(ALLOCNO_SET, ALLOCNO, CODE) \
00182 do { \
00183 int i_; \
00184 int allocno_; \
00185 INT_TYPE *p_ = (ALLOCNO_SET); \
00186 \
00187 for (i_ = allocno_row_words - 1, allocno_ = 0; i_ >= 0; \
00188 i_--, allocno_ += INT_BITS) \
00189 { \
00190 unsigned INT_TYPE word_ = (unsigned INT_TYPE) *p_++; \
00191 \
00192 for ((ALLOCNO) = allocno_; word_; word_ >>= 1, (ALLOCNO)++) \
00193 { \
00194 if (word_ & 1) \
00195 {CODE;} \
00196 } \
00197 } \
00198 } while (0)
00199
00200
00201 #if 0
00202
00203
00204
00205 #define EXECUTE_IF_CONFLICT(IN_ALLOCNO, OUT_ALLOCNO, CODE)\
00206 EXECUTE_IF_SET_IN_ALLOCNO_SET (conflicts + (IN_ALLOCNO) * allocno_row_words,\
00207 OUT_ALLOCNO, (CODE))
00208 #endif
00209
00210
00211
00212 static HARD_REG_SET hard_regs_live;
00213
00214
00215
00216 static HARD_REG_SET no_global_alloc_regs;
00217
00218
00219
00220 static HARD_REG_SET regs_used_so_far;
00221
00222
00223
00224
00225 static int local_reg_n_refs[FIRST_PSEUDO_REGISTER];
00226
00227
00228 static int local_reg_freq[FIRST_PSEUDO_REGISTER];
00229
00230
00231
00232
00233 static int local_reg_live_length[FIRST_PSEUDO_REGISTER];
00234
00235
00236
00237
00238 #define SET_REGBIT(TABLE, I, J) SET_HARD_REG_BIT (allocno[I].TABLE, J)
00239
00240
00241
00242 static INT_TYPE *allocnos_live;
00243
00244
00245
00246
00247 #define SET_ALLOCNO_LIVE(I) \
00248 (allocnos_live[(unsigned) (I) / INT_BITS] \
00249 |= ((INT_TYPE) 1 << ((unsigned) (I) % INT_BITS)))
00250
00251 #define CLEAR_ALLOCNO_LIVE(I) \
00252 (allocnos_live[(unsigned) (I) / INT_BITS] \
00253 &= ~((INT_TYPE) 1 << ((unsigned) (I) % INT_BITS)))
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 #if 0
00270
00271
00272
00273 #define NUM_NO_CONFLICT_PAIRS 4
00274
00275 int n_no_conflict_pairs;
00276 static struct { int allocno1, allocno2;}
00277 no_conflict_pairs[NUM_NO_CONFLICT_PAIRS];
00278 #endif
00279
00280
00281
00282
00283 static rtx *regs_set;
00284 static int n_regs_set;
00285
00286
00287
00288 static HARD_REG_SET eliminable_regset;
00289
00290 static int allocno_compare PARAMS ((const PTR, const PTR));
00291 static void global_conflicts PARAMS ((void));
00292 static void mirror_conflicts PARAMS ((void));
00293 static void expand_preferences PARAMS ((void));
00294 static void prune_preferences PARAMS ((void));
00295 static void find_reg PARAMS ((int, HARD_REG_SET, int, int, int));
00296 static void record_one_conflict PARAMS ((int));
00297 static void record_conflicts PARAMS ((int *, int));
00298 static void mark_reg_store PARAMS ((rtx, rtx, void *));
00299 static void mark_reg_clobber PARAMS ((rtx, rtx, void *));
00300 static void mark_reg_conflicts PARAMS ((rtx));
00301 static void mark_reg_death PARAMS ((rtx));
00302 static void mark_reg_live_nc PARAMS ((int, enum machine_mode));
00303 static void set_preference PARAMS ((rtx, rtx));
00304 static void dump_conflicts PARAMS ((FILE *));
00305 static void reg_becomes_live PARAMS ((rtx, rtx, void *));
00306 static void reg_dies PARAMS ((int, enum machine_mode,
00307 struct insn_chain *));
00308
00309
00310
00311
00312
00313
00314
00315
00316 int
00317 global_alloc (file)
00318 FILE *file;
00319 {
00320 int retval;
00321 #ifdef ELIMINABLE_REGS
00322 static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
00323 #endif
00324 int need_fp
00325 = (! flag_omit_frame_pointer
00326 #ifdef EXIT_IGNORE_STACK
00327 || (current_function_calls_alloca && EXIT_IGNORE_STACK)
00328 #endif
00329 || FRAME_POINTER_REQUIRED);
00330
00331 size_t i;
00332 rtx x;
00333
00334 max_allocno = 0;
00335
00336
00337
00338
00339 CLEAR_HARD_REG_SET (no_global_alloc_regs);
00340
00341
00342
00343 #ifdef ELIMINABLE_REGS
00344 for (i = 0; i < ARRAY_SIZE (eliminables); i++)
00345 {
00346 SET_HARD_REG_BIT (eliminable_regset, eliminables[i].from);
00347
00348 if (! CAN_ELIMINATE (eliminables[i].from, eliminables[i].to)
00349 || (eliminables[i].to == STACK_POINTER_REGNUM && need_fp))
00350 SET_HARD_REG_BIT (no_global_alloc_regs, eliminables[i].from);
00351 }
00352 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
00353 SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM);
00354 if (need_fp)
00355 SET_HARD_REG_BIT (no_global_alloc_regs, HARD_FRAME_POINTER_REGNUM);
00356 #endif
00357
00358 #else
00359 SET_HARD_REG_BIT (eliminable_regset, FRAME_POINTER_REGNUM);
00360 if (need_fp)
00361 SET_HARD_REG_BIT (no_global_alloc_regs, FRAME_POINTER_REGNUM);
00362 #endif
00363
00364
00365
00366
00367
00368 CLEAR_HARD_REG_SET (regs_used_so_far);
00369 #ifdef LEAF_REGISTERS
00370
00371
00372
00373
00374 {
00375 const char *cheap_regs;
00376 const char *const leaf_regs = LEAF_REGISTERS;
00377
00378 if (only_leaf_regs_used () && leaf_function_p ())
00379 cheap_regs = leaf_regs;
00380 else
00381 cheap_regs = call_used_regs;
00382 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00383 if (regs_ever_live[i] || cheap_regs[i])
00384 SET_HARD_REG_BIT (regs_used_so_far, i);
00385 }
00386 #else
00387
00388
00389 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00390 if (regs_ever_live[i] || call_used_regs[i])
00391 SET_HARD_REG_BIT (regs_used_so_far, i);
00392 #endif
00393
00394 for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++)
00395 if (reg_renumber[i] >= 0)
00396 SET_HARD_REG_BIT (regs_used_so_far, reg_renumber[i]);
00397
00398
00399
00400
00401 reg_allocno = (int *) xmalloc (max_regno * sizeof (int));
00402
00403 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00404 reg_allocno[i] = -1;
00405
00406
00407
00408 reg_may_share = (int *) xcalloc (max_regno, sizeof (int));
00409 for (x = regs_may_share; x; x = XEXP (XEXP (x, 1), 1))
00410 {
00411 int r1 = REGNO (XEXP (x, 0));
00412 int r2 = REGNO (XEXP (XEXP (x, 1), 0));
00413 if (r1 > r2)
00414 reg_may_share[r1] = r2;
00415 else
00416 reg_may_share[r2] = r1;
00417 }
00418
00419 for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++)
00420
00421
00422
00423 if (REG_N_REFS (i) != 0 && REG_LIVE_LENGTH (i) != -1
00424
00425
00426 && (! current_function_has_nonlocal_label
00427 || REG_N_CALLS_CROSSED (i) == 0))
00428 {
00429 if (reg_renumber[i] < 0 && reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0)
00430 reg_allocno[i] = reg_allocno[reg_may_share[i]];
00431 else
00432 reg_allocno[i] = max_allocno++;
00433 if (REG_LIVE_LENGTH (i) == 0)
00434 abort ();
00435 }
00436 else
00437 reg_allocno[i] = -1;
00438
00439 allocno = (struct allocno *) xcalloc (max_allocno, sizeof (struct allocno));
00440
00441 for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++)
00442 if (reg_allocno[i] >= 0)
00443 {
00444 int num = reg_allocno[i];
00445 allocno[num].reg = i;
00446 allocno[num].size = PSEUDO_REGNO_SIZE (i);
00447 allocno[num].calls_crossed += REG_N_CALLS_CROSSED (i);
00448 allocno[num].n_refs += REG_N_REFS (i);
00449 allocno[num].freq += REG_FREQ (i);
00450 if (allocno[num].live_length < REG_LIVE_LENGTH (i))
00451 allocno[num].live_length = REG_LIVE_LENGTH (i);
00452 }
00453
00454
00455
00456
00457 memset ((char *) local_reg_live_length, 0, sizeof local_reg_live_length);
00458 memset ((char *) local_reg_n_refs, 0, sizeof local_reg_n_refs);
00459 memset ((char *) local_reg_freq, 0, sizeof local_reg_freq);
00460 for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++)
00461 if (reg_renumber[i] >= 0)
00462 {
00463 int regno = reg_renumber[i];
00464 int endregno = regno + HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
00465 int j;
00466
00467 for (j = regno; j < endregno; j++)
00468 {
00469 local_reg_n_refs[j] += REG_N_REFS (i);
00470 local_reg_freq[j] += REG_FREQ (i);
00471 local_reg_live_length[j] += REG_LIVE_LENGTH (i);
00472 }
00473 }
00474
00475
00476 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00477 if (regs_ever_live[i])
00478 local_reg_n_refs[i] = 0, local_reg_freq[i] = 0;
00479
00480 allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS;
00481
00482
00483
00484
00485 conflicts = (INT_TYPE *) xcalloc (max_allocno * allocno_row_words,
00486 sizeof (INT_TYPE));
00487
00488 allocnos_live = (INT_TYPE *) xmalloc (allocno_row_words * sizeof (INT_TYPE));
00489
00490
00491
00492
00493 if (max_allocno > 0)
00494 {
00495
00496
00497
00498 global_conflicts ();
00499
00500 mirror_conflicts ();
00501
00502
00503
00504
00505
00506
00507
00508
00509 for (i = 0; i < (size_t) max_allocno; i++)
00510 {
00511 AND_COMPL_HARD_REG_SET (allocno[i].hard_reg_conflicts,
00512 eliminable_regset);
00513 AND_COMPL_HARD_REG_SET (allocno[i].hard_reg_copy_preferences,
00514 eliminable_regset);
00515 AND_COMPL_HARD_REG_SET (allocno[i].hard_reg_preferences,
00516 eliminable_regset);
00517 }
00518
00519
00520
00521 expand_preferences ();
00522
00523
00524
00525 allocno_order = (int *) xmalloc (max_allocno * sizeof (int));
00526 for (i = 0; i < (size_t) max_allocno; i++)
00527 allocno_order[i] = i;
00528
00529
00530
00531
00532
00533
00534
00535
00536 for (i = 0; i < (size_t) max_allocno; i++)
00537 {
00538 if (allocno[i].size == 0)
00539 allocno[i].size = 1;
00540 if (allocno[i].live_length == 0)
00541 allocno[i].live_length = -1;
00542 }
00543
00544 qsort (allocno_order, max_allocno, sizeof (int), allocno_compare);
00545
00546 prune_preferences ();
00547
00548 if (file)
00549 dump_conflicts (file);
00550
00551
00552
00553
00554 for (i = 0; i < (size_t) max_allocno; i++)
00555 if (reg_renumber[allocno[allocno_order[i]].reg] < 0
00556 && REG_LIVE_LENGTH (allocno[allocno_order[i]].reg) >= 0)
00557 {
00558
00559
00560
00561 if (N_REG_CLASSES > 1)
00562 {
00563 find_reg (allocno_order[i], 0, 0, 0, 0);
00564 if (reg_renumber[allocno[allocno_order[i]].reg] >= 0)
00565 continue;
00566 }
00567 if (reg_alternate_class (allocno[allocno_order[i]].reg) != NO_REGS)
00568 find_reg (allocno_order[i], 0, 1, 0, 0);
00569 }
00570
00571 free (allocno_order);
00572 }
00573
00574
00575
00576
00577 #if 0
00578
00579 if (n_basic_blocks > 0)
00580 #endif
00581 {
00582 build_insn_chain (get_insns ());
00583 retval = reload (get_insns (), 1);
00584 }
00585
00586
00587 free (reg_allocno);
00588 free (reg_may_share);
00589 free (allocno);
00590 free (conflicts);
00591 free (allocnos_live);
00592
00593 return retval;
00594 }
00595
00596
00597
00598
00599 static int
00600 allocno_compare (v1p, v2p)
00601 const PTR v1p;
00602 const PTR v2p;
00603 {
00604 int v1 = *(const int *)v1p, v2 = *(const int *)v2p;
00605
00606
00607
00608
00609
00610 int pri1
00611 = (((double) (floor_log2 (allocno[v1].n_refs) * allocno[v1].freq)
00612 / allocno[v1].live_length)
00613 * (10000 / REG_FREQ_MAX) * allocno[v1].size);
00614 int pri2
00615 = (((double) (floor_log2 (allocno[v2].n_refs) * allocno[v2].freq)
00616 / allocno[v2].live_length)
00617 * (10000 / REG_FREQ_MAX) * allocno[v2].size);
00618 if (pri2 - pri1)
00619 return pri2 - pri1;
00620
00621
00622
00623 return v1 - v2;
00624 }
00625
00626
00627
00628
00629 static void
00630 global_conflicts ()
00631 {
00632 int i;
00633 basic_block b;
00634 rtx insn;
00635 int *block_start_allocnos;
00636
00637
00638 regs_set = (rtx *) xmalloc (max_parallel * sizeof (rtx) * 2);
00639
00640 block_start_allocnos = (int *) xmalloc (max_allocno * sizeof (int));
00641
00642 FOR_EACH_BB (b)
00643 {
00644 memset ((char *) allocnos_live, 0, allocno_row_words * sizeof (INT_TYPE));
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660 {
00661 regset old = b->global_live_at_start;
00662 int ax = 0;
00663
00664 REG_SET_TO_HARD_REG_SET (hard_regs_live, old);
00665 EXECUTE_IF_SET_IN_REG_SET (old, FIRST_PSEUDO_REGISTER, i,
00666 {
00667 int a = reg_allocno[i];
00668 if (a >= 0)
00669 {
00670 SET_ALLOCNO_LIVE (a);
00671 block_start_allocnos[ax++] = a;
00672 }
00673 else if ((a = reg_renumber[i]) >= 0)
00674 mark_reg_live_nc
00675 (a, PSEUDO_REGNO_MODE (i));
00676 });
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 record_conflicts (block_start_allocnos, ax);
00703
00704 #ifdef STACK_REGS
00705 {
00706
00707
00708
00709 edge e;
00710 for (e = b->pred; e ; e = e->pred_next)
00711 if (e->flags & EDGE_ABNORMAL)
00712 break;
00713 if (e != NULL)
00714 {
00715 EXECUTE_IF_SET_IN_ALLOCNO_SET (allocnos_live, ax,
00716 {
00717 allocno[ax].no_stack_reg = 1;
00718 });
00719 for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
00720 record_one_conflict (ax);
00721 }
00722 }
00723 #endif
00724 }
00725
00726 insn = b->head;
00727
00728
00729
00730
00731
00732 while (1)
00733 {
00734 RTX_CODE code = GET_CODE (insn);
00735 rtx link;
00736
00737
00738
00739 n_regs_set = 0;
00740
00741 if (code == INSN || code == CALL_INSN || code == JUMP_INSN)
00742 {
00743
00744 #if 0
00745 int i = 0;
00746 for (link = REG_NOTES (insn);
00747 link && i < NUM_NO_CONFLICT_PAIRS;
00748 link = XEXP (link, 1))
00749 if (REG_NOTE_KIND (link) == REG_NO_CONFLICT)
00750 {
00751 no_conflict_pairs[i].allocno1
00752 = reg_allocno[REGNO (SET_DEST (PATTERN (insn)))];
00753 no_conflict_pairs[i].allocno2
00754 = reg_allocno[REGNO (XEXP (link, 0))];
00755 i++;
00756 }
00757 #endif
00758
00759
00760
00761
00762 note_stores (PATTERN (insn), mark_reg_clobber, NULL);
00763
00764
00765
00766 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
00767 if (REG_NOTE_KIND (link) == REG_DEAD)
00768 mark_reg_death (XEXP (link, 0));
00769
00770
00771
00772
00773
00774
00775 note_stores (PATTERN (insn), mark_reg_store, NULL);
00776
00777 #ifdef AUTO_INC_DEC
00778 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
00779 if (REG_NOTE_KIND (link) == REG_INC)
00780 mark_reg_store (XEXP (link, 0), NULL_RTX, NULL);
00781 #endif
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794 if (GET_CODE (PATTERN (insn)) == PARALLEL && multiple_sets (insn))
00795 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
00796 if (REG_NOTE_KIND (link) == REG_DEAD)
00797 {
00798 int used_in_output = 0;
00799 int i;
00800 rtx reg = XEXP (link, 0);
00801
00802 for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
00803 {
00804 rtx set = XVECEXP (PATTERN (insn), 0, i);
00805 if (GET_CODE (set) == SET
00806 && GET_CODE (SET_DEST (set)) != REG
00807 && !rtx_equal_p (reg, SET_DEST (set))
00808 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
00809 used_in_output = 1;
00810 }
00811 if (used_in_output)
00812 mark_reg_conflicts (reg);
00813 }
00814
00815
00816
00817 while (n_regs_set-- > 0)
00818 {
00819 rtx note = find_regno_note (insn, REG_UNUSED,
00820 REGNO (regs_set[n_regs_set]));
00821 if (note)
00822 mark_reg_death (XEXP (note, 0));
00823 }
00824 }
00825
00826 if (insn == b->end)
00827 break;
00828 insn = NEXT_INSN (insn);
00829 }
00830 }
00831
00832
00833 free (block_start_allocnos);
00834 free (regs_set);
00835 }
00836
00837
00838
00839
00840 static void
00841 expand_preferences ()
00842 {
00843 rtx insn;
00844 rtx link;
00845 rtx set;
00846
00847
00848
00849
00850 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
00851 if (INSN_P (insn)
00852 && (set = single_set (insn)) != 0
00853 && GET_CODE (SET_DEST (set)) == REG
00854 && reg_allocno[REGNO (SET_DEST (set))] >= 0)
00855 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
00856 if (REG_NOTE_KIND (link) == REG_DEAD
00857 && GET_CODE (XEXP (link, 0)) == REG
00858 && reg_allocno[REGNO (XEXP (link, 0))] >= 0
00859 && ! CONFLICTP (reg_allocno[REGNO (SET_DEST (set))],
00860 reg_allocno[REGNO (XEXP (link, 0))]))
00861 {
00862 int a1 = reg_allocno[REGNO (SET_DEST (set))];
00863 int a2 = reg_allocno[REGNO (XEXP (link, 0))];
00864
00865 if (XEXP (link, 0) == SET_SRC (set))
00866 {
00867 IOR_HARD_REG_SET (allocno[a1].hard_reg_copy_preferences,
00868 allocno[a2].hard_reg_copy_preferences);
00869 IOR_HARD_REG_SET (allocno[a2].hard_reg_copy_preferences,
00870 allocno[a1].hard_reg_copy_preferences);
00871 }
00872
00873 IOR_HARD_REG_SET (allocno[a1].hard_reg_preferences,
00874 allocno[a2].hard_reg_preferences);
00875 IOR_HARD_REG_SET (allocno[a2].hard_reg_preferences,
00876 allocno[a1].hard_reg_preferences);
00877 IOR_HARD_REG_SET (allocno[a1].hard_reg_full_preferences,
00878 allocno[a2].hard_reg_full_preferences);
00879 IOR_HARD_REG_SET (allocno[a2].hard_reg_full_preferences,
00880 allocno[a1].hard_reg_full_preferences);
00881 }
00882 }
00883
00884
00885
00886
00887
00888
00889
00890
00891 static void
00892 prune_preferences ()
00893 {
00894 int i;
00895 int num;
00896 int *allocno_to_order = (int *) xmalloc (max_allocno * sizeof (int));
00897
00898
00899
00900
00901
00902
00903 for (i = max_allocno - 1; i >= 0; i--)
00904 {
00905 HARD_REG_SET temp;
00906
00907 num = allocno_order[i];
00908 allocno_to_order[num] = i;
00909 COPY_HARD_REG_SET (temp, allocno[num].hard_reg_conflicts);
00910
00911 if (allocno[num].calls_crossed == 0)
00912 IOR_HARD_REG_SET (temp, fixed_reg_set);
00913 else
00914 IOR_HARD_REG_SET (temp, call_used_reg_set);
00915
00916 IOR_COMPL_HARD_REG_SET
00917 (temp,
00918 reg_class_contents[(int) reg_preferred_class (allocno[num].reg)]);
00919
00920 AND_COMPL_HARD_REG_SET (allocno[num].hard_reg_preferences, temp);
00921 AND_COMPL_HARD_REG_SET (allocno[num].hard_reg_copy_preferences, temp);
00922 AND_COMPL_HARD_REG_SET (allocno[num].hard_reg_full_preferences, temp);
00923 }
00924
00925 for (i = max_allocno - 1; i >= 0; i--)
00926 {
00927
00928
00929
00930
00931
00932 HARD_REG_SET temp, temp2;
00933 int allocno2;
00934
00935 num = allocno_order[i];
00936
00937 CLEAR_HARD_REG_SET (temp);
00938 CLEAR_HARD_REG_SET (temp2);
00939
00940 EXECUTE_IF_SET_IN_ALLOCNO_SET (conflicts + num * allocno_row_words,
00941 allocno2,
00942 {
00943 if (allocno_to_order[allocno2] > i)
00944 {
00945 if (allocno[allocno2].size <= allocno[num].size)
00946 IOR_HARD_REG_SET (temp,
00947 allocno[allocno2].hard_reg_full_preferences);
00948 else
00949 IOR_HARD_REG_SET (temp2,
00950 allocno[allocno2].hard_reg_full_preferences);
00951 }
00952 });
00953
00954 AND_COMPL_HARD_REG_SET (temp, allocno[num].hard_reg_full_preferences);
00955 IOR_HARD_REG_SET (temp, temp2);
00956 COPY_HARD_REG_SET (allocno[num].regs_someone_prefers, temp);
00957 }
00958 free (allocno_to_order);
00959 }
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 static void
00980 find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
00981 int num;
00982 HARD_REG_SET losers;
00983 int alt_regs_p;
00984 int accept_call_clobbered;
00985 int retrying;
00986 {
00987 int i, best_reg, pass;
00988 HARD_REG_SET used, used1, used2;
00989
00990 enum reg_class class = (alt_regs_p
00991 ? reg_alternate_class (allocno[num].reg)
00992 : reg_preferred_class (allocno[num].reg));
00993 enum machine_mode mode = PSEUDO_REGNO_MODE (allocno[num].reg);
00994
00995 if (accept_call_clobbered)
00996 COPY_HARD_REG_SET (used1, call_fixed_reg_set);
00997 else if (allocno[num].calls_crossed == 0)
00998 COPY_HARD_REG_SET (used1, fixed_reg_set);
00999 else
01000 COPY_HARD_REG_SET (used1, call_used_reg_set);
01001
01002
01003 IOR_HARD_REG_SET (used1, no_global_alloc_regs);
01004 if (losers)
01005 IOR_HARD_REG_SET (used1, losers);
01006
01007 IOR_COMPL_HARD_REG_SET (used1, reg_class_contents[(int) class]);
01008 COPY_HARD_REG_SET (used2, used1);
01009
01010 IOR_HARD_REG_SET (used1, allocno[num].hard_reg_conflicts);
01011
01012 #ifdef CANNOT_CHANGE_MODE_CLASS
01013 cannot_change_mode_set_regs (&used1, mode, allocno[num].reg);
01014 #endif
01015
01016
01017
01018
01019
01020
01021
01022 COPY_HARD_REG_SET (used, used1);
01023 IOR_COMPL_HARD_REG_SET (used, regs_used_so_far);
01024 IOR_HARD_REG_SET (used, allocno[num].regs_someone_prefers);
01025
01026 best_reg = -1;
01027 for (i = FIRST_PSEUDO_REGISTER, pass = 0;
01028 pass <= 1 && i >= FIRST_PSEUDO_REGISTER;
01029 pass++)
01030 {
01031 if (pass == 1)
01032 COPY_HARD_REG_SET (used, used1);
01033 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01034 {
01035 #ifdef REG_ALLOC_ORDER
01036 int regno = reg_alloc_order[i];
01037 #else
01038 int regno = i;
01039 #endif
01040 if (! TEST_HARD_REG_BIT (used, regno)
01041 && HARD_REGNO_MODE_OK (regno, mode)
01042 && (allocno[num].calls_crossed == 0
01043 || accept_call_clobbered
01044 || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
01045 {
01046 int j;
01047 int lim = regno + HARD_REGNO_NREGS (regno, mode);
01048 for (j = regno + 1;
01049 (j < lim
01050 && ! TEST_HARD_REG_BIT (used, j));
01051 j++);
01052 if (j == lim)
01053 {
01054 best_reg = regno;
01055 break;
01056 }
01057 #ifndef REG_ALLOC_ORDER
01058 i = j;
01059 #endif
01060 }
01061 }
01062 }
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075 AND_COMPL_HARD_REG_SET (allocno[num].hard_reg_copy_preferences, used);
01076 GO_IF_HARD_REG_SUBSET (allocno[num].hard_reg_copy_preferences,
01077 reg_class_contents[(int) NO_REGS], no_copy_prefs);
01078
01079 if (best_reg >= 0)
01080 {
01081 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01082 if (TEST_HARD_REG_BIT (allocno[num].hard_reg_copy_preferences, i)
01083 && HARD_REGNO_MODE_OK (i, mode)
01084 && (allocno[num].calls_crossed == 0
01085 || accept_call_clobbered
01086 || ! HARD_REGNO_CALL_PART_CLOBBERED (i, mode))
01087 && (REGNO_REG_CLASS (i) == REGNO_REG_CLASS (best_reg)
01088 || reg_class_subset_p (REGNO_REG_CLASS (i),
01089 REGNO_REG_CLASS (best_reg))
01090 || reg_class_subset_p (REGNO_REG_CLASS (best_reg),
01091 REGNO_REG_CLASS (i))))
01092 {
01093 int j;
01094 int lim = i + HARD_REGNO_NREGS (i, mode);
01095 for (j = i + 1;
01096 (j < lim
01097 && ! TEST_HARD_REG_BIT (used, j)
01098 && (REGNO_REG_CLASS (j)
01099 == REGNO_REG_CLASS (best_reg + (j - i))
01100 || reg_class_subset_p (REGNO_REG_CLASS (j),
01101 REGNO_REG_CLASS (best_reg + (j - i)))
01102 || reg_class_subset_p (REGNO_REG_CLASS (best_reg + (j - i)),
01103 REGNO_REG_CLASS (j))));
01104 j++);
01105 if (j == lim)
01106 {
01107 best_reg = i;
01108 goto no_prefs;
01109 }
01110 }
01111 }
01112 no_copy_prefs:
01113
01114 AND_COMPL_HARD_REG_SET (allocno[num].hard_reg_preferences, used);
01115 GO_IF_HARD_REG_SUBSET (allocno[num].hard_reg_preferences,
01116 reg_class_contents[(int) NO_REGS], no_prefs);
01117
01118 if (best_reg >= 0)
01119 {
01120 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01121 if (TEST_HARD_REG_BIT (allocno[num].hard_reg_preferences, i)
01122 && HARD_REGNO_MODE_OK (i, mode)
01123 && (allocno[num].calls_crossed == 0
01124 || accept_call_clobbered
01125 || ! HARD_REGNO_CALL_PART_CLOBBERED (i, mode))
01126 && (REGNO_REG_CLASS (i) == REGNO_REG_CLASS (best_reg)
01127 || reg_class_subset_p (REGNO_REG_CLASS (i),
01128 REGNO_REG_CLASS (best_reg))
01129 || reg_class_subset_p (REGNO_REG_CLASS (best_reg),
01130 REGNO_REG_CLASS (i))))
01131 {
01132 int j;
01133 int lim = i + HARD_REGNO_NREGS (i, mode);
01134 for (j = i + 1;
01135 (j < lim
01136 && ! TEST_HARD_REG_BIT (used, j)
01137 && (REGNO_REG_CLASS (j)
01138 == REGNO_REG_CLASS (best_reg + (j - i))
01139 || reg_class_subset_p (REGNO_REG_CLASS (j),
01140 REGNO_REG_CLASS (best_reg + (j - i)))
01141 || reg_class_subset_p (REGNO_REG_CLASS (best_reg + (j - i)),
01142 REGNO_REG_CLASS (j))));
01143 j++);
01144 if (j == lim)
01145 {
01146 best_reg = i;
01147 break;
01148 }
01149 }
01150 }
01151 no_prefs:
01152
01153
01154
01155
01156
01157
01158 if (flag_caller_saves && best_reg < 0)
01159 {
01160
01161
01162
01163 if (! accept_call_clobbered
01164 && allocno[num].calls_crossed != 0
01165 && CALLER_SAVE_PROFITABLE (allocno[num].n_refs,
01166 allocno[num].calls_crossed))
01167 {
01168 HARD_REG_SET new_losers;
01169 if (! losers)
01170 CLEAR_HARD_REG_SET (new_losers);
01171 else
01172 COPY_HARD_REG_SET (new_losers, losers);
01173
01174 IOR_HARD_REG_SET(new_losers, losing_caller_save_reg_set);
01175 find_reg (num, new_losers, alt_regs_p, 1, retrying);
01176 if (reg_renumber[allocno[num].reg] >= 0)
01177 {
01178 caller_save_needed = 1;
01179 return;
01180 }
01181 }
01182 }
01183
01184
01185
01186
01187
01188
01189 if (best_reg < 0 && !retrying
01190
01191 && allocno[num].size == 1)
01192 {
01193
01194 for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
01195 {
01196 #ifdef REG_ALLOC_ORDER
01197 int regno = reg_alloc_order[i];
01198 #else
01199 int regno = i;
01200 #endif
01201
01202 if (local_reg_n_refs[regno] != 0
01203
01204 && ! TEST_HARD_REG_BIT (used2, regno)
01205 && HARD_REGNO_MODE_OK (regno, mode)
01206
01207
01208
01209
01210 && HARD_REGNO_NREGS (regno, mode) == 1
01211 && (allocno[num].calls_crossed == 0
01212 || accept_call_clobbered
01213 || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
01214 #ifdef CANNOT_CHANGE_MODE_CLASS
01215 && ! invalid_mode_change_p (regno, REGNO_REG_CLASS (regno),
01216 mode)
01217 #endif
01218 #ifdef STACK_REGS
01219 && (!allocno[num].no_stack_reg
01220 || regno < FIRST_STACK_REG || regno > LAST_STACK_REG)
01221 #endif
01222 )
01223 {
01224
01225
01226
01227
01228 double tmp1 = ((double) local_reg_freq[regno]
01229 / local_reg_live_length[regno]);
01230 double tmp2 = ((double) allocno[num].freq
01231 / allocno[num].live_length);
01232
01233 if (tmp1 < tmp2)
01234 {
01235
01236
01237 int k;
01238 for (k = 0; k < max_regno; k++)
01239 if (reg_renumber[k] >= 0)
01240 {
01241 int r = reg_renumber[k];
01242 int endregno
01243 = r + HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (k));
01244
01245 if (regno >= r && regno < endregno)
01246 reg_renumber[k] = -1;
01247 }
01248
01249 best_reg = regno;
01250 break;
01251 }
01252 }
01253 }
01254 }
01255
01256
01257
01258 if (best_reg >= 0)
01259 {
01260 int lim, j;
01261 HARD_REG_SET this_reg;
01262
01263
01264 reg_renumber[allocno[num].reg] = best_reg;
01265
01266 if (reg_may_share[allocno[num].reg])
01267 for (j = FIRST_PSEUDO_REGISTER; j < max_regno; j++)
01268 if (reg_allocno[j] == num)
01269 reg_renumber[j] = best_reg;
01270
01271
01272 CLEAR_HARD_REG_SET (this_reg);
01273 lim = best_reg + HARD_REGNO_NREGS (best_reg, mode);
01274 for (j = best_reg; j < lim; j++)
01275 {
01276 SET_HARD_REG_BIT (this_reg, j);
01277 SET_HARD_REG_BIT (regs_used_so_far, j);
01278
01279 local_reg_n_refs[j] = 0;
01280 local_reg_freq[j] = 0;
01281 }
01282
01283
01284 lim = num;
01285 EXECUTE_IF_SET_IN_ALLOCNO_SET (conflicts + lim * allocno_row_words, j,
01286 {
01287 IOR_HARD_REG_SET (allocno[j].hard_reg_conflicts, this_reg);
01288 });
01289 }
01290 }
01291
01292
01293
01294
01295
01296
01297
01298
01299 void
01300 retry_global_alloc (regno, forbidden_regs)
01301 int regno;
01302 HARD_REG_SET forbidden_regs;
01303 {
01304 int alloc_no = reg_allocno[regno];
01305 if (alloc_no >= 0)
01306 {
01307
01308
01309
01310 if (N_REG_CLASSES > 1)
01311 find_reg (alloc_no, forbidden_regs, 0, 0, 1);
01312 if (reg_renumber[regno] < 0
01313 && reg_alternate_class (regno) != NO_REGS)
01314 find_reg (alloc_no, forbidden_regs, 1, 0, 1);
01315
01316
01317
01318 if (reg_renumber[regno] >= 0)
01319 {
01320 REGNO (regno_reg_rtx[regno]) = reg_renumber[regno];
01321 mark_home_live (regno);
01322 }
01323 }
01324 }
01325
01326
01327
01328
01329
01330
01331
01332 static void
01333 record_one_conflict (regno)
01334 int regno;
01335 {
01336 int j;
01337
01338 if (regno < FIRST_PSEUDO_REGISTER)
01339
01340
01341 EXECUTE_IF_SET_IN_ALLOCNO_SET (allocnos_live, j,
01342 {
01343 SET_HARD_REG_BIT (allocno[j].hard_reg_conflicts, regno);
01344 });
01345 else
01346
01347
01348
01349 {
01350 int ialloc = reg_allocno[regno];
01351 int ialloc_prod = ialloc * allocno_row_words;
01352
01353 IOR_HARD_REG_SET (allocno[ialloc].hard_reg_conflicts, hard_regs_live);
01354 for (j = allocno_row_words - 1; j >= 0; j--)
01355 {
01356 #if 0
01357 int k;
01358 for (k = 0; k < n_no_conflict_pairs; k++)
01359 if (! ((j == no_conflict_pairs[k].allocno1
01360 && ialloc == no_conflict_pairs[k].allocno2)
01361 ||
01362 (j == no_conflict_pairs[k].allocno2
01363 && ialloc == no_conflict_pairs[k].allocno1)))
01364 #endif
01365 conflicts[ialloc_prod + j] |= allocnos_live[j];
01366 }
01367 }
01368 }
01369
01370
01371
01372
01373
01374
01375
01376 static void
01377 record_conflicts (allocno_vec, len)
01378 int *allocno_vec;
01379 int len;
01380 {
01381 int num;
01382 int ialloc_prod;
01383
01384 while (--len >= 0)
01385 {
01386 num = allocno_vec[len];
01387 ialloc_prod = num * allocno_row_words;
01388 IOR_HARD_REG_SET (allocno[num].hard_reg_conflicts, hard_regs_live);
01389 }
01390 }
01391
01392
01393 static void
01394 mirror_conflicts ()
01395 {
01396 int i, j;
01397 int rw = allocno_row_words;
01398 int rwb = rw * INT_BITS;
01399 INT_TYPE *p = conflicts;
01400 INT_TYPE *q0 = conflicts, *q1, *q2;
01401 unsigned INT_TYPE mask;
01402
01403 for (i = max_allocno - 1, mask = 1; i >= 0; i--, mask <<= 1)
01404 {
01405 if (! mask)
01406 {
01407 mask = 1;
01408 q0++;
01409 }
01410 for (j = allocno_row_words - 1, q1 = q0; j >= 0; j--, q1 += rwb)
01411 {
01412 unsigned INT_TYPE word;
01413
01414 for (word = (unsigned INT_TYPE) *p++, q2 = q1; word;
01415 word >>= 1, q2 += rw)
01416 {
01417 if (word & 1)
01418 *q2 |= mask;
01419 }
01420 }
01421 }
01422 }
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441 static void
01442 mark_reg_store (reg, setter, data)
01443 rtx reg, setter;
01444 void *data ATTRIBUTE_UNUSED;
01445 {
01446 int regno;
01447
01448 if (GET_CODE (reg) == SUBREG)
01449 reg = SUBREG_REG (reg);
01450
01451 if (GET_CODE (reg) != REG)
01452 return;
01453
01454 regs_set[n_regs_set++] = reg;
01455
01456 if (setter && GET_CODE (setter) != CLOBBER)
01457 set_preference (reg, SET_SRC (setter));
01458
01459 regno = REGNO (reg);
01460
01461
01462
01463 if (regno >= FIRST_PSEUDO_REGISTER)
01464 {
01465 if (reg_allocno[regno] >= 0)
01466 {
01467 SET_ALLOCNO_LIVE (reg_allocno[regno]);
01468 record_one_conflict (regno);
01469 }
01470 }
01471
01472 if (reg_renumber[regno] >= 0)
01473 regno = reg_renumber[regno];
01474
01475
01476 if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
01477 {
01478 int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
01479 while (regno < last)
01480 {
01481 record_one_conflict (regno);
01482 SET_HARD_REG_BIT (hard_regs_live, regno);
01483 regno++;
01484 }
01485 }
01486 }
01487
01488
01489
01490 static void
01491 mark_reg_clobber (reg, setter, data)
01492 rtx reg, setter;
01493 void *data ATTRIBUTE_UNUSED;
01494 {
01495 if (GET_CODE (setter) == CLOBBER)
01496 mark_reg_store (reg, setter, data);
01497 }
01498
01499
01500
01501
01502 static void
01503 mark_reg_conflicts (reg)
01504 rtx reg;
01505 {
01506 int regno;
01507
01508 if (GET_CODE (reg) == SUBREG)
01509 reg = SUBREG_REG (reg);
01510
01511 if (GET_CODE (reg) != REG)
01512 return;
01513
01514 regno = REGNO (reg);
01515
01516
01517
01518 if (regno >= FIRST_PSEUDO_REGISTER)
01519 {
01520 if (reg_allocno[regno] >= 0)
01521 record_one_conflict (regno);
01522 }
01523
01524 if (reg_renumber[regno] >= 0)
01525 regno = reg_renumber[regno];
01526
01527
01528 if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
01529 {
01530 int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
01531 while (regno < last)
01532 {
01533 record_one_conflict (regno);
01534 regno++;
01535 }
01536 }
01537 }
01538
01539
01540
01541
01542 static void
01543 mark_reg_death (reg)
01544 rtx reg;
01545 {
01546 int regno = REGNO (reg);
01547
01548
01549
01550 if (regno >= FIRST_PSEUDO_REGISTER)
01551 {
01552 if (reg_allocno[regno] >= 0)
01553 CLEAR_ALLOCNO_LIVE (reg_allocno[regno]);
01554 }
01555
01556
01557 if (reg_renumber[regno] >= 0)
01558 regno = reg_renumber[regno];
01559
01560
01561 if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
01562 {
01563
01564
01565 int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
01566 while (regno < last)
01567 {
01568 CLEAR_HARD_REG_BIT (hard_regs_live, regno);
01569 regno++;
01570 }
01571 }
01572 }
01573
01574
01575
01576
01577
01578
01579 static void
01580 mark_reg_live_nc (regno, mode)
01581 int regno;
01582 enum machine_mode mode;
01583 {
01584 int last = regno + HARD_REGNO_NREGS (regno, mode);
01585 while (regno < last)
01586 {
01587 SET_HARD_REG_BIT (hard_regs_live, regno);
01588 regno++;
01589 }
01590 }
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601 static void
01602 set_preference (dest, src)
01603 rtx dest, src;
01604 {
01605 unsigned int src_regno, dest_regno;
01606
01607
01608 int offset = 0;
01609 unsigned int i;
01610 int copy = 1;
01611
01612 if (GET_RTX_FORMAT (GET_CODE (src))[0] == 'e')
01613 src = XEXP (src, 0), copy = 0;
01614
01615
01616
01617
01618 if (GET_CODE (src) == REG)
01619 src_regno = REGNO (src);
01620 else if (GET_CODE (src) == SUBREG && GET_CODE (SUBREG_REG (src)) == REG)
01621 {
01622 src_regno = REGNO (SUBREG_REG (src));
01623
01624 if (REGNO (SUBREG_REG (src)) < FIRST_PSEUDO_REGISTER)
01625 offset += subreg_regno_offset (REGNO (SUBREG_REG (src)),
01626 GET_MODE (SUBREG_REG (src)),
01627 SUBREG_BYTE (src),
01628 GET_MODE (src));
01629 else
01630 offset += (SUBREG_BYTE (src)
01631 / REGMODE_NATURAL_SIZE (GET_MODE (src)));
01632 }
01633 else
01634 return;
01635
01636 if (GET_CODE (dest) == REG)
01637 dest_regno = REGNO (dest);
01638 else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
01639 {
01640 dest_regno = REGNO (SUBREG_REG (dest));
01641
01642 if (REGNO (SUBREG_REG (dest)) < FIRST_PSEUDO_REGISTER)
01643 offset -= subreg_regno_offset (REGNO (SUBREG_REG (dest)),
01644 GET_MODE (SUBREG_REG (dest)),
01645 SUBREG_BYTE (dest),
01646 GET_MODE (dest));
01647 else
01648 offset -= (SUBREG_BYTE (dest)
01649 / REGMODE_NATURAL_SIZE (GET_MODE (dest)));
01650 }
01651 else
01652 return;
01653
01654
01655
01656 if (reg_renumber[src_regno] >= 0)
01657 src_regno = reg_renumber[src_regno];
01658
01659 if (reg_renumber[dest_regno] >= 0)
01660 dest_regno = reg_renumber[dest_regno];
01661
01662
01663
01664
01665 if (dest_regno < FIRST_PSEUDO_REGISTER && src_regno >= FIRST_PSEUDO_REGISTER
01666 && reg_allocno[src_regno] >= 0)
01667 {
01668 dest_regno -= offset;
01669 if (dest_regno < FIRST_PSEUDO_REGISTER)
01670 {
01671 if (copy)
01672 SET_REGBIT (hard_reg_copy_preferences,
01673 reg_allocno[src_regno], dest_regno);
01674
01675 SET_REGBIT (hard_reg_preferences,
01676 reg_allocno[src_regno], dest_regno);
01677 for (i = dest_regno;
01678 i < dest_regno + HARD_REGNO_NREGS (dest_regno, GET_MODE (dest));
01679 i++)
01680 SET_REGBIT (hard_reg_full_preferences, reg_allocno[src_regno], i);
01681 }
01682 }
01683
01684 if (src_regno < FIRST_PSEUDO_REGISTER && dest_regno >= FIRST_PSEUDO_REGISTER
01685 && reg_allocno[dest_regno] >= 0)
01686 {
01687 src_regno += offset;
01688 if (src_regno < FIRST_PSEUDO_REGISTER)
01689 {
01690 if (copy)
01691 SET_REGBIT (hard_reg_copy_preferences,
01692 reg_allocno[dest_regno], src_regno);
01693
01694 SET_REGBIT (hard_reg_preferences,
01695 reg_allocno[dest_regno], src_regno);
01696 for (i = src_regno;
01697 i < src_regno + HARD_REGNO_NREGS (src_regno, GET_MODE (src));
01698 i++)
01699 SET_REGBIT (hard_reg_full_preferences, reg_allocno[dest_regno], i);
01700 }
01701 }
01702 }
01703
01704
01705
01706
01707
01708
01709 void
01710 mark_elimination (from, to)
01711 int from, to;
01712 {
01713 basic_block bb;
01714
01715 FOR_EACH_BB (bb)
01716 {
01717 regset r = bb->global_live_at_start;
01718 if (REGNO_REG_SET_P (r, from))
01719 {
01720 CLEAR_REGNO_REG_SET (r, from);
01721 SET_REGNO_REG_SET (r, to);
01722 }
01723 }
01724 }
01725
01726
01727
01728 static regset live_relevant_regs;
01729
01730
01731
01732 static void
01733 reg_becomes_live (reg, setter, regs_set)
01734 rtx reg;
01735 rtx setter ATTRIBUTE_UNUSED;
01736 void *regs_set;
01737 {
01738 int regno;
01739
01740 if (GET_CODE (reg) == SUBREG)
01741 reg = SUBREG_REG (reg);
01742
01743 if (GET_CODE (reg) != REG)
01744 return;
01745
01746 regno = REGNO (reg);
01747 if (regno < FIRST_PSEUDO_REGISTER)
01748 {
01749 int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
01750 while (nregs-- > 0)
01751 {
01752 SET_REGNO_REG_SET (live_relevant_regs, regno);
01753 if (! fixed_regs[regno])
01754 SET_REGNO_REG_SET ((regset) regs_set, regno);
01755 regno++;
01756 }
01757 }
01758 else if (reg_renumber[regno] >= 0)
01759 {
01760 SET_REGNO_REG_SET (live_relevant_regs, regno);
01761 SET_REGNO_REG_SET ((regset) regs_set, regno);
01762 }
01763 }
01764
01765
01766 static void
01767 reg_dies (regno, mode, chain)
01768 int regno;
01769 enum machine_mode mode;
01770 struct insn_chain *chain;
01771 {
01772 if (regno < FIRST_PSEUDO_REGISTER)
01773 {
01774 int nregs = HARD_REGNO_NREGS (regno, mode);
01775 while (nregs-- > 0)
01776 {
01777 CLEAR_REGNO_REG_SET (live_relevant_regs, regno);
01778 if (! fixed_regs[regno])
01779 SET_REGNO_REG_SET (&chain->dead_or_set, regno);
01780 regno++;
01781 }
01782 }
01783 else
01784 {
01785 CLEAR_REGNO_REG_SET (live_relevant_regs, regno);
01786 if (reg_renumber[regno] >= 0)
01787 SET_REGNO_REG_SET (&chain->dead_or_set, regno);
01788 }
01789 }
01790
01791
01792
01793 void
01794 build_insn_chain (first)
01795 rtx first;
01796 {
01797 struct insn_chain **p = &reload_insn_chain;
01798 struct insn_chain *prev = 0;
01799 basic_block b = ENTRY_BLOCK_PTR->next_bb;
01800 regset_head live_relevant_regs_head;
01801
01802 live_relevant_regs = INITIALIZE_REG_SET (live_relevant_regs_head);
01803
01804 for (; first; first = NEXT_INSN (first))
01805 {
01806 struct insn_chain *c;
01807
01808 if (first == b->head)
01809 {
01810 int i;
01811
01812 CLEAR_REG_SET (live_relevant_regs);
01813
01814 EXECUTE_IF_SET_IN_BITMAP
01815 (b->global_live_at_start, 0, i,
01816 {
01817 if (i < FIRST_PSEUDO_REGISTER
01818 ? ! TEST_HARD_REG_BIT (eliminable_regset, i)
01819 : reg_renumber[i] >= 0)
01820 SET_REGNO_REG_SET (live_relevant_regs, i);
01821 });
01822 }
01823
01824 if (GET_CODE (first) != NOTE && GET_CODE (first) != BARRIER)
01825 {
01826 c = new_insn_chain ();
01827 c->prev = prev;
01828 prev = c;
01829 *p = c;
01830 p = &c->next;
01831 c->insn = first;
01832 c->block = b->index;
01833
01834 if (INSN_P (first))
01835 {
01836 rtx link;
01837
01838
01839
01840 for (link = REG_NOTES (first); link; link = XEXP (link, 1))
01841 if (REG_NOTE_KIND (link) == REG_DEAD
01842 && GET_CODE (XEXP (link, 0)) == REG)
01843 reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)),
01844 c);
01845
01846 COPY_REG_SET (&c->live_throughout, live_relevant_regs);
01847
01848
01849
01850 note_stores (PATTERN (first), reg_becomes_live,
01851 &c->dead_or_set);
01852 }
01853 else
01854 COPY_REG_SET (&c->live_throughout, live_relevant_regs);
01855
01856 if (INSN_P (first))
01857 {
01858 rtx link;
01859
01860
01861
01862 for (link = REG_NOTES (first); link; link = XEXP (link, 1))
01863 if (REG_NOTE_KIND (link) == REG_UNUSED
01864 && GET_CODE (XEXP (link, 0)) == REG)
01865 reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)),
01866 c);
01867 }
01868 }
01869
01870 if (first == b->end)
01871 b = b->next_bb;
01872
01873
01874
01875
01876
01877
01878
01879 if (b == EXIT_BLOCK_PTR)
01880 {
01881 for (first = NEXT_INSN (first) ; first; first = NEXT_INSN (first))
01882 if (INSN_P (first)
01883 && GET_CODE (PATTERN (first)) != USE
01884 && ! ((GET_CODE (PATTERN (first)) == ADDR_VEC
01885 || GET_CODE (PATTERN (first)) == ADDR_DIFF_VEC)
01886 && prev_real_insn (first) != 0
01887 && GET_CODE (prev_real_insn (first)) == JUMP_INSN))
01888 abort ();
01889 break;
01890 }
01891 }
01892 FREE_REG_SET (live_relevant_regs);
01893 *p = 0;
01894 }
01895
01896
01897
01898
01899 static void
01900 dump_conflicts (file)
01901 FILE *file;
01902 {
01903 int i;
01904 int has_preferences;
01905 int nregs;
01906 nregs = 0;
01907 for (i = 0; i < max_allocno; i++)
01908 {
01909 if (reg_renumber[allocno[allocno_order[i]].reg] >= 0)
01910 continue;
01911 nregs++;
01912 }
01913 fprintf (file, ";; %d regs to allocate:", nregs);
01914 for (i = 0; i < max_allocno; i++)
01915 {
01916 int j;
01917 if (reg_renumber[allocno[allocno_order[i]].reg] >= 0)
01918 continue;
01919 fprintf (file, " %d", allocno[allocno_order[i]].reg);
01920 for (j = 0; j < max_regno; j++)
01921 if (reg_allocno[j] == allocno_order[i]
01922 && j != allocno[allocno_order[i]].reg)
01923 fprintf (file, "+%d", j);
01924 if (allocno[allocno_order[i]].size != 1)
01925 fprintf (file, " (%d)", allocno[allocno_order[i]].size);
01926 }
01927 fprintf (file, "\n");
01928
01929 for (i = 0; i < max_allocno; i++)
01930 {
01931 int j;
01932 fprintf (file, ";; %d conflicts:", allocno[i].reg);
01933 for (j = 0; j < max_allocno; j++)
01934 if (CONFLICTP (j, i))
01935 fprintf (file, " %d", allocno[j].reg);
01936 for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
01937 if (TEST_HARD_REG_BIT (allocno[i].hard_reg_conflicts, j))
01938 fprintf (file, " %d", j);
01939 fprintf (file, "\n");
01940
01941 has_preferences = 0;
01942 for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
01943 if (TEST_HARD_REG_BIT (allocno[i].hard_reg_preferences, j))
01944 has_preferences = 1;
01945
01946 if (! has_preferences)
01947 continue;
01948 fprintf (file, ";; %d preferences:", allocno[i].reg);
01949 for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
01950 if (TEST_HARD_REG_BIT (allocno[i].hard_reg_preferences, j))
01951 fprintf (file, " %d", j);
01952 fprintf (file, "\n");
01953 }
01954 fprintf (file, "\n");
01955 }
01956
01957 void
01958 dump_global_regs (file)
01959 FILE *file;
01960 {
01961 int i, j;
01962
01963 fprintf (file, ";; Register dispositions:\n");
01964 for (i = FIRST_PSEUDO_REGISTER, j = 0; i < max_regno; i++)
01965 if (reg_renumber[i] >= 0)
01966 {
01967 fprintf (file, "%d in %d ", i, reg_renumber[i]);
01968 if (++j % 6 == 0)
01969 fprintf (file, "\n");
01970 }
01971
01972 fprintf (file, "\n\n;; Hard regs used: ");
01973 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01974 if (regs_ever_live[i])
01975 fprintf (file, " %d", i);
01976 fprintf (file, "\n\n");
01977 }