diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 370f701c20c..df995ab6804 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2006-01-25 Roger Sayle + + 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 * global.c: Fix comment typos. diff --git a/gcc/combine.c b/gcc/combine.c index 0ec45808a8a..2c90be5a2e4 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 28d3297c26d..075def5ca25 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2006-01-25 Jan Hubicka + Roger Sayle + + 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 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 00000000000..cbb4e65d06f --- /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 00000000000..7964ca1cc86 --- /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; +} +