From 38a898c637382a0aee991ab84f5719a2f0a72a35 Mon Sep 17 00:00:00 2001 From: aoliva Date: Thu, 17 Apr 2003 01:07:12 +0000 Subject: [PATCH] * reload1.c (reload_cse_noop_set_p): Return false if mode of SET_DEST is not the same as that returned by... * cselib.h (cselib_reg_set_mode): ... new function. * cselib.c (cselib_reg_set_mode): Define it. (REG_VALUES): Document semantics of first element as set mode. (cselib_subst_to_values): Skip first element if ELT is NULL. (cselib_lookup): Likewise. Insert past the first element. (cselib_invalidate_regno): NULLify first element. (cselib_record_set): Set first element. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@65713 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 12 +++++++++ gcc/cselib.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++----------- gcc/cselib.h | 3 ++- gcc/reload1.c | 3 +++ 4 files changed, 88 insertions(+), 16 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 19fdf5af8fc..a34da4061a7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2003-04-16 Alexandre Oliva + + * reload1.c (reload_cse_noop_set_p): Return false if mode of + SET_DEST is not the same as that returned by... + * cselib.h (cselib_reg_set_mode): ... new function. + * cselib.c (cselib_reg_set_mode): Define it. + (REG_VALUES): Document semantics of first element as set mode. + (cselib_subst_to_values): Skip first element if ELT is NULL. + (cselib_lookup): Likewise. Insert past the first element. + (cselib_invalidate_regno): NULLify first element. + (cselib_record_set): Set first element. + 2003-04-16 Olivier Hainque * tree.c (skip_simple_arithmetics_at, saved_expr_p): New functions. diff --git a/gcc/cselib.c b/gcc/cselib.c index 3aac058df27..cf3394f237a 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -1,6 +1,6 @@ /* Common subexpression elimination library for GNU compiler. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001 Free Software Foundation, Inc. + 1999, 2000, 2001, 2003 Free Software Foundation, Inc. This file is part of GCC. @@ -99,9 +99,13 @@ static int n_useless_values; /* Number of useless values before we remove them from the hash table. */ #define MAX_USELESS_VALUES 32 -/* This table maps from register number to values. It does not contain - pointers to cselib_val structures, but rather elt_lists. The purpose is - to be able to refer to the same register in different modes. */ +/* This table maps from register number to values. It does not + contain pointers to cselib_val structures, but rather elt_lists. + The purpose is to be able to refer to the same register in + different modes. The first element of the list defines the mode in + which the register was set; if the mode is unknown or the value is + no longer valid in that mode, ELT will be NULL for the first + element. */ static GTY(()) varray_type reg_values; static GTY((deletable (""))) varray_type reg_values_old; #define REG_VALUES(I) VARRAY_ELT_LIST (reg_values, (I)) @@ -402,6 +406,25 @@ remove_useless_values () abort (); } +/* Return the mode in which a register was last set. If X is not a + register, return its mode. If the mode in which the register was + set is not known, or the value was already clobbered, return + VOIDmode. */ + +enum machine_mode +cselib_reg_set_mode (x) + rtx x; +{ + if (GET_CODE (x) != REG) + return GET_MODE (x); + + if (REG_VALUES (REGNO (x)) == NULL + || REG_VALUES (REGNO (x))->elt == NULL) + return VOIDmode; + + return GET_MODE (REG_VALUES (REGNO (x))->elt->u.val_rtx); +} + /* Return nonzero if we can prove that X and Y contain the same value, taking our gathered information into account. */ @@ -812,7 +835,10 @@ cselib_subst_to_values (x) switch (code) { case REG: - for (l = REG_VALUES (REGNO (x)); l; l = l->next) + l = REG_VALUES (REGNO (x)); + if (l && l->elt == NULL) + l = l->next; + for (; l; l = l->next) if (GET_MODE (l->elt->u.val_rtx) == GET_MODE (x)) return l->elt->u.val_rtx; @@ -909,7 +935,10 @@ cselib_lookup (x, mode, create) struct elt_list *l; unsigned int i = REGNO (x); - for (l = REG_VALUES (i); l; l = l->next) + l = REG_VALUES (i); + if (l && l->elt == NULL) + l = l->next; + for (; l; l = l->next) if (mode == GET_MODE (l->elt->u.val_rtx)) return l->elt; @@ -927,8 +956,14 @@ cselib_lookup (x, mode, create) e = new_cselib_val (++next_unknown_value, GET_MODE (x)); e->locs = new_elt_loc_list (e->locs, x); if (REG_VALUES (i) == 0) - VARRAY_PUSH_UINT (used_regs, i); - REG_VALUES (i) = new_elt_list (REG_VALUES (i), e); + { + /* Maintain the invariant that the first entry of + REG_VALUES, if present, must be the value used to set the + register, or NULL. */ + VARRAY_PUSH_UINT (used_regs, i); + REG_VALUES (i) = new_elt_list (REG_VALUES (i), NULL); + } + REG_VALUES (i)->next = new_elt_list (REG_VALUES (i)->next, e); slot = htab_find_slot_with_hash (hash_table, x, e->value, INSERT); *slot = e; return e; @@ -1011,17 +1046,28 @@ cselib_invalidate_regno (regno, mode) struct elt_loc_list **p; unsigned int this_last = i; - if (i < FIRST_PSEUDO_REGISTER) + if (i < FIRST_PSEUDO_REGISTER && v != NULL) this_last += HARD_REGNO_NREGS (i, GET_MODE (v->u.val_rtx)) - 1; - if (this_last < regno) + if (this_last < regno || v == NULL) { l = &(*l)->next; continue; } /* We have an overlap. */ - unchain_one_elt_list (l); + if (*l == REG_VALUES (i)) + { + /* Maintain the invariant that the first entry of + REG_VALUES, if present, must be the value used to set + the register, or NULL. This is also nice because + then we won't push the same regno onto user_regs + multiple times. */ + (*l)->elt = NULL; + l = &(*l)->next; + } + else + unchain_one_elt_list (l); /* Now, we clear the mapping from value to reg. It must exist, so this code will crash intentionally if it doesn't. */ @@ -1213,9 +1259,6 @@ cselib_record_set (dest, src_elt, dest_addr_elt) if (dreg >= 0) { - if (REG_VALUES (dreg) == 0) - VARRAY_PUSH_UINT (used_regs, dreg); - if (dreg < FIRST_PSEUDO_REGISTER) { unsigned int n = HARD_REGNO_NREGS (dreg, GET_MODE (dest)); @@ -1224,7 +1267,20 @@ cselib_record_set (dest, src_elt, dest_addr_elt) max_value_regs = n; } - REG_VALUES (dreg) = new_elt_list (REG_VALUES (dreg), src_elt); + if (REG_VALUES (dreg) == 0) + { + VARRAY_PUSH_UINT (used_regs, dreg); + REG_VALUES (dreg) = new_elt_list (REG_VALUES (dreg), src_elt); + } + else + { + if (REG_VALUES (dreg)->elt == 0) + REG_VALUES (dreg)->elt = src_elt; + else + /* The register should have been invalidated. */ + abort (); + } + if (src_elt->locs == 0) n_useless_values--; src_elt->locs = new_elt_loc_list (src_elt->locs, dest); diff --git a/gcc/cselib.h b/gcc/cselib.h index 9cceddbfcbc..073384d85ab 100644 --- a/gcc/cselib.h +++ b/gcc/cselib.h @@ -1,6 +1,6 @@ /* Common subexpression elimination for GNU compiler. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999 Free Software Foundation, Inc. + 1999, 2003 Free Software Foundation, Inc. This file is part of GCC. @@ -67,6 +67,7 @@ extern void cselib_update_varray_sizes PARAMS ((void)); extern void cselib_init PARAMS ((void)); extern void cselib_finish PARAMS ((void)); extern void cselib_process_insn PARAMS ((rtx)); +extern enum machine_mode cselib_reg_set_mode PARAMS ((rtx)); extern int rtx_equal_for_cselib_p PARAMS ((rtx, rtx)); extern int references_value_p PARAMS ((rtx, int)); extern rtx cselib_subst_to_values PARAMS ((rtx)); diff --git a/gcc/reload1.c b/gcc/reload1.c index a6e41ddeae2..54d163ee00c 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -8025,6 +8025,9 @@ static int reload_cse_noop_set_p (set) rtx set; { + if (cselib_reg_set_mode (SET_DEST (set)) != GET_MODE (SET_DEST (set))) + return 0; + return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set)); } -- 2.11.0