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

Xiangling Liao via cfe-dev cfe-dev at lists.llvm.org
Thu Aug 20 14:49:42 PDT 2020

Thank you for your explanation. They are very helpful. I agree that we
should only use "PreferredAlignment" for creating a complete object. I will
create a phabricator patch later based on our discussions here for reviews.

And due to migration reasons, we would still propose adding an extra flag
without default argument instead like the following:

/// Set "NeedsPreferredAlignment" as true only when allocating memory for a
variable on

/// the stack or in global/thread local memory. The preferred alignment
applies only to a complete

/// object.

CharUnits ASTContext::getTypeAlignInChars(QualType T, *bool
NeedsPreferredAlignment*) const {
   if (*NeedsPreferredAlignment*)
     return toCharUnitsFromBits(getPreferredTypeAlign(T.getTypePtr()));

   return toCharUnitsFromBits(getTypeAlign(T));

And in the proposed patch, we will go through "getTypeAlignInChars" similar
functions case-by-case and pass a value to the flag as needed.

By doing this, we would expect developers to consciously know and also
patch reviewers consciously agree on which alignment needs to be used.

Later, when we finish the migration process(probably in a few months), we
may remove the flag and replace the "true" flag with invoking
"getPreferredTypeAlign" directly.

Any opinions on this proposal? Please let me know if there are any concerns
and suggestions.

Thank you,


On Thu, Aug 20, 2020 at 12:35 PM David Rector <davrecthreads at gmail.com>

> 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>
> 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,
> Dave
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200820/0e806ac9/attachment-0001.html>

More information about the cfe-dev mailing list