[cfe-dev] [RFC] Use preferred alignment instead of ABI alignment for complete object when applicable

David Rector via cfe-dev cfe-dev at lists.llvm.org
Thu Aug 20 09:35:18 PDT 2020

> On Aug 20, 2020, at 9:26 AM, James Y Knight <jyknight at google.com> wrote:
> On Wed, Aug 19, 2020 at 8:53 PM David Rector <davrecthreads at gmail.com <mailto:davrecthreads at gmail.com>> wrote:
> For that matter "preferred alignment" is also confusing.  Who prefers it?  When might that preference not be met?
> Here is my full understanding so far, expressed in the hope that pointing out my confusions here might better help answer Xiangling’s questions below:
> The "ABI" alignment of a type = the ABI-guaranteed minimum alignment of any object of that type built by any standard-conformant compiler.
> Correct, this is the guaranteed alignment of any(***) object of that type (either top-level complete object or a subobject).
> The "preferred" alignment of a type = the actual alignment, at least as large as the ABI alignment, that our compiler will always use in constructing an object of that type.
> When constructing a global or local variable, yes, we do.
> Therefore, whenever we are dealing with an object we know our compiler has constructed, we can use the "preferred" alignment.
> And thereby take advantage of target-specific optimizations like AIX.
> However, whenever we are dealing with e.g. a pointer to an object we are not sure we built — i.e. which may have been constructed within a function not compiled by our compiler (e.g. a function compiled without AIX in some library might have constructed that object and passed a pointer to it to some function our compiler is presently building) -- we are forced to use only the ABI-guaranteed minimum alignment.
> `-And thereby miss out on AIX.
> The most critical difference isn't really our compiler vs someone else's compiler. The "preferred" alignment is actually part of the ABI, too (yet another reason why "ABI alignment" is an awful name, and "guaranteed alignment" is better).
> The preferred alignment applies only to creation of a full object, not, for example, to fields within a struct. E.g. on x86-32:
>    struct Foo { int i; double d; }; 
> the double is placed at offset 4 within the struct, not 8. So, on x86-32, when we have a pointer than could be pointing to such an object, we must only assume the pointee has alignment of 4, not 8.
> Whenever a type has alignas(N), that alignment will be returned for…both the ABI and the preferred alignments?  It will override both?  Is that right?  I recall it overrides the preferred alignment in Xiangling’s implementation, at least, not sure about the ABI case.
> Yes. Except that alignas can never reduce the alignment below the guaranteed alignment according to the C/C++ language rules, so in effect it can only override preferred alignment. (The nonstandard `__attribute__((aligned))` and `__attribute__((packed))` can reduce alignment below the default abi alignment, and in that case, you do override both.)
> alignof(T) / __alignof(T) must return the "ABI" and "preferred" alignments of T, respectively.
> Yep.
> ***: Of course, with the nonstandard packed/aligned attributes, you can create objects which violate these alignment guarantees. If you do so, you must be extremely careful to only access such an object through the appropriately attributed type, and not through a normal unadorned pointer.

Thank you for this great explanation.  I agree that calling the minimum-guaranteed alignment the "ABI" alignment is a big source of confusion.

It sounds like Xiangling’s most feasible option is to change dynamic memory allocation to build objects using their preferred alignment, but perhaps that may not have any great effect since the minimum alignment used in such cases is already quite high (8 or 16 as you say). 

To the extent their are benefits to accessing a pointee using its "preferred" vs. "ABI" alignment, perhaps Xiangling and the rest of us would benefit from a new attribute which guarantees either that, if a particular type is ever placed within an aggregate, that subobject is aligned according to its preferred alignment (i.e., as if it were not in an aggregate at all).  

This could either be a class attribute applied to every instance, e.g. 
struct __attribute__((preferred_aligned)) Foo {…};

Or to support it built in types too it could be enforced as a type qualifier on variables/parameters a la "const", e.g.
void f(__attribute__((preferred_aligned)) double *d, 
       __attribute__((preferred_aligned)) Foo *f);

For any type so qualified, we could always use its preferred alignment, as Xiangling wishes.  

Of course by solving the potential-subobject problem we would then have to confront the interfacing-with-other-compilers problem, but if they were assumed to play along, perhaps there could be significant benefits.

I’m sure I'm still missing something but in any case I look forward to seeing how this is resolved -- thanks James and good luck Xiangling,


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200820/c33da5ac/attachment-0001.html>

More information about the cfe-dev mailing list