Bug 70066 - alignas imposes the wrong limit on data members
Summary: alignas imposes the wrong limit on data members
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 6.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: 58601
  Show dependency treegraph
 
Reported: 2016-03-03 17:58 UTC by Martin Sebor
Modified: 2016-03-04 17:13 UTC (History)
2 users (show)

See Also:
Host:
Target: x86_64-*-*
Build:
Known to work:
Known to fail: 4.9.3, 5.3.0, 6.0
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2016-03-03 17:58:23 UTC
On the x86_64-*-linux-gnu target, G++ enforces 128 bytes as the maximum alignment for data members, even though GCC accepts much more restrictive alignments.  For example, in the program below the struct is aligned on a 128-byte boundary in C++ but on a 256-byte boundary in C.

The C++ restriction is enforced by the check_cxx_fundamental_alignment_constraints() function defined in c-family/c-common.c.  The function uses the locally defined macro MAX_TARGET_FIELD_ALIGNMENT as the upper bound on the alignment:

  #ifdef BIGGEST_FIELD_ALIGNMENT
  #define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_FIELD_ALIGNMENT
  #else
  #define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_ALIGNMENT
  #endif

The macro BIGGEST_FIELD_ALIGNMENT is not defined in this file, so the function falls back on BIGGEST_ALIGNMENT which is 128 (the __BIGGEST_ALIGNMENT__ user macro is defined to 16).

The BIGGEST_FIELD_ALIGNMENT macro is defined in config/i386/i386.h with the following comment:

  /* ??? Blah -- this macro is used directly by libobjc.  Since it
     supports no vector modes, cut out the complexity and fall back
     on BIGGEST_FIELD_ALIGNMENT.  */
  #ifdef IN_TARGET_LIBS
  #ifdef __x86_64__
  #define BIGGEST_FIELD_ALIGNMENT 128
  ...

which happens to be the same as BIGGEST_ALIGNMENT.  However, both alignments are in *bits* not *bytes* as assumed by the C++ functions, so G++ not only enforces a more restrictive limit than G++, it also uses the wrong units.

In contrast, the far more liberal alignment limit enforced by the C front end in the check_user_alignment() function uses the following test, allowing for alignments of as great as 2^28 bytes:

  else if (i >= HOST_BITS_PER_INT - BITS_PER_UNIT_LOG)
    {
      error ("requested alignment is too large");
      return -1;


$ (set -x; cat t.c; cc="/build/gcc-trunk/gcc/xgcc -B /build/gcc-trunk/gcc"; for lang in c c++; do $cc -S -Wall -Wextra -Wpedantic -x$lang t.c; done)
+ cat t.c
#if !__cplusplus
#  define alignas _Alignas
#endif

struct S { alignas (256) int i; };
+ cc='/build/gcc-trunk/gcc/xgcc -B /build/gcc-trunk/gcc'
+ for lang in c c++
+ /build/gcc-trunk/gcc/xgcc -B /build/gcc-trunk/gcc -S -Wall -Wextra -Wpedantic -xc t.c
+ for lang in c c++
+ /build/gcc-trunk/gcc/xgcc -B /build/gcc-trunk/gcc -S -Wall -Wextra -Wpedantic -xc++ t.c
t.c:5:30: warning: requested alignment 256 is larger than 128 [-Wattributes]
 struct S { alignas (256) int i; };
                              ^
Comment 1 Martin Sebor 2016-03-03 18:00:44 UTC
The behavior looks the same in all supported GCC version going all the way back to 4.9.3.
Comment 2 Andrew Pinski 2016-03-03 18:10:05 UTC
> The BIGGEST_FIELD_ALIGNMENT macro is defined in config/i386/i386.h with the
> following comment:
...
>  #ifdef IN_TARGET_LIBS

This definition version is only ever used in libobjc and libgcc.
Comment 3 Andrew Pinski 2016-03-03 18:13:42 UTC
This is the definition which matters:

/* Minimum size in bits of the largest boundary to which any
   and all fundamental data types supported by the hardware
   might need to be aligned. No data type wants to be aligned
   rounder than this.

   Pentium+ prefers DFmode values to be aligned to 64 bit boundary
   and Pentium Pro XFmode values at 128 bit boundaries.

   When increasing the maximum, also update
   TARGET_ABSOLUTE_BIGGEST_ALIGNMENT.  */

#define BIGGEST_ALIGNMENT \
  (TARGET_IAMCU ? 32 : (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : 128)))
Comment 4 Andrew Pinski 2016-03-03 18:18:47 UTC
@defmac BIGGEST_ALIGNMENT
Biggest alignment that any data type can require on this machine, in
bits.  Note that this is not the biggest alignment that is supported,
just the biggest alignment that, when violated, may cause a fault.
@end defmac


@deftypevr {Target Hook} HOST_WIDE_INT TARGET_ABSOLUTE_BIGGEST_ALIGNMENT
If defined, this target hook specifies the absolute biggest alignment
that a type or variable can have on this machine, otherwise,
@code{BIGGEST_ALIGNMENT} is used.
@end deftypevr

....

#undef TARGET_ABSOLUTE_BIGGEST_ALIGNMENT
#define TARGET_ABSOLUTE_BIGGEST_ALIGNMENT 512




I suspect there is a target issue here or the front-end should be using TARGET_ABSOLUTE_BIGGEST_ALIGNMENT instead.  The back-end is confused about byte vs bit here and even the comment before the definition of BIGGEST_ALIGNMENT is incorrect.
Comment 5 Martin Sebor 2016-03-03 19:13:53 UTC
I should note that attribute aligned is accepted with larger values than 128, so the problem is limited to enforcing the limit requested via the C++ 11 alignas operator.  As evident from the number of bugs linked to bug 58601, alignas and its interaction with attribute aligned suffers from many problems in G++.

While the x86_64 back end might be confused about some of the alignment macros I think the underlying problem here is thec heck_cxx_fundamental_alignment_constraints() function and its use of the macros.