[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
Mon Aug 24 09:09:57 PDT 2020
ping.
On Thu, Aug 20, 2020 at 5:49 PM Xiangling Liao <xiangxdh at gmail.com> wrote:
> 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,
>
> Xiangling
>
>
>
>
>
> On Thu, Aug 20, 2020 at 12:35 PM David Rector <davrecthreads at gmail.com>
> wrote:
>
>>
>>
>> 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/20200824/0a6970d5/attachment.html>
More information about the cfe-dev
mailing list