Commit 60fa6660 by Alexandre Oliva Committed by Alexandre Oliva

reload1.c (reload_cse_noop_set_p): Return false if mode of SET_DEST is not the…

reload1.c (reload_cse_noop_set_p): Return false if mode of SET_DEST is not the same as that returned by...

* 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.

From-SVN: r65713
parent e34d367d
2003-04-16 Alexandre Oliva <aoliva@redhat.com>
* 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 <hainque@act-europe.fr> 2003-04-16 Olivier Hainque <hainque@act-europe.fr>
* tree.c (skip_simple_arithmetics_at, saved_expr_p): New functions. * tree.c (skip_simple_arithmetics_at, saved_expr_p): New functions.
......
/* Common subexpression elimination library for GNU compiler. /* Common subexpression elimination library for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 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. This file is part of GCC.
...@@ -99,9 +99,13 @@ static int n_useless_values; ...@@ -99,9 +99,13 @@ static int n_useless_values;
/* Number of useless values before we remove them from the hash table. */ /* Number of useless values before we remove them from the hash table. */
#define MAX_USELESS_VALUES 32 #define MAX_USELESS_VALUES 32
/* This table maps from register number to values. It does not contain /* This table maps from register number to values. It does not
pointers to cselib_val structures, but rather elt_lists. The purpose is contain pointers to cselib_val structures, but rather elt_lists.
to be able to refer to the same register in different modes. */ 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(()) varray_type reg_values;
static GTY((deletable (""))) varray_type reg_values_old; static GTY((deletable (""))) varray_type reg_values_old;
#define REG_VALUES(I) VARRAY_ELT_LIST (reg_values, (I)) #define REG_VALUES(I) VARRAY_ELT_LIST (reg_values, (I))
...@@ -402,6 +406,25 @@ remove_useless_values () ...@@ -402,6 +406,25 @@ remove_useless_values ()
abort (); 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 /* Return nonzero if we can prove that X and Y contain the same value, taking
our gathered information into account. */ our gathered information into account. */
...@@ -812,7 +835,10 @@ cselib_subst_to_values (x) ...@@ -812,7 +835,10 @@ cselib_subst_to_values (x)
switch (code) switch (code)
{ {
case REG: 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)) if (GET_MODE (l->elt->u.val_rtx) == GET_MODE (x))
return l->elt->u.val_rtx; return l->elt->u.val_rtx;
...@@ -909,7 +935,10 @@ cselib_lookup (x, mode, create) ...@@ -909,7 +935,10 @@ cselib_lookup (x, mode, create)
struct elt_list *l; struct elt_list *l;
unsigned int i = REGNO (x); 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)) if (mode == GET_MODE (l->elt->u.val_rtx))
return l->elt; return l->elt;
...@@ -927,8 +956,14 @@ cselib_lookup (x, mode, create) ...@@ -927,8 +956,14 @@ cselib_lookup (x, mode, create)
e = new_cselib_val (++next_unknown_value, GET_MODE (x)); e = new_cselib_val (++next_unknown_value, GET_MODE (x));
e->locs = new_elt_loc_list (e->locs, x); e->locs = new_elt_loc_list (e->locs, x);
if (REG_VALUES (i) == 0) 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 = htab_find_slot_with_hash (hash_table, x, e->value, INSERT);
*slot = e; *slot = e;
return e; return e;
...@@ -1011,17 +1046,28 @@ cselib_invalidate_regno (regno, mode) ...@@ -1011,17 +1046,28 @@ cselib_invalidate_regno (regno, mode)
struct elt_loc_list **p; struct elt_loc_list **p;
unsigned int this_last = i; 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; 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; l = &(*l)->next;
continue; continue;
} }
/* We have an overlap. */ /* 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 /* Now, we clear the mapping from value to reg. It must exist, so
this code will crash intentionally if it doesn't. */ this code will crash intentionally if it doesn't. */
...@@ -1213,9 +1259,6 @@ cselib_record_set (dest, src_elt, dest_addr_elt) ...@@ -1213,9 +1259,6 @@ cselib_record_set (dest, src_elt, dest_addr_elt)
if (dreg >= 0) if (dreg >= 0)
{ {
if (REG_VALUES (dreg) == 0)
VARRAY_PUSH_UINT (used_regs, dreg);
if (dreg < FIRST_PSEUDO_REGISTER) if (dreg < FIRST_PSEUDO_REGISTER)
{ {
unsigned int n = HARD_REGNO_NREGS (dreg, GET_MODE (dest)); unsigned int n = HARD_REGNO_NREGS (dreg, GET_MODE (dest));
...@@ -1224,7 +1267,20 @@ cselib_record_set (dest, src_elt, dest_addr_elt) ...@@ -1224,7 +1267,20 @@ cselib_record_set (dest, src_elt, dest_addr_elt)
max_value_regs = n; 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) if (src_elt->locs == 0)
n_useless_values--; n_useless_values--;
src_elt->locs = new_elt_loc_list (src_elt->locs, dest); src_elt->locs = new_elt_loc_list (src_elt->locs, dest);
......
/* Common subexpression elimination for GNU compiler. /* Common subexpression elimination for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 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. This file is part of GCC.
...@@ -67,6 +67,7 @@ extern void cselib_update_varray_sizes PARAMS ((void)); ...@@ -67,6 +67,7 @@ extern void cselib_update_varray_sizes PARAMS ((void));
extern void cselib_init PARAMS ((void)); extern void cselib_init PARAMS ((void));
extern void cselib_finish PARAMS ((void)); extern void cselib_finish PARAMS ((void));
extern void cselib_process_insn PARAMS ((rtx)); 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 rtx_equal_for_cselib_p PARAMS ((rtx, rtx));
extern int references_value_p PARAMS ((rtx, int)); extern int references_value_p PARAMS ((rtx, int));
extern rtx cselib_subst_to_values PARAMS ((rtx)); extern rtx cselib_subst_to_values PARAMS ((rtx));
...@@ -8025,6 +8025,9 @@ static int ...@@ -8025,6 +8025,9 @@ static int
reload_cse_noop_set_p (set) reload_cse_noop_set_p (set)
rtx 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)); return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment