Patchwork Improve simplify_subreg

login
register
mail settings
Submitter Jakub Jelinek
Date May 3, 2013, 5:13 p.m.
Message ID <20130503171323.GE28963@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/241355/
State New
Headers show

Comments

Jakub Jelinek - May 3, 2013, 5:13 p.m.
On Thu, May 02, 2013 at 06:53:31PM +0100, Richard Sandiford wrote:
> Jakub Jelinek <jakub@redhat.com> writes:
> > When working on PR57130, I've wondered why we don't simplify it much earlier
> > and end up with creating such weirdness.
> >
> > The following patch fixes that, by using nonzero_bits to see if all the low
> > bits must be zero and in that case just return zero.
> >
> > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> >
> > 2013-05-02  Jakub Jelinek  <jakub@redhat.com>
> >
> > 	* simplify-rtx.c (simplify_truncation): If nonzero_bits
> > 	on op shows all bits zero in mode, return zero.
> 
> I'm probably wrong, but just in case: it looks like this might
> fall foul of:
> 
> /* Try to simplify a MODE truncation of OP, which has OP_MODE.
>    Only handle cases where the truncated value is inherently an rvalue.
> 
> If op is a register, it might be being used as an lvalue instead of an rvalue.
> We don't want to simplify (subreg (reg ..)) to (const_int 0) in that case.
> 
> It should be OK to put this under the TRUNCATE case in
> simplify_unary_operation_1, but I don't know if that'd be good
> enough for your testcase.

I understand, if simplify_subreg would be called on LHS, that would be a bad
transformation.  Unfortunately, simplify_rtx isn't called on the testcase
and there isn't a TRUNCATE, just a SUBREG, so simplify_unary_operation_1
wouldn't be the right spot for it anyway.

What about this?  Is combine_simplify_rtx only called on rvalues?

This improves the *.combine dump on the testcase too.

Bootstrapped/regtested on x86_64-linux and i686-linux.

2013-05-03  Jakub Jelinek  <jakub@redhat.com>

	* combine.c (combine_simplify_rtx) <case SUBREG>: If nonzero_bits
	on op shows all bits zero in mode of a lowpart subreg, return zero.



	Jakub
Richard Sandiford - May 4, 2013, 8:40 a.m.
Jakub Jelinek <jakub@redhat.com> writes:
> On Thu, May 02, 2013 at 06:53:31PM +0100, Richard Sandiford wrote:
>> Jakub Jelinek <jakub@redhat.com> writes:
>> > When working on PR57130, I've wondered why we don't simplify it much earlier
>> > and end up with creating such weirdness.
>> >
>> > The following patch fixes that, by using nonzero_bits to see if all the low
>> > bits must be zero and in that case just return zero.
>> >
>> > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>> >
>> > 2013-05-02  Jakub Jelinek  <jakub@redhat.com>
>> >
>> > 	* simplify-rtx.c (simplify_truncation): If nonzero_bits
>> > 	on op shows all bits zero in mode, return zero.
>> 
>> I'm probably wrong, but just in case: it looks like this might
>> fall foul of:
>> 
>> /* Try to simplify a MODE truncation of OP, which has OP_MODE.
>>    Only handle cases where the truncated value is inherently an rvalue.
>> 
>> If op is a register, it might be being used as an lvalue instead of an rvalue.
>> We don't want to simplify (subreg (reg ..)) to (const_int 0) in that case.
>> 
>> It should be OK to put this under the TRUNCATE case in
>> simplify_unary_operation_1, but I don't know if that'd be good
>> enough for your testcase.
>
> I understand, if simplify_subreg would be called on LHS, that would be a bad
> transformation.  Unfortunately, simplify_rtx isn't called on the testcase
> and there isn't a TRUNCATE, just a SUBREG, so simplify_unary_operation_1
> wouldn't be the right spot for it anyway.
>
> What about this?  Is combine_simplify_rtx only called on rvalues?

Both lvalues and rvalues I think, but at least in_dest says which.
The patch looks good to me with an "&& !in_dest".

Thanks,
Richard

Patch

--- gcc/combine.c.jj	2013-05-03 14:55:32.000000000 +0200
+++ gcc/combine.c	2013-05-03 15:46:31.923323029 +0200
@@ -5417,6 +5417,16 @@  combine_simplify_rtx (rtx x, enum machin
 				SUBREG_BYTE (x));
 	if (temp)
 	  return temp;
+
+	/* If op is known to have all lower bits zero, the result is zero.  */
+	if (SCALAR_INT_MODE_P (mode)
+	    && SCALAR_INT_MODE_P (op0_mode)
+	    && GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (op0_mode)
+	    && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x)
+	    && HWI_COMPUTABLE_MODE_P (op0_mode)
+	    && (nonzero_bits (SUBREG_REG (x), op0_mode)
+		& GET_MODE_MASK (mode)) == 0)
+	  return CONST0_RTX (mode);
       }
 
       /* Don't change the mode of the MEM if that would change the meaning