This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Char shifts promoted to int. Why?
- From: Paul Schlie <schlie at comcast dot net>
- To: Paul Brook <paul at codesourcery dot com>, <gcc at gcc dot gnu dot org>
- Date: Mon, 18 Dec 2006 05:24:47 -0500
- Subject: Re: Char shifts promoted to int. Why?
> From: Paul Brook <paul@codesourcery.com>
> On Monday 18 December 2006 01:15, Paul Schlie wrote:
>> Chris Lattner wrote:
>>> On Dec 17, 2006, at 12:40 PM, Rask Engelmann Lamberts wrote:
>>>> I seem unable to get a QImode shift instruction from this code:
>>>>
>>>> unsigned char x;
>>>>
>>>> void qishifttest2 (unsigned int c)
>>>> {
>>>> x <<= c;
>>>> }
>>>>
>>>> should have been generated. Also, notice the redundant zero extension.
>>>> Why are we not generating a QImode shift instruction?
>>>
>>> Consider when c = 16. With the (required) integer promotion, the result
>>> is defined (the result is zero). If converted to QImode, the shift would
>>> be undefined, because the (dynamic) shift amount would be larger than the
>>> data type.
>>
>> ??? A left shift >= the precision of its shifted unsigned operand can only
>> logically result in a value of 0 regardless of its potential promotion.
>
> Shifting >= the size of the value being shifted can and do give nonzero
> results on common hardware. Typically hardware will truncate the shift count.
> eg. x << 8 implemented with a QImode shift will give x, not 0.
>
>> Although integer promotion as specified by C may technically be performed
>> lazily as a function of the implicit target precision required for a given
>> operation, GCC tends to initially promote everything and then attempt to
>> determine if an operation's precision may be subsequently lowered after
>> having already lost critical knowledge of its originally specified
>> operand's precision.
>
> No. You're confusing some language you just invented with C.
>
> The operand of the shift operator is of type unsigned int.
> "x <<= c" is exactly the same as "((int)x) << c"
> It doesn't matter whether the promotion is explicit or implicit, the semantics
> are the same.
((char)x) = ((char)( ((int)((char)x)) << ((int)c) ) ) ::
((char)x) = ((char)( ((char)x) << ((int)c) ) )
if the shift count ((int)x) is semantically preserved.
thereby conditionally shifting left ((char)x) by ((int)c) if c is less than
the smaller of it's shifted operand's or target's precision (both being char
in this instance) or otherwise returning 0; is semantically equivalent and
typically more efficient on smaller lightly pipelined machines without
needing to literally promote the shifted operand to int width.
(I believe)