On Tue, Mar 29, 2016 at 11:34:29AM -0600, Jeff Law wrote:
> >This is a case similar to the LSHIFTRT I've fixed recently.
> >But, unlike LSHIFTRT, which can be handled by masking at the outer level,
> >ASHIFTRT would need outer sign extension, so most of the time 2 outer
> >operations in addition to the kept two inner shifts, which is IMHO very
> >unlikely to ever be successfully combined on any target nor actually
> >beneficial.  So this patch just avoids that optimization for ASHIFTRT
> >if there are different modes.
> >
> >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> >
> >2016-03-29  Jakub Jelinek  <ja...@redhat.com>
> >
> >     PR rtl-optimization/70429
> >     * combine.c (simplify_shift_const_1): For ASHIFTRT don't optimize
> >     (cst1 >> count) >> cst2 into (cst1 >> cst2) >> count if
> >     mode != result_mode.
> >
> >     * gcc.c-torture/execute/pr70429.c: New test.
> But isn't the point of this code that cst1 >> cst2 turns into a compile time
> constant just leaving one runtime shift of the result by count?

But with the mode change then you are changing
(cst1 >> count) >> cst2
into
((((cst1 >> cst2) >> count) << (bitsz - cst2)) >> (bitsz - cst2))
so even when cst1 >> cst2 from there is a constant, the rest is not.
Even on targets that have instructions that let you sign extend
in one insn (more often only for selected values of cst2), it is still
trading two shifts for one shift and one sign extension.

If mode == result_mode, then we'll still optimize
(cst1 >> count) >> cst2, it is just the
((narrowing_conversion) (cst1 >> count)) >> cst2 which this patch changes.

        Jakub

Reply via email to