<div dir="ltr">+Johannes, are there other folks who care about LLVM IR attributes that we can add?<br><br>WDYT about trying to separate actual argument memory alignment from pointer argument alignment?</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Feb 17, 2021 at 4:24 AM Momchil Velikov <<a href="mailto:momchil.velikov@gmail.com">momchil.velikov@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Currently we don't have a way to express in LLVM IR the alignment<br>
requirements of the function arguments. The `align` attribute is<br>
applicable to pointers only, and only for some special ways of passing<br>
arguments (e..g `byval`). When implementing AAPCS32/AAPCS64, clang<br>
resorts to dubious hacks of coercing to types, which naturally have<br>
the needed alignment.<br>
<br>
But we don't have enough types to cover all the cases.<br>
<br>
The problem appeared when passing over-aligned Homogeneous<br>
Floating-Point Aggregates (HFAs). When we pass a type with increased<br>
alignment requirements, for example<br>
<br>
struct S {<br>
  __attribute__ ((__aligned__(16))) double v[4];<br>
};<br>
<br>
Clang uses `[4 x double]` for the parameter, which is passed on the stack<br>
at alignment 8, whereas it should be at alignment 16.<br>
<br>
The trick of coercing to, say, `[i128, i128]` does not work, because<br>
the argument may end up in GP registers. A hypothetical coercion to<br>
`[f128, f128]` won't work either, because argument needs to be<br>
expanded to consecutive FP registers and they aren't overlapping on<br>
AArch64 (e.g. Q1 does not overlap D2/D3).<br>
<br>
There was a deficiency in the ABI<br>
which is addressed in a proposed fix<br>
(<a href="https://github.com/ARM-software/abi-aa/pull/67" rel="noreferrer" target="_blank">https://github.com/ARM-software/abi-aa/pull/67</a>), which matches GCC<br>
behaviour and the original intent.<br>
<br>
With this ABI fix, we would need alignments of 8 and 16 to pass HFA<br>
arguments, although we should be ideally looking at a generic<br>
solution.<br>
<br>
There are similar issues with AAPCS32.<br>
<br>
One proposal was to adopt the `stackalign` attribute to convey these<br>
alignment requirement, <a href="https://reviews.llvm.org/D75903" rel="noreferrer" target="_blank">https://reviews.llvm.org/D75903</a>.<br>
<br>
Another option is to extend the `align` attribute semantics to apply<br>
to non-pointer arguments (I have a patch for that, which looks very<br>
much as the one above).<br>
<br>
To which Reid Kleckner commented like:<br>
<br>
> Mostly I think I meant that this will be a big change in the meaning<br>
> of either the align or the alignstack attributes, and that should be<br>
> hashed out on llvm-dev.<br>
><br>
> Right now align is kind of a hybrid between an optimization annotation<br>
> attribute, like dereferenceable or nonnull, and an ABI attribute, like<br>
> byval or inreg. When align is used with byval, it affects argument<br>
> memory layout. When byval is not present, it is just an optimizer<br>
> hint. IMO, ideally, we should separate those two roles.<br>
><br>
> I should be able to control the alignment of the memory used to pass a<br>
> pointer argument, at the same time that I annotate which low bits of<br>
> the pointer are known to be zero.<br>
<br>
Thoughts?<br>
<br>
~chill<br>
--<br>
Compiler scrub, Arm<br>
</blockquote></div>