On Thu, May 02, 2013 at 06:53:31PM +0100, Richard Sandiford wrote: > Jakub Jelinek <ja...@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 <ja...@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 <ja...@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. --- 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 Jakub