On 03/29/2016 12:03 PM, Jakub Jelinek wrote:
On Tue, Mar 29, 2016 at 11:47:57AM -0600, Jeff Law wrote:
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 - cst))
Why can't we sign extend cst1 >> cst2 at compile time and use a ASHIFTRT for
the >> count shift? Even if we've got a mode change to deal with, we can
generate the constant in whatever mode we want.
I don't understand how you could do that.
In the original source there is a variable shift count first, then narrowing
cast, then further arithmetic shift by constant.
So sure, you can shift the cst1 by cst2, but which bit you want to sign
extend on depends on the count value, only known at runtime.
Consider the testcase I've posted in the patch:
__attribute__((noinline, noclone)) int
foo (int a)
{
return (int) (0x14ff6e2207db5d1fLL >> a) >> 4;
}
if a is 1, 0x14ff6e2207db5d1fLL >> a is
0xa7fb71103edae8f
and bit 31 of this is 0, so in the end you get
0x03edae8f >> 4
If a is 2, 0x14ff6e2207db5d1fLL >> a is
0x53fdb8881f6d747
and bit 31 of this is 1, so in the end you get
0xffffffff81f6d747 >> 4
Now, if you want to shift by 4 first, you have cst1 >> cst2
0x14ff6e2207db5d1LL, but you need to sign extend this, but which bit
from depends on count (and the difference between bitsizes of mode and
result_mode).
Ah, I see. I should have looked at your test. It's the variable shift
that's defines the sign bit that we're using for the conversion. Hence
we can't know its value at compile-time.
Jeff