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