diff options
author | Roger Sayle <sayle@gcc.gnu.org> | 2006-01-26 02:48:01 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2006-01-26 02:48:01 +0000 |
commit | d89b36e1a2179df76edf089cc2a11f5f3409cb72 (patch) | |
tree | 8f729514e4450856c50071a4d4fd1e43842ed815 | |
parent | 51302a4168aced438d184aa0dce95c9766aefd97 (diff) | |
download | gcc-d89b36e1a2179df76edf089cc2a11f5f3409cb72.zip gcc-d89b36e1a2179df76edf089cc2a11f5f3409cb72.tar.gz gcc-d89b36e1a2179df76edf089cc2a11f5f3409cb72.tar.bz2 |
re PR rtl-optimization/25703 (ACATS cxa4024 failure)
PR rtl-optimization/25703
* combine.c (try_combine): Handle zero_extract and strict_low_part
of non-lowpart SUBREGs for constant reg_subword_p set optimization.
* gcc.target/i386/20060125-1.c: New test case.
* gcc.target/i386/20060125-2.c: New test case.
From-SVN: r110242
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/combine.c | 38 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/20060125-1.c | 30 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/20060125-2.c | 30 |
5 files changed, 91 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 370f701..df995ab 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2006-01-25 Roger Sayle <roger@eyesopen.com> + + PR rtl-optimization/25703 + * combine.c (try_combine): Handle zero_extract and strict_low_part + of non-lowpart SUBREGs for constant reg_subword_p set optimization. + 2006-01-25 Peter Bergner <bergner@vnet.ibm.com> * global.c: Fix comment typos. diff --git a/gcc/combine.c b/gcc/combine.c index 0ec4580..2c90be5 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1951,40 +1951,38 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) int offset = -1; int width = 0; - if (GET_CODE (dest) == STRICT_LOW_PART) - { - width = GET_MODE_BITSIZE (GET_MODE (XEXP (dest, 0))); - offset = 0; - } - else if (GET_CODE (dest) == ZERO_EXTRACT) + if (GET_CODE (dest) == ZERO_EXTRACT) { if (GET_CODE (XEXP (dest, 1)) == CONST_INT && GET_CODE (XEXP (dest, 2)) == CONST_INT) { width = INTVAL (XEXP (dest, 1)); offset = INTVAL (XEXP (dest, 2)); - + dest = XEXP (dest, 0); if (BITS_BIG_ENDIAN) - offset = GET_MODE_BITSIZE (GET_MODE (XEXP (dest, 0))) - - width - offset; + offset = GET_MODE_BITSIZE (GET_MODE (dest)) - width - offset; } } - else if (subreg_lowpart_p (dest)) + else { + if (GET_CODE (dest) == STRICT_LOW_PART) + dest = XEXP (dest, 0); width = GET_MODE_BITSIZE (GET_MODE (dest)); offset = 0; } - /* ??? Preserve the original logic to handle setting the high word - of double-word pseudos, where inner is half the size of outer - but not the lowpart. This could be generalized by handling - SUBREG_BYTE, WORDS_BIG_ENDIAN and BYTES_BIG_ENDIAN ourselves. - Unfortunately this logic is tricky to get right and probably - not worth the effort. */ - else if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (temp))) - == 2 * GET_MODE_BITSIZE (GET_MODE (dest))) + + if (offset >= 0) { - width = GET_MODE_BITSIZE (GET_MODE (dest)); - offset = width; + /* If this is the low part, we're done. */ + if (subreg_lowpart_p (dest)) + ; + /* Handle the case where inner is twice the size of outer. */ + else if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (temp))) + == 2 * GET_MODE_BITSIZE (GET_MODE (dest))) + offset += GET_MODE_BITSIZE (GET_MODE (dest)); + /* Otherwise give up for now. */ + else + offset = -1; } if (offset >= 0) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 28d3297..075def5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2006-01-25 Jan Hubicka <jh@suse.cz> + Roger Sayle <roger@eyesopen.com> + + PR rtl-optimization/25703 + * gcc.target/i386/20060125-1.c: New test case. + * gcc.target/i386/20060125-2.c: New test case. + 2006-01-25 Tobias Schlüter <tobias.schlueter@physik.uni-muenchen.de> PR fortran/18540 diff --git a/gcc/testsuite/gcc.target/i386/20060125-1.c b/gcc/testsuite/gcc.target/i386/20060125-1.c new file mode 100644 index 0000000..cbb4e65 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/20060125-1.c @@ -0,0 +1,30 @@ +/* PR rtl-optimization/25703 */ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 -mtune=i486" } */ + +extern void abort (void); + +struct a +{ + int a; + char b,c,d,e; +}; + +__attribute__ ((noinline)) +__attribute__ ((regparm(1))) t(struct a a) +{ + if (a.a!=1 || a.b!=1 || a.c!=1) + abort(); +} + +int main() +{ + struct a a; + a.c=1; + a.a=1; + a.b=1; + t(a); + return 0; +} + diff --git a/gcc/testsuite/gcc.target/i386/20060125-2.c b/gcc/testsuite/gcc.target/i386/20060125-2.c new file mode 100644 index 0000000..7964ca1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/20060125-2.c @@ -0,0 +1,30 @@ +/* PR rtl-optimization/25703 */ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 -mtune=pentiumpro" } */ + +extern void abort (void); + +struct a +{ + int a; + char b,c,d,e; +}; + +__attribute__ ((noinline)) +__attribute__ ((regparm(1))) t(struct a a) +{ + if (a.a!=1 || a.b!=1 || a.c!=1) + abort(); +} + +int main() +{ + struct a a; + a.c=1; + a.a=1; + a.b=1; + t(a); + return 0; +} + |