Bug 115954 - Alignment of _Atomic structs incompatible between GCC and LLVM
Summary: Alignment of _Atomic structs incompatible between GCC and LLVM
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 14.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: ABI
Depends on:
Blocks:
 
Reported: 2024-07-16 10:57 UTC by Wilco
Modified: 2024-10-02 12:02 UTC (History)
4 users (show)

See Also:
Host:
Target: aarch64 x86_64-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Wilco 2024-07-16 10:57:31 UTC
The following code shows ABI inconsistencies between GCC and LLVM:

#include <stdio.h>
#include <stdatomic.h>
#include <stdalign.h>

_Atomic struct A3 { char a[3]; } a3;
_Atomic struct A7 { char a[7]; } a7;
_Atomic struct A8 { char a[8]; } a8;
_Atomic struct A9 { char a[9]; } a9;
_Atomic struct A16 { char a[16]; } a16;

int main (void)
{
   printf("size %ld align %ld lockfree %d\n", sizeof (a3), alignof (a3), atomic_is_lock_free (&a3));
   printf("size %ld align %ld lockfree %d\n", sizeof (a7), alignof (a7), atomic_is_lock_free (&a7));
   printf("size %ld align %ld lockfree %d\n", sizeof (a8), alignof (a8), atomic_is_lock_free (&a8));
   printf("size %ld align %ld lockfree %d\n", sizeof (a9), alignof (a9), atomic_is_lock_free (&a9));
   printf("size %ld align %ld lockfree %d\n", sizeof (a16), alignof (a16), atomic_is_lock_free (&a16));
   return 0;
}

Compiled with GCC -O2 -latomic I get this on AArch64:

size 3 align 1 lockfree 1
size 7 align 1 lockfree 1
size 8 align 8 lockfree 1
size 9 align 1 lockfree 0
size 16 align 16 lockfree 0

However LLVM reports:

size 4 align 4 lockfree 1
size 8 align 8 lockfree 1
size 8 align 8 lockfree 1
size 16 align 16 lockfree 1
size 16 align 16 lockfree 1

The same is true for x86_64 GCC:

size 3 align 1 lockfree 0
size 7 align 1 lockfree 1  (due to alignment in libatomic)
size 8 align 8 lockfree 1
size 9 align 1 lockfree 0
size 16 align 16 lockfree 0

and LLVM:

size 4 align 4 lockfree 1
size 8 align 8 lockfree 1
size 8 align 8 lockfree 1
size 16 align 16 lockfree 0
size 16 align 16 lockfree 0

Increasing the alignment of small _Atomic structs to a power of 2 means these will always be lock free rather than sometimes depending on alignment.

This also has the nice property that all types smaller than the maximum supported atomic size are always lock free so there is no need to make libatomic calls.
Comment 1 Richard Biener 2024-07-16 11:10:15 UTC
Not sure what the x86 psABI says here (possibly nothing for aggregate _Atomic).
Comment 2 Richard Biener 2024-07-16 11:18:02 UTC
(In reply to Richard Biener from comment #1)
> Not sure what the x86 psABI says here (possibly nothing for aggregate
> _Atomic).

It doesn't consider _Atomic [influencing the ABI] at all.

Note I think your test queries actual object alignment which a compiler
can of course increase vs. what the ABI requires as minimum alignment,
you should possibly cross-check with alignof/sizeof of the type.

On x86 clang returns size 8 and align 8 for the atomic A7 type (GCC does not).
Comment 3 Richard Biener 2024-07-16 11:21:27 UTC
And I'll note the original JTC1/SC22/WG14 - N2771 Title: C23 Atomics paper
mentions "ABI would have been fully determined to be compatible with non-atomic type, leaving no room to implementations for introducing inconsistencies." but
I can't find where/if this went into the actual standard.
Comment 4 Jonathan Wakely 2024-07-16 11:25:53 UTC
(In reply to Richard Biener from comment #1)
> Not sure what the x86 psABI says here (possibly nothing for aggregate
> _Atomic).

I've been asking for it to say something for years.
https://groups.google.com/g/ia32-abi/c/Tlu6Hs-ohPY
Comment 5 Wilco 2024-07-16 11:27:35 UTC
(In reply to Richard Biener from comment #2)
> (In reply to Richard Biener from comment #1)
> > Not sure what the x86 psABI says here (possibly nothing for aggregate
> > _Atomic).
> 
> It doesn't consider _Atomic [influencing the ABI] at all.
> 
> Note I think your test queries actual object alignment which a compiler
> can of course increase vs. what the ABI requires as minimum alignment,
> you should possibly cross-check with alignof/sizeof of the type.
> 
> On x86 clang returns size 8 and align 8 for the atomic A7 type (GCC does
> not).

I tried using the type for sizeof/alignof, and it returns the same values. So GCC overaligns structs that are an exact power of 2.
Comment 6 Andrew Pinski 2024-07-16 14:45:40 UTC
https://gitlab.com/x86-psABIs/i386-ABI/-/issues/1 for x86_64 abi.

Aarch64 should most likely also do the same ...
Comment 7 Wilco 2024-07-16 15:17:46 UTC
(In reply to Andrew Pinski from comment #6)
> https://gitlab.com/x86-psABIs/i386-ABI/-/issues/1 for x86_64 abi.
> 
> Aarch64 should most likely also do the same ...

Yes, that's why I raised this - GCC only over aligning some sizes seems more an accident rather than a designed ABI.
Comment 9 Andrew Pinski 2024-07-16 19:26:43 UTC
Note this was raised on the LLVM side back in 2016:
https://github.com/llvm/llvm-project/issues/26836
Comment 11 Andrew Pinski 2024-07-16 21:32:54 UTC
Can someone please raise this also to https://github.com/ARM-software/abi-aa/issues ? Looks like the riscv folks are ahead of the curve of defining the size/alignment here, see https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/112  and https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/117 .
Comment 12 Wilco 2024-07-17 09:41:23 UTC
This came out of the AArch64 Atomic ABI design work: https://github.com/ARM-software/abi-aa/pull/256