On Fri, Oct 14, 2011 at 9:23 AM, Paolo Bonzini <bonz...@gnu.org> wrote: > On 10/14/2011 05:36 PM, H.J. Lu wrote: >> >> There is a testcase at >> >> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50696 >> >> It passes with my patch. > > Cool, so let's wait for the results of testing. > > Paolo >
Here is the complete patch with a testcase. I will check it in if there are no performance regressions with SPEC CPU 2K/2006 on Linux/ia32/x86-64/x32. Thanks. -- H.J. --- gcc/ 2011-10-13 H.J. Lu <hongjiu...@intel.com> PR rtl-optimization/50696 * combine.c (make_compound_operation): Turn (and (OP) M) into extraction if M is an extraction mask. gcc/testsuite/ 2011-10-13 H.J. Lu <hongjiu...@intel.com> PR rtl-optimization/50696 * gcc.target/i386/pr50696.c: New.
gcc/ 2011-10-13 H.J. Lu <hongjiu...@intel.com> PR rtl-optimization/50696 * combine.c (make_compound_operation): Turn (and (OP) M) into extraction if M is an extraction mask. gcc/testsuite/ 2011-10-13 H.J. Lu <hongjiu...@intel.com> PR rtl-optimization/50696 * gcc.target/i386/pr50696.c: New. diff --git a/gcc/combine.c b/gcc/combine.c index 6c3b17c..4b57b88 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -7739,16 +7739,6 @@ make_compound_operation (rtx x, enum rtx_code in_code) XEXP (XEXP (x, 0), 1))); } - /* If the constant is one less than a power of two, this might be - representable by an extraction even if no shift is present. - If it doesn't end up being a ZERO_EXTEND, we will ignore it unless - we are in a COMPARE. */ - else if ((i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0) - new_rtx = make_extraction (mode, - make_compound_operation (XEXP (x, 0), - next_code), - 0, NULL_RTX, i, 1, 0, in_code == COMPARE); - /* If we are in a comparison and this is an AND with a power of two, convert this into the appropriate bit extract. */ else if (in_code == COMPARE @@ -7758,6 +7748,26 @@ make_compound_operation (rtx x, enum rtx_code in_code) next_code), i, NULL_RTX, 1, 1, 0, 1); + /* If the constant is an extraction mask with the zero bits in + the first operand ignored, this might be representable by an + extraction even if no shift is present. If it doesn't end up + being a ZERO_EXTEND, we will ignore it unless we are in a + COMPARE. */ + else + { + unsigned HOST_WIDE_INT nonzero = + nonzero_bits (XEXP (x, 0), GET_MODE (XEXP (x, 0))); + unsigned HOST_WIDE_INT mask = UINTVAL (XEXP (x, 1)); + unsigned HOST_WIDE_INT len = ceil_log2 (mask); + if ((nonzero & (((unsigned HOST_WIDE_INT) 1 << len) - 1)) + == (nonzero & mask)) + { + new_rtx = make_compound_operation (XEXP (x, 0), next_code); + new_rtx = make_extraction (mode, new_rtx, 0, NULL_RTX, + len, 1, 0, in_code == COMPARE); + } + } + break; case LSHIFTRT: diff --git a/gcc/testsuite/gcc.target/i386/pr50696.c b/gcc/testsuite/gcc.target/i386/pr50696.c new file mode 100644 index 0000000..b1ec2c5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr50696.c @@ -0,0 +1,19 @@ +/* { dg-do compile { target { x32 } } } */ +/* { dg-options "-O2 -mtune=generic" } */ + +struct s { int val[16]; }; + +extern void f (struct s pb); + +void +foo () +{ + struct s x; + int i; + + for (i = 0; i < 16; i++) + x.val[i] = i + 1; + f (x); +} + +/* { dg-final { scan-assembler-not "lea\[lq\]" } } */