This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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)



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]