DATA_ALIGNMENT vs. DECL_USER_ALIGNMENT

Geert Bosch bosch@gnat.com
Thu Apr 24 21:32:00 GMT 2003


On Thursday, Apr 24, 2003, at 13:16 America/New_York, Jason Merrill 
wrote:
> I was referring to what dewar said here:
>
> On Mon, 21 Apr 2003 17:35:51 -0400 (EDT), dewar@gnat.com (Robert 
> Dewar) wrote:
>
>>   type A is ...
>>
>>   B : A;
>>   for B'Alignment use 4;
>>
>>   Put_Line (Integer'Image (B'Alignment));
>>
>> This must output 4. Of course the compiler could still silently put
>> B on a bigger alignment, since there would be no way to tell that it
>> was doing this systematically, but this would be a poor 
>> implementation.
>
> To me, this means that DECL_ALIGN for B must be exactly 4, whereas 
> giving A a TYPE_ALIGN of 4 would only mean that DECL_ALIGN for B must 
> be at least 4.

Exactly. A TYPE_ALIGN of 4 means that any variable of the type is
aligned to at least 4. So the maximum alignment the compiler can
assume for any pointer to a 4-byte aligned type is 4.

>> Of course the compiler should have a good reason to increase, but 
>> that's a quality of implementation issue. For example, a compiler 
>> might well align all 14-byte local objects of a 2-byte aligned type 
>> to 16 bytes and then take advantage of that stricter alignment in 
>> code generation.

> This seems to conflict with what dewar is saying.
No it does not. Note that this is the case where no DECL_ALIGN has been
specified. Such as:
   type T is record
      X, Y, Z : Unsigned_16; -- 16-bit unsigned type
   end T;
   for T'Size use 48; --  48 bits
   for T'Alignment use 2;

   R : T := (1, 2, 3);
   Put (R'Alignment);

This may output a value that is a multiple of 2. Here the compiler
might decide to align R on a 8-byte boundary for efficiency. This
may enable the initialization to be done with a single 64-bit write,
for example. Of course, the knowledge about the better alignment
of R will get lost when passing (a pointer to) it to another
function. Still, increasing the alignment of objects is a
significant optimization that can speed up code immensely.
This will only be more true when the compiler will learn
more about vector instructions.

>> Specifying an alignment for a type means "don't reduce" the alignment
>> for any allocations of objects of this type and "don't assume 
>> increased" alignment for any objects accessed of this type.
>
> I think everyone agrees about this.  The alignment for a type is a 
> contract between definitions and uses.
>
> So, what exactly do we need to be able to express?
>
> 1) For types, we want to be able to force a minimum alignment for
>   efficiency/correctness of access.
> 2) For fields, we want to be able to force a minimum alignment.
> 3) For fields, we want to be able to reduce alignment for packing 
> efficiency.
Note where you write "field", this really means "component of a
composite type", where a composite type can either be a record
or array.
> 4) For objects, we want to be able to force a minimum alignment.
Yes, where minimum alignment is not smaller than the type alignment.
> 5) For objects, we want to be able to force an exact alignment for 
> building up special sections (and for other reasons?).
How would this interact with reordering of objects (for example,
sorting by decreasing size, or for increasing cache efficiency)?
Also, do we guarantee that the compiler will not decide to output
extra objects between user-defined ones?
> 1 is handled by TYPE_ALIGN/TYPE_USER_ALIGN.
> 2 and 4/5 are handled by DECL_ALIGN/DECL_USER_ALIGN.
> 3 is handled by DECL_PACKED.
>
> It seems to me that the question people have been arguing about is 
> what to do about the distinction between 4 and 5.  I think that 
> DECL_USER_ALIGN was intended to mean 2, which logically extends to 4.
Agreed.
>
> rth's patch of 2001-08-15 changed it to mean 5.
>
> It makes sense to inherit DECL_USER_ALIGN from TYPE_USER_ALIGN if it 
> means 4, but not if it means 5; that's why we're seeing the S/390 
> problem.

I don't think inheriting is a good idea, even for 4. This way
we loose the capability to over-align objects for which no specific
alignment was specified. It is important that we can do this,
especially as it allows small records to be stored in registers.
> There would seem to be two ways to fix this:
>
> A) Stop inheriting DECL_USER_ALIGN from TYPE_USER_ALIGN on VAR_DECLs.
> B) Change DECL_USER_ALIGN to mean 4, and use DECL_PACKED to mean 5.
>
> I'm partial to solution B.  Other opinions?

I'm in favor of A, since it differentiates between the case where
the compiler has freedom to choose the alignment that gives the
most efficient code on each machine and the case where the user
has good reasons to pin down the details.

   -Geert



More information about the Gcc mailing list