On Mon, 14 Jan 2008, Richard Guenther wrote:

> Can you clarify on the resulting promotions?  As I remember the
> standard defines promotions based on the representable values, so
> long : 15 gets promoted to int, but long : 33 doesn't get promoted.
> In the C++ FE at least we promote to the _declared_ type, that is,
> to long in this case.  (Which I find more natural, but may be not
> what the standard says).

Types (including the bit-field width as part of the type) narrower than 
int are promoted based on representable values (so to int).  Types wider 
than int are left unchanged by the promotions.

> Now, if you assign a rank to long : 15 (is it the same as int : 15?),

They are the same; we only provide a single signed and a single unsigned 
bit-field type of each width.  (For int : 32, or other cases where the 
width is the full width of the declared type, we used the declared type; 
for cases where the width is that of a narrower standard type, we use that 
narrower standard type, with c_build_bitfield_integer_type determining 
preferences among types of the same width.)

> would it still promote to int or would it promote to long or neither?

To int, because int can represent all the values.

> The question arises when computing the value of say long : 33 i;
> i << 16 >> 16.  Is the shift performed in long : 33 type?  Is an
> out-of-range value truncated?

Performed in long : 33, according to the rules for shifts defined in 
implement-c.texi (which define some cases ISO C leaves 
implementation-defined, and one that's implementation-defined in C90 but 
undefined in C99.)

Arithmetic also follows the usual ISO C rules (e.g. signed overflow 
undefined, subject to -fwrapv making it modulo; unsigned overflow modulo).  
Arithmetic in narrow bit-field types e.g. int:25 won't appear at the 
language level any more than arithmetic in short does, because both get 
promoted to int.

> > * Say that bit-fields are assigned such types.
> 
> Does behavior change for bit-fields that are standard conforming or
> only for implementation defined bit-fields of long.

I don't believe anything is abservable for int and unsigned int (or _Bool) 
bit-fields about the types chosen, beyond the promotions and questions of 
whether certain out-of-range floating point to bit-field conversions are 
defined.  (There are however testcases in the GCC testsuite for e.g. 
diagnostics of out-of-range initializers that get implicitly converted to 
the bit-field type, such as storing 1 in a signed int : 1 bit-field that 
can only hold 0 and -1.)

> > * Make the gimplifier (or a later tree-ssa pass) insert whatever 
> > conversions / reductions in precision may be needed to produce trees 
> > acceptable to expand, if you think expand can't handle the special types 
> > reliably.  In particular, for arithmetic on such types and on all 
> > conversions to such types.  (Without special types, special code is still 
> > needed for assignments to bit-fields, no longer handled as conversions.)
> 
> (The problem is that I'm trying to exactly define what it should mean
> to the middle-end to for example do a NOP conversion to a bitfield - this
> is not at all clear)

The conversions between integer types should I think be defined in GIMPLE 
to follow the same rules as the C language conversions, documented in 
implement-c.texi for cases ISO C leaves implemenation-defined: that is, 
always reducing modulo 2^N to fit within the range of the type (except for 
conversions to _Bool).

> Right.  C requests this via a langhook (which C++ doesn't use).  So for
> C++ we for example miscompile

C++ probably should not have started using these types without also using 
the langhook.  (There may also be bugs in expand where the langhook is 
inadequate, and of course we should aim for the semantics of GIMPLE to be 
defined without needing such a langhook.)

As a general principle, very little before the RTL stages should care 
about machine modes; code that cares about them may be using them as a 
proxy for precision that goes wrong in the presence of bit-field types, 
and in any case they seem like the wrong level of abstraction for the 
earlier stages of the compiler.  At expand stage at the latest, the full 
set of types (possibly including bit-field types such as long:33, or Ada 
types with unusual ranges, or other such constructs) then needs to be 
mapped onto the lower level machine modes of RTL (at which point many 
operations also lose the signed/unsigned distinction).  Whether this is 
done at expand, at gimplification or somewhere inbetween may depend on 
whether we think the tree optimizers can usefully optimize arithmetic on 
special types before lowering, or whether they should be optimizing 
arithmetic after lowering (with extra shift/mask operations inserted), or 
both.

-- 
Joseph S. Myers
[EMAIL PROTECTED]

Reply via email to