[PATCH] Allow widening the mode of right-shifts in simplify_shift_const_1

Jeff Law law@redhat.com
Fri Jul 17 12:42:00 GMT 2009


Adam Nemet wrote:
> This is a follow-up to
> <http://gcc.gnu.org/ml/gcc-patches/2009-05/msg01253.html>.  As I mentioned
> there, the truncate after the sign-extraction is redundant.  However I missed
> at the time that so is the subsequent sign-extension.  This patch removes the
> sign-extension.
>
> Compound operations are optimized in their expanded from in combine and
> redundant sign-extensions are normally removed in simplify_shift_const_1:
>
> 	case LSHIFTRT:
> 	case ASHIFT:
> 	case ROTATE:
> 	[...]
> 	      /* If this was (ashiftrt (ashift foo C1) C2) and FOO has more
> 		 than C1 high-order bits equal to the sign bit, we can convert
> 		 this to either an ASHIFT or an ASHIFTRT depending on the
> 		 two counts.
>
> 		 We cannot do this if VAROP's mode is not SHIFT_MODE.  */
>
> 	      if (code == ASHIFTRT && first_code == ASHIFT
> 		  && GET_MODE (varop) == shift_mode
> 		  && (num_sign_bit_copies (XEXP (varop, 0), shift_mode)
> 		      > first_count))
> 		{
> 		  varop = XEXP (varop, 0);
> 		  count -= first_count;
> 		  if (count < 0)
> 		    {
> 		      count = -count;
> 		      code = ASHIFT;
> 		    }
>
> 		  continue;
> 		}
>
> Using the new testcase, which extracts 14 bits, we start with these patterns:
>
> 7: (set (reg:DI 202)
>         (sign_extract:DI (reg:DI 200)
>             (const_int 14 [0xe])
>             (const_int 32 [0x20])))
>
> 8: (set (reg:HI 203)
>         (truncate:HI (reg:DI 202)))
>
> 9: (set (reg:SI 197)
>         (sign_extend:SI (reg:HI 203)))
>
> then fail to combine this:
>
> Trying 8 -> 9:
> Failed to match this instruction:
> (set (reg:SI 197)
>     (ashiftrt:SI (subreg:SI (ashift:DI (reg:DI 202)
>                 (const_int 16 [0x10])) 4)
>         (const_int 16 [0x10])))
>
>
> The subreg is in the way of merging the two shifts into nothing.  (The
> truncate was turned into a subreg by the TARGET_MODE_REP_EXTENDED machinery.)
>
> In general we're not allowed to widen the mode of right shifts because instead
> of zero or the value of the sign-bit we'd bring in high-order bits.  This is
> however allowed if we can prove that the high-order bits contain what would
> normally be shifted in.
>
> This is what my patch does first for ASHIFTRT.  Further patches will add the
> other cases.  (I split this up to help bisecting.)  We can widen the mode of
> an ASHIFTRT if the bits brought in are identical to the sign-bit of the
> original mode.
>
> My code makes it more explicit that we're always widening the mode here.  This
> is guaranteed because MODE is initialized to RESULT_MODE and only set under
> case SUBREG: if the new mode is wider than the original value of MODE.  So
> MODE can never be narrower than RESULT_MODE.
>
> The patch also reverts the work-around I had to install for the MIPS tests due
> to this limitation.
>
> Bootstrapped and regtested on {mips64octeon,x86_64}-linux and regtested on
> mipsisa64r2-elf.
>
> OK for trunk?
>
> Adam
>
>
> 	* combine.c (simplify_shift_const_1): Split code to determine
> 	shift_mode into ...
> 	(try_widen_shift_mode): ... here.  Allow widening for ASHIFTRT if the
> 	new bits shifted in are identical to the old sign bit.
>
> testsuite/
> 	* gcc.target/mips/octeon-exts-7.c: New test.
> 	* gcc.target/mips/octeon-exts-2.c: Revert previous change.
> 	* gcc.target/mips/octeon-exts-5.c: Likewise.
>   
OK.

jeff



More information about the Gcc-patches mailing list