But we don't have enough types to cover all the cases.
The problem appeared when passing over-aligned Homogeneous
Floating-Point Aggregates (HFAs). When we pass a type with increased
alignment requirements, for example
struct S {
__attribute__ ((__aligned__(16))) double v[4];
};
Clang uses `[4 x double]` for the parameter, which is passed on the stack
at alignment 8, whereas it should be at alignment 16.
The trick of coercing to, say, `[i128, i128]` does not work, because
the argument may end up in GP registers. A hypothetical coercion to
`[f128, f128]` won't work either, because argument needs to be
expanded to consecutive FP registers and they aren't overlapping on
AArch64 (e.g. Q1 does not overlap D2/D3).
There was a deficiency in the ABI
which is addressed in a proposed fix
(https://github.com/ARM-software/abi-aa/pull/67), which matches GCC
behaviour and the original intent.
With this ABI fix, we would need alignments of 8 and 16 to pass HFA
arguments, although we should be ideally looking at a generic
solution.
There are similar issues with AAPCS32.
One proposal was to adopt the `stackalign` attribute to convey these
alignment requirement, https://reviews.llvm.org/D75903.
Another option is to extend the `align` attribute semantics to apply
to non-pointer arguments (I have a patch for that, which looks very
much as the one above).
To which Reid Kleckner commented like:
> Mostly I think I meant that this will be a big change in the meaning
> of either the align or the alignstack attributes, and that should be
> hashed out on llvm-dev.
>
> Right now align is kind of a hybrid between an optimization annotation
> attribute, like dereferenceable or nonnull, and an ABI attribute, like
> byval or inreg. When align is used with byval, it affects argument
> memory layout. When byval is not present, it is just an optimizer
> hint. IMO, ideally, we should separate those two roles.
>
> I should be able to control the alignment of the memory used to pass a
> pointer argument, at the same time that I annotate which low bits of
> the pointer are known to be zero.
Thoughts?
~chill
--
Compiler scrub, Arm
_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
To double check, the problem is the last argument here
https://godbolt.org/z/Gqva4Y does not carry the align(16)
information anymore, correct?
If so, I don't see an immediate problem with allowing an "alignment"
be applied to non-pointer values. The semantics would probably say
that if the value is demoted to memory/stack, the associated alignment
has to be guaranteed. As noted before [0], `align` is actually a hint
and not a requirement. I'm unsure if we could not make it binding TBH,
will think about that, interested in opinions.
I take it we can't/don't want to legalize the constraints in the
backend, right? I mean, use `%sturct.S* align(16) byval(%sturct.S) %p`
in the IR. On that thought, what happens if we have a `struct S *`
argument in source which we then promote to pass it by value?
Thus, a pointer argument having both `align(A)` and `alignstack(B)`
would itself be allocated at B boundary (if it happens to be passed in
memory),
while it would contain an A-aligned address?
> Using alignstack for byval would also eliminate the special rule (for
> align) there I guess.
So, `byval` arguments adopt the `stackalign` attribute with the same
semantics as the current `align`
and then `align` is invalid for `byval` arguments ?
Looks good to me.
--
Compiler scrub, Arm
Just to be clear, the suggestion is to introduce `alignstack` to
affect argument alignment, while retaining
the current semantics for `align`?
Thus, a pointer argument having both `align(A)` and `alignstack(B)`
would itself be allocated at B boundary (if it happens to be passed in
memory),
while it would contain an A-aligned address?
> Using alignstack for byval would also eliminate the special rule (for
> align) there I guess.
So, `byval` arguments adopt the `stackalign` attribute with the same
semantics as the current `align`
and then `align` is invalid for `byval` arguments ?
From: Reid Kleckner <r...@google.com>
Updating the FE to emit `stackalign` for `byval` arguments would cause quite a bit of churn in the testsuite, but
the updates can be done automatically.
Then in the BE, `byval` arguments will use `stackalign`, missing that, fall back to uisng `align` to affect
stack slot alignment.
~chill