00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024
00025 #include "rtl.h"
00026 #include "tm_p.h"
00027 #include "regs.h"
00028 #include "hard-reg-set.h"
00029 #include "flags.h"
00030 #include "real.h"
00031 #include "insn-config.h"
00032 #include "recog.h"
00033 #include "function.h"
00034 #include "expr.h"
00035 #include "toplev.h"
00036 #include "output.h"
00037 #include "ggc.h"
00038 #include "hashtab.h"
00039 #include "cselib.h"
00040
00041 static int entry_and_rtx_equal_p PARAMS ((const void *, const void *));
00042 static hashval_t get_value_hash PARAMS ((const void *));
00043 static struct elt_list *new_elt_list PARAMS ((struct elt_list *,
00044 cselib_val *));
00045 static struct elt_loc_list *new_elt_loc_list PARAMS ((struct elt_loc_list *,
00046 rtx));
00047 static void unchain_one_value PARAMS ((cselib_val *));
00048 static void unchain_one_elt_list PARAMS ((struct elt_list **));
00049 static void unchain_one_elt_loc_list PARAMS ((struct elt_loc_list **));
00050 static void clear_table PARAMS ((int));
00051 static int discard_useless_locs PARAMS ((void **, void *));
00052 static int discard_useless_values PARAMS ((void **, void *));
00053 static void remove_useless_values PARAMS ((void));
00054 static rtx wrap_constant PARAMS ((enum machine_mode, rtx));
00055 static unsigned int hash_rtx PARAMS ((rtx, enum machine_mode, int));
00056 static cselib_val *new_cselib_val PARAMS ((unsigned int,
00057 enum machine_mode));
00058 static void add_mem_for_addr PARAMS ((cselib_val *, cselib_val *,
00059 rtx));
00060 static cselib_val *cselib_lookup_mem PARAMS ((rtx, int));
00061 static void cselib_invalidate_regno PARAMS ((unsigned int,
00062 enum machine_mode));
00063 static int cselib_mem_conflict_p PARAMS ((rtx, rtx));
00064 static int cselib_invalidate_mem_1 PARAMS ((void **, void *));
00065 static void cselib_invalidate_mem PARAMS ((rtx));
00066 static void cselib_invalidate_rtx PARAMS ((rtx, rtx, void *));
00067 static void cselib_record_set PARAMS ((rtx, cselib_val *,
00068 cselib_val *));
00069 static void cselib_record_sets PARAMS ((rtx));
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 static GTY((param_is (cselib_val))) htab_t hash_table;
00082
00083
00084
00085 static rtx cselib_current_insn;
00086 static bool cselib_current_insn_in_libcall;
00087
00088
00089 static unsigned int next_unknown_value;
00090
00091
00092 static unsigned int cselib_nregs;
00093
00094
00095
00096 static int n_useless_values;
00097
00098
00099 #define MAX_USELESS_VALUES 32
00100
00101
00102
00103
00104 static GTY(()) varray_type reg_values;
00105 static GTY((deletable (""))) varray_type reg_values_old;
00106 #define REG_VALUES(I) VARRAY_ELT_LIST (reg_values, (I))
00107
00108
00109
00110 static unsigned int max_value_regs;
00111
00112
00113
00114 static GTY(()) varray_type used_regs;
00115 static GTY((deletable (""))) varray_type used_regs_old;
00116
00117
00118
00119 static GTY(()) rtx callmem;
00120
00121
00122 static GTY((deletable (""))) cselib_val *empty_vals;
00123 static GTY((deletable (""))) struct elt_list *empty_elt_lists;
00124 static GTY((deletable (""))) struct elt_loc_list *empty_elt_loc_lists;
00125
00126
00127
00128 static int values_became_useless;
00129
00130
00131
00132
00133
00134 static struct elt_list *
00135 new_elt_list (next, elt)
00136 struct elt_list *next;
00137 cselib_val *elt;
00138 {
00139 struct elt_list *el = empty_elt_lists;
00140
00141 if (el)
00142 empty_elt_lists = el->next;
00143 else
00144 el = (struct elt_list *) ggc_alloc (sizeof (struct elt_list));
00145 el->next = next;
00146 el->elt = elt;
00147 return el;
00148 }
00149
00150
00151
00152
00153 static struct elt_loc_list *
00154 new_elt_loc_list (next, loc)
00155 struct elt_loc_list *next;
00156 rtx loc;
00157 {
00158 struct elt_loc_list *el = empty_elt_loc_lists;
00159
00160 if (el)
00161 empty_elt_loc_lists = el->next;
00162 else
00163 el = (struct elt_loc_list *) ggc_alloc (sizeof (struct elt_loc_list));
00164 el->next = next;
00165 el->loc = loc;
00166 el->setting_insn = cselib_current_insn;
00167 el->in_libcall = cselib_current_insn_in_libcall;
00168 return el;
00169 }
00170
00171
00172
00173
00174 static void
00175 unchain_one_elt_list (pl)
00176 struct elt_list **pl;
00177 {
00178 struct elt_list *l = *pl;
00179
00180 *pl = l->next;
00181 l->next = empty_elt_lists;
00182 empty_elt_lists = l;
00183 }
00184
00185
00186
00187 static void
00188 unchain_one_elt_loc_list (pl)
00189 struct elt_loc_list **pl;
00190 {
00191 struct elt_loc_list *l = *pl;
00192
00193 *pl = l->next;
00194 l->next = empty_elt_loc_lists;
00195 empty_elt_loc_lists = l;
00196 }
00197
00198
00199
00200
00201 static void
00202 unchain_one_value (v)
00203 cselib_val *v;
00204 {
00205 while (v->addr_list)
00206 unchain_one_elt_list (&v->addr_list);
00207
00208 v->u.next_free = empty_vals;
00209 empty_vals = v;
00210 }
00211
00212
00213
00214
00215
00216 static void
00217 clear_table (clear_all)
00218 int clear_all;
00219 {
00220 unsigned int i;
00221
00222 if (clear_all)
00223 for (i = 0; i < cselib_nregs; i++)
00224 REG_VALUES (i) = 0;
00225 else
00226 for (i = 0; i < VARRAY_ACTIVE_SIZE (used_regs); i++)
00227 REG_VALUES (VARRAY_UINT (used_regs, i)) = 0;
00228
00229 max_value_regs = 0;
00230
00231 VARRAY_POP_ALL (used_regs);
00232
00233 htab_empty (hash_table);
00234
00235 n_useless_values = 0;
00236
00237 next_unknown_value = 0;
00238 }
00239
00240
00241
00242
00243
00244
00245 static int
00246 entry_and_rtx_equal_p (entry, x_arg)
00247 const void *entry, *x_arg;
00248 {
00249 struct elt_loc_list *l;
00250 const cselib_val *v = (const cselib_val *) entry;
00251 rtx x = (rtx) x_arg;
00252 enum machine_mode mode = GET_MODE (x);
00253
00254 if (GET_CODE (x) == CONST_INT
00255 || (mode == VOIDmode && GET_CODE (x) == CONST_DOUBLE))
00256 abort ();
00257 if (mode != GET_MODE (v->u.val_rtx))
00258 return 0;
00259
00260
00261 if (GET_CODE (x) == CONST
00262 && (GET_CODE (XEXP (x, 0)) == CONST_INT
00263 || GET_CODE (XEXP (x, 0)) == CONST_DOUBLE))
00264 x = XEXP (x, 0);
00265
00266
00267
00268 for (l = v->locs; l; l = l->next)
00269 if (rtx_equal_for_cselib_p (l->loc, x))
00270 return 1;
00271
00272 return 0;
00273 }
00274
00275
00276
00277
00278
00279 static hashval_t
00280 get_value_hash (entry)
00281 const void *entry;
00282 {
00283 const cselib_val *v = (const cselib_val *) entry;
00284 return v->value;
00285 }
00286
00287
00288
00289
00290
00291
00292 int
00293 references_value_p (x, only_useless)
00294 rtx x;
00295 int only_useless;
00296 {
00297 enum rtx_code code = GET_CODE (x);
00298 const char *fmt = GET_RTX_FORMAT (code);
00299 int i, j;
00300
00301 if (GET_CODE (x) == VALUE
00302 && (! only_useless || CSELIB_VAL_PTR (x)->locs == 0))
00303 return 1;
00304
00305 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00306 {
00307 if (fmt[i] == 'e' && references_value_p (XEXP (x, i), only_useless))
00308 return 1;
00309 else if (fmt[i] == 'E')
00310 for (j = 0; j < XVECLEN (x, i); j++)
00311 if (references_value_p (XVECEXP (x, i, j), only_useless))
00312 return 1;
00313 }
00314
00315 return 0;
00316 }
00317
00318
00319
00320
00321
00322 static int
00323 discard_useless_locs (x, info)
00324 void **x;
00325 void *info ATTRIBUTE_UNUSED;
00326 {
00327 cselib_val *v = (cselib_val *)*x;
00328 struct elt_loc_list **p = &v->locs;
00329 int had_locs = v->locs != 0;
00330
00331 while (*p)
00332 {
00333 if (references_value_p ((*p)->loc, 1))
00334 unchain_one_elt_loc_list (p);
00335 else
00336 p = &(*p)->next;
00337 }
00338
00339 if (had_locs && v->locs == 0)
00340 {
00341 n_useless_values++;
00342 values_became_useless = 1;
00343 }
00344 return 1;
00345 }
00346
00347
00348
00349 static int
00350 discard_useless_values (x, info)
00351 void **x;
00352 void *info ATTRIBUTE_UNUSED;
00353 {
00354 cselib_val *v = (cselib_val *)*x;
00355
00356 if (v->locs == 0)
00357 {
00358 htab_clear_slot (hash_table, x);
00359 unchain_one_value (v);
00360 n_useless_values--;
00361 }
00362
00363 return 1;
00364 }
00365
00366
00367
00368
00369 static void
00370 remove_useless_values ()
00371 {
00372
00373
00374 do
00375 {
00376 values_became_useless = 0;
00377 htab_traverse (hash_table, discard_useless_locs, 0);
00378 }
00379 while (values_became_useless);
00380
00381
00382 htab_traverse (hash_table, discard_useless_values, 0);
00383
00384 if (n_useless_values != 0)
00385 abort ();
00386 }
00387
00388
00389
00390
00391 int
00392 rtx_equal_for_cselib_p (x, y)
00393 rtx x, y;
00394 {
00395 enum rtx_code code;
00396 const char *fmt;
00397 int i;
00398
00399 if (GET_CODE (x) == REG || GET_CODE (x) == MEM)
00400 {
00401 cselib_val *e = cselib_lookup (x, GET_MODE (x), 0);
00402
00403 if (e)
00404 x = e->u.val_rtx;
00405 }
00406
00407 if (GET_CODE (y) == REG || GET_CODE (y) == MEM)
00408 {
00409 cselib_val *e = cselib_lookup (y, GET_MODE (y), 0);
00410
00411 if (e)
00412 y = e->u.val_rtx;
00413 }
00414
00415 if (x == y)
00416 return 1;
00417
00418 if (GET_CODE (x) == VALUE && GET_CODE (y) == VALUE)
00419 return CSELIB_VAL_PTR (x) == CSELIB_VAL_PTR (y);
00420
00421 if (GET_CODE (x) == VALUE)
00422 {
00423 cselib_val *e = CSELIB_VAL_PTR (x);
00424 struct elt_loc_list *l;
00425
00426 for (l = e->locs; l; l = l->next)
00427 {
00428 rtx t = l->loc;
00429
00430
00431 if (GET_CODE (t) == REG || GET_CODE (t) == MEM)
00432 continue;
00433 else if (rtx_equal_for_cselib_p (t, y))
00434 return 1;
00435 }
00436
00437 return 0;
00438 }
00439
00440 if (GET_CODE (y) == VALUE)
00441 {
00442 cselib_val *e = CSELIB_VAL_PTR (y);
00443 struct elt_loc_list *l;
00444
00445 for (l = e->locs; l; l = l->next)
00446 {
00447 rtx t = l->loc;
00448
00449 if (GET_CODE (t) == REG || GET_CODE (t) == MEM)
00450 continue;
00451 else if (rtx_equal_for_cselib_p (x, t))
00452 return 1;
00453 }
00454
00455 return 0;
00456 }
00457
00458 if (GET_CODE (x) != GET_CODE (y) || GET_MODE (x) != GET_MODE (y))
00459 return 0;
00460
00461
00462 if (GET_CODE (x) == LABEL_REF)
00463 return XEXP (x, 0) == XEXP (y, 0);
00464
00465 code = GET_CODE (x);
00466 fmt = GET_RTX_FORMAT (code);
00467
00468 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00469 {
00470 int j;
00471
00472 switch (fmt[i])
00473 {
00474 case 'w':
00475 if (XWINT (x, i) != XWINT (y, i))
00476 return 0;
00477 break;
00478
00479 case 'n':
00480 case 'i':
00481 if (XINT (x, i) != XINT (y, i))
00482 return 0;
00483 break;
00484
00485 case 'V':
00486 case 'E':
00487
00488 if (XVECLEN (x, i) != XVECLEN (y, i))
00489 return 0;
00490
00491
00492 for (j = 0; j < XVECLEN (x, i); j++)
00493 if (! rtx_equal_for_cselib_p (XVECEXP (x, i, j),
00494 XVECEXP (y, i, j)))
00495 return 0;
00496 break;
00497
00498 case 'e':
00499 if (! rtx_equal_for_cselib_p (XEXP (x, i), XEXP (y, i)))
00500 return 0;
00501 break;
00502
00503 case 'S':
00504 case 's':
00505 if (strcmp (XSTR (x, i), XSTR (y, i)))
00506 return 0;
00507 break;
00508
00509 case 'u':
00510
00511 break;
00512
00513 case '0':
00514 case 't':
00515 break;
00516
00517
00518
00519
00520 default:
00521 abort ();
00522 }
00523 }
00524 return 1;
00525 }
00526
00527
00528
00529
00530 static rtx
00531 wrap_constant (mode, x)
00532 enum machine_mode mode;
00533 rtx x;
00534 {
00535 if (GET_CODE (x) != CONST_INT
00536 && (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != VOIDmode))
00537 return x;
00538 if (mode == VOIDmode)
00539 abort ();
00540 return gen_rtx_CONST (mode, x);
00541 }
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 static unsigned int
00553 hash_rtx (x, mode, create)
00554 rtx x;
00555 enum machine_mode mode;
00556 int create;
00557 {
00558 cselib_val *e;
00559 int i, j;
00560 enum rtx_code code;
00561 const char *fmt;
00562 unsigned int hash = 0;
00563
00564 code = GET_CODE (x);
00565 hash += (unsigned) code + (unsigned) GET_MODE (x);
00566
00567 switch (code)
00568 {
00569 case MEM:
00570 case REG:
00571 e = cselib_lookup (x, GET_MODE (x), create);
00572 if (! e)
00573 return 0;
00574
00575 return e->value;
00576
00577 case CONST_INT:
00578 hash += ((unsigned) CONST_INT << 7) + (unsigned) mode + INTVAL (x);
00579 return hash ? hash : (unsigned int) CONST_INT;
00580
00581 case CONST_DOUBLE:
00582
00583
00584 hash += (unsigned) code + (unsigned) GET_MODE (x);
00585 if (GET_MODE (x) != VOIDmode)
00586 hash += real_hash (CONST_DOUBLE_REAL_VALUE (x));
00587 else
00588 hash += ((unsigned) CONST_DOUBLE_LOW (x)
00589 + (unsigned) CONST_DOUBLE_HIGH (x));
00590 return hash ? hash : (unsigned int) CONST_DOUBLE;
00591
00592 case CONST_VECTOR:
00593 {
00594 int units;
00595 rtx elt;
00596
00597 units = CONST_VECTOR_NUNITS (x);
00598
00599 for (i = 0; i < units; ++i)
00600 {
00601 elt = CONST_VECTOR_ELT (x, i);
00602 hash += hash_rtx (elt, GET_MODE (elt), 0);
00603 }
00604
00605 return hash;
00606 }
00607
00608
00609 case LABEL_REF:
00610 hash
00611 += ((unsigned) LABEL_REF << 7) + (unsigned long) XEXP (x, 0);
00612 return hash ? hash : (unsigned int) LABEL_REF;
00613
00614 case SYMBOL_REF:
00615 hash
00616 += ((unsigned) SYMBOL_REF << 7) + (unsigned long) XSTR (x, 0);
00617 return hash ? hash : (unsigned int) SYMBOL_REF;
00618
00619 case PRE_DEC:
00620 case PRE_INC:
00621 case POST_DEC:
00622 case POST_INC:
00623 case POST_MODIFY:
00624 case PRE_MODIFY:
00625 case PC:
00626 case CC0:
00627 case CALL:
00628 case UNSPEC_VOLATILE:
00629 return 0;
00630
00631 case ASM_OPERANDS:
00632 if (MEM_VOLATILE_P (x))
00633 return 0;
00634
00635 break;
00636
00637 default:
00638 break;
00639 }
00640
00641 i = GET_RTX_LENGTH (code) - 1;
00642 fmt = GET_RTX_FORMAT (code);
00643 for (; i >= 0; i--)
00644 {
00645 if (fmt[i] == 'e')
00646 {
00647 rtx tem = XEXP (x, i);
00648 unsigned int tem_hash = hash_rtx (tem, 0, create);
00649
00650 if (tem_hash == 0)
00651 return 0;
00652
00653 hash += tem_hash;
00654 }
00655 else if (fmt[i] == 'E')
00656 for (j = 0; j < XVECLEN (x, i); j++)
00657 {
00658 unsigned int tem_hash = hash_rtx (XVECEXP (x, i, j), 0, create);
00659
00660 if (tem_hash == 0)
00661 return 0;
00662
00663 hash += tem_hash;
00664 }
00665 else if (fmt[i] == 's')
00666 {
00667 const unsigned char *p = (const unsigned char *) XSTR (x, i);
00668
00669 if (p)
00670 while (*p)
00671 hash += *p++;
00672 }
00673 else if (fmt[i] == 'i')
00674 hash += XINT (x, i);
00675 else if (fmt[i] == '0' || fmt[i] == 't')
00676 ;
00677 else
00678 abort ();
00679 }
00680
00681 return hash ? hash : 1 + (unsigned int) GET_CODE (x);
00682 }
00683
00684
00685
00686
00687 static cselib_val *
00688 new_cselib_val (value, mode)
00689 unsigned int value;
00690 enum machine_mode mode;
00691 {
00692 cselib_val *e = empty_vals;
00693
00694 if (e)
00695 empty_vals = e->u.next_free;
00696 else
00697 e = (cselib_val *) ggc_alloc (sizeof (cselib_val));
00698
00699 if (value == 0)
00700 abort ();
00701
00702 e->value = value;
00703 e->u.val_rtx = gen_rtx_VALUE (mode);
00704 CSELIB_VAL_PTR (e->u.val_rtx) = e;
00705 e->addr_list = 0;
00706 e->locs = 0;
00707 return e;
00708 }
00709
00710
00711
00712
00713
00714 static void
00715 add_mem_for_addr (addr_elt, mem_elt, x)
00716 cselib_val *addr_elt, *mem_elt;
00717 rtx x;
00718 {
00719 struct elt_loc_list *l;
00720
00721
00722 for (l = mem_elt->locs; l; l = l->next)
00723 if (GET_CODE (l->loc) == MEM
00724 && CSELIB_VAL_PTR (XEXP (l->loc, 0)) == addr_elt)
00725 return;
00726
00727 addr_elt->addr_list = new_elt_list (addr_elt->addr_list, mem_elt);
00728 mem_elt->locs
00729 = new_elt_loc_list (mem_elt->locs,
00730 replace_equiv_address_nv (x, addr_elt->u.val_rtx));
00731 }
00732
00733
00734
00735
00736 static cselib_val *
00737 cselib_lookup_mem (x, create)
00738 rtx x;
00739 int create;
00740 {
00741 enum machine_mode mode = GET_MODE (x);
00742 void **slot;
00743 cselib_val *addr;
00744 cselib_val *mem_elt;
00745 struct elt_list *l;
00746
00747 if (MEM_VOLATILE_P (x) || mode == BLKmode
00748 || (FLOAT_MODE_P (mode) && flag_float_store))
00749 return 0;
00750
00751
00752 addr = cselib_lookup (XEXP (x, 0), mode, create);
00753 if (! addr)
00754 return 0;
00755
00756
00757 for (l = addr->addr_list; l; l = l->next)
00758 if (GET_MODE (l->elt->u.val_rtx) == mode)
00759 return l->elt;
00760
00761 if (! create)
00762 return 0;
00763
00764 mem_elt = new_cselib_val (++next_unknown_value, mode);
00765 add_mem_for_addr (addr, mem_elt, x);
00766 slot = htab_find_slot_with_hash (hash_table, wrap_constant (mode, x),
00767 mem_elt->value, INSERT);
00768 *slot = mem_elt;
00769 return mem_elt;
00770 }
00771
00772
00773
00774
00775
00776
00777
00778 rtx
00779 cselib_subst_to_values (x)
00780 rtx x;
00781 {
00782 enum rtx_code code = GET_CODE (x);
00783 const char *fmt = GET_RTX_FORMAT (code);
00784 cselib_val *e;
00785 struct elt_list *l;
00786 rtx copy = x;
00787 int i;
00788
00789 switch (code)
00790 {
00791 case REG:
00792 for (l = REG_VALUES (REGNO (x)); l; l = l->next)
00793 if (GET_MODE (l->elt->u.val_rtx) == GET_MODE (x))
00794 return l->elt->u.val_rtx;
00795
00796 abort ();
00797
00798 case MEM:
00799 e = cselib_lookup_mem (x, 0);
00800 if (! e)
00801 {
00802
00803
00804 e = new_cselib_val (++next_unknown_value, GET_MODE (x));
00805 }
00806 return e->u.val_rtx;
00807
00808 case CONST_DOUBLE:
00809 case CONST_VECTOR:
00810 case CONST_INT:
00811 return x;
00812
00813 case POST_INC:
00814 case PRE_INC:
00815 case POST_DEC:
00816 case PRE_DEC:
00817 case POST_MODIFY:
00818 case PRE_MODIFY:
00819 e = new_cselib_val (++next_unknown_value, GET_MODE (x));
00820 return e->u.val_rtx;
00821
00822 default:
00823 break;
00824 }
00825
00826 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00827 {
00828 if (fmt[i] == 'e')
00829 {
00830 rtx t = cselib_subst_to_values (XEXP (x, i));
00831
00832 if (t != XEXP (x, i) && x == copy)
00833 copy = shallow_copy_rtx (x);
00834
00835 XEXP (copy, i) = t;
00836 }
00837 else if (fmt[i] == 'E')
00838 {
00839 int j, k;
00840
00841 for (j = 0; j < XVECLEN (x, i); j++)
00842 {
00843 rtx t = cselib_subst_to_values (XVECEXP (x, i, j));
00844
00845 if (t != XVECEXP (x, i, j) && XVEC (x, i) == XVEC (copy, i))
00846 {
00847 if (x == copy)
00848 copy = shallow_copy_rtx (x);
00849
00850 XVEC (copy, i) = rtvec_alloc (XVECLEN (x, i));
00851 for (k = 0; k < j; k++)
00852 XVECEXP (copy, i, k) = XVECEXP (x, i, k);
00853 }
00854
00855 XVECEXP (copy, i, j) = t;
00856 }
00857 }
00858 }
00859
00860 return copy;
00861 }
00862
00863
00864
00865
00866
00867
00868 cselib_val *
00869 cselib_lookup (x, mode, create)
00870 rtx x;
00871 enum machine_mode mode;
00872 int create;
00873 {
00874 void **slot;
00875 cselib_val *e;
00876 unsigned int hashval;
00877
00878 if (GET_MODE (x) != VOIDmode)
00879 mode = GET_MODE (x);
00880
00881 if (GET_CODE (x) == VALUE)
00882 return CSELIB_VAL_PTR (x);
00883
00884 if (GET_CODE (x) == REG)
00885 {
00886 struct elt_list *l;
00887 unsigned int i = REGNO (x);
00888
00889 for (l = REG_VALUES (i); l; l = l->next)
00890 if (mode == GET_MODE (l->elt->u.val_rtx))
00891 return l->elt;
00892
00893 if (! create)
00894 return 0;
00895
00896 if (i < FIRST_PSEUDO_REGISTER)
00897 {
00898 unsigned int n = HARD_REGNO_NREGS (i, mode);
00899
00900 if (n > max_value_regs)
00901 max_value_regs = n;
00902 }
00903
00904 e = new_cselib_val (++next_unknown_value, GET_MODE (x));
00905 e->locs = new_elt_loc_list (e->locs, x);
00906 if (REG_VALUES (i) == 0)
00907 VARRAY_PUSH_UINT (used_regs, i);
00908 REG_VALUES (i) = new_elt_list (REG_VALUES (i), e);
00909 slot = htab_find_slot_with_hash (hash_table, x, e->value, INSERT);
00910 *slot = e;
00911 return e;
00912 }
00913
00914 if (GET_CODE (x) == MEM)
00915 return cselib_lookup_mem (x, create);
00916
00917 hashval = hash_rtx (x, mode, create);
00918
00919 if (! hashval)
00920 return 0;
00921
00922 slot = htab_find_slot_with_hash (hash_table, wrap_constant (mode, x),
00923 hashval, create ? INSERT : NO_INSERT);
00924 if (slot == 0)
00925 return 0;
00926
00927 e = (cselib_val *) *slot;
00928 if (e)
00929 return e;
00930
00931 e = new_cselib_val (hashval, mode);
00932
00933
00934
00935
00936 *slot = (void *) e;
00937 e->locs = new_elt_loc_list (e->locs, cselib_subst_to_values (x));
00938 return e;
00939 }
00940
00941
00942
00943
00944
00945
00946
00947 static void
00948 cselib_invalidate_regno (regno, mode)
00949 unsigned int regno;
00950 enum machine_mode mode;
00951 {
00952 unsigned int endregno;
00953 unsigned int i;
00954
00955
00956 if (reload_completed && regno >= FIRST_PSEUDO_REGISTER
00957 && reg_renumber[regno] >= 0)
00958 abort ();
00959
00960
00961
00962
00963
00964 if (regno < FIRST_PSEUDO_REGISTER)
00965 {
00966 if (mode == VOIDmode)
00967 abort ();
00968
00969 if (regno < max_value_regs)
00970 i = 0;
00971 else
00972 i = regno - max_value_regs;
00973
00974 endregno = regno + HARD_REGNO_NREGS (regno, mode);
00975 }
00976 else
00977 {
00978 i = regno;
00979 endregno = regno + 1;
00980 }
00981
00982 for (; i < endregno; i++)
00983 {
00984 struct elt_list **l = ®_VALUES (i);
00985
00986
00987
00988 while (*l)
00989 {
00990 cselib_val *v = (*l)->elt;
00991 struct elt_loc_list **p;
00992 unsigned int this_last = i;
00993
00994 if (i < FIRST_PSEUDO_REGISTER)
00995 this_last += HARD_REGNO_NREGS (i, GET_MODE (v->u.val_rtx)) - 1;
00996
00997 if (this_last < regno)
00998 {
00999 l = &(*l)->next;
01000 continue;
01001 }
01002
01003
01004 unchain_one_elt_list (l);
01005
01006
01007
01008 for (p = &v->locs; ; p = &(*p)->next)
01009 {
01010 rtx x = (*p)->loc;
01011
01012 if (GET_CODE (x) == REG && REGNO (x) == i)
01013 {
01014 unchain_one_elt_loc_list (p);
01015 break;
01016 }
01017 }
01018 if (v->locs == 0)
01019 n_useless_values++;
01020 }
01021 }
01022 }
01023
01024
01025
01026
01027 static int
01028 cselib_mem_conflict_p (mem_base, val)
01029 rtx mem_base;
01030 rtx val;
01031 {
01032 enum rtx_code code;
01033 const char *fmt;
01034 int i, j;
01035
01036 code = GET_CODE (val);
01037 switch (code)
01038 {
01039
01040 case REG:
01041 case PC:
01042 case CC0:
01043 case SCRATCH:
01044 case CONST:
01045 case CONST_INT:
01046 case CONST_DOUBLE:
01047 case CONST_VECTOR:
01048 case SYMBOL_REF:
01049 case LABEL_REF:
01050 return 0;
01051
01052 case MEM:
01053 if (GET_MODE (mem_base) == BLKmode
01054 || GET_MODE (val) == BLKmode
01055 || anti_dependence (val, mem_base))
01056 return 1;
01057
01058
01059 break;
01060
01061 default:
01062 break;
01063 }
01064
01065 fmt = GET_RTX_FORMAT (code);
01066 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
01067 {
01068 if (fmt[i] == 'e')
01069 {
01070 if (cselib_mem_conflict_p (mem_base, XEXP (val, i)))
01071 return 1;
01072 }
01073 else if (fmt[i] == 'E')
01074 for (j = 0; j < XVECLEN (val, i); j++)
01075 if (cselib_mem_conflict_p (mem_base, XVECEXP (val, i, j)))
01076 return 1;
01077 }
01078
01079 return 0;
01080 }
01081
01082
01083
01084
01085 static int
01086 cselib_invalidate_mem_1 (slot, info)
01087 void **slot;
01088 void *info;
01089 {
01090 cselib_val *v = (cselib_val *) *slot;
01091 rtx mem_rtx = (rtx) info;
01092 struct elt_loc_list **p = &v->locs;
01093 int had_locs = v->locs != 0;
01094
01095 while (*p)
01096 {
01097 rtx x = (*p)->loc;
01098 cselib_val *addr;
01099 struct elt_list **mem_chain;
01100
01101
01102
01103 if (GET_CODE (x) != MEM
01104 || ! cselib_mem_conflict_p (mem_rtx, x))
01105 {
01106 p = &(*p)->next;
01107 continue;
01108 }
01109
01110
01111
01112
01113 addr = cselib_lookup (XEXP (x, 0), VOIDmode, 0);
01114 mem_chain = &addr->addr_list;
01115 for (;;)
01116 {
01117 if ((*mem_chain)->elt == v)
01118 {
01119 unchain_one_elt_list (mem_chain);
01120 break;
01121 }
01122
01123 mem_chain = &(*mem_chain)->next;
01124 }
01125
01126 unchain_one_elt_loc_list (p);
01127 }
01128
01129 if (had_locs && v->locs == 0)
01130 n_useless_values++;
01131
01132 return 1;
01133 }
01134
01135
01136
01137
01138
01139 static void
01140 cselib_invalidate_mem (mem_rtx)
01141 rtx mem_rtx;
01142 {
01143 htab_traverse (hash_table, cselib_invalidate_mem_1, mem_rtx);
01144 }
01145
01146
01147
01148
01149
01150 static void
01151 cselib_invalidate_rtx (dest, ignore, data)
01152 rtx dest;
01153 rtx ignore ATTRIBUTE_UNUSED;
01154 void *data ATTRIBUTE_UNUSED;
01155 {
01156 while (GET_CODE (dest) == STRICT_LOW_PART || GET_CODE (dest) == SIGN_EXTRACT
01157 || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == SUBREG)
01158 dest = XEXP (dest, 0);
01159
01160 if (GET_CODE (dest) == REG)
01161 cselib_invalidate_regno (REGNO (dest), GET_MODE (dest));
01162 else if (GET_CODE (dest) == MEM)
01163 cselib_invalidate_mem (dest);
01164
01165
01166
01167
01168
01169 if (push_operand (dest, GET_MODE (dest)))
01170 cselib_invalidate_rtx (stack_pointer_rtx, NULL_RTX, NULL);
01171 }
01172
01173
01174
01175
01176
01177 static void
01178 cselib_record_set (dest, src_elt, dest_addr_elt)
01179 rtx dest;
01180 cselib_val *src_elt, *dest_addr_elt;
01181 {
01182 int dreg = GET_CODE (dest) == REG ? (int) REGNO (dest) : -1;
01183
01184 if (src_elt == 0 || side_effects_p (dest))
01185 return;
01186
01187 if (dreg >= 0)
01188 {
01189 if (REG_VALUES (dreg) == 0)
01190 VARRAY_PUSH_UINT (used_regs, dreg);
01191
01192 if (dreg < FIRST_PSEUDO_REGISTER)
01193 {
01194 unsigned int n = HARD_REGNO_NREGS (dreg, GET_MODE (dest));
01195
01196 if (n > max_value_regs)
01197 max_value_regs = n;
01198 }
01199
01200 REG_VALUES (dreg) = new_elt_list (REG_VALUES (dreg), src_elt);
01201 if (src_elt->locs == 0)
01202 n_useless_values--;
01203 src_elt->locs = new_elt_loc_list (src_elt->locs, dest);
01204 }
01205 else if (GET_CODE (dest) == MEM && dest_addr_elt != 0)
01206 {
01207 if (src_elt->locs == 0)
01208 n_useless_values--;
01209 add_mem_for_addr (dest_addr_elt, src_elt, dest);
01210 }
01211 }
01212
01213
01214 struct set
01215 {
01216 rtx src;
01217 rtx dest;
01218 cselib_val *src_elt;
01219 cselib_val *dest_addr_elt;
01220 };
01221
01222
01223
01224 #define MAX_SETS (FIRST_PSEUDO_REGISTER * 2)
01225
01226
01227 static void
01228 cselib_record_sets (insn)
01229 rtx insn;
01230 {
01231 int n_sets = 0;
01232 int i;
01233 struct set sets[MAX_SETS];
01234 rtx body = PATTERN (insn);
01235 rtx cond = 0;
01236
01237 body = PATTERN (insn);
01238 if (GET_CODE (body) == COND_EXEC)
01239 {
01240 cond = COND_EXEC_TEST (body);
01241 body = COND_EXEC_CODE (body);
01242 }
01243
01244
01245 if (GET_CODE (body) == SET)
01246 {
01247 sets[0].src = SET_SRC (body);
01248 sets[0].dest = SET_DEST (body);
01249 n_sets = 1;
01250 }
01251 else if (GET_CODE (body) == PARALLEL)
01252 {
01253
01254
01255 for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
01256 {
01257 rtx x = XVECEXP (body, 0, i);
01258
01259 if (GET_CODE (x) == SET)
01260 {
01261 sets[n_sets].src = SET_SRC (x);
01262 sets[n_sets].dest = SET_DEST (x);
01263 n_sets++;
01264 }
01265 }
01266 }
01267
01268
01269
01270 for (i = 0; i < n_sets; i++)
01271 {
01272 rtx dest = sets[i].dest;
01273
01274
01275
01276 if (GET_CODE (sets[i].dest) == STRICT_LOW_PART)
01277 sets[i].dest = dest = XEXP (dest, 0);
01278
01279
01280 if (GET_CODE (dest) == REG || GET_CODE (dest) == MEM)
01281 {
01282 rtx src = sets[i].src;
01283 if (cond)
01284 src = gen_rtx_IF_THEN_ELSE (GET_MODE (src), cond, src, dest);
01285 sets[i].src_elt = cselib_lookup (src, GET_MODE (dest), 1);
01286 if (GET_CODE (dest) == MEM)
01287 sets[i].dest_addr_elt = cselib_lookup (XEXP (dest, 0), Pmode, 1);
01288 else
01289 sets[i].dest_addr_elt = 0;
01290 }
01291 }
01292
01293
01294
01295
01296 note_stores (body, cselib_invalidate_rtx, NULL);
01297
01298
01299 for (i = 0; i < n_sets; i++)
01300 {
01301 rtx dest = sets[i].dest;
01302 if (GET_CODE (dest) == REG || GET_CODE (dest) == MEM)
01303 cselib_record_set (dest, sets[i].src_elt, sets[i].dest_addr_elt);
01304 }
01305 }
01306
01307
01308
01309 void
01310 cselib_process_insn (insn)
01311 rtx insn;
01312 {
01313 int i;
01314 rtx x;
01315
01316 if (find_reg_note (insn, REG_LIBCALL, NULL))
01317 cselib_current_insn_in_libcall = true;
01318 if (find_reg_note (insn, REG_RETVAL, NULL))
01319 cselib_current_insn_in_libcall = false;
01320 cselib_current_insn = insn;
01321
01322
01323 if (GET_CODE (insn) == CODE_LABEL
01324 || (GET_CODE (insn) == CALL_INSN
01325 && find_reg_note (insn, REG_SETJMP, NULL))
01326 || (GET_CODE (insn) == INSN
01327 && GET_CODE (PATTERN (insn)) == ASM_OPERANDS
01328 && MEM_VOLATILE_P (PATTERN (insn))))
01329 {
01330 clear_table (0);
01331 return;
01332 }
01333
01334 if (! INSN_P (insn))
01335 {
01336 cselib_current_insn = 0;
01337 return;
01338 }
01339
01340
01341
01342
01343 if (GET_CODE (insn) == CALL_INSN)
01344 {
01345 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01346 if (call_used_regs[i])
01347 cselib_invalidate_regno (i, reg_raw_mode[i]);
01348
01349 if (! CONST_OR_PURE_CALL_P (insn))
01350 cselib_invalidate_mem (callmem);
01351 }
01352
01353 cselib_record_sets (insn);
01354
01355 #ifdef AUTO_INC_DEC
01356
01357
01358
01359 for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
01360 if (REG_NOTE_KIND (x) == REG_INC)
01361 cselib_invalidate_rtx (XEXP (x, 0), NULL_RTX, NULL);
01362 #endif
01363
01364
01365
01366 if (GET_CODE (insn) == CALL_INSN)
01367 for (x = CALL_INSN_FUNCTION_USAGE (insn); x; x = XEXP (x, 1))
01368 if (GET_CODE (XEXP (x, 0)) == CLOBBER)
01369 cselib_invalidate_rtx (XEXP (XEXP (x, 0), 0), NULL_RTX, NULL);
01370
01371 cselib_current_insn = 0;
01372
01373 if (n_useless_values > MAX_USELESS_VALUES)
01374 remove_useless_values ();
01375 }
01376
01377
01378
01379
01380 void
01381 cselib_update_varray_sizes ()
01382 {
01383 unsigned int nregs = max_reg_num ();
01384
01385 if (nregs == cselib_nregs)
01386 return;
01387
01388 cselib_nregs = nregs;
01389 VARRAY_GROW (reg_values, nregs);
01390 VARRAY_GROW (used_regs, nregs);
01391 }
01392
01393
01394
01395
01396 void
01397 cselib_init ()
01398 {
01399
01400 if (! callmem)
01401 callmem = gen_rtx_MEM (BLKmode, const0_rtx);
01402
01403 cselib_nregs = max_reg_num ();
01404 if (reg_values_old != NULL && VARRAY_SIZE (reg_values_old) >= cselib_nregs)
01405 {
01406 reg_values = reg_values_old;
01407 used_regs = used_regs_old;
01408 VARRAY_CLEAR (reg_values);
01409 VARRAY_CLEAR (used_regs);
01410 }
01411 else
01412 {
01413 VARRAY_ELT_LIST_INIT (reg_values, cselib_nregs, "reg_values");
01414 VARRAY_UINT_INIT (used_regs, cselib_nregs, "used_regs");
01415 }
01416 hash_table = htab_create_ggc (31, get_value_hash, entry_and_rtx_equal_p,
01417 NULL);
01418 clear_table (1);
01419 cselib_current_insn_in_libcall = false;
01420 }
01421
01422
01423
01424 void
01425 cselib_finish ()
01426 {
01427 reg_values_old = reg_values;
01428 reg_values = 0;
01429 used_regs_old = used_regs;
01430 used_regs = 0;
01431 hash_table = 0;
01432 n_useless_values = 0;
01433 next_unknown_value = 0;
01434 }
01435
01436 #include "gt-cselib.h"