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

James Y Knight via cfe-dev cfe-dev at lists.llvm.org
Wed Aug 19 12:16:08 PDT 2020


I wasn't talking about the alignment of a pointer, but rather the alignment
of a value of type 'double', which has a preferred alignment of 8.

Not all double values in memory are 8 byte aligned -- some are placed only
at 4 byte aligned offsets. Therefore, the compiler can only assume an
alignment of 4 for an unknown object of type 'double' -- this is the abi
alignment.

On Tue, Aug 18, 2020, 3:07 PM Xiangling Liao <xiangxdh at gmail.com> wrote:

> Yeah, I agree that the alignment of a pointer to double on AIX should be 4
> under 32-bit.
>
> I should've made it clearer.  By "useless" I mean, we can always trust
> "PreferredAlignment" but not "ABI alignment" to give us the actual
> alignment value on AIX of a type "T".
>
> More specifically, regarding aggregate, double, long double type,
> "PreferredAlignment" gives us the actual alignment of these types. For
> other types, on AIX, "PreferredAlignment" also gives us the actual
> alignment of these types by containing the ABI alignment value underneath.
> So that means, for the example you mentioned previously, even if the
> alignment of the pointer under 32-bit would take "PreferredAlignment", it
> is actually using "ABI alignment" which is 4.
>
> That's why we proposed to use "PreferredAlignment" for AIX almost
> everywhere instead and use "flag" to force using ABI alignment when
> necessary.
>
> And I understand that we can investigate each spot where an ABI alignment
> is used, and may replace it with "PreferredAlignment" if needed, but it
> seems pretty time-consuming and I am not confident to know each usage of
> those four functions well and make the right decision.
>
> Regards,
> Xiangling
>
> On Tue, Aug 18, 2020 at 12:21 PM James Y Knight <jyknight at google.com>
> wrote:
>
>>
>>
>> On Tue, Aug 18, 2020 at 11:01 AM Xiangling Liao <xiangxdh at gmail.com>
>> wrote:
>>
>>> It looks to me as if at least examples 1, 2, and 4 are places that
>>> should *not* be changed to use the "AIX preferred" alignment, because
>>> they are inquiring about the guaranteed alignment of an existing pointer,
>>> which may well not have been placed at the preferred alignment. I haven't
>>> dug into the code beyond your snippet so I'm not sure about examples 3 and
>>> 5.
>>>
>>>
>>>
>>> To be honest, I am not familiar with every snippet where functions like
>>> “getTypeAlignInChars” is used. So I just list some locations that call
>>> “getTypeAlignInChars”. But I did mean that we probably should replace them
>>> with “PreferredAlignment” for AIX.
>>>
>>>
>>>
>>> 1. In AIX rules, not only an aggregate can now have a different
>>> preferred alignment from guaranteed alignment, but also double, long double.
>>>
>>>
>>>
>>> We see the semantic of “PreferredAlignment” on AIX represents a “T”’s
>>> actual alignment. In other words, ABI alignment on AIX is kinda useless
>>> except for being used to let “alignof(T)” return a correct value.
>>>
>>>
>> I feel like there's a fundamental misunderstanding here -- the ABI
>> alignment is not at all useless. Please see my previous email about the two
>> different concepts of alignment.
>>
>> For example, the AIX preferred alignment of 'double' is 8, and the
>> guaranteed ("ABI") alignment is 4. If you compile the following function,
>> the load/store instructions must be emitted with "align 4" and not "align
>> 8" on them, because that's all that you know about a pointer to double.
>>   void foo(double* out, double* in) { *out = *in * 2; }
>>
>> 2. For the example1, you mentioned the “the guaranteed alignment of an
>>> existing pointer may well not have been placed at the preferred alignment”.
>>> But as I know, what function “getPreferredTypeAlign” does is to get the
>>> ABI/guaranteed alignment of a “T” first by invoking “getTypeInfo”, and then
>>> minor adjust some values. So we seems don’t need to worry about we cannot
>>> get a pointer’s ABI alignment, and many other cases as well, if that’s the
>>> correct one for AIX.
>>>
>>>
>>>
>>> Besides, I am not sure if I understand the code snippet right in
>>> example1.
>>>
>>>
>>>
>>>>>>
>>>   // If that failed, return the type's alignment.
>>>
>>>   return S.Context.getTypeAlignInChars(E->getType()->getPointeeType());
>>>
>>> }
>>>
>>>>>>
>>>
>>>
>>> A pointer’s pointeeType can be anything, which may be an aggregate,  double,
>>> or long doble etc. For those types, on AIX, we do need to get the
>>> “PreferredAlignment”?
>>>
>>>
>>>
>>> 3. So far, I didn’t investigate every usage of those four functions:
>>>
>>> 1) getTypeAlignInChars [invokes getTypeAlign]
>>>
>>> 2) getTypeAlign <=> getTypeInfo(T).Align
>>> <https://clang.llvm.org/doxygen/structclang_1_1TypeInfo.html#af98dcefc364629eff868a1bb4010ebd8>
>>>
>>> 3) getTypeInfo [ invokes ‘getTypeInfoImpl’]
>>>
>>> 4) getTypeInfoInChars
>>>
>>>
>>>
>>> Because I am not sure if we really want to spend a lot of time on
>>> digging each crack. An initial scan of them shows a large amount of
>>> them used in Clang. How do you think about this?
>>>
>>>
>>>
>>>
>>>
>>> And most importantly, besides of “adding a flag” way to handle speical
>>> alignment on AIX, I am wondering in which way we can handle it better?
>>>
>>>
>>>
>>>
>>> Regards,
>>> Xiangling
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> On Tue, Aug 18, 2020 at 8:48 AM James Y Knight <jyknight at google.com>
>>> wrote:
>>>
>>>>
>>>>
>>>> On Tue, Aug 18, 2020, 12:54 AM David Rector <davrecthreads at gmail.com>
>>>> wrote:
>>>>
>>>>> I would have to think that, whatever the documentation for  e.g.
>>>>> getTypeAlignInChars(T), most users expect it to return T’s actual
>>>>> alignment for their target, whether it was determined from the ABI, or the
>>>>> AIX alignment scheme, or whatever.
>>>>>
>>>>
>>>> There really are two concepts at play here.
>>>>
>>>> 1. Given a pointer to some object of type T or a field of type T inside
>>>> another object, what can I know for sure about the alignment of that
>>>> pointer? (How many of the low bits are absolutely guaranteed to be 0,
>>>> assuming the program doesn't involve Undefined Behavior?)
>>>>
>>>> 2. If I want to allocate a brand new complete object of type T, at what
>>>> alignment should I use to place it? This must be at least the alignment
>>>> from 1. But beyond that, it could differ by circumstance, e.g. stack,
>>>> global, and function parameter allocations could make different choices. In
>>>> some cases, increasing the alignment of an allocation above the required
>>>> minimum may just be an optimization, but in other cases it has an ABI
>>>> impact.
>>>>
>>>> AIX is not the first platform where these alignments differ -- the type
>>>> 'double' on x86-32 being the other notable example. But, the AIX rules
>>>> trigger differences in more circumstances than we've had before, and thus
>>>> we now need to potentially make a choice in other parts of the code.
>>>> Importantly: in AIX rules, an aggregate can now have a different preferred
>>>> alignment from guaranteed alignment, too.
>>>>
>>>> The first case brought up where this surely matters, is 'new T[100]'
>>>> where T has a destructor. This thread is exploring whether there are other
>>>> such cases that we might need to change, too. I suspect that there are not
>>>> many, but that remains to be determined.
>>>>
>>>>
>>>>
>>>>
>>>>> In fact, maybe we can go further: I would think that any valid use of
>>>>> type alignment which explicitly ignores AIX or other target-specific
>>>>> alignment schemes are probably just implementation details used only in the
>>>>> calculation of some composed type’s alignment under that scheme.  In other
>>>>> words I would assume every function call in which AIX preferred alignment
>>>>> needed to be ignored is in the some layout-building implementation — is
>>>>> that right?
>>>>>
>>>>> E.g. the lib/AST/RecordLayoutBuilder.cpp example you cite below fits
>>>>> this description — in LayoutField(FieldDecl *D, …) you propose to
>>>>> change the call to fetch the ABI/non-AIX type info via
>>>>> getTypeInfo(D->getType(), true/* NeedsABIAlignment */);
>>>>> but only so that you can later tweak that info whenever
>>>>> DefaultsToAIXPowerAlignment==true.
>>>>>
>>>>> If all the changes you would need to make are indeed similar to this,
>>>>> these expanded usages are really only implementation details needed to
>>>>> build type layouts, and thus the goal should simply be to sufficiently hide
>>>>> these details from common programmers who don’t need to build type layouts,
>>>>> only access them.
>>>>>
>>>>> I think your original option #2 ("add a flag"), i.e. adding new
>>>>> defaulted parameters to a few functions, seems to be a reasonable way to
>>>>> hide these new details, so long as the new parameters are well named and
>>>>> documented.  It also seems sufficiently general to be useful for
>>>>> implementing other special default alignment schemes in the future.
>>>>>
>>>>> Dave
>>>>>
>>>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200819/849429a8/attachment-0001.html>


More information about the cfe-dev mailing list