diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2008-01-14 12:16:58 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2008-01-14 12:16:58 +0000 |
commit | d556d1813e6dec467128591daae0a9bebc8b0efe (patch) | |
tree | 6ee45e3f1b54b348479a34238b5dc118623582a8 /gcc/cse.c | |
parent | 6bf4cbe817462e6c5f7f37cc22e0f2ba34986864 (diff) | |
download | gcc-d556d1813e6dec467128591daae0a9bebc8b0efe.zip gcc-d556d1813e6dec467128591daae0a9bebc8b0efe.tar.gz gcc-d556d1813e6dec467128591daae0a9bebc8b0efe.tar.bz2 |
re PR rtl-optimization/31944 (Endless loop while building a 64-bit 2.6.20 kernel)
PR rtl-optimization/31944
* cse.c (remove_pseudo_from_table): New function.
(merge_equiv_classes): Use above function to remove pseudo-registers.
(invalidate): Likewise.
From-SVN: r131522
Diffstat (limited to 'gcc/cse.c')
-rw-r--r-- | gcc/cse.c | 30 |
1 files changed, 20 insertions, 10 deletions
@@ -554,7 +554,8 @@ static void delete_reg_equiv (unsigned int); static int mention_regs (rtx); static int insert_regs (rtx, struct table_elt *, int); static void remove_from_table (struct table_elt *, unsigned); -static struct table_elt *lookup (rtx, unsigned, enum machine_mode); +static void remove_pseudo_from_table (rtx, unsigned); +static struct table_elt *lookup (rtx, unsigned, enum machine_mode); static struct table_elt *lookup_for_remove (rtx, unsigned, enum machine_mode); static rtx lookup_as_function (rtx, enum rtx_code); static struct table_elt *insert (rtx, struct table_elt *, unsigned, @@ -1288,6 +1289,19 @@ remove_from_table (struct table_elt *elt, unsigned int hash) free_element_chain = elt; } +/* Same as above, but X is a pseudo-register. */ + +static void +remove_pseudo_from_table (rtx x, unsigned int hash) +{ + struct table_elt *elt; + + /* Because a pseudo-register can be referenced in more than one + mode, we might have to remove more than one table entry. */ + while ((elt = lookup_for_remove (x, hash, VOIDmode))) + remove_from_table (elt, hash); +} + /* Look up X in the hash table and return its table element, or 0 if X is not in the table. @@ -1605,7 +1619,10 @@ merge_equiv_classes (struct table_elt *class1, struct table_elt *class2) delete_reg_equiv (REGNO (exp)); } - remove_from_table (elt, hash); + if (REG_P (exp) && REGNO (exp) >= FIRST_PSEUDO_REGISTER) + remove_pseudo_from_table (exp, hash); + else + remove_from_table (elt, hash); if (insert_regs (exp, class1, 0) || need_rehash) { @@ -1701,14 +1718,7 @@ invalidate (rtx x, enum machine_mode full_mode) SUBREG_TICKED (regno) = -1; if (regno >= FIRST_PSEUDO_REGISTER) - { - /* Because a register can be referenced in more than one mode, - we might have to remove more than one table entry. */ - struct table_elt *elt; - - while ((elt = lookup_for_remove (x, hash, GET_MODE (x)))) - remove_from_table (elt, hash); - } + remove_pseudo_from_table (x, hash); else { HOST_WIDE_INT in_table |