X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcselib.c;h=56f2b7f9ffe3a2c0edc2e1dcfd15450b424181b0;hb=97f190cd6b8b78295b9d73b2e0e6279e48e7773d;hp=456c8750b63df8d0aceb469a853027bf40a991f5;hpb=0e508b4940b78e4db0284ba08178287dcf27aa92;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cselib.c b/gcc/cselib.c index 456c8750b63..56f2b7f9ffe 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -52,6 +52,7 @@ struct elt_list { static bool cselib_record_memory; static bool cselib_preserve_constants; +static bool cselib_any_perm_equivs; static int entry_and_rtx_equal_p (const void *, const void *); static hashval_t get_value_hash (const void *); static struct elt_list *new_elt_list (struct elt_list *, cselib_val *); @@ -383,22 +384,29 @@ cselib_clear_table (void) cselib_reset_table (1); } -/* Remove from hash table all VALUEs except constants - and function invariants. */ +/* Return TRUE if V is a constant, a function invariant or a VALUE + equivalence; FALSE otherwise. */ -static int -preserve_only_constants (void **x, void *info ATTRIBUTE_UNUSED) +static bool +invariant_or_equiv_p (cselib_val *v) { - cselib_val *v = (cselib_val *)*x; struct elt_loc_list *l; + if (v == cfa_base_preserved_val) + return true; + + /* Keep VALUE equivalences around. */ + for (l = v->locs; l; l = l->next) + if (GET_CODE (l->loc) == VALUE) + return true; + if (v->locs != NULL && v->locs->next == NULL) { if (CONSTANT_P (v->locs->loc) && (GET_CODE (v->locs->loc) != CONST || !references_value_p (v->locs->loc, 0))) - return 1; + return true; /* Although a debug expr may be bound to different expressions, we can preserve it as if it was constant, to get unification and proper merging within var-tracking. */ @@ -406,24 +414,29 @@ preserve_only_constants (void **x, void *info ATTRIBUTE_UNUSED) || GET_CODE (v->locs->loc) == DEBUG_IMPLICIT_PTR || GET_CODE (v->locs->loc) == ENTRY_VALUE || GET_CODE (v->locs->loc) == DEBUG_PARAMETER_REF) - return 1; - if (cfa_base_preserved_val) - { - if (v == cfa_base_preserved_val) - return 1; - if (GET_CODE (v->locs->loc) == PLUS - && CONST_INT_P (XEXP (v->locs->loc, 1)) - && XEXP (v->locs->loc, 0) == cfa_base_preserved_val->val_rtx) - return 1; - } + return true; + + /* (plus (value V) (const_int C)) is invariant iff V is invariant. */ + if (GET_CODE (v->locs->loc) == PLUS + && CONST_INT_P (XEXP (v->locs->loc, 1)) + && GET_CODE (XEXP (v->locs->loc, 0)) == VALUE + && invariant_or_equiv_p (CSELIB_VAL_PTR (XEXP (v->locs->loc, 0)))) + return true; } - /* Keep VALUE equivalences around. */ - for (l = v->locs; l; l = l->next) - if (GET_CODE (l->loc) == VALUE) - return 1; + return false; +} + +/* Remove from hash table all VALUEs except constants, function + invariants and VALUE equivalences. */ + +static int +preserve_constants_and_equivs (void **x, void *info ATTRIBUTE_UNUSED) +{ + cselib_val *v = (cselib_val *)*x; - htab_clear_slot (cselib_hash_table, x); + if (!invariant_or_equiv_p (v)) + htab_clear_slot (cselib_hash_table, x); return 1; } @@ -463,9 +476,12 @@ cselib_reset_table (unsigned int num) } if (cselib_preserve_constants) - htab_traverse (cselib_hash_table, preserve_only_constants, NULL); + htab_traverse (cselib_hash_table, preserve_constants_and_equivs, NULL); else - htab_empty (cselib_hash_table); + { + htab_empty (cselib_hash_table); + gcc_checking_assert (!cselib_any_perm_equivs); + } n_useless_values = 0; n_useless_debug_values = 0; @@ -1372,8 +1388,18 @@ expand_loc (struct elt_loc_list *p, struct expand_value_data *evd, unsigned int regno = UINT_MAX; struct elt_loc_list *p_in = p; - for (; p; p = p -> next) + for (; p; p = p->next) { + /* Return these right away to avoid returning stack pointer based + expressions for frame pointer and vice versa, which is something + that would confuse DSE. See the comment in cselib_expand_value_rtx_1 + for more details. */ + if (REG_P (p->loc) + && (REGNO (p->loc) == STACK_POINTER_REGNUM + || REGNO (p->loc) == FRAME_POINTER_REGNUM + || REGNO (p->loc) == HARD_FRAME_POINTER_REGNUM + || REGNO (p->loc) == cfa_base_preserved_regno)) + return p->loc; /* Avoid infinite recursion trying to expand a reg into a the same reg. */ if ((REG_P (p->loc)) @@ -1895,6 +1921,19 @@ cselib_subst_to_values (rtx x, enum machine_mode memmode) return copy; } +/* Wrapper for cselib_subst_to_values, that indicates X is in INSN. */ + +rtx +cselib_subst_to_values_from_insn (rtx x, enum machine_mode memmode, rtx insn) +{ + rtx ret; + gcc_assert (!cselib_current_insn); + cselib_current_insn = insn; + ret = cselib_subst_to_values (x, memmode); + cselib_current_insn = NULL; + return ret; +} + /* Look up the rtl expression X in our tables and return the value it has. If CREATE is zero, we return NULL if we don't know the value. Otherwise, we create a new one if possible, using mode MODE if X @@ -2353,6 +2392,8 @@ cselib_add_permanent_equiv (cselib_val *elt, rtx x, rtx insn) if (nelt != elt) { + cselib_any_perm_equivs = true; + if (!PRESERVED_VALUE_P (nelt->val_rtx)) cselib_preserve_value (nelt); @@ -2362,6 +2403,14 @@ cselib_add_permanent_equiv (cselib_val *elt, rtx x, rtx insn) cselib_current_insn = save_cselib_current_insn; } +/* Return TRUE if any permanent equivalences have been recorded since + the table was last initialized. */ +bool +cselib_have_permanent_equivalences (void) +{ + return cselib_any_perm_equivs; +} + /* There is no good way to determine how many elements there can be in a PARALLEL. Since it's fairly cheap, use a really large number. */ #define MAX_SETS (FIRST_PSEUDO_REGISTER * 2) @@ -2616,6 +2665,7 @@ cselib_init (int record_what) value_pool = create_alloc_pool ("value", RTX_CODE_SIZE (VALUE), 100); cselib_record_memory = record_what & CSELIB_RECORD_MEMORY; cselib_preserve_constants = record_what & CSELIB_PRESERVE_CONSTANTS; + cselib_any_perm_equivs = false; /* (mem:BLK (scratch)) is a special mechanism to conflict with everything, see canon_true_dependence. This is only created once. */ @@ -2649,6 +2699,7 @@ cselib_finish (void) { cselib_discard_hook = NULL; cselib_preserve_constants = false; + cselib_any_perm_equivs = false; cfa_base_preserved_val = NULL; cfa_base_preserved_regno = INVALID_REGNUM; free_alloc_pool (elt_list_pool);