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 #include "target.h"
00045
00046 static bool cselib_record_memory;
00047 static int entry_and_rtx_equal_p (const void *, const void *);
00048 static hashval_t get_value_hash (const void *);
00049 static struct elt_list *new_elt_list (struct elt_list *, cselib_val *);
00050 static struct elt_loc_list *new_elt_loc_list (struct elt_loc_list *, rtx);
00051 static void unchain_one_value (cselib_val *);
00052 static void unchain_one_elt_list (struct elt_list **);
00053 static void unchain_one_elt_loc_list (struct elt_loc_list **);
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, 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 cselib_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 static struct elt_list **reg_values;
00105 static 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 void
00204 cselib_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 (cselib_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 (cselib_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 (cselib_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 (cselib_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 switch (GET_CODE (x))
00467 {
00468 case CONST_DOUBLE:
00469 return 0;
00470
00471 case LABEL_REF:
00472 return XEXP (x, 0) == XEXP (y, 0);
00473
00474 default:
00475 break;
00476 }
00477
00478 code = GET_CODE (x);
00479 fmt = GET_RTX_FORMAT (code);
00480
00481 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00482 {
00483 int j;
00484
00485 switch (fmt[i])
00486 {
00487 case 'w':
00488 if (XWINT (x, i) != XWINT (y, i))
00489 return 0;
00490 break;
00491
00492 case 'n':
00493 case 'i':
00494 if (XINT (x, i) != XINT (y, i))
00495 return 0;
00496 break;
00497
00498 case 'V':
00499 case 'E':
00500
00501 if (XVECLEN (x, i) != XVECLEN (y, i))
00502 return 0;
00503
00504
00505 for (j = 0; j < XVECLEN (x, i); j++)
00506 if (! rtx_equal_for_cselib_p (XVECEXP (x, i, j),
00507 XVECEXP (y, i, j)))
00508 return 0;
00509 break;
00510
00511 case 'e':
00512 if (i == 1
00513 && targetm.commutative_p (x, UNKNOWN)
00514 && rtx_equal_for_cselib_p (XEXP (x, 1), XEXP (y, 0))
00515 && rtx_equal_for_cselib_p (XEXP (x, 0), XEXP (y, 1)))
00516 return 1;
00517 if (! rtx_equal_for_cselib_p (XEXP (x, i), XEXP (y, i)))
00518 return 0;
00519 break;
00520
00521 case 'S':
00522 case 's':
00523 if (strcmp (XSTR (x, i), XSTR (y, i)))
00524 return 0;
00525 break;
00526
00527 case 'u':
00528
00529 break;
00530
00531 case '0':
00532 case 't':
00533 break;
00534
00535
00536
00537
00538 default:
00539 gcc_unreachable ();
00540 }
00541 }
00542 return 1;
00543 }
00544
00545
00546
00547
00548 static rtx
00549 wrap_constant (enum machine_mode mode, rtx x)
00550 {
00551 if (GET_CODE (x) != CONST_INT
00552 && (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != VOIDmode))
00553 return x;
00554 gcc_assert (mode != VOIDmode);
00555 return gen_rtx_CONST (mode, x);
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 static unsigned int
00579 cselib_hash_rtx (rtx x, int create)
00580 {
00581 cselib_val *e;
00582 int i, j;
00583 enum rtx_code code;
00584 const char *fmt;
00585 unsigned int hash = 0;
00586
00587 code = GET_CODE (x);
00588 hash += (unsigned) code + (unsigned) GET_MODE (x);
00589
00590 switch (code)
00591 {
00592 case MEM:
00593 case REG:
00594 e = cselib_lookup (x, GET_MODE (x), create);
00595 if (! e)
00596 return 0;
00597
00598 return e->value;
00599
00600 case CONST_INT:
00601 hash += ((unsigned) CONST_INT << 7) + INTVAL (x);
00602 return hash ? hash : (unsigned int) CONST_INT;
00603
00604 case CONST_DOUBLE:
00605
00606
00607 hash += (unsigned) code + (unsigned) GET_MODE (x);
00608 if (GET_MODE (x) != VOIDmode)
00609 hash += real_hash (CONST_DOUBLE_REAL_VALUE (x));
00610 else
00611 hash += ((unsigned) CONST_DOUBLE_LOW (x)
00612 + (unsigned) CONST_DOUBLE_HIGH (x));
00613 return hash ? hash : (unsigned int) CONST_DOUBLE;
00614
00615 case CONST_VECTOR:
00616 {
00617 int units;
00618 rtx elt;
00619
00620 units = CONST_VECTOR_NUNITS (x);
00621
00622 for (i = 0; i < units; ++i)
00623 {
00624 elt = CONST_VECTOR_ELT (x, i);
00625 hash += cselib_hash_rtx (elt, 0);
00626 }
00627
00628 return hash;
00629 }
00630
00631
00632 case LABEL_REF:
00633
00634
00635 hash += (((unsigned int) LABEL_REF << 7)
00636 + CODE_LABEL_NUMBER (XEXP (x, 0)));
00637 return hash ? hash : (unsigned int) LABEL_REF;
00638
00639 case SYMBOL_REF:
00640 {
00641
00642
00643
00644
00645
00646 unsigned int h = 0;
00647 const unsigned char *p = (const unsigned char *) XSTR (x, 0);
00648
00649 while (*p)
00650 h += (h << 7) + *p++;
00651
00652 hash += ((unsigned int) SYMBOL_REF << 7) + h;
00653 return hash ? hash : (unsigned int) SYMBOL_REF;
00654 }
00655
00656 case PRE_DEC:
00657 case PRE_INC:
00658 case POST_DEC:
00659 case POST_INC:
00660 case POST_MODIFY:
00661 case PRE_MODIFY:
00662 case PC:
00663 case CC0:
00664 case CALL:
00665 case UNSPEC_VOLATILE:
00666 return 0;
00667
00668 case ASM_OPERANDS:
00669 if (MEM_VOLATILE_P (x))
00670 return 0;
00671
00672 break;
00673
00674 default:
00675 break;
00676 }
00677
00678 i = GET_RTX_LENGTH (code) - 1;
00679 fmt = GET_RTX_FORMAT (code);
00680 for (; i >= 0; i--)
00681 {
00682 switch (fmt[i])
00683 {
00684 case 'e':
00685 {
00686 rtx tem = XEXP (x, i);
00687 unsigned int tem_hash = cselib_hash_rtx (tem, create);
00688
00689 if (tem_hash == 0)
00690 return 0;
00691
00692 hash += tem_hash;
00693 }
00694 break;
00695 case 'E':
00696 for (j = 0; j < XVECLEN (x, i); j++)
00697 {
00698 unsigned int tem_hash
00699 = cselib_hash_rtx (XVECEXP (x, i, j), create);
00700
00701 if (tem_hash == 0)
00702 return 0;
00703
00704 hash += tem_hash;
00705 }
00706 break;
00707
00708 case 's':
00709 {
00710 const unsigned char *p = (const unsigned char *) XSTR (x, i);
00711
00712 if (p)
00713 while (*p)
00714 hash += *p++;
00715 break;
00716 }
00717
00718 case 'i':
00719 hash += XINT (x, i);
00720 break;
00721
00722 case '0':
00723 case 't':
00724
00725 break;
00726
00727 default:
00728 gcc_unreachable ();
00729 }
00730 }
00731
00732 return hash ? hash : 1 + (unsigned int) GET_CODE (x);
00733 }
00734
00735
00736
00737
00738 static inline cselib_val *
00739 new_cselib_val (unsigned int value, enum machine_mode mode)
00740 {
00741 cselib_val *e = pool_alloc (cselib_val_pool);
00742
00743 gcc_assert (value);
00744
00745 e->value = value;
00746
00747
00748
00749
00750
00751 e->u.val_rtx = pool_alloc (value_pool);
00752 memset (e->u.val_rtx, 0, RTX_HDR_SIZE);
00753 PUT_CODE (e->u.val_rtx, VALUE);
00754 PUT_MODE (e->u.val_rtx, mode);
00755 CSELIB_VAL_PTR (e->u.val_rtx) = e;
00756 e->addr_list = 0;
00757 e->locs = 0;
00758 e->next_containing_mem = 0;
00759 return e;
00760 }
00761
00762
00763
00764
00765
00766 static void
00767 add_mem_for_addr (cselib_val *addr_elt, cselib_val *mem_elt, rtx x)
00768 {
00769 struct elt_loc_list *l;
00770
00771
00772 for (l = mem_elt->locs; l; l = l->next)
00773 if (MEM_P (l->loc)
00774 && CSELIB_VAL_PTR (XEXP (l->loc, 0)) == addr_elt)
00775 return;
00776
00777 addr_elt->addr_list = new_elt_list (addr_elt->addr_list, mem_elt);
00778 mem_elt->locs
00779 = new_elt_loc_list (mem_elt->locs,
00780 replace_equiv_address_nv (x, addr_elt->u.val_rtx));
00781 if (mem_elt->next_containing_mem == NULL)
00782 {
00783 mem_elt->next_containing_mem = first_containing_mem;
00784 first_containing_mem = mem_elt;
00785 }
00786 }
00787
00788
00789
00790
00791 static cselib_val *
00792 cselib_lookup_mem (rtx x, int create)
00793 {
00794 enum machine_mode mode = GET_MODE (x);
00795 void **slot;
00796 cselib_val *addr;
00797 cselib_val *mem_elt;
00798 struct elt_list *l;
00799
00800 if (MEM_VOLATILE_P (x) || mode == BLKmode
00801 || !cselib_record_memory
00802 || (FLOAT_MODE_P (mode) && flag_float_store))
00803 return 0;
00804
00805
00806 addr = cselib_lookup (XEXP (x, 0), mode, create);
00807 if (! addr)
00808 return 0;
00809
00810
00811 for (l = addr->addr_list; l; l = l->next)
00812 if (GET_MODE (l->elt->u.val_rtx) == mode)
00813 return l->elt;
00814
00815 if (! create)
00816 return 0;
00817
00818 mem_elt = new_cselib_val (++next_unknown_value, mode);
00819 add_mem_for_addr (addr, mem_elt, x);
00820 slot = htab_find_slot_with_hash (cselib_hash_table, wrap_constant (mode, x),
00821 mem_elt->value, INSERT);
00822 *slot = mem_elt;
00823 return mem_elt;
00824 }
00825
00826
00827
00828
00829
00830
00831
00832 rtx
00833 cselib_subst_to_values (rtx x)
00834 {
00835 enum rtx_code code = GET_CODE (x);
00836 const char *fmt = GET_RTX_FORMAT (code);
00837 cselib_val *e;
00838 struct elt_list *l;
00839 rtx copy = x;
00840 int i;
00841
00842 switch (code)
00843 {
00844 case REG:
00845 l = REG_VALUES (REGNO (x));
00846 if (l && l->elt == NULL)
00847 l = l->next;
00848 for (; l; l = l->next)
00849 if (GET_MODE (l->elt->u.val_rtx) == GET_MODE (x))
00850 return l->elt->u.val_rtx;
00851
00852 gcc_unreachable ();
00853
00854 case MEM:
00855 e = cselib_lookup_mem (x, 0);
00856 if (! e)
00857 {
00858
00859
00860 e = new_cselib_val (++next_unknown_value, GET_MODE (x));
00861 }
00862 return e->u.val_rtx;
00863
00864 case CONST_DOUBLE:
00865 case CONST_VECTOR:
00866 case CONST_INT:
00867 return x;
00868
00869 case POST_INC:
00870 case PRE_INC:
00871 case POST_DEC:
00872 case PRE_DEC:
00873 case POST_MODIFY:
00874 case PRE_MODIFY:
00875 e = new_cselib_val (++next_unknown_value, GET_MODE (x));
00876 return e->u.val_rtx;
00877
00878 default:
00879 break;
00880 }
00881
00882 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00883 {
00884 if (fmt[i] == 'e')
00885 {
00886 rtx t = cselib_subst_to_values (XEXP (x, i));
00887
00888 if (t != XEXP (x, i) && x == copy)
00889 copy = shallow_copy_rtx (x);
00890
00891 XEXP (copy, i) = t;
00892 }
00893 else if (fmt[i] == 'E')
00894 {
00895 int j, k;
00896
00897 for (j = 0; j < XVECLEN (x, i); j++)
00898 {
00899 rtx t = cselib_subst_to_values (XVECEXP (x, i, j));
00900
00901 if (t != XVECEXP (x, i, j) && XVEC (x, i) == XVEC (copy, i))
00902 {
00903 if (x == copy)
00904 copy = shallow_copy_rtx (x);
00905
00906 XVEC (copy, i) = rtvec_alloc (XVECLEN (x, i));
00907 for (k = 0; k < j; k++)
00908 XVECEXP (copy, i, k) = XVECEXP (x, i, k);
00909 }
00910
00911 XVECEXP (copy, i, j) = t;
00912 }
00913 }
00914 }
00915
00916 return copy;
00917 }
00918
00919
00920
00921
00922
00923
00924 cselib_val *
00925 cselib_lookup (rtx x, enum machine_mode mode, int create)
00926 {
00927 void **slot;
00928 cselib_val *e;
00929 unsigned int hashval;
00930
00931 if (GET_MODE (x) != VOIDmode)
00932 mode = GET_MODE (x);
00933
00934 if (GET_CODE (x) == VALUE)
00935 return CSELIB_VAL_PTR (x);
00936
00937 if (REG_P (x))
00938 {
00939 struct elt_list *l;
00940 unsigned int i = REGNO (x);
00941
00942 l = REG_VALUES (i);
00943 if (l && l->elt == NULL)
00944 l = l->next;
00945 for (; l; l = l->next)
00946 if (mode == GET_MODE (l->elt->u.val_rtx))
00947 return l->elt;
00948
00949 if (! create)
00950 return 0;
00951
00952 if (i < FIRST_PSEUDO_REGISTER)
00953 {
00954 unsigned int n = hard_regno_nregs[i][mode];
00955
00956 if (n > max_value_regs)
00957 max_value_regs = n;
00958 }
00959
00960 e = new_cselib_val (++next_unknown_value, GET_MODE (x));
00961 e->locs = new_elt_loc_list (e->locs, x);
00962 if (REG_VALUES (i) == 0)
00963 {
00964
00965
00966
00967 used_regs[n_used_regs++] = i;
00968 REG_VALUES (i) = new_elt_list (REG_VALUES (i), NULL);
00969 }
00970 REG_VALUES (i)->next = new_elt_list (REG_VALUES (i)->next, e);
00971 slot = htab_find_slot_with_hash (cselib_hash_table, x, e->value, INSERT);
00972 *slot = e;
00973 return e;
00974 }
00975
00976 if (MEM_P (x))
00977 return cselib_lookup_mem (x, create);
00978
00979 hashval = cselib_hash_rtx (x, create);
00980
00981 if (! hashval)
00982 return 0;
00983
00984 slot = htab_find_slot_with_hash (cselib_hash_table, wrap_constant (mode, x),
00985 hashval, create ? INSERT : NO_INSERT);
00986 if (slot == 0)
00987 return 0;
00988
00989 e = (cselib_val *) *slot;
00990 if (e)
00991 return e;
00992
00993 e = new_cselib_val (hashval, mode);
00994
00995
00996
00997
00998 *slot = (void *) e;
00999 e->locs = new_elt_loc_list (e->locs, cselib_subst_to_values (x));
01000 return e;
01001 }
01002
01003
01004
01005
01006
01007
01008
01009 static void
01010 cselib_invalidate_regno (unsigned int regno, enum machine_mode mode)
01011 {
01012 unsigned int endregno;
01013 unsigned int i;
01014
01015
01016 gcc_assert (!reload_completed || regno < FIRST_PSEUDO_REGISTER
01017 || reg_renumber[regno] < 0);
01018
01019
01020
01021
01022
01023 if (regno < FIRST_PSEUDO_REGISTER)
01024 {
01025 gcc_assert (mode != VOIDmode);
01026
01027 if (regno < max_value_regs)
01028 i = 0;
01029 else
01030 i = regno - max_value_regs;
01031
01032 endregno = regno + hard_regno_nregs[regno][mode];
01033 }
01034 else
01035 {
01036 i = regno;
01037 endregno = regno + 1;
01038 }
01039
01040 for (; i < endregno; i++)
01041 {
01042 struct elt_list **l = ®_VALUES (i);
01043
01044
01045
01046 while (*l)
01047 {
01048 cselib_val *v = (*l)->elt;
01049 struct elt_loc_list **p;
01050 unsigned int this_last = i;
01051
01052 if (i < FIRST_PSEUDO_REGISTER && v != NULL)
01053 this_last += hard_regno_nregs[i][GET_MODE (v->u.val_rtx)] - 1;
01054
01055 if (this_last < regno || v == NULL)
01056 {
01057 l = &(*l)->next;
01058 continue;
01059 }
01060
01061
01062 if (*l == REG_VALUES (i))
01063 {
01064
01065
01066
01067
01068
01069 (*l)->elt = NULL;
01070 l = &(*l)->next;
01071 }
01072 else
01073 unchain_one_elt_list (l);
01074
01075
01076
01077 for (p = &v->locs; ; p = &(*p)->next)
01078 {
01079 rtx x = (*p)->loc;
01080
01081 if (REG_P (x) && REGNO (x) == i)
01082 {
01083 unchain_one_elt_loc_list (p);
01084 break;
01085 }
01086 }
01087 if (v->locs == 0)
01088 n_useless_values++;
01089 }
01090 }
01091 }
01092
01093
01094
01095
01096
01097 static int
01098 cselib_rtx_varies_p (rtx x ATTRIBUTE_UNUSED, int from_alias ATTRIBUTE_UNUSED)
01099 {
01100
01101
01102
01103
01104 return 0;
01105 }
01106
01107
01108
01109
01110
01111 static void
01112 cselib_invalidate_mem (rtx mem_rtx)
01113 {
01114 cselib_val **vp, *v, *next;
01115 int num_mems = 0;
01116 rtx mem_addr;
01117
01118 mem_addr = canon_rtx (get_addr (XEXP (mem_rtx, 0)));
01119 mem_rtx = canon_rtx (mem_rtx);
01120
01121 vp = &first_containing_mem;
01122 for (v = *vp; v != &dummy_val; v = next)
01123 {
01124 bool has_mem = false;
01125 struct elt_loc_list **p = &v->locs;
01126 int had_locs = v->locs != 0;
01127
01128 while (*p)
01129 {
01130 rtx x = (*p)->loc;
01131 cselib_val *addr;
01132 struct elt_list **mem_chain;
01133
01134
01135
01136 if (!MEM_P (x))
01137 {
01138 p = &(*p)->next;
01139 continue;
01140 }
01141 if (num_mems < PARAM_VALUE (PARAM_MAX_CSELIB_MEMORY_LOCATIONS)
01142 && ! canon_true_dependence (mem_rtx, GET_MODE (mem_rtx), mem_addr,
01143 x, cselib_rtx_varies_p))
01144 {
01145 has_mem = true;
01146 num_mems++;
01147 p = &(*p)->next;
01148 continue;
01149 }
01150
01151
01152
01153
01154 addr = cselib_lookup (XEXP (x, 0), VOIDmode, 0);
01155 mem_chain = &addr->addr_list;
01156 for (;;)
01157 {
01158 if ((*mem_chain)->elt == v)
01159 {
01160 unchain_one_elt_list (mem_chain);
01161 break;
01162 }
01163
01164 mem_chain = &(*mem_chain)->next;
01165 }
01166
01167 unchain_one_elt_loc_list (p);
01168 }
01169
01170 if (had_locs && v->locs == 0)
01171 n_useless_values++;
01172
01173 next = v->next_containing_mem;
01174 if (has_mem)
01175 {
01176 *vp = v;
01177 vp = &(*vp)->next_containing_mem;
01178 }
01179 else
01180 v->next_containing_mem = NULL;
01181 }
01182 *vp = &dummy_val;
01183 }
01184
01185
01186
01187 void
01188 cselib_invalidate_rtx (rtx dest)
01189 {
01190 while (GET_CODE (dest) == SUBREG
01191 || GET_CODE (dest) == ZERO_EXTRACT
01192 || GET_CODE (dest) == STRICT_LOW_PART)
01193 dest = XEXP (dest, 0);
01194
01195 if (REG_P (dest))
01196 cselib_invalidate_regno (REGNO (dest), GET_MODE (dest));
01197 else if (MEM_P (dest))
01198 cselib_invalidate_mem (dest);
01199
01200
01201
01202
01203
01204 if (push_operand (dest, GET_MODE (dest)))
01205 cselib_invalidate_rtx (stack_pointer_rtx);
01206 }
01207
01208
01209
01210 static void
01211 cselib_invalidate_rtx_note_stores (rtx dest, rtx ignore ATTRIBUTE_UNUSED,
01212 void *data ATTRIBUTE_UNUSED)
01213 {
01214 cselib_invalidate_rtx (dest);
01215 }
01216
01217
01218
01219
01220
01221 static void
01222 cselib_record_set (rtx dest, cselib_val *src_elt, cselib_val *dest_addr_elt)
01223 {
01224 int dreg = REG_P (dest) ? (int) REGNO (dest) : -1;
01225
01226 if (src_elt == 0 || side_effects_p (dest))
01227 return;
01228
01229 if (dreg >= 0)
01230 {
01231 if (dreg < FIRST_PSEUDO_REGISTER)
01232 {
01233 unsigned int n = hard_regno_nregs[dreg][GET_MODE (dest)];
01234
01235 if (n > max_value_regs)
01236 max_value_regs = n;
01237 }
01238
01239 if (REG_VALUES (dreg) == 0)
01240 {
01241 used_regs[n_used_regs++] = dreg;
01242 REG_VALUES (dreg) = new_elt_list (REG_VALUES (dreg), src_elt);
01243 }
01244 else
01245 {
01246
01247 gcc_assert (REG_VALUES (dreg)->elt == 0);
01248 REG_VALUES (dreg)->elt = src_elt;
01249 }
01250
01251 if (src_elt->locs == 0)
01252 n_useless_values--;
01253 src_elt->locs = new_elt_loc_list (src_elt->locs, dest);
01254 }
01255 else if (MEM_P (dest) && dest_addr_elt != 0
01256 && cselib_record_memory)
01257 {
01258 if (src_elt->locs == 0)
01259 n_useless_values--;
01260 add_mem_for_addr (dest_addr_elt, src_elt, dest);
01261 }
01262 }
01263
01264
01265 struct set
01266 {
01267 rtx src;
01268 rtx dest;
01269 cselib_val *src_elt;
01270 cselib_val *dest_addr_elt;
01271 };
01272
01273
01274
01275 #define MAX_SETS (FIRST_PSEUDO_REGISTER * 2)
01276
01277
01278 static void
01279 cselib_record_sets (rtx insn)
01280 {
01281 int n_sets = 0;
01282 int i;
01283 struct set sets[MAX_SETS];
01284 rtx body = PATTERN (insn);
01285 rtx cond = 0;
01286
01287 body = PATTERN (insn);
01288 if (GET_CODE (body) == COND_EXEC)
01289 {
01290 cond = COND_EXEC_TEST (body);
01291 body = COND_EXEC_CODE (body);
01292 }
01293
01294
01295 if (GET_CODE (body) == SET)
01296 {
01297 sets[0].src = SET_SRC (body);
01298 sets[0].dest = SET_DEST (body);
01299 n_sets = 1;
01300 }
01301 else if (GET_CODE (body) == PARALLEL)
01302 {
01303
01304
01305 for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
01306 {
01307 rtx x = XVECEXP (body, 0, i);
01308
01309 if (GET_CODE (x) == SET)
01310 {
01311 sets[n_sets].src = SET_SRC (x);
01312 sets[n_sets].dest = SET_DEST (x);
01313 n_sets++;
01314 }
01315 }
01316 }
01317
01318
01319
01320 for (i = 0; i < n_sets; i++)
01321 {
01322 rtx dest = sets[i].dest;
01323
01324
01325
01326 if (GET_CODE (sets[i].dest) == STRICT_LOW_PART)
01327 sets[i].dest = dest = XEXP (dest, 0);
01328
01329
01330 if (REG_P (dest)
01331 || (MEM_P (dest) && cselib_record_memory))
01332 {
01333 rtx src = sets[i].src;
01334 if (cond)
01335 src = gen_rtx_IF_THEN_ELSE (GET_MODE (src), cond, src, dest);
01336 sets[i].src_elt = cselib_lookup (src, GET_MODE (dest), 1);
01337 if (MEM_P (dest))
01338 sets[i].dest_addr_elt = cselib_lookup (XEXP (dest, 0), Pmode, 1);
01339 else
01340 sets[i].dest_addr_elt = 0;
01341 }
01342 }
01343
01344
01345
01346
01347 note_stores (body, cselib_invalidate_rtx_note_stores, NULL);
01348
01349
01350
01351
01352
01353
01354 if (n_sets >= 2 && asm_noperands (body) >= 0)
01355 {
01356 for (i = 0; i < n_sets; i++)
01357 {
01358 rtx dest = sets[i].dest;
01359 if (REG_P (dest) || MEM_P (dest))
01360 {
01361 int j;
01362 for (j = i + 1; j < n_sets; j++)
01363 if (rtx_equal_p (dest, sets[j].dest))
01364 {
01365 sets[i].dest = pc_rtx;
01366 sets[j].dest = pc_rtx;
01367 }
01368 }
01369 }
01370 }
01371
01372
01373 for (i = 0; i < n_sets; i++)
01374 {
01375 rtx dest = sets[i].dest;
01376 if (REG_P (dest)
01377 || (MEM_P (dest) && cselib_record_memory))
01378 cselib_record_set (dest, sets[i].src_elt, sets[i].dest_addr_elt);
01379 }
01380 }
01381
01382
01383
01384 void
01385 cselib_process_insn (rtx insn)
01386 {
01387 int i;
01388 rtx x;
01389
01390 if (find_reg_note (insn, REG_LIBCALL, NULL))
01391 cselib_current_insn_in_libcall = true;
01392 cselib_current_insn = insn;
01393
01394
01395 if (LABEL_P (insn)
01396 || (CALL_P (insn)
01397 && find_reg_note (insn, REG_SETJMP, NULL))
01398 || (NONJUMP_INSN_P (insn)
01399 && GET_CODE (PATTERN (insn)) == ASM_OPERANDS
01400 && MEM_VOLATILE_P (PATTERN (insn))))
01401 {
01402 if (find_reg_note (insn, REG_RETVAL, NULL))
01403 cselib_current_insn_in_libcall = false;
01404 cselib_clear_table ();
01405 return;
01406 }
01407
01408 if (! INSN_P (insn))
01409 {
01410 if (find_reg_note (insn, REG_RETVAL, NULL))
01411 cselib_current_insn_in_libcall = false;
01412 cselib_current_insn = 0;
01413 return;
01414 }
01415
01416
01417
01418
01419 if (CALL_P (insn))
01420 {
01421 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01422 if (call_used_regs[i]
01423 || (REG_VALUES (i) && REG_VALUES (i)->elt
01424 && HARD_REGNO_CALL_PART_CLOBBERED (i,
01425 GET_MODE (REG_VALUES (i)->elt->u.val_rtx))))
01426 cselib_invalidate_regno (i, reg_raw_mode[i]);
01427
01428 if (! CONST_OR_PURE_CALL_P (insn))
01429 cselib_invalidate_mem (callmem);
01430 }
01431
01432 cselib_record_sets (insn);
01433
01434 #ifdef AUTO_INC_DEC
01435
01436
01437
01438 for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
01439 if (REG_NOTE_KIND (x) == REG_INC)
01440 cselib_invalidate_rtx (XEXP (x, 0));
01441 #endif
01442
01443
01444
01445 if (CALL_P (insn))
01446 for (x = CALL_INSN_FUNCTION_USAGE (insn); x; x = XEXP (x, 1))
01447 if (GET_CODE (XEXP (x, 0)) == CLOBBER)
01448 cselib_invalidate_rtx (XEXP (XEXP (x, 0), 0));
01449
01450 if (find_reg_note (insn, REG_RETVAL, NULL))
01451 cselib_current_insn_in_libcall = false;
01452 cselib_current_insn = 0;
01453
01454 if (n_useless_values > MAX_USELESS_VALUES
01455
01456
01457
01458 && (unsigned int)n_useless_values > cselib_hash_table->n_elements / 4)
01459 remove_useless_values ();
01460 }
01461
01462
01463
01464
01465 void
01466 cselib_init (bool record_memory)
01467 {
01468 elt_list_pool = create_alloc_pool ("elt_list",
01469 sizeof (struct elt_list), 10);
01470 elt_loc_list_pool = create_alloc_pool ("elt_loc_list",
01471 sizeof (struct elt_loc_list), 10);
01472 cselib_val_pool = create_alloc_pool ("cselib_val_list",
01473 sizeof (cselib_val), 10);
01474 value_pool = create_alloc_pool ("value", RTX_CODE_SIZE (VALUE), 100);
01475 cselib_record_memory = record_memory;
01476
01477 if (! callmem)
01478 callmem = gen_rtx_MEM (BLKmode, const0_rtx);
01479
01480 cselib_nregs = max_reg_num ();
01481
01482
01483
01484 if (!reg_values || reg_values_size < cselib_nregs
01485 || (reg_values_size > 10 && reg_values_size > cselib_nregs * 4))
01486 {
01487 if (reg_values)
01488 free (reg_values);
01489
01490
01491 reg_values_size = cselib_nregs + (63 + cselib_nregs) / 16;
01492 reg_values = XCNEWVEC (struct elt_list *, reg_values_size);
01493 }
01494 used_regs = XNEWVEC (unsigned int, cselib_nregs);
01495 n_used_regs = 0;
01496 cselib_hash_table = htab_create (31, get_value_hash,
01497 entry_and_rtx_equal_p, NULL);
01498 cselib_current_insn_in_libcall = false;
01499 }
01500
01501
01502
01503 void
01504 cselib_finish (void)
01505 {
01506 free_alloc_pool (elt_list_pool);
01507 free_alloc_pool (elt_loc_list_pool);
01508 free_alloc_pool (cselib_val_pool);
01509 free_alloc_pool (value_pool);
01510 cselib_clear_table ();
01511 htab_delete (cselib_hash_table);
01512 free (used_regs);
01513 used_regs = 0;
01514 cselib_hash_table = 0;
01515 n_useless_values = 0;
01516 next_unknown_value = 0;
01517 }
01518
01519 #include "gt-cselib.h"