Re: Where attribute((aligned)) is allowed to decrease alignment

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi!

On Fri, Jun 13, 2025 at 08:21:34PM +0100, Tom V wrote:
> On Fri, 13 Jun 2025 13:37 Segher Boessenkool wrote:
> > On Fri, Jun 13, 2025 at 06:52:19PM +0100, Tom V wrote:
> 
> > As the documentation says:
> >      When used on a struct, or struct member, the 'aligned' attribute
> >      can only increase the alignment; in order to decrease it, the
> >      'packed' attribute must be specified as well.  When used as part
> > of a typedef, the 'aligned' attribute can both increase and decrease
> >      alignment, and specifying the 'packed' attribute generates a
> >      warning.
> 
> The documentation is clear for struct members.  I am not asking about
> that (although it is tangentially related).
> 
> Suppose I declare:
> 
> typedef int a_type;
> typedef int __attribute__((aligned(1))) b_type;
> typedef int __attribute__((aligned(32))) c_type;
> 
> a_type * a;
> b_type * b;
> c_type * c;
> 
> a is a pointer to a normally aligned int. 

Normal for the ABI in effect, yes.  Typically "naturally aligned", i.e.
aligned to as many bytes as the size of the datum.

> b is a pointer to a possibly unaligned int.

Yup.  Aligned to a multiple of 1 (if the backend allows that, or maybe a
bit higher), and that indeed might not work, the GIGO principple in full
effect :-)

> c is a pointer to a "super-aligned" int.
> 
> Any time the compiler generates a read or write access to *b it
> correctly generates only instructions that work at non-aligned
> addresses.

I'm not sure how to parse what you say here.  The compiler will generate
whatever code it wants to generate to access an "int", and that code
might not work correctly (or at all) with the datum underaligned (for
the ABI, for the ISA, for whatever :-) )

> On a platform where being more aligned than normal was
> helpful, I expect it would also be able to generate instructions to
> make use of that feature when accessing *c.

Yup.  That is exactly the intended use of attribute ((aligned (...))) .

> However, if I declare the exact same thing in one go without a typedef,
> it doesn't work:
> 
> int * a;
> int __attribute__((aligned(1))) * b;
> int __attribute__((aligned(32))) * c;

You want to put the attribute after the variable name.  What happens if
you do what you write here, the compiler throws an error?  Is that error
less than helpful maybe?

Or, does it work and the pointed to thing is aligned, not the variable?

> The attribute on the pointed-to type can only increase alignment, much
> like a struct member, however because this is not inside a struct,
> adding attribute((packed)) causes an error, so the alignment cannot be
> decreased.

You cannot pack something that is not a thing that can be packed,
sure :-)

> When these are function arguments, the behaviour is different again:
> 
> void foo(int * a);
> void bar(int __attribute__((aligned(1))) * b);
> void baz(int __attribute__((aligned(32))) * c);
> 
> The declarations with the aligned attribute here cause an error.  This

You don't tell us what error.  If you suspect a copiler bug, there is
https://gcc.gnu.org/bugs.html ?

> seems to be a bug.  Obviously a function argument has to be at an exact
> specific location (register or stack) but it seems like the checking
> code that is disallowing the aligned attribute on the argument is
> incorrectly disallowing it on the pointed-to type. 

We might want some extra language in the manual, no matter what.  This
stuff is confusing.  And yes, it has history, some of the text was
written many years before we arrived at the current state of things, so
some of the exposure is likely less than ideal, etc.


Segher



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux