Add alloc_align attribute to memalign et al

GCC 4.9.0 added the alloc_align attribute to say that a function
argument specifies the alignment of the returned pointer. Clang supports
the attribute too. Using the attribute can allow a compiler to generate
better code if it knows the returned pointer has a minimum alignment.
See https://gcc.gnu.org/PR60092 for more details.

GCC implicitly knows the semantics of aligned_alloc and posix_memalign,
but not the obsolete memalign. As a result, GCC generates worse code
when memalign is used, compared to aligned_alloc.  Clang knows about
aligned_alloc and memalign, but not posix_memalign.

This change adds a new __attribute_alloc_align__ macro to <sys/cdefs.h>
and then uses it on memalign (where it helps GCC) and aligned_alloc
(where GCC and Clang already know the semantics, but it doesn't hurt)
and xposix_memalign. It can't be used on posix_memalign because that
doesn't return a pointer (the allocated pointer is returned via a void**
parameter instead).

Unlike the alloc_size attribute, alloc_align only allows a single
argument. That means the new __attribute_alloc_align__ macro doesn't
really need to be used with double parentheses to protect a comma
between its arguments. For consistency with __attribute_alloc_size__
this patch defines it the same way, so that double parentheses are
required.

Signed-off-by: Jonathan Wakely <jwakely@redhat.com>

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
This commit is contained in:
Jonathan Wakely 2021-10-06 20:05:48 +01:00
parent aa783f9a7b
commit 8a9a593115
4 changed files with 19 additions and 5 deletions

View file

@ -1,5 +1,6 @@
/* Prototypes and definition for malloc implementation. /* Prototypes and definition for malloc implementation.
Copyright (C) 1996-2021 Free Software Foundation, Inc. Copyright (C) 1996-2021 Free Software Foundation, Inc.
Copyright The GNU Toolchain Authors.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -64,8 +65,8 @@ extern void free (void *__ptr) __THROW;
/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
extern void *memalign (size_t __alignment, size_t __size) extern void *memalign (size_t __alignment, size_t __size)
__THROW __attribute_malloc__ __attribute_alloc_size__ ((2)) __wur __THROW __attribute_malloc__ __attribute_alloc_align__ ((1))
__attr_dealloc_free; __attribute_alloc_size__ ((2)) __wur __attr_dealloc_free;
/* Allocate SIZE bytes on a page boundary. */ /* Allocate SIZE bytes on a page boundary. */
extern void *valloc (size_t __size) __THROW __attribute_malloc__ extern void *valloc (size_t __size) __THROW __attribute_malloc__

View file

@ -1,4 +1,5 @@
/* Copyright (C) 1992-2021 Free Software Foundation, Inc. /* Copyright (C) 1992-2021 Free Software Foundation, Inc.
Copyright The GNU Toolchain Authors.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -290,6 +291,15 @@
# define __attribute_alloc_size__(params) /* Ignore. */ # define __attribute_alloc_size__(params) /* Ignore. */
#endif #endif
/* Tell the compiler which argument to an allocation function
indicates the alignment of the allocation. */
#if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__alloc_align__)
# define __attribute_alloc_align__(param) \
__attribute__ ((__alloc_align__ param))
#else
# define __attribute_alloc_align__(param) /* Ignore. */
#endif
/* At some point during the gcc 2.96 development the `pure' attribute /* At some point during the gcc 2.96 development the `pure' attribute
for functions was introduced. We don't want to use it unconditionally for functions was introduced. We don't want to use it unconditionally
(although this would be possible) since it generates warnings. */ (although this would be possible) since it generates warnings. */

View file

@ -1,4 +1,5 @@
/* Copyright (C) 1991-2021 Free Software Foundation, Inc. /* Copyright (C) 1991-2021 Free Software Foundation, Inc.
Copyright The GNU Toolchain Authors.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -589,7 +590,8 @@ extern int posix_memalign (void **__memptr, size_t __alignment, size_t __size)
#ifdef __USE_ISOC11 #ifdef __USE_ISOC11
/* ISO C variant of aligned allocation. */ /* ISO C variant of aligned allocation. */
extern void *aligned_alloc (size_t __alignment, size_t __size) extern void *aligned_alloc (size_t __alignment, size_t __size)
__THROW __attribute_malloc__ __attribute_alloc_size__ ((2)) __wur; __THROW __attribute_malloc__ __attribute_alloc_align__ ((1))
__attribute_alloc_size__ ((2)) __wur;
#endif #endif
/* Abort execution and generate a core-dump. */ /* Abort execution and generate a core-dump. */

View file

@ -1,5 +1,6 @@
/* Common extra functions. /* Common extra functions.
Copyright (C) 2016-2021 Free Software Foundation, Inc. Copyright (C) 2016-2021 Free Software Foundation, Inc.
Copyright The GNU Toolchain Authors.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -104,8 +105,8 @@ extern void *xrealloc (void *o, size_t n)
extern char *xstrdup (const char *) __attribute_malloc__ __attr_dealloc_free extern char *xstrdup (const char *) __attribute_malloc__ __attr_dealloc_free
__returns_nonnull; __returns_nonnull;
void *xposix_memalign (size_t alignment, size_t n) void *xposix_memalign (size_t alignment, size_t n)
__attribute_malloc__ __attribute_alloc_size__ ((2)) __attr_dealloc_free __attribute_malloc__ __attribute_alloc_align__ ((1))
__returns_nonnull; __attribute_alloc_size__ ((2)) __attr_dealloc_free __returns_nonnull;
char *xasprintf (const char *format, ...) char *xasprintf (const char *format, ...)
__attribute__ ((format (printf, 1, 2), malloc)) __attr_dealloc_free __attribute__ ((format (printf, 1, 2), malloc)) __attr_dealloc_free
__returns_nonnull; __returns_nonnull;