00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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 #include "config.h"
00063 #include "system.h"
00064 #include "hard-reg-set.h"
00065 #include "rtl.h"
00066 #include "tm_p.h"
00067 #include "flags.h"
00068 #include "basic-block.h"
00069 #include "regs.h"
00070 #include "function.h"
00071 #include "insn-config.h"
00072 #include "insn-attr.h"
00073 #include "recog.h"
00074 #include "output.h"
00075 #include "toplev.h"
00076 #include "except.h"
00077 #include "integrate.h"
00078
00079
00080
00081 static int next_qty;
00082
00083
00084 struct qty
00085 {
00086
00087
00088 int n_refs;
00089
00090
00091
00092 int freq;
00093
00094
00095
00096
00097 int birth;
00098
00099
00100
00101
00102
00103
00104
00105 int death;
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 int size;
00116
00117
00118
00119 int n_calls_crossed;
00120
00121
00122
00123
00124
00125 int first_reg;
00126
00127
00128
00129
00130
00131 enum reg_class min_class;
00132
00133
00134
00135
00136 enum reg_class alternate_class;
00137
00138
00139
00140
00141 enum machine_mode mode;
00142
00143
00144
00145
00146 short phys_reg;
00147 };
00148
00149 static struct qty *qty;
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 static HARD_REG_SET *qty_phys_copy_sugg;
00165
00166
00167
00168
00169 static HARD_REG_SET *qty_phys_sugg;
00170
00171
00172
00173 static short *qty_phys_num_copy_sugg;
00174
00175
00176
00177 static short *qty_phys_num_sugg;
00178
00179
00180
00181
00182
00183 static int *reg_next_in_qty;
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 static int *reg_qty;
00201
00202
00203
00204
00205
00206 static char *reg_offset;
00207
00208
00209
00210
00211
00212
00213
00214
00215 short *reg_renumber;
00216
00217
00218
00219
00220 static HARD_REG_SET regs_live;
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 static HARD_REG_SET *regs_live_at;
00233
00234
00235
00236 static int this_insn_number;
00237 static rtx this_insn;
00238
00239 struct equivalence
00240 {
00241
00242
00243
00244 char replace;
00245
00246
00247
00248
00249
00250 rtx replacement;
00251
00252 rtx *src_p;
00253
00254
00255
00256
00257 int loop_depth;
00258
00259
00260
00261 rtx init_insns;
00262 };
00263
00264
00265
00266
00267 static struct equivalence *reg_equiv;
00268
00269
00270 static int recorded_label_ref;
00271
00272 static void alloc_qty PARAMS ((int, enum machine_mode, int, int));
00273 static void validate_equiv_mem_from_store PARAMS ((rtx, rtx, void *));
00274 static int validate_equiv_mem PARAMS ((rtx, rtx, rtx));
00275 static int equiv_init_varies_p PARAMS ((rtx));
00276 static int equiv_init_movable_p PARAMS ((rtx, int));
00277 static int contains_replace_regs PARAMS ((rtx));
00278 static int memref_referenced_p PARAMS ((rtx, rtx));
00279 static int memref_used_between_p PARAMS ((rtx, rtx, rtx));
00280 static void update_equiv_regs PARAMS ((void));
00281 static void no_equiv PARAMS ((rtx, rtx, void *));
00282 static void block_alloc PARAMS ((int));
00283 static int qty_sugg_compare PARAMS ((int, int));
00284 static int qty_sugg_compare_1 PARAMS ((const PTR, const PTR));
00285 static int qty_compare PARAMS ((int, int));
00286 static int qty_compare_1 PARAMS ((const PTR, const PTR));
00287 static int combine_regs PARAMS ((rtx, rtx, int, int, rtx, int));
00288 static int reg_meets_class_p PARAMS ((int, enum reg_class));
00289 static void update_qty_class PARAMS ((int, int));
00290 static void reg_is_set PARAMS ((rtx, rtx, void *));
00291 static void reg_is_born PARAMS ((rtx, int));
00292 static void wipe_dead_reg PARAMS ((rtx, int));
00293 static int find_free_reg PARAMS ((enum reg_class, enum machine_mode,
00294 int, int, int, int, int));
00295 static void mark_life PARAMS ((int, enum machine_mode, int));
00296 static void post_mark_life PARAMS ((int, enum machine_mode, int, int, int));
00297 static int no_conflict_p PARAMS ((rtx, rtx, rtx));
00298 static int requires_inout PARAMS ((const char *));
00299
00300
00301
00302
00303
00304 static void
00305 alloc_qty (regno, mode, size, birth)
00306 int regno;
00307 enum machine_mode mode;
00308 int size, birth;
00309 {
00310 int qtyno = next_qty++;
00311
00312 reg_qty[regno] = qtyno;
00313 reg_offset[regno] = 0;
00314 reg_next_in_qty[regno] = -1;
00315
00316 qty[qtyno].first_reg = regno;
00317 qty[qtyno].size = size;
00318 qty[qtyno].mode = mode;
00319 qty[qtyno].birth = birth;
00320 qty[qtyno].n_calls_crossed = REG_N_CALLS_CROSSED (regno);
00321 qty[qtyno].min_class = reg_preferred_class (regno);
00322 qty[qtyno].alternate_class = reg_alternate_class (regno);
00323 qty[qtyno].n_refs = REG_N_REFS (regno);
00324 qty[qtyno].freq = REG_FREQ (regno);
00325 }
00326
00327
00328
00329 int
00330 local_alloc ()
00331 {
00332 int i;
00333 int max_qty;
00334 basic_block b;
00335
00336
00337
00338 recorded_label_ref = 0;
00339
00340
00341
00342
00343 #ifdef ORDER_REGS_FOR_LOCAL_ALLOC
00344 ORDER_REGS_FOR_LOCAL_ALLOC;
00345 #endif
00346
00347
00348
00349 if (optimize)
00350 update_equiv_regs ();
00351
00352
00353
00354 max_qty = (max_regno - FIRST_PSEUDO_REGISTER);
00355
00356
00357
00358
00359
00360 qty = (struct qty *) xmalloc (max_qty * sizeof (struct qty));
00361 qty_phys_copy_sugg
00362 = (HARD_REG_SET *) xmalloc (max_qty * sizeof (HARD_REG_SET));
00363 qty_phys_num_copy_sugg = (short *) xmalloc (max_qty * sizeof (short));
00364 qty_phys_sugg = (HARD_REG_SET *) xmalloc (max_qty * sizeof (HARD_REG_SET));
00365 qty_phys_num_sugg = (short *) xmalloc (max_qty * sizeof (short));
00366
00367 reg_qty = (int *) xmalloc (max_regno * sizeof (int));
00368 reg_offset = (char *) xmalloc (max_regno * sizeof (char));
00369 reg_next_in_qty = (int *) xmalloc (max_regno * sizeof (int));
00370
00371
00372
00373
00374
00375
00376
00377
00378 for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
00379 {
00380 if (REG_BASIC_BLOCK (i) >= 0 && REG_N_DEATHS (i) == 1)
00381 reg_qty[i] = -2;
00382 else
00383 reg_qty[i] = -1;
00384 }
00385
00386
00387 next_qty = max_qty;
00388
00389
00390
00391 FOR_EACH_BB (b)
00392 {
00393
00394
00395
00396
00397
00398
00399
00400 if (next_qty < 6)
00401 {
00402 for (i = 0; i < next_qty; i++)
00403 {
00404 CLEAR_HARD_REG_SET (qty_phys_copy_sugg[i]);
00405 qty_phys_num_copy_sugg[i] = 0;
00406 CLEAR_HARD_REG_SET (qty_phys_sugg[i]);
00407 qty_phys_num_sugg[i] = 0;
00408 }
00409 }
00410 else
00411 {
00412 #define CLEAR(vector) \
00413 memset ((char *) (vector), 0, (sizeof (*(vector))) * next_qty);
00414
00415 CLEAR (qty_phys_copy_sugg);
00416 CLEAR (qty_phys_num_copy_sugg);
00417 CLEAR (qty_phys_sugg);
00418 CLEAR (qty_phys_num_sugg);
00419 }
00420
00421 next_qty = 0;
00422
00423 block_alloc (b->index);
00424 }
00425
00426 free (qty);
00427 free (qty_phys_copy_sugg);
00428 free (qty_phys_num_copy_sugg);
00429 free (qty_phys_sugg);
00430 free (qty_phys_num_sugg);
00431
00432 free (reg_qty);
00433 free (reg_offset);
00434 free (reg_next_in_qty);
00435
00436 return recorded_label_ref;
00437 }
00438
00439
00440
00441 static rtx equiv_mem;
00442
00443
00444 static int equiv_mem_modified;
00445
00446
00447
00448
00449 static void
00450 validate_equiv_mem_from_store (dest, set, data)
00451 rtx dest;
00452 rtx set ATTRIBUTE_UNUSED;
00453 void *data ATTRIBUTE_UNUSED;
00454 {
00455 if ((GET_CODE (dest) == REG
00456 && reg_overlap_mentioned_p (dest, equiv_mem))
00457 || (GET_CODE (dest) == MEM
00458 && true_dependence (dest, VOIDmode, equiv_mem, rtx_varies_p)))
00459 equiv_mem_modified = 1;
00460 }
00461
00462
00463
00464
00465
00466
00467
00468
00469 static int
00470 validate_equiv_mem (start, reg, memref)
00471 rtx start;
00472 rtx reg;
00473 rtx memref;
00474 {
00475 rtx insn;
00476 rtx note;
00477
00478 equiv_mem = memref;
00479 equiv_mem_modified = 0;
00480
00481
00482
00483 if (side_effects_p (memref))
00484 return 0;
00485
00486 for (insn = start; insn && ! equiv_mem_modified; insn = NEXT_INSN (insn))
00487 {
00488 if (! INSN_P (insn))
00489 continue;
00490
00491 if (find_reg_note (insn, REG_DEAD, reg))
00492 return 1;
00493
00494 if (GET_CODE (insn) == CALL_INSN && ! RTX_UNCHANGING_P (memref)
00495 && ! CONST_OR_PURE_CALL_P (insn))
00496 return 0;
00497
00498 note_stores (PATTERN (insn), validate_equiv_mem_from_store, NULL);
00499
00500
00501
00502
00503
00504
00505 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
00506 if ((REG_NOTE_KIND (note) == REG_INC
00507 || REG_NOTE_KIND (note) == REG_DEAD)
00508 && GET_CODE (XEXP (note, 0)) == REG
00509 && reg_overlap_mentioned_p (XEXP (note, 0), memref))
00510 return 0;
00511 }
00512
00513 return 0;
00514 }
00515
00516
00517
00518 static int
00519 equiv_init_varies_p (x)
00520 rtx x;
00521 {
00522 RTX_CODE code = GET_CODE (x);
00523 int i;
00524 const char *fmt;
00525
00526 switch (code)
00527 {
00528 case MEM:
00529 return ! RTX_UNCHANGING_P (x) || equiv_init_varies_p (XEXP (x, 0));
00530
00531 case QUEUED:
00532 return 1;
00533
00534 case CONST:
00535 case CONST_INT:
00536 case CONST_DOUBLE:
00537 case CONST_VECTOR:
00538 case SYMBOL_REF:
00539 case LABEL_REF:
00540 return 0;
00541
00542 case REG:
00543 return reg_equiv[REGNO (x)].replace == 0 && rtx_varies_p (x, 0);
00544
00545 case ASM_OPERANDS:
00546 if (MEM_VOLATILE_P (x))
00547 return 1;
00548
00549
00550
00551 default:
00552 break;
00553 }
00554
00555 fmt = GET_RTX_FORMAT (code);
00556 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00557 if (fmt[i] == 'e')
00558 {
00559 if (equiv_init_varies_p (XEXP (x, i)))
00560 return 1;
00561 }
00562 else if (fmt[i] == 'E')
00563 {
00564 int j;
00565 for (j = 0; j < XVECLEN (x, i); j++)
00566 if (equiv_init_varies_p (XVECEXP (x, i, j)))
00567 return 1;
00568 }
00569
00570 return 0;
00571 }
00572
00573
00574
00575
00576
00577
00578 static int
00579 equiv_init_movable_p (x, regno)
00580 rtx x;
00581 int regno;
00582 {
00583 int i, j;
00584 const char *fmt;
00585 enum rtx_code code = GET_CODE (x);
00586
00587 switch (code)
00588 {
00589 case SET:
00590 return equiv_init_movable_p (SET_SRC (x), regno);
00591
00592 case CC0:
00593 case CLOBBER:
00594 return 0;
00595
00596 case PRE_INC:
00597 case PRE_DEC:
00598 case POST_INC:
00599 case POST_DEC:
00600 case PRE_MODIFY:
00601 case POST_MODIFY:
00602 return 0;
00603
00604 case REG:
00605 return (reg_equiv[REGNO (x)].loop_depth >= reg_equiv[regno].loop_depth
00606 && reg_equiv[REGNO (x)].replace)
00607 || (REG_BASIC_BLOCK (REGNO (x)) < 0 && ! rtx_varies_p (x, 0));
00608
00609 case UNSPEC_VOLATILE:
00610 return 0;
00611
00612 case ASM_OPERANDS:
00613 if (MEM_VOLATILE_P (x))
00614 return 0;
00615
00616
00617
00618 default:
00619 break;
00620 }
00621
00622 fmt = GET_RTX_FORMAT (code);
00623 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00624 switch (fmt[i])
00625 {
00626 case 'e':
00627 if (! equiv_init_movable_p (XEXP (x, i), regno))
00628 return 0;
00629 break;
00630 case 'E':
00631 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
00632 if (! equiv_init_movable_p (XVECEXP (x, i, j), regno))
00633 return 0;
00634 break;
00635 }
00636
00637 return 1;
00638 }
00639
00640
00641
00642 static int
00643 contains_replace_regs (x)
00644 rtx x;
00645 {
00646 int i, j;
00647 const char *fmt;
00648 enum rtx_code code = GET_CODE (x);
00649
00650 switch (code)
00651 {
00652 case CONST_INT:
00653 case CONST:
00654 case LABEL_REF:
00655 case SYMBOL_REF:
00656 case CONST_DOUBLE:
00657 case CONST_VECTOR:
00658 case PC:
00659 case CC0:
00660 case HIGH:
00661 return 0;
00662
00663 case REG:
00664 return reg_equiv[REGNO (x)].replace;
00665
00666 default:
00667 break;
00668 }
00669
00670 fmt = GET_RTX_FORMAT (code);
00671 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00672 switch (fmt[i])
00673 {
00674 case 'e':
00675 if (contains_replace_regs (XEXP (x, i)))
00676 return 1;
00677 break;
00678 case 'E':
00679 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
00680 if (contains_replace_regs (XVECEXP (x, i, j)))
00681 return 1;
00682 break;
00683 }
00684
00685 return 0;
00686 }
00687
00688
00689
00690
00691 static int
00692 memref_referenced_p (memref, x)
00693 rtx x;
00694 rtx memref;
00695 {
00696 int i, j;
00697 const char *fmt;
00698 enum rtx_code code = GET_CODE (x);
00699
00700 switch (code)
00701 {
00702 case CONST_INT:
00703 case CONST:
00704 case LABEL_REF:
00705 case SYMBOL_REF:
00706 case CONST_DOUBLE:
00707 case CONST_VECTOR:
00708 case PC:
00709 case CC0:
00710 case HIGH:
00711 case LO_SUM:
00712 return 0;
00713
00714 case REG:
00715 return (reg_equiv[REGNO (x)].replacement
00716 && memref_referenced_p (memref,
00717 reg_equiv[REGNO (x)].replacement));
00718
00719 case MEM:
00720 if (true_dependence (memref, VOIDmode, x, rtx_varies_p))
00721 return 1;
00722 break;
00723
00724 case SET:
00725
00726
00727 if (GET_CODE (SET_DEST (x)) == MEM)
00728 {
00729 if (memref_referenced_p (memref, XEXP (SET_DEST (x), 0)))
00730 return 1;
00731 }
00732 else if (memref_referenced_p (memref, SET_DEST (x)))
00733 return 1;
00734
00735 return memref_referenced_p (memref, SET_SRC (x));
00736
00737 default:
00738 break;
00739 }
00740
00741 fmt = GET_RTX_FORMAT (code);
00742 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00743 switch (fmt[i])
00744 {
00745 case 'e':
00746 if (memref_referenced_p (memref, XEXP (x, i)))
00747 return 1;
00748 break;
00749 case 'E':
00750 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
00751 if (memref_referenced_p (memref, XVECEXP (x, i, j)))
00752 return 1;
00753 break;
00754 }
00755
00756 return 0;
00757 }
00758
00759
00760
00761
00762 static int
00763 memref_used_between_p (memref, start, end)
00764 rtx memref;
00765 rtx start;
00766 rtx end;
00767 {
00768 rtx insn;
00769
00770 for (insn = NEXT_INSN (start); insn != NEXT_INSN (end);
00771 insn = NEXT_INSN (insn))
00772 if (INSN_P (insn) && memref_referenced_p (memref, PATTERN (insn)))
00773 return 1;
00774
00775 return 0;
00776 }
00777
00778
00779
00780
00781
00782
00783
00784
00785 int
00786 function_invariant_p (x)
00787 rtx x;
00788 {
00789 if (CONSTANT_P (x))
00790 return 1;
00791 if (x == frame_pointer_rtx || x == arg_pointer_rtx)
00792 return 1;
00793 if (GET_CODE (x) == PLUS
00794 && (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx)
00795 && CONSTANT_P (XEXP (x, 1)))
00796 return 1;
00797 return 0;
00798 }
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 static void
00809 update_equiv_regs ()
00810 {
00811 rtx insn;
00812 basic_block bb;
00813 int loop_depth;
00814 regset_head cleared_regs;
00815 int clear_regnos = 0;
00816
00817 reg_equiv = (struct equivalence *) xcalloc (max_regno, sizeof *reg_equiv);
00818 INIT_REG_SET (&cleared_regs);
00819
00820 init_alias_analysis ();
00821
00822
00823
00824
00825 FOR_EACH_BB (bb)
00826 {
00827 loop_depth = bb->loop_depth;
00828
00829 for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = NEXT_INSN (insn))
00830 {
00831 rtx note;
00832 rtx set;
00833 rtx dest, src;
00834 int regno;
00835
00836 if (! INSN_P (insn))
00837 continue;
00838
00839 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
00840 if (REG_NOTE_KIND (note) == REG_INC)
00841 no_equiv (XEXP (note, 0), note, NULL);
00842
00843 set = single_set (insn);
00844
00845
00846
00847 if (set == 0)
00848 {
00849 note_stores (PATTERN (insn), no_equiv, NULL);
00850 continue;
00851 }
00852 else if (GET_CODE (PATTERN (insn)) == PARALLEL)
00853 {
00854 int i;
00855
00856 for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
00857 {
00858 rtx part = XVECEXP (PATTERN (insn), 0, i);
00859 if (part != set)
00860 note_stores (part, no_equiv, NULL);
00861 }
00862 }
00863
00864 dest = SET_DEST (set);
00865 src = SET_SRC (set);
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888 if (GET_CODE (dest) == MEM && GET_CODE (src) == REG
00889 && (regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER
00890 && REG_BASIC_BLOCK (regno) >= 0
00891 && REG_N_SETS (regno) == 1
00892 && reg_equiv[regno].init_insns != 0
00893 && reg_equiv[regno].init_insns != const0_rtx
00894 && ! find_reg_note (XEXP (reg_equiv[regno].init_insns, 0),
00895 REG_EQUIV, NULL_RTX)
00896 && ! contains_replace_regs (XEXP (dest, 0)))
00897 {
00898 rtx init_insn = XEXP (reg_equiv[regno].init_insns, 0);
00899 if (validate_equiv_mem (init_insn, src, dest)
00900 && ! memref_used_between_p (dest, init_insn, insn))
00901 REG_NOTES (init_insn)
00902 = gen_rtx_EXPR_LIST (REG_EQUIV, dest, REG_NOTES (init_insn));
00903 }
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917 if (GET_CODE (dest) != REG
00918 || (regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER
00919 || reg_equiv[regno].init_insns == const0_rtx
00920 || (CLASS_LIKELY_SPILLED_P (reg_preferred_class (regno))
00921 && GET_CODE (src) == MEM))
00922 {
00923
00924
00925 note_stores (set, no_equiv, NULL);
00926 continue;
00927 }
00928
00929 note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
00930
00931
00932
00933
00934 if (! note && ! rtx_varies_p (src, 0))
00935 note = set_unique_reg_note (insn, REG_EQUAL, src);
00936
00937
00938
00939 if (note && GET_CODE (XEXP (note, 0)) == EXPR_LIST)
00940 note = NULL_RTX;
00941
00942 if (REG_N_SETS (regno) != 1
00943 && (! note
00944 || rtx_varies_p (XEXP (note, 0), 0)
00945 || (reg_equiv[regno].replacement
00946 && ! rtx_equal_p (XEXP (note, 0),
00947 reg_equiv[regno].replacement))))
00948 {
00949 no_equiv (dest, set, NULL);
00950 continue;
00951 }
00952
00953 reg_equiv[regno].init_insns
00954 = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv[regno].init_insns);
00955
00956
00957
00958 if (note && ! rtx_varies_p (XEXP (note, 0), 0))
00959 PUT_MODE (note, (enum machine_mode) REG_EQUIV);
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976 note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
00977
00978 if (note == 0 && REG_BASIC_BLOCK (regno) >= 0
00979 && GET_CODE (SET_SRC (set)) == MEM
00980 && validate_equiv_mem (insn, dest, SET_SRC (set)))
00981 REG_NOTES (insn) = note = gen_rtx_EXPR_LIST (REG_EQUIV, SET_SRC (set),
00982 REG_NOTES (insn));
00983
00984 if (note)
00985 {
00986 int regno = REGNO (dest);
00987
00988
00989
00990
00991
00992
00993 if (GET_CODE (XEXP (note, 0)) == LABEL_REF
00994 || (GET_CODE (XEXP (note, 0)) == CONST
00995 && GET_CODE (XEXP (XEXP (note, 0), 0)) == PLUS
00996 && (GET_CODE (XEXP (XEXP (XEXP (note, 0), 0), 0))
00997 == LABEL_REF)))
00998 recorded_label_ref = 1;
00999
01000 reg_equiv[regno].replacement = XEXP (note, 0);
01001 reg_equiv[regno].src_p = &SET_SRC (set);
01002 reg_equiv[regno].loop_depth = loop_depth;
01003
01004
01005 if (REG_LIVE_LENGTH (regno) >= 0 && optimize)
01006 {
01007
01008
01009 REG_LIVE_LENGTH (regno) *= 2;
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021 if (REG_N_REFS (regno) == 2
01022 && (rtx_equal_p (XEXP (note, 0), src)
01023 || ! equiv_init_varies_p (src))
01024 && GET_CODE (insn) == INSN
01025 && equiv_init_movable_p (PATTERN (insn), regno))
01026 reg_equiv[regno].replace = 1;
01027 }
01028 }
01029 }
01030 }
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040 FOR_EACH_BB_REVERSE (bb)
01041 {
01042 loop_depth = bb->loop_depth;
01043 for (insn = bb->end; insn != PREV_INSN (bb->head); insn = PREV_INSN (insn))
01044 {
01045 rtx link;
01046
01047 if (! INSN_P (insn))
01048 continue;
01049
01050 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
01051 {
01052 if (REG_NOTE_KIND (link) == REG_DEAD
01053
01054 && reg_mentioned_p (XEXP (link, 0), PATTERN (insn)))
01055 {
01056 int regno = REGNO (XEXP (link, 0));
01057 rtx equiv_insn;
01058
01059 if (! reg_equiv[regno].replace
01060 || reg_equiv[regno].loop_depth < loop_depth)
01061 continue;
01062
01063
01064
01065
01066
01067
01068 if (reg_equiv[regno].init_insns == NULL_RTX
01069 || XEXP (reg_equiv[regno].init_insns, 1) != NULL_RTX)
01070 abort ();
01071 equiv_insn = XEXP (reg_equiv[regno].init_insns, 0);
01072
01073
01074
01075
01076 if (can_throw_internal (equiv_insn))
01077 continue;
01078
01079 if (asm_noperands (PATTERN (equiv_insn)) < 0
01080 && validate_replace_rtx (regno_reg_rtx[regno],
01081 *(reg_equiv[regno].src_p), insn))
01082 {
01083 rtx equiv_link;
01084 rtx last_link;
01085 rtx note;
01086
01087
01088 for (last_link = link; XEXP (last_link, 1);
01089 last_link = XEXP (last_link, 1))
01090 ;
01091
01092
01093 equiv_link = REG_NOTES (equiv_insn);
01094 while (equiv_link)
01095 {
01096 note = equiv_link;
01097 equiv_link = XEXP (equiv_link, 1);
01098 if (REG_NOTE_KIND (note) == REG_DEAD)
01099 {
01100 remove_note (equiv_insn, note);
01101 XEXP (last_link, 1) = note;
01102 XEXP (note, 1) = NULL_RTX;
01103 last_link = note;
01104 }
01105 }
01106
01107 remove_death (regno, insn);
01108 REG_N_REFS (regno) = 0;
01109 REG_FREQ (regno) = 0;
01110 delete_insn (equiv_insn);
01111
01112 reg_equiv[regno].init_insns
01113 = XEXP (reg_equiv[regno].init_insns, 1);
01114 }
01115
01116
01117 else if (PREV_INSN (insn) != equiv_insn)
01118 {
01119 rtx new_insn;
01120
01121 new_insn = emit_insn_before (PATTERN (equiv_insn), insn);
01122 REG_NOTES (new_insn) = REG_NOTES (equiv_insn);
01123 REG_NOTES (equiv_insn) = 0;
01124
01125
01126
01127 INSN_CODE (new_insn) = INSN_CODE (equiv_insn);
01128
01129 delete_insn (equiv_insn);
01130
01131 XEXP (reg_equiv[regno].init_insns, 0) = new_insn;
01132
01133 REG_BASIC_BLOCK (regno) = bb->index;
01134 REG_N_CALLS_CROSSED (regno) = 0;
01135 REG_LIVE_LENGTH (regno) = 2;
01136
01137 if (insn == bb->head)
01138 bb->head = PREV_INSN (insn);
01139
01140
01141
01142 SET_REGNO_REG_SET (&cleared_regs, regno);
01143 clear_regnos++;
01144 }
01145 }
01146 }
01147 }
01148 }
01149
01150
01151 if (clear_regnos)
01152 {
01153 int j;
01154 if (clear_regnos > 8)
01155 {
01156 FOR_EACH_BB (bb)
01157 {
01158 AND_COMPL_REG_SET (bb->global_live_at_start, &cleared_regs);
01159 AND_COMPL_REG_SET (bb->global_live_at_end, &cleared_regs);
01160 }
01161 }
01162 else
01163 EXECUTE_IF_SET_IN_REG_SET (&cleared_regs, 0, j,
01164 {
01165 FOR_EACH_BB (bb)
01166 {
01167 CLEAR_REGNO_REG_SET (bb->global_live_at_start, j);
01168 CLEAR_REGNO_REG_SET (bb->global_live_at_end, j);
01169 }
01170 });
01171 }
01172
01173
01174 end_alias_analysis ();
01175 CLEAR_REG_SET (&cleared_regs);
01176 free (reg_equiv);
01177 }
01178
01179
01180
01181
01182
01183
01184
01185
01186 static void
01187 no_equiv (reg, store, data)
01188 rtx reg, store ATTRIBUTE_UNUSED;
01189 void *data ATTRIBUTE_UNUSED;
01190 {
01191 int regno;
01192 rtx list;
01193
01194 if (GET_CODE (reg) != REG)
01195 return;
01196 regno = REGNO (reg);
01197 list = reg_equiv[regno].init_insns;
01198 if (list == const0_rtx)
01199 return;
01200 for (; list; list = XEXP (list, 1))
01201 {
01202 rtx insn = XEXP (list, 0);
01203 remove_note (insn, find_reg_note (insn, REG_EQUIV, NULL_RTX));
01204 }
01205 reg_equiv[regno].init_insns = const0_rtx;
01206 reg_equiv[regno].replacement = NULL_RTX;
01207 }
01208
01209
01210
01211
01212 static void
01213 block_alloc (b)
01214 int b;
01215 {
01216 int i, q;
01217 rtx insn;
01218 rtx note, hard_reg;
01219 int insn_number = 0;
01220 int insn_count = 0;
01221 int max_uid = get_max_uid ();
01222 int *qty_order;
01223 int no_conflict_combined_regno = -1;
01224
01225
01226
01227 insn = BLOCK_END (b);
01228 while (1)
01229 {
01230 if (GET_CODE (insn) != NOTE)
01231 if (++insn_count > max_uid)
01232 abort ();
01233 if (insn == BLOCK_HEAD (b))
01234 break;
01235 insn = PREV_INSN (insn);
01236 }
01237
01238
01239
01240 regs_live_at = (HARD_REG_SET *) xcalloc ((2 * insn_count + 2),
01241 sizeof (HARD_REG_SET));
01242
01243
01244
01245 REG_SET_TO_HARD_REG_SET (regs_live, BASIC_BLOCK (b)->global_live_at_start);
01246
01247
01248
01249
01250
01251 insn = BLOCK_HEAD (b);
01252 while (1)
01253 {
01254 if (GET_CODE (insn) != NOTE)
01255 insn_number++;
01256
01257 if (INSN_P (insn))
01258 {
01259 rtx link, set;
01260 int win = 0;
01261 rtx r0, r1 = NULL_RTX;
01262 int combined_regno = -1;
01263 int i;
01264
01265 this_insn_number = insn_number;
01266 this_insn = insn;
01267
01268 extract_insn (insn);
01269 which_alternative = -1;
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289 if (optimize
01290 && recog_data.n_operands > 1
01291 && recog_data.constraints[0][0] == '='
01292 && recog_data.constraints[0][1] != '&')
01293 {
01294
01295 int must_match_0 = -1;
01296
01297
01298 int n_matching_alts = 0;
01299
01300 for (i = 1; i < recog_data.n_operands; i++)
01301 {
01302 const char *p = recog_data.constraints[i];
01303 int this_match = requires_inout (p);
01304
01305 n_matching_alts += this_match;
01306 if (this_match == recog_data.n_alternatives)
01307 must_match_0 = i;
01308 }
01309
01310 r0 = recog_data.operand[0];
01311 for (i = 1; i < recog_data.n_operands; i++)
01312 {
01313
01314
01315
01316
01317 if (must_match_0 >= 0 && i != must_match_0
01318 && ! (i == must_match_0 + 1
01319 && recog_data.constraints[i-1][0] == '%')
01320 && ! (i == must_match_0 - 1
01321 && recog_data.constraints[i][0] == '%'))
01322 continue;
01323
01324
01325
01326
01327
01328
01329 if (n_matching_alts == recog_data.n_alternatives
01330 && 0 == requires_inout (recog_data.constraints[i]))
01331 continue;
01332
01333 r1 = recog_data.operand[i];
01334
01335
01336
01337
01338 if (recog_data.constraints[i][0] == 'p'
01339 || EXTRA_ADDRESS_CONSTRAINT (recog_data.constraints[i][0]))
01340 while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
01341 r1 = XEXP (r1, 0);
01342
01343
01344
01345 hard_reg = get_hard_reg_initial_reg (cfun, r1);
01346 if (hard_reg != NULL_RTX)
01347 {
01348 if (GET_CODE (hard_reg) == REG
01349 && IN_RANGE (REGNO (hard_reg),
01350 0, FIRST_PSEUDO_REGISTER - 1)
01351 && ! call_used_regs[REGNO (hard_reg)])
01352 continue;
01353 }
01354
01355 if (GET_CODE (r0) == REG || GET_CODE (r0) == SUBREG)
01356 {
01357
01358
01359
01360
01361 int may_save_copy
01362 = (r1 == recog_data.operand[i] && must_match_0 >= 0);
01363
01364 if (GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG)
01365 win = combine_regs (r1, r0, may_save_copy,
01366 insn_number, insn, 0);
01367 }
01368 if (win)
01369 break;
01370 }
01371 }
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387 if (optimize
01388 && GET_CODE (PATTERN (insn)) == CLOBBER
01389 && (r0 = XEXP (PATTERN (insn), 0),
01390 GET_CODE (r0) == REG)
01391 && (link = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0
01392 && XEXP (link, 0) != 0
01393 && GET_CODE (XEXP (link, 0)) == INSN
01394 && (set = single_set (XEXP (link, 0))) != 0
01395 && SET_DEST (set) == r0 && SET_SRC (set) == r0
01396 && (note = find_reg_note (XEXP (link, 0), REG_EQUAL,
01397 NULL_RTX)) != 0)
01398 {
01399 if (r1 = XEXP (note, 0), GET_CODE (r1) == REG
01400
01401 && no_conflict_p (insn, r0, r1))
01402 win = combine_regs (r1, r0, 1, insn_number, insn, 1);
01403 else if (GET_RTX_FORMAT (GET_CODE (XEXP (note, 0)))[0] == 'e'
01404 && (r1 = XEXP (XEXP (note, 0), 0),
01405 GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG)
01406 && no_conflict_p (insn, r0, r1))
01407 win = combine_regs (r1, r0, 0, insn_number, insn, 1);
01408
01409
01410
01411 else if ((GET_CODE (XEXP (note, 0)) == EQ
01412 || GET_CODE (XEXP (note, 0)) == NE
01413 || GET_RTX_CLASS (GET_CODE (XEXP (note, 0))) == 'c')
01414 && (r1 = XEXP (XEXP (note, 0), 1),
01415 (GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG))
01416 && no_conflict_p (insn, r0, r1))
01417 win = combine_regs (r1, r0, 0, insn_number, insn, 1);
01418
01419
01420
01421 if (win)
01422 no_conflict_combined_regno = REGNO (r1);
01423 }
01424
01425
01426
01427
01428
01429
01430 if (win)
01431 {
01432 while (GET_CODE (r1) == SUBREG)
01433 r1 = SUBREG_REG (r1);
01434 combined_regno = REGNO (r1);
01435 }
01436
01437
01438
01439
01440 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
01441 if (REG_NOTE_KIND (link) == REG_DEAD
01442 && GET_CODE (XEXP (link, 0)) == REG
01443 && combined_regno != (int) REGNO (XEXP (link, 0))
01444 && (no_conflict_combined_regno != (int) REGNO (XEXP (link, 0))
01445 || ! find_reg_note (insn, REG_NO_CONFLICT,
01446 XEXP (link, 0))))
01447 wipe_dead_reg (XEXP (link, 0), 0);
01448
01449
01450
01451
01452
01453 note_stores (PATTERN (insn), reg_is_set, NULL);
01454
01455
01456
01457
01458
01459
01460
01461 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
01462 if (REG_NOTE_KIND (link) == REG_UNUSED
01463 && GET_CODE (XEXP (link, 0)) == REG)
01464 wipe_dead_reg (XEXP (link, 0), 1);
01465
01466
01467
01468
01469 if ((note = find_reg_note (insn, REG_RETVAL, NULL_RTX)) != 0
01470 && GET_CODE (XEXP (note, 0)) == INSN
01471 && GET_CODE (PATTERN (XEXP (note, 0))) == CLOBBER)
01472 no_conflict_combined_regno = -1;
01473 }
01474
01475
01476
01477
01478
01479 IOR_HARD_REG_SET (regs_live_at[2 * insn_number], regs_live);
01480 IOR_HARD_REG_SET (regs_live_at[2 * insn_number + 1], regs_live);
01481
01482 if (insn == BLOCK_END (b))
01483 break;
01484
01485 insn = NEXT_INSN (insn);
01486 }
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496 qty_order = (int *) xmalloc (next_qty * sizeof (int));
01497 for (i = 0; i < next_qty; i++)
01498 qty_order[i] = i;
01499
01500 #define EXCHANGE(I1, I2) \
01501 { i = qty_order[I1]; qty_order[I1] = qty_order[I2]; qty_order[I2] = i; }
01502
01503 switch (next_qty)
01504 {
01505 case 3:
01506
01507 if (qty_sugg_compare (0, 1) > 0)
01508 EXCHANGE (0, 1);
01509 if (qty_sugg_compare (1, 2) > 0)
01510 EXCHANGE (2, 1);
01511
01512
01513 case 2:
01514
01515 if (qty_sugg_compare (0, 1) > 0)
01516 EXCHANGE (0, 1);
01517
01518
01519
01520 case 1:
01521 case 0:
01522
01523 break;
01524
01525 default:
01526 qsort (qty_order, next_qty, sizeof (int), qty_sugg_compare_1);
01527 }
01528
01529
01530
01531
01532 for (i = 0; i < next_qty; i++)
01533 {
01534 q = qty_order[i];
01535 if (qty_phys_num_sugg[q] != 0 || qty_phys_num_copy_sugg[q] != 0)
01536 qty[q].phys_reg = find_free_reg (qty[q].min_class, qty[q].mode, q,
01537 0, 1, qty[q].birth, qty[q].death);
01538 else
01539 qty[q].phys_reg = -1;
01540 }
01541
01542
01543
01544
01545
01546 for (i = 0; i < next_qty; i++)
01547 qty_order[i] = i;
01548
01549 #define EXCHANGE(I1, I2) \
01550 { i = qty_order[I1]; qty_order[I1] = qty_order[I2]; qty_order[I2] = i; }
01551
01552 switch (next_qty)
01553 {
01554 case 3:
01555
01556 if (qty_compare (0, 1) > 0)
01557 EXCHANGE (0, 1);
01558 if (qty_compare (1, 2) > 0)
01559 EXCHANGE (2, 1);
01560
01561
01562 case 2:
01563
01564 if (qty_compare (0, 1) > 0)
01565 EXCHANGE (0, 1);
01566
01567
01568
01569 case 1:
01570 case 0:
01571
01572 break;
01573
01574 default:
01575 qsort (qty_order, next_qty, sizeof (int), qty_compare_1);
01576 }
01577
01578
01579
01580
01581
01582
01583 for (i = 0; i < next_qty; i++)
01584 {
01585 q = qty_order[i];
01586 if (qty[q].phys_reg < 0)
01587 {
01588 #ifdef INSN_SCHEDULING
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606 int fake_birth = MAX (0, qty[q].birth - 2 + qty[q].birth % 2);
01607 int fake_death = MIN (insn_number * 2 + 1,
01608 qty[q].death + 2 - qty[q].death % 2);
01609 #endif
01610
01611 if (N_REG_CLASSES > 1)
01612 {
01613 #ifdef INSN_SCHEDULING
01614
01615
01616
01617
01618
01619
01620
01621 if (flag_schedule_insns_after_reload
01622 && !optimize_size
01623 && !SMALL_REGISTER_CLASSES)
01624 {
01625 qty[q].phys_reg = find_free_reg (qty[q].min_class,
01626 qty[q].mode, q, 0, 0,
01627 fake_birth, fake_death);
01628 if (qty[q].phys_reg >= 0)
01629 continue;
01630 }
01631 #endif
01632 qty[q].phys_reg = find_free_reg (qty[q].min_class,
01633 qty[q].mode, q, 0, 0,
01634 qty[q].birth, qty[q].death);
01635 if (qty[q].phys_reg >= 0)
01636 continue;
01637 }
01638
01639 #ifdef INSN_SCHEDULING
01640
01641 if (flag_schedule_insns_after_reload
01642 && !optimize_size
01643 && !SMALL_REGISTER_CLASSES
01644 && qty[q].alternate_class != NO_REGS)
01645 qty[q].phys_reg = find_free_reg (qty[q].alternate_class,
01646 qty[q].mode, q, 0, 0,
01647 fake_birth, fake_death);
01648 #endif
01649 if (qty[q].alternate_class != NO_REGS)
01650 qty[q].phys_reg = find_free_reg (qty[q].alternate_class,
01651 qty[q].mode, q, 0, 0,
01652 qty[q].birth, qty[q].death);
01653 }
01654 }
01655
01656
01657
01658
01659 for (q = 0; q < next_qty; q++)
01660 if (qty[q].phys_reg >= 0)
01661 {
01662 for (i = qty[q].first_reg; i >= 0; i = reg_next_in_qty[i])
01663 reg_renumber[i] = qty[q].phys_reg + reg_offset[i];
01664 }
01665
01666
01667 free (regs_live_at);
01668 free (qty_order);
01669 }
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688 #define QTY_CMP_PRI(q) \
01689 ((int) (((double) (floor_log2 (qty[q].n_refs) * qty[q].freq * qty[q].size) \
01690 / (qty[q].death - qty[q].birth)) * (10000 / REG_FREQ_MAX)))
01691
01692 static int
01693 qty_compare (q1, q2)
01694 int q1, q2;
01695 {
01696 return QTY_CMP_PRI (q2) - QTY_CMP_PRI (q1);
01697 }
01698
01699 static int
01700 qty_compare_1 (q1p, q2p)
01701 const PTR q1p;
01702 const PTR q2p;
01703 {
01704 int q1 = *(const int *) q1p, q2 = *(const int *) q2p;
01705 int tem = QTY_CMP_PRI (q2) - QTY_CMP_PRI (q1);
01706
01707 if (tem != 0)
01708 return tem;
01709
01710
01711
01712 return q1 - q2;
01713 }
01714
01715
01716
01717
01718
01719
01720
01721
01722 #define QTY_CMP_SUGG(q) \
01723 (qty_phys_num_copy_sugg[q] \
01724 ? qty_phys_num_copy_sugg[q] \
01725 : qty_phys_num_sugg[q] * FIRST_PSEUDO_REGISTER)
01726
01727 static int
01728 qty_sugg_compare (q1, q2)
01729 int q1, q2;
01730 {
01731 int tem = QTY_CMP_SUGG (q1) - QTY_CMP_SUGG (q2);
01732
01733 if (tem != 0)
01734 return tem;
01735
01736 return QTY_CMP_PRI (q2) - QTY_CMP_PRI (q1);
01737 }
01738
01739 static int
01740 qty_sugg_compare_1 (q1p, q2p)
01741 const PTR q1p;
01742 const PTR q2p;
01743 {
01744 int q1 = *(const int *) q1p, q2 = *(const int *) q2p;
01745 int tem = QTY_CMP_SUGG (q1) - QTY_CMP_SUGG (q2);
01746
01747 if (tem != 0)
01748 return tem;
01749
01750 tem = QTY_CMP_PRI (q2) - QTY_CMP_PRI (q1);
01751 if (tem != 0)
01752 return tem;
01753
01754
01755
01756 return q1 - q2;
01757 }
01758
01759 #undef QTY_CMP_SUGG
01760 #undef QTY_CMP_PRI
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784 static int
01785 combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
01786 rtx usedreg, setreg;
01787 int may_save_copy;
01788 int insn_number;
01789 rtx insn;
01790 int already_dead;
01791 {
01792 int ureg, sreg;
01793 int offset = 0;
01794 int usize, ssize;
01795 int sqty;
01796
01797
01798
01799
01800
01801 while (GET_CODE (usedreg) == SUBREG)
01802 {
01803 rtx subreg = SUBREG_REG (usedreg);
01804
01805 if (GET_CODE (subreg) == REG)
01806 {
01807 if (GET_MODE_SIZE (GET_MODE (subreg)) > UNITS_PER_WORD)
01808 may_save_copy = 0;
01809
01810 if (REGNO (subreg) < FIRST_PSEUDO_REGISTER)
01811 offset += subreg_regno_offset (REGNO (subreg),
01812 GET_MODE (subreg),
01813 SUBREG_BYTE (usedreg),
01814 GET_MODE (usedreg));
01815 else
01816 offset += (SUBREG_BYTE (usedreg)
01817 / REGMODE_NATURAL_SIZE (GET_MODE (usedreg)));
01818 }
01819
01820 usedreg = subreg;
01821 }
01822
01823 if (GET_CODE (usedreg) != REG)
01824 return 0;
01825
01826 ureg = REGNO (usedreg);
01827 if (ureg < FIRST_PSEUDO_REGISTER)
01828 usize = HARD_REGNO_NREGS (ureg, GET_MODE (usedreg));
01829 else
01830 usize = ((GET_MODE_SIZE (GET_MODE (usedreg))
01831 + (REGMODE_NATURAL_SIZE (GET_MODE (usedreg)) - 1))
01832 / REGMODE_NATURAL_SIZE (GET_MODE (usedreg)));
01833
01834 while (GET_CODE (setreg) == SUBREG)
01835 {
01836 rtx subreg = SUBREG_REG (setreg);
01837
01838 if (GET_CODE (subreg) == REG)
01839 {
01840 if (GET_MODE_SIZE (GET_MODE (subreg)) > UNITS_PER_WORD)
01841 may_save_copy = 0;
01842
01843 if (REGNO (subreg) < FIRST_PSEUDO_REGISTER)
01844 offset -= subreg_regno_offset (REGNO (subreg),
01845 GET_MODE (subreg),
01846 SUBREG_BYTE (setreg),
01847 GET_MODE (setreg));
01848 else
01849 offset -= (SUBREG_BYTE (setreg)
01850 / REGMODE_NATURAL_SIZE (GET_MODE (setreg)));
01851 }
01852
01853 setreg = subreg;
01854 }
01855
01856 if (GET_CODE (setreg) != REG)
01857 return 0;
01858
01859 sreg = REGNO (setreg);
01860 if (sreg < FIRST_PSEUDO_REGISTER)
01861 ssize = HARD_REGNO_NREGS (sreg, GET_MODE (setreg));
01862 else
01863 ssize = ((GET_MODE_SIZE (GET_MODE (setreg))
01864 + (REGMODE_NATURAL_SIZE (GET_MODE (setreg)) - 1))
01865 / REGMODE_NATURAL_SIZE (GET_MODE (setreg)));
01866
01867
01868
01869
01870 if ((ureg >= FIRST_PSEUDO_REGISTER && reg_qty[ureg] < 0)
01871
01872 || (offset > 0 && usize + offset > ssize)
01873 || (offset < 0 && usize + offset < ssize)
01874
01875
01876 || (ssize > usize && ureg >= FIRST_PSEUDO_REGISTER
01877 && usize < qty[reg_qty[ureg]].size)
01878
01879 || (sreg >= FIRST_PSEUDO_REGISTER && reg_qty[sreg] == -1)
01880
01881
01882
01883 || (ureg >= FIRST_PSEUDO_REGISTER
01884 && find_reg_note (insn, REG_NO_CONFLICT, usedreg))
01885
01886
01887
01888 || ureg == sreg
01889
01890 || (ureg < FIRST_PSEUDO_REGISTER && sreg < FIRST_PSEUDO_REGISTER)
01891
01892
01893 || !MODES_TIEABLE_P (GET_MODE (usedreg), GET_MODE (setreg)))
01894 return 0;
01895
01896
01897
01898
01899
01900
01901
01902
01903 if (ureg < FIRST_PSEUDO_REGISTER)
01904 {
01905
01906
01907 if (reg_qty[sreg] == -2)
01908 reg_is_born (setreg, 2 * insn_number);
01909
01910 if (reg_qty[sreg] >= 0)
01911 {
01912 if (may_save_copy
01913 && ! TEST_HARD_REG_BIT (qty_phys_copy_sugg[reg_qty[sreg]], ureg))
01914 {
01915 SET_HARD_REG_BIT (qty_phys_copy_sugg[reg_qty[sreg]], ureg);
01916 qty_phys_num_copy_sugg[reg_qty[sreg]]++;
01917 }
01918 else if (! TEST_HARD_REG_BIT (qty_phys_sugg[reg_qty[sreg]], ureg))
01919 {
01920 SET_HARD_REG_BIT (qty_phys_sugg[reg_qty[sreg]], ureg);
01921 qty_phys_num_sugg[reg_qty[sreg]]++;
01922 }
01923 }
01924 return 0;
01925 }
01926
01927
01928
01929 if (sreg < FIRST_PSEUDO_REGISTER)
01930 {
01931 if (may_save_copy
01932 && ! TEST_HARD_REG_BIT (qty_phys_copy_sugg[reg_qty[ureg]], sreg))
01933 {
01934 SET_HARD_REG_BIT (qty_phys_copy_sugg[reg_qty[ureg]], sreg);
01935 qty_phys_num_copy_sugg[reg_qty[ureg]]++;
01936 }
01937 else if (! TEST_HARD_REG_BIT (qty_phys_sugg[reg_qty[ureg]], sreg))
01938 {
01939 SET_HARD_REG_BIT (qty_phys_sugg[reg_qty[ureg]], sreg);
01940 qty_phys_num_sugg[reg_qty[ureg]]++;
01941 }
01942 return 0;
01943 }
01944
01945
01946
01947
01948 if (reg_qty[sreg] >= -1
01949
01950
01951 || (current_function_has_nonlocal_label
01952 && ((REG_N_CALLS_CROSSED (ureg) > 0)
01953 != (REG_N_CALLS_CROSSED (sreg) > 0))))
01954 return 0;
01955
01956
01957
01958
01959
01960 if ((already_dead || find_regno_note (insn, REG_DEAD, ureg))
01961 && reg_meets_class_p (sreg, qty[reg_qty[ureg]].min_class))
01962 {
01963
01964 sqty = reg_qty[ureg];
01965 reg_qty[sreg] = sqty;
01966 reg_offset[sreg] = reg_offset[ureg] + offset;
01967 reg_next_in_qty[sreg] = qty[sqty].first_reg;
01968 qty[sqty].first_reg = sreg;
01969
01970
01971 update_qty_class (sqty, sreg);
01972
01973
01974 qty[sqty].n_calls_crossed += REG_N_CALLS_CROSSED (sreg);
01975 qty[sqty].n_refs += REG_N_REFS (sreg);
01976 qty[sqty].freq += REG_FREQ (sreg);
01977 if (usize < ssize)
01978 {
01979 int i;
01980
01981 for (i = qty[sqty].first_reg; i >= 0; i = reg_next_in_qty[i])
01982 reg_offset[i] -= offset;
01983
01984 qty[sqty].size = ssize;
01985 qty[sqty].mode = GET_MODE (setreg);
01986 }
01987 }
01988 else
01989 return 0;
01990
01991 return 1;
01992 }
01993
01994
01995
01996
01997
01998 static int
01999 reg_meets_class_p (reg, class)
02000 int reg;
02001 enum reg_class class;
02002 {
02003 enum reg_class rclass = reg_preferred_class (reg);
02004 return (reg_class_subset_p (rclass, class)
02005 || reg_class_subset_p (class, rclass));
02006 }
02007
02008
02009
02010 static void
02011 update_qty_class (qtyno, reg)
02012 int qtyno;
02013 int reg;
02014 {
02015 enum reg_class rclass = reg_preferred_class (reg);
02016 if (reg_class_subset_p (rclass, qty[qtyno].min_class))
02017 qty[qtyno].min_class = rclass;
02018
02019 rclass = reg_alternate_class (reg);
02020 if (reg_class_subset_p (rclass, qty[qtyno].alternate_class))
02021 qty[qtyno].alternate_class = rclass;
02022 }
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033 static void
02034 reg_is_set (reg, setter, data)
02035 rtx reg;
02036 rtx setter;
02037 void *data ATTRIBUTE_UNUSED;
02038 {
02039
02040
02041
02042 if (GET_CODE (reg) != SUBREG
02043 && GET_CODE (reg) != REG)
02044 return;
02045
02046
02047
02048
02049
02050 reg_is_born (reg, 2 * this_insn_number - (GET_CODE (setter) == CLOBBER));
02051 }
02052
02053
02054
02055
02056 static void
02057 reg_is_born (reg, birth)
02058 rtx reg;
02059 int birth;
02060 {
02061 int regno;
02062
02063 if (GET_CODE (reg) == SUBREG)
02064 {
02065 regno = REGNO (SUBREG_REG (reg));
02066 if (regno < FIRST_PSEUDO_REGISTER)
02067 regno = subreg_hard_regno (reg, 1);
02068 }
02069 else
02070 regno = REGNO (reg);
02071
02072 if (regno < FIRST_PSEUDO_REGISTER)
02073 {
02074 mark_life (regno, GET_MODE (reg), 1);
02075
02076
02077
02078 if (birth < 2 * this_insn_number)
02079 post_mark_life (regno, GET_MODE (reg), 1, birth, 2 * this_insn_number);
02080 }
02081 else
02082 {
02083 if (reg_qty[regno] == -2)
02084 alloc_qty (regno, GET_MODE (reg), PSEUDO_REGNO_SIZE (regno), birth);
02085
02086
02087 if (reg_qty[regno] >= 0)
02088 qty[reg_qty[regno]].death = -1;
02089 }
02090 }
02091
02092
02093
02094
02095
02096
02097 static void
02098 wipe_dead_reg (reg, output_p)
02099 rtx reg;
02100 int output_p;
02101 {
02102 int regno = REGNO (reg);
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115 if (GET_CODE (PATTERN (this_insn)) == PARALLEL
02116 && multiple_sets (this_insn))
02117 {
02118 int i;
02119 for (i = XVECLEN (PATTERN (this_insn), 0) - 1; i >= 0; i--)
02120 {
02121 rtx set = XVECEXP (PATTERN (this_insn), 0, i);
02122 if (GET_CODE (set) == SET
02123 && GET_CODE (SET_DEST (set)) != REG
02124 && !rtx_equal_p (reg, SET_DEST (set))
02125 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
02126 output_p = 1;
02127 }
02128 }
02129
02130
02131
02132
02133 if (! output_p && find_regno_note (this_insn, REG_INC, regno))
02134 output_p = 1;
02135
02136 if (regno < FIRST_PSEUDO_REGISTER)
02137 {
02138 mark_life (regno, GET_MODE (reg), 0);
02139
02140
02141
02142
02143 if (output_p)
02144 post_mark_life (regno, GET_MODE (reg), 1,
02145 2 * this_insn_number, 2 * this_insn_number + 1);
02146 }
02147
02148 else if (reg_qty[regno] >= 0)
02149 qty[reg_qty[regno]].death = 2 * this_insn_number + output_p;
02150 }
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164 static int
02165 find_free_reg (class, mode, qtyno, accept_call_clobbered, just_try_suggested,
02166 born_index, dead_index)
02167 enum reg_class class;
02168 enum machine_mode mode;
02169 int qtyno;
02170 int accept_call_clobbered;
02171 int just_try_suggested;
02172 int born_index, dead_index;
02173 {
02174 int i, ins;
02175 HARD_REG_SET first_used, used;
02176 #ifdef ELIMINABLE_REGS
02177 static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
02178 #endif
02179
02180
02181 if (born_index < 0 || born_index > dead_index)
02182 abort ();
02183
02184
02185
02186 if (current_function_has_nonlocal_label
02187 && qty[qtyno].n_calls_crossed > 0)
02188 return -1;
02189
02190 if (accept_call_clobbered)
02191 COPY_HARD_REG_SET (used, call_fixed_reg_set);
02192 else if (qty[qtyno].n_calls_crossed == 0)
02193 COPY_HARD_REG_SET (used, fixed_reg_set);
02194 else
02195 COPY_HARD_REG_SET (used, call_used_reg_set);
02196
02197 if (accept_call_clobbered)
02198 IOR_HARD_REG_SET (used, losing_caller_save_reg_set);
02199
02200 for (ins = born_index; ins < dead_index; ins++)
02201 IOR_HARD_REG_SET (used, regs_live_at[ins]);
02202
02203 IOR_COMPL_HARD_REG_SET (used, reg_class_contents[(int) class]);
02204
02205
02206
02207
02208
02209
02210
02211 #ifdef ELIMINABLE_REGS
02212 for (i = 0; i < (int) ARRAY_SIZE (eliminables); i++)
02213 SET_HARD_REG_BIT (used, eliminables[i].from);
02214 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
02215
02216
02217 SET_HARD_REG_BIT (used, HARD_FRAME_POINTER_REGNUM);
02218 #endif
02219 #else
02220 SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM);
02221 #endif
02222
02223 #ifdef CANNOT_CHANGE_MODE_CLASS
02224 cannot_change_mode_set_regs (&used, mode, qty[qtyno].first_reg);
02225 #endif
02226
02227
02228
02229
02230
02231
02232
02233 COPY_HARD_REG_SET (first_used, used);
02234
02235 if (just_try_suggested)
02236 {
02237 if (qty_phys_num_copy_sugg[qtyno] != 0)
02238 IOR_COMPL_HARD_REG_SET (first_used, qty_phys_copy_sugg[qtyno]);
02239 else
02240 IOR_COMPL_HARD_REG_SET (first_used, qty_phys_sugg[qtyno]);
02241 }
02242
02243
02244 GO_IF_HARD_REG_SUBSET (reg_class_contents[(int) ALL_REGS], first_used, fail);
02245
02246
02247
02248 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
02249 {
02250 #ifdef REG_ALLOC_ORDER
02251 int regno = reg_alloc_order[i];
02252 #else
02253 int regno = i;
02254 #endif
02255 if (! TEST_HARD_REG_BIT (first_used, regno)
02256 && HARD_REGNO_MODE_OK (regno, mode)
02257 && (qty[qtyno].n_calls_crossed == 0
02258 || accept_call_clobbered
02259 || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
02260 {
02261 int j;
02262 int size1 = HARD_REGNO_NREGS (regno, mode);
02263 for (j = 1; j < size1 && ! TEST_HARD_REG_BIT (used, regno + j); j++);
02264 if (j == size1)
02265 {
02266
02267
02268 post_mark_life (regno, mode, 1, born_index, dead_index);
02269 return regno;
02270 }
02271 #ifndef REG_ALLOC_ORDER
02272
02273 i += j;
02274 #endif
02275 }
02276 }
02277
02278 fail:
02279
02280
02281
02282
02283
02284
02285 if (just_try_suggested && qty_phys_num_copy_sugg[qtyno] != 0
02286 && qty_phys_num_sugg[qtyno] != 0)
02287 {
02288
02289 qty_phys_num_copy_sugg[qtyno] = 0;
02290 return find_free_reg (class, mode, qtyno, accept_call_clobbered, 1,
02291 born_index, dead_index);
02292 }
02293
02294
02295
02296
02297
02298 if (! accept_call_clobbered
02299 && flag_caller_saves
02300 && ! just_try_suggested
02301 && qty[qtyno].n_calls_crossed != 0
02302 && CALLER_SAVE_PROFITABLE (qty[qtyno].n_refs,
02303 qty[qtyno].n_calls_crossed))
02304 {
02305 i = find_free_reg (class, mode, qtyno, 1, 0, born_index, dead_index);
02306 if (i >= 0)
02307 caller_save_needed = 1;
02308 return i;
02309 }
02310 return -1;
02311 }
02312
02313
02314
02315
02316
02317 static void
02318 mark_life (regno, mode, life)
02319 int regno;
02320 enum machine_mode mode;
02321 int life;
02322 {
02323 int j = HARD_REGNO_NREGS (regno, mode);
02324 if (life)
02325 while (--j >= 0)
02326 SET_HARD_REG_BIT (regs_live, regno + j);
02327 else
02328 while (--j >= 0)
02329 CLEAR_HARD_REG_BIT (regs_live, regno + j);
02330 }
02331
02332
02333
02334
02335
02336 static void
02337 post_mark_life (regno, mode, life, birth, death)
02338 int regno;
02339 enum machine_mode mode;
02340 int life, birth, death;
02341 {
02342 int j = HARD_REGNO_NREGS (regno, mode);
02343 #ifdef HARD_REG_SET
02344
02345 register
02346 #endif
02347 HARD_REG_SET this_reg;
02348
02349 CLEAR_HARD_REG_SET (this_reg);
02350 while (--j >= 0)
02351 SET_HARD_REG_BIT (this_reg, regno + j);
02352
02353 if (life)
02354 while (birth < death)
02355 {
02356 IOR_HARD_REG_SET (regs_live_at[birth], this_reg);
02357 birth++;
02358 }
02359 else
02360 while (birth < death)
02361 {
02362 AND_COMPL_HARD_REG_SET (regs_live_at[birth], this_reg);
02363 birth++;
02364 }
02365 }
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376 static int
02377 no_conflict_p (insn, r0, r1)
02378 rtx insn, r0 ATTRIBUTE_UNUSED, r1;
02379 {
02380 int ok = 0;
02381 rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
02382 rtx p, last;
02383
02384
02385
02386
02387 if (note == 0
02388 || (GET_CODE (r1) == REG && REGNO (r1) < FIRST_PSEUDO_REGISTER)
02389 || (GET_CODE (r1) == SUBREG && GET_CODE (SUBREG_REG (r1)) == REG
02390 && REGNO (SUBREG_REG (r1)) < FIRST_PSEUDO_REGISTER))
02391 return 0;
02392
02393 last = XEXP (note, 0);
02394
02395 for (p = NEXT_INSN (insn); p && p != last; p = NEXT_INSN (p))
02396 if (INSN_P (p))
02397 {
02398 if (find_reg_note (p, REG_DEAD, r1))
02399 ok = 1;
02400
02401
02402
02403
02404
02405
02406 if (! find_reg_note (p, REG_NO_CONFLICT, r1))
02407 return 0;
02408 }
02409
02410 return ok;
02411 }
02412
02413
02414
02415
02416
02417 static int
02418 requires_inout (p)
02419 const char *p;
02420 {
02421 char c;
02422 int found_zero = 0;
02423 int reg_allowed = 0;
02424 int num_matching_alts = 0;
02425
02426 while ((c = *p++))
02427 switch (c)
02428 {
02429 case '=': case '+': case '?':
02430 case '#': case '&': case '!':
02431 case '*': case '%':
02432 case 'm': case '<': case '>': case 'V': case 'o':
02433 case 'E': case 'F': case 'G': case 'H':
02434 case 's': case 'i': case 'n':
02435 case 'I': case 'J': case 'K': case 'L':
02436 case 'M': case 'N': case 'O': case 'P':
02437 case 'X':
02438
02439 break;
02440
02441 case ',':
02442 if (found_zero && ! reg_allowed)
02443 num_matching_alts++;
02444
02445 found_zero = reg_allowed = 0;
02446 break;
02447
02448 case '0':
02449 found_zero = 1;
02450 break;
02451
02452 case '1': case '2': case '3': case '4': case '5':
02453 case '6': case '7': case '8': case '9':
02454
02455 while (ISDIGIT (*p))
02456 p++;
02457 break;
02458
02459 default:
02460 if (REG_CLASS_FROM_LETTER (c) == NO_REGS
02461 && !EXTRA_ADDRESS_CONSTRAINT (c))
02462 break;
02463
02464 case 'p':
02465 case 'g': case 'r':
02466 reg_allowed = 1;
02467 break;
02468 }
02469
02470 if (found_zero && ! reg_allowed)
02471 num_matching_alts++;
02472
02473 return num_matching_alts;
02474 }
02475
02476 void
02477 dump_local_alloc (file)
02478 FILE *file;
02479 {
02480 int i;
02481 for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
02482 if (reg_renumber[i] != -1)
02483 fprintf (file, ";; Register %d in %d.\n", i, reg_renumber[i]);
02484 }