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