Make max_align_t respect _Float128.
authorJoseph Myers <joseph@codesourcery.com>
Mon, 19 Sep 2016 21:51:56 +0000 (22:51 +0100)
committerJoseph Myers <jsm28@gcc.gnu.org>
Mon, 19 Sep 2016 21:51:56 +0000 (22:51 +0100)
The _FloatN, _FloatNx, _DecimalN and _DecimalNx types are specified in
such a way that they are basic types, meaning that max_align_t must be
at least as aligned as those types.

On 32-bit x86, max_align_t is currently 8-byte aligned, but
_Decimal128 and _Float128 are 16-byte aligned, so the alignment of
max_align_t needs to increase to meet the standard requirements for
these types.

This patch implements such an increase.  Because max_align_t needs to
be usable for C++ as well as for C, <stddef.h> can't actually refer to
_Float128, but needs to use __float128 (or some other notation for the
type) instead.  And since __float128 is architecture-specific, there
isn't a preprocessor conditional that means "__float128 is available"
(whereas one could test __FLT128_MANT_DIG__ to see if _Float128 is
available; __SIZEOF_FLOAT128__ is available on x86 only).  But I
believe the only case that actually has an alignment problem here is
32-bit x86, and <stddef.h> already has lots of conditional specific to
particular architectures or OSes, so this patch uses a conditional on
__i386__; that also is the minimal change that ensures neither size
nor alignment of max_align_t is changed in any case other than where
it is necessary.  If any other architectures turn out to have such an
issue, it will show up as failures of one of the testcases added by
this patch.

Such an increase is of course an ABI change, but a reasonably safe
one, in that max_align_t doesn't tend to appear in library interfaces
(rather, it's something to use when writing allocators and similar
code; most matches found on codesearch.debian.net look like copies of
the gnulib stddef.h module rather than anything actually using
max_align_t at all).

max_align_t_align has a corresponding change (adding _Float128 to the
types considered).

(I think glibc malloc alignment should also increase to 16-byte on
32-bit x86 so it works for allocating objects of these types, which is
now straightforward given the fix made for 32-bit powerpc.)

Bootstrapped with no regressions on x86_64-pc-linux-gnu, and
spot-tested with -m32 that the new float128-align.c test now compiles
where previously it didn't.

gcc:
* ginclude/stddef.h (max_align_t) [__i386__]: Add __float128
element.

gcc/c-family:
* c-common.c (max_align_t_align): Also consider alignment of
float128_type_node.

gcc/testsuite:
* gcc.dg/float128-align.c, gcc.dg/float128x-align.c,
gcc.dg/float16-align.c, gcc.dg/float32-align.c,
gcc.dg/float32x-align.c, gcc.dg/float64-align.c,
gcc.dg/float64x-align.c, gcc.dg/floatn-align.h: New tests.

From-SVN: r240248

13 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/ginclude/stddef.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/float128-align.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/float128x-align.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/float16-align.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/float32-align.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/float32x-align.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/float64-align.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/float64x-align.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/floatn-align.h [new file with mode: 0644]

index bc0be5ca932a22269be8e76f95a5eacf5186f420..e3ec20e9020da9d1b5c01d34d5937e52a9388c4d 100644 (file)
@@ -1,3 +1,8 @@
+2016-09-19  Joseph Myers  <joseph@codesourcery.com>
+
+       * ginclude/stddef.h (max_align_t) [__i386__]: Add __float128
+       element.
+
 2016-09-19  Vladimir Makarov  <vmakarov@redhat.com>
 
        PR rtl-optimization/77416
index fa9b96140fd97e40119a0eddd2d7c43c9334474c..41afbc5af9b760f994664c0eea63c0a1ff371554 100644 (file)
@@ -1,3 +1,8 @@
+2016-09-19  Joseph Myers  <joseph@codesourcery.com>
+
+       * c-common.c (max_align_t_align): Also consider alignment of
+       float128_type_node.
+
 2016-09-15  Jason Merrill  <jason@redhat.com>
 
        * c-common.c (check_cxx_fundamental_alignment_constraints): Check
index fc256867ec5fbe05191603400f53d81d4914fdc4..b6545c08105dace088dfb2f447553787e9472cc6 100644 (file)
@@ -12850,8 +12850,11 @@ scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1,
 unsigned
 max_align_t_align ()
 {
-  return MAX (TYPE_ALIGN (long_long_integer_type_node),
-             TYPE_ALIGN (long_double_type_node));
+  unsigned int max_align = MAX (TYPE_ALIGN (long_long_integer_type_node),
+                               TYPE_ALIGN (long_double_type_node));
+  if (float128_type_node != NULL_TREE)
+    max_align = MAX (max_align, TYPE_ALIGN (float128_type_node));
+  return max_align;
 }
 
 /* Return true iff ALIGN is an integral constant that is a fundamental
index d711530d0535c7adc6f32948d5a0c95f9c1d0e06..ced2d8555ee0624f43e6bf8f9945a0ef10f82104 100644 (file)
@@ -426,6 +426,14 @@ typedef __WINT_TYPE__ wint_t;
 typedef struct {
   long long __max_align_ll __attribute__((__aligned__(__alignof__(long long))));
   long double __max_align_ld __attribute__((__aligned__(__alignof__(long double))));
+  /* _Float128 is defined as a basic type, so max_align_t must be
+     sufficiently aligned for it.  This code must work in C++, so we
+     use __float128 here; that is only available on some
+     architectures, but only on i386 is extra alignment needed for
+     __float128.  */
+#ifdef __i386__
+  __float128 __max_align_f128 __attribute__((__aligned__(__alignof(__float128))));
+#endif
 } max_align_t;
 #endif
 #endif /* C11 or C++11.  */
index 29763fd1a16084286d42bc3ebf7c9341c343bbb3..741ec97005437abea9087ce72f16bc123f0cfcd0 100644 (file)
@@ -1,3 +1,10 @@
+2016-09-19  Joseph Myers  <joseph@codesourcery.com>
+
+       * gcc.dg/float128-align.c, gcc.dg/float128x-align.c,
+       gcc.dg/float16-align.c, gcc.dg/float32-align.c,
+       gcc.dg/float32x-align.c, gcc.dg/float64-align.c,
+       gcc.dg/float64x-align.c, gcc.dg/floatn-align.h: New tests.
+
 2016-09-19  Vladimir Makarov  <vmakarov@redhat.com>
 
        PR rtl-optimization/77416
diff --git a/gcc/testsuite/gcc.dg/float128-align.c b/gcc/testsuite/gcc.dg/float128-align.c
new file mode 100644 (file)
index 0000000..511540b
--- /dev/null
@@ -0,0 +1,9 @@
+/* Test _Float128 alignment.  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float128 } */
+/* { dg-require-effective-target float128 } */
+
+#define WIDTH 128
+#define EXT 0
+#include "floatn-align.h"
diff --git a/gcc/testsuite/gcc.dg/float128x-align.c b/gcc/testsuite/gcc.dg/float128x-align.c
new file mode 100644 (file)
index 0000000..45b3e5b
--- /dev/null
@@ -0,0 +1,9 @@
+/* Test _Float128 alignment.  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float128x } */
+/* { dg-require-effective-target float128x } */
+
+#define WIDTH 128
+#define EXT 1
+#include "floatn-align.h"
diff --git a/gcc/testsuite/gcc.dg/float16-align.c b/gcc/testsuite/gcc.dg/float16-align.c
new file mode 100644 (file)
index 0000000..90e6f45
--- /dev/null
@@ -0,0 +1,9 @@
+/* Test _Float16 alignment.  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float16 } */
+/* { dg-require-effective-target float16 } */
+
+#define WIDTH 16
+#define EXT 0
+#include "floatn-align.h"
diff --git a/gcc/testsuite/gcc.dg/float32-align.c b/gcc/testsuite/gcc.dg/float32-align.c
new file mode 100644 (file)
index 0000000..c881700
--- /dev/null
@@ -0,0 +1,9 @@
+/* Test _Float32 alignment.  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float32 } */
+/* { dg-require-effective-target float32 } */
+
+#define WIDTH 32
+#define EXT 0
+#include "floatn-align.h"
diff --git a/gcc/testsuite/gcc.dg/float32x-align.c b/gcc/testsuite/gcc.dg/float32x-align.c
new file mode 100644 (file)
index 0000000..da396c6
--- /dev/null
@@ -0,0 +1,9 @@
+/* Test _Float32 alignment.  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float32x } */
+/* { dg-require-effective-target float32x } */
+
+#define WIDTH 32
+#define EXT 1
+#include "floatn-align.h"
diff --git a/gcc/testsuite/gcc.dg/float64-align.c b/gcc/testsuite/gcc.dg/float64-align.c
new file mode 100644 (file)
index 0000000..82266e3
--- /dev/null
@@ -0,0 +1,9 @@
+/* Test _Float64 alignment.  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float64 } */
+/* { dg-require-effective-target float64 } */
+
+#define WIDTH 64
+#define EXT 0
+#include "floatn-align.h"
diff --git a/gcc/testsuite/gcc.dg/float64x-align.c b/gcc/testsuite/gcc.dg/float64x-align.c
new file mode 100644 (file)
index 0000000..8916071
--- /dev/null
@@ -0,0 +1,9 @@
+/* Test _Float64 alignment.  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float64x } */
+/* { dg-require-effective-target float64x } */
+
+#define WIDTH 64
+#define EXT 1
+#include "floatn-align.h"
diff --git a/gcc/testsuite/gcc.dg/floatn-align.h b/gcc/testsuite/gcc.dg/floatn-align.h
new file mode 100644 (file)
index 0000000..3196f33
--- /dev/null
@@ -0,0 +1,18 @@
+/* Tests for _FloatN / _FloatNx types: test max_align_t alignment.
+   Before including this file, define WIDTH as the value N; define EXT
+   to 1 for _FloatNx and 0 for _FloatN.  */
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
+
+#if EXT
+# define TYPE CONCAT3 (_Float, WIDTH, x)
+#else
+# define TYPE CONCAT (_Float, WIDTH)
+#endif
+
+#include <stddef.h>
+
+_Static_assert (_Alignof (max_align_t) >= _Alignof (TYPE),
+               "max_align_t must be at least as aligned as _Float* types");