From 977ffed28cc3760d30a20d644bde86241c7bbab5 Mon Sep 17 00:00:00 2001 From: pbrook Date: Thu, 20 Jul 2006 13:57:31 +0000 Subject: 2006-07-20 Paul Brook PR 27363 gcc/ * cse.c (cse_insn): Add destination addresses to hash table. Check if they are invalidated by this instruction. gcc/testsuite/ * gcc.dg/pr27363.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@115614 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 6 ++++++ gcc/cse.c | 48 ++++++++++++++++++++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/pr27363.c | 39 ++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr27363.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 213f3d817f1..5d9e52ecac1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2006-07-20 Paul Brook + + PR 27363 + * cse.c (cse_insn): Add destination addresses to hash table. Check if + they are invalidated by this instruction. + 2006-07-21 Danny Smith PR target/28427 diff --git a/gcc/cse.c b/gcc/cse.c index 65a4a0ab172..9e6fec091da 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -4739,6 +4739,8 @@ struct set unsigned src_const_hash; /* Table entry for constant equivalent for SET_SRC, if any. */ struct table_elt *src_const_elt; + /* Table entry for the destination address. */ + struct table_elt *dest_addr_elt; }; static void @@ -5970,6 +5972,40 @@ cse_insn (rtx insn, rtx libcall_insn) so that the destination goes into that class. */ sets[i].src_elt = src_eqv_elt; + /* Record destination addresses in the hash table. This allows us to + check if they are invalidated by other sets. */ + for (i = 0; i < n_sets; i++) + { + if (sets[i].rtl) + { + rtx x = sets[i].inner_dest; + struct table_elt *elt; + enum machine_mode mode; + unsigned hash; + + if (MEM_P (x)) + { + x = XEXP (x, 0); + mode = GET_MODE (x); + hash = HASH (x, mode); + elt = lookup (x, hash, mode); + if (!elt) + { + if (insert_regs (x, NULL, 0)) + { + rehash_using_reg (x); + hash = HASH (x, mode); + } + elt = insert (x, NULL, hash, mode); + } + + sets[i].dest_addr_elt = elt; + } + else + sets[i].dest_addr_elt = NULL; + } + } + invalidate_from_clobbers (x); /* Some registers are invalidated by subroutine calls. Memory is @@ -6062,12 +6098,20 @@ cse_insn (rtx insn, rtx libcall_insn) } /* We may have just removed some of the src_elt's from the hash table. - So replace each one with the current head of the same class. */ + So replace each one with the current head of the same class. + Also check if destination addresses have been removed. */ for (i = 0; i < n_sets; i++) if (sets[i].rtl) { - if (sets[i].src_elt && sets[i].src_elt->first_same_value == 0) + if (sets[i].dest_addr_elt + && sets[i].dest_addr_elt->first_same_value == 0) + { + /* The elt was removed, which means this destination s not + valid after this instruction. */ + sets[i].rtl = NULL_RTX; + } + else if (sets[i].src_elt && sets[i].src_elt->first_same_value == 0) /* If elt was removed, find current head of same class, or 0 if nothing remains of that class. */ { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f6ca4c799ae..414d3143d99 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-07-20 Paul Brook + + PR 27363 + * gcc.dg/pr27363.c: New test. + 2006-07-19 Mark Mitchell PR c++/28338 diff --git a/gcc/testsuite/gcc.dg/pr27363.c b/gcc/testsuite/gcc.dg/pr27363.c new file mode 100644 index 00000000000..40a3c6b3526 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr27363.c @@ -0,0 +1,39 @@ +/* PR27363. CSE was breaking on the arm store multiple insn used for + structure copies. */ +/* { dg-do run } */ +/* { dg-options "-Os" } */ +extern void abort (void); + +struct snd_mask { + unsigned int bits[6]; +}; + +static int __attribute__((noinline)) +snd_mask_refine(struct snd_mask *mask) +{ + struct snd_mask old; + + old = *mask; + if (mask->bits[0]==0 && mask->bits[1]==0) + return 1; + + return old.bits[0] != mask->bits[0]; +} + +int main(int argc, char *argv[]) +{ + struct snd_mask mask; + + + mask.bits[0] = 23; + mask.bits[1] = 42; + mask.bits[2] = 0; + mask.bits[3] = 0; + mask.bits[4] = 0; + mask.bits[5] = 0; + + + if (snd_mask_refine(&mask)) + abort(); + return 0; +} -- cgit v1.2.1