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\]" } } */

Reply via email to