[llvm-dev] Controlling parameter alignment

Momchil Velikov via llvm-dev llvm-dev at lists.llvm.org
Wed Feb 17 04:24:06 PST 2021


Currently we don't have a way to express in LLVM IR the alignment
requirements of the function arguments. The `align` attribute is
applicable to pointers only, and only for some special ways of passing
arguments (e..g `byval`). When implementing AAPCS32/AAPCS64, clang
resorts to dubious hacks of coercing to types, which naturally have
the needed alignment.

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


More information about the llvm-dev mailing list