diff mbox

Optimize nested SIGN_EXTENDs/ZERO_EXTENDs (PR target/45336)

Message ID 20100819163330.GX702@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Aug. 19, 2010, 4:33 p.m. UTC
Hi!

This patch optimizes
 	pextrw	$3, %xmm0, %eax
-	cwtl
-	cltq
+	movswq	%ax, %rax
 	ret
and
 	pextrb	$4, %xmm0, %eax
-	movsbl	%al, %eax
-	cltq
+	movsbq	%al, %rax
 	ret
in the testcase from the PR.  While H.J. said he is working on something
for the intrinsics, the patch below attempts to simplify the generic case
of nested SIGN or ZERO_EXTENDs.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2010-08-19  Jakub Jelinek  <jakub@redhat.com>

	PR target/45336
	* simplify-rtx.c (simplify_unary_operation_1): Optimize nested
	SIGN_EXTENDs or ZERO_EXTENDs.


	Jakub

Comments

Bernd Schmidt Aug. 19, 2010, 5:23 p.m. UTC | #1
On 08/19/2010 06:33 PM, Jakub Jelinek wrote:
> +      /* (sign_extend:M (ashirtrt:O (ashift <X> (const_int N)) (const_int N)))
> +	 is (sign_extend:M (subreg:P <X>)) if there is mode with
> +	 GET_MODE_BITSIZE (O) - N bits.  */

Why not do the same with zero_extend and lshiftrt?  Otherwise ok.


Bernd
Eric Botcazou Aug. 19, 2010, 5:25 p.m. UTC | #2
> 2010-08-19  Jakub Jelinek  <jakub@redhat.com>
>
> 	PR target/45336
> 	* simplify-rtx.c (simplify_unary_operation_1): Optimize nested
> 	SIGN_EXTENDs or ZERO_EXTENDs.

OK modulo:

> +      /* (sign_extend:M (ashirtrt:O (ashift <X> (const_int N)) (const_int
> N))) +	 is (sign_extend:M (subreg:P <X>)) if there is mode with
> +	 GET_MODE_BITSIZE (O) - N bits.  */

ashiftrt instead of ashirtrt.  Please keep using N as a mode like in the 2 
other comments, use I or Y for the CONST_INT, thanks.
Jakub Jelinek Aug. 19, 2010, 5:32 p.m. UTC | #3
On Thu, Aug 19, 2010 at 07:23:24PM +0200, Bernd Schmidt wrote:
> On 08/19/2010 06:33 PM, Jakub Jelinek wrote:
> > +      /* (sign_extend:M (ashirtrt:O (ashift <X> (const_int N)) (const_int N)))
> > +	 is (sign_extend:M (subreg:P <X>)) if there is mode with
> > +	 GET_MODE_BITSIZE (O) - N bits.  */
> 
> Why not do the same with zero_extend and lshiftrt?  Otherwise ok.

ZERO_EXTEND is expanded into AND instead of LSHIFTRT/ASHIFT by combine, and
two nested ANDs should be easily optimized.  If you really want, I can
handle the ZERO_EXTEND (AND <X> mask) case as a follow-up.

	Jakub
Bernd Schmidt Aug. 19, 2010, 5:58 p.m. UTC | #4
On 08/19/2010 07:32 PM, Jakub Jelinek wrote:
> On Thu, Aug 19, 2010 at 07:23:24PM +0200, Bernd Schmidt wrote:
>> On 08/19/2010 06:33 PM, Jakub Jelinek wrote:
>>> +      /* (sign_extend:M (ashirtrt:O (ashift <X> (const_int N)) (const_int N)))
>>> +	 is (sign_extend:M (subreg:P <X>)) if there is mode with
>>> +	 GET_MODE_BITSIZE (O) - N bits.  */
>>
>> Why not do the same with zero_extend and lshiftrt?  Otherwise ok.
> 
> ZERO_EXTEND is expanded into AND instead of LSHIFTRT/ASHIFT by combine, and
> two nested ANDs should be easily optimized.  If you really want, I can
> handle the ZERO_EXTEND (AND <X> mask) case as a follow-up.

Oh, in expand_compound_operation?  I was thinking about finding such
shifts in a pair of insns (happens on Thumb).  Also, what about callers
other than combine?


Bernd
Paolo Bonzini Aug. 20, 2010, 9:46 a.m. UTC | #5
On 08/19/2010 06:33 PM, Jakub Jelinek wrote:
> +      /* (sign_extend:M (sign_extend:N<X>)) is (sign_extend:M<X>).  */
> +      if (GET_CODE (op) == SIGN_EXTEND)
> +	return simplify_gen_unary (SIGN_EXTEND, mode, XEXP (op, 0),
> +				   GET_MODE (XEXP (op, 0)));

Maybe

/* (sign_extend:M (sign_extend:N<X>)) is (sign_extend:M<X>).
    (sign_extend:M (zero_extend:N<X>)) is (zero_extend:M<X>).  */
if (GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND)
   {
     gcc_assert (GET_MODE (op) != mode);
     return simplify_gen_unary (GET_CODE (op), mode, XEXP (op, 0),
                                GET_MODE (XEXP (op, 0)));
   }

?

Paolo
diff mbox

Patch

--- gcc/simplify-rtx.c.jj	2010-08-11 21:08:06.000000000 +0200
+++ gcc/simplify-rtx.c	2010-08-19 14:49:20.000000000 +0200
@@ -1010,6 +1010,31 @@  simplify_unary_operation_1 (enum rtx_cod
 	  && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
 	return rtl_hooks.gen_lowpart_no_emit (mode, op);
 
+      /* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>).  */
+      if (GET_CODE (op) == SIGN_EXTEND)
+	return simplify_gen_unary (SIGN_EXTEND, mode, XEXP (op, 0),
+				   GET_MODE (XEXP (op, 0)));
+
+      /* (sign_extend:M (ashirtrt:O (ashift <X> (const_int N)) (const_int N)))
+	 is (sign_extend:M (subreg:P <X>)) if there is mode with
+	 GET_MODE_BITSIZE (O) - N bits.  */
+      if (GET_CODE (op) == ASHIFTRT
+	  && GET_CODE (XEXP (op, 0)) == ASHIFT
+	  && CONST_INT_P (XEXP (op, 1))
+	  && XEXP (XEXP (op, 0), 1) == XEXP (op, 1)
+	  && GET_MODE_BITSIZE (GET_MODE (op)) > INTVAL (XEXP (op, 1)))
+	{
+	  enum machine_mode tmode
+	    = mode_for_size (GET_MODE_BITSIZE (GET_MODE (op))
+			     - INTVAL (XEXP (op, 1)), MODE_INT, 1);
+	  if (tmode != BLKmode)
+	    {
+	      rtx inner =
+		rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0));
+	      return simplify_gen_unary (SIGN_EXTEND, mode, inner, tmode);
+	    }
+	}
+
 #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
       /* As we do not know which address space the pointer is refering to,
 	 we can do this only if the target does not support different pointer
@@ -1036,6 +1061,11 @@  simplify_unary_operation_1 (enum rtx_cod
 	  && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
 	return rtl_hooks.gen_lowpart_no_emit (mode, op);
 
+      /* (zero_extend:M (zero_extend:N <X>)) is (zero_extend:M <X>).  */
+      if (GET_CODE (op) == ZERO_EXTEND)
+	return simplify_gen_unary (ZERO_EXTEND, mode, XEXP (op, 0),
+				   GET_MODE (XEXP (op, 0)));
+
 #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
       /* As we do not know which address space the pointer is refering to,
 	 we can do this only if the target does not support different pointer