git: 8fa6abb6f4f6 - main - Expose clang's alignment builtins and use them for roundup2/rounddown2
Ryan Libby
rlibby at freebsd.org
Wed Feb 17 20:46:50 UTC 2021
On Wed, Feb 3, 2021 at 8:04 AM Alex Richardson <arichardson at freebsd.org> wrote:
>
> The branch main has been updated by arichardson:
>
> URL: https://cgit.FreeBSD.org/src/commit/?id=8fa6abb6f4f64f4f23e2920e2aea7996566851a4
>
> commit 8fa6abb6f4f64f4f23e2920e2aea7996566851a4
> Author: Alex Richardson <arichardson at FreeBSD.org>
> AuthorDate: 2021-02-03 15:27:17 +0000
> Commit: Alex Richardson <arichardson at FreeBSD.org>
> CommitDate: 2021-02-03 16:02:54 +0000
>
> Expose clang's alignment builtins and use them for roundup2/rounddown2
>
> This makes roundup2/rounddown2 type- and const-preserving and allows
> using it on pointer types without casting to uintptr_t first. Not
> performing pointer-to-integer conversions also helps the compiler's
> optimization passes and can therefore result in better code generation.
> When using it with integer values there should be no change other than
> the compiler checking that the alignment value is a valid power-of-two.
>
> I originally implemented these builtins for CHERI a few years ago and
> they have been very useful for CheriBSD. However, they are also useful
> for non-CHERI code so I was able to upstream them for Clang 10.0.
>
> Rationale from the clang documentation:
> Clang provides builtins to support checking and adjusting alignment
> of pointers and integers. These builtins can be used to avoid relying
> on implementation-defined behavior of arithmetic on integers derived
> from pointers. Additionally, these builtins retain type information
> and, unlike bitwise arithmetic, they can perform semantic checking on
> the alignment value.
>
> There is also a feature request for GCC, so GCC may also support it in
> the future: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98641
>
> Reviewed By: brooks, jhb, imp
> Differential Revision: https://reviews.freebsd.org/D28332
> ---
> sys/sys/cdefs.h | 19 +++++++++++++++++++
> sys/sys/param.h | 4 ++--
> 2 files changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/sys/sys/cdefs.h b/sys/sys/cdefs.h
> index 75bedd4b8128..72ef942084f2 100644
> --- a/sys/sys/cdefs.h
> +++ b/sys/sys/cdefs.h
> @@ -884,4 +884,23 @@
> #define __guarded_by(x) __lock_annotate(guarded_by(x))
> #define __pt_guarded_by(x) __lock_annotate(pt_guarded_by(x))
>
> +/* Alignment builtins for better type checking and improved code generation. */
> +/* Provide fallback versions for other compilers (GCC/Clang < 10): */
> +#if !__has_builtin(__builtin_is_aligned)
> +#define __builtin_is_aligned(x, align) \
> + (((__uintptr_t)x & ((align) - 1)) == 0)
> +#endif
> +#if !__has_builtin(__builtin_align_up)
> +#define __builtin_align_up(x, align) \
> + ((__typeof__(x))(((__uintptr_t)(x)+((align)-1))&(~((align)-1))))
> +#endif
> +#if !__has_builtin(__builtin_align_down)
> +#define __builtin_align_down(x, align) \
> + ((__typeof__(x))((x)&(~((align)-1))))
> +#endif
> +
> +#define __align_up(x, y) __builtin_align_up(x, y)
> +#define __align_down(x, y) __builtin_align_down(x, y)
> +#define __is_aligned(x, y) __builtin_is_aligned(x, y)
> +
Since these are only valid for powers of 2, I think it would be good to
indicate that in the names (__align_up2() etc).
> #endif /* !_SYS_CDEFS_H_ */
> diff --git a/sys/sys/param.h b/sys/sys/param.h
> index 079357a19d47..d6f1eb21dcd2 100644
> --- a/sys/sys/param.h
> +++ b/sys/sys/param.h
> @@ -305,9 +305,9 @@
> #endif
> #define nitems(x) (sizeof((x)) / sizeof((x)[0]))
> #define rounddown(x, y) (((x)/(y))*(y))
> -#define rounddown2(x, y) ((x)&(~((y)-1))) /* if y is power of two */
> +#define rounddown2(x, y) __align_down(x, y) /* if y is power of two */
> #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */
> -#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
> +#define roundup2(x, y) __align_up(x, y) /* if y is powers of two */
> #define powerof2(x) ((((x)-1)&(x))==0)
>
> /* Macros for min/max. */
This broke the gcc build:
https://ci.freebsd.org/job/FreeBSD-main-amd64-gcc6_build/3200/console
00:40:30 --- all_subdir_firewire ---
00:40:30 In file included from /workspace/src/sys/sys/types.h:43:0,
00:40:30 from /workspace/src/sys/sys/param.h:99,
00:40:30 from /workspace/src/sys/dev/firewire/fwohci.c:40:
00:40:30 /workspace/src/sys/dev/firewire/fwohci.c: In function
'fwohci_get_plen':
00:40:30 /workspace/src/sys/dev/firewire/fwohci.c:2699:17: error:
'typeof' applied to a bit-field
00:40:30 r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t));
We could:
- Drop the cast for the fallback.
- Cast with (__typeof__(+(x))) which unfortunately promotes e.g. char
to int but otherwise I think behaves okay, and the promotion was
previously happening for roundup2/rounddown2 anyway.
- Punt the casting burden to callers of roundup2/rounddown2.
Ryan
More information about the dev-commits-src-all
mailing list