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

Richard Smith via cfe-dev cfe-dev at lists.llvm.org
Wed Aug 19 14:57:39 PDT 2020


On Wed, 19 Aug 2020 at 12:16, James Y Knight via cfe-dev <
cfe-dev at lists.llvm.org> wrote:

> 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.
>

It seems to me that the term "ABI alignment" is actively confusing matters
here -- both alignment values are part of the ABI in the AIX case. Perhaps
"minimum alignment" would be a better term for the alignment that all
objects of the type are guaranteed to have?

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
>>>>>>
>>>>>> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200819/97ca4492/attachment-0001.html>


More information about the cfe-dev mailing list