[PATCH 1/3] Compiler Attributes: Add __assume macro

Heiko Carstens posted 3 patches 4 months, 4 weeks ago
There is a newer version of this series
[PATCH 1/3] Compiler Attributes: Add __assume macro
Posted by Heiko Carstens 4 months, 4 weeks ago
Make the statement attribute "assume" with a new __assume macro available.

This allows compilers to generate better code, however code which makes use
of __assume must be written as if the compiler ignores the hint. Otherwise
this may lead to subtle bugs if code is compiled with compilers which do
not support the attribute.

Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
---
 include/linux/compiler_attributes.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
index c16d4199bf92..16c3d4a865e2 100644
--- a/include/linux/compiler_attributes.h
+++ b/include/linux/compiler_attributes.h
@@ -54,6 +54,22 @@
  */
 #define __always_inline                 inline __attribute__((__always_inline__))
 
+/*
+ * Beware: Code which makes use of __assume must be written as if the compiler
+ * ignores the hint. Otherwise this may lead to subtle bugs if code is compiled
+ * with compilers which do not support the attribute.
+ *
+ * Optional: only supported since GCC >= 13.1, clang >= 12.0
+ *
+ *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#index-assume-statement-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#assume
+ */
+#if __has_attribute(assume)
+# define __assume(expr)                 __attribute__((__assume__(expr)))
+#else
+# define __assume(expr)
+#endif
+
 /*
  * The second argument is optional (default 0), so we use a variadic macro
  * to make the shorthand.
-- 
2.48.1
Re: [PATCH 1/3] Compiler Attributes: Add __assume macro
Posted by Miguel Ojeda 4 months, 4 weeks ago
On Wed, Sep 10, 2025 at 5:12 PM Heiko Carstens <hca@linux.ibm.com> wrote:
>
> + * Beware: Code which makes use of __assume must be written as if the compiler
> + * ignores the hint. Otherwise this may lead to subtle bugs if code is compiled
> + * with compilers which do not support the attribute.

I am not sure I understand this "Beware:" comment: is it referring to
evaluation side-effects? If so, the GCC docs say it is not evaluated.
The real danger is triggering UB with it, but that is different, i.e.
one needs to be really, really sure the expression is true.

Cheers,
Miguel
Re: [PATCH 1/3] Compiler Attributes: Add __assume macro
Posted by Heiko Carstens 4 months, 3 weeks ago
On Thu, Sep 11, 2025 at 08:59:29PM +0200, Miguel Ojeda wrote:
> On Wed, Sep 10, 2025 at 5:12 PM Heiko Carstens <hca@linux.ibm.com> wrote:
> >
> > + * Beware: Code which makes use of __assume must be written as if the compiler
> > + * ignores the hint. Otherwise this may lead to subtle bugs if code is compiled
> > + * with compilers which do not support the attribute.
> 
> I am not sure I understand this "Beware:" comment: is it referring to
> evaluation side-effects? If so, the GCC docs say it is not evaluated.
> The real danger is triggering UB with it, but that is different, i.e.
> one needs to be really, really sure the expression is true.

No, I was referring to the original build error where the missing "& 127" lead
to a warning / build error. So what I was trying to say: if you have a
construct like:

	...
	return a & 127;

and then make this:

	...
	__assume(a < 64);
	return a & 127;

then it is not possible to leave the "& 127" part away, since __assume() is
optional. But thinking about this again, I guess the comment is misleading,
like also your reply proved.

This is not about subtle bugs, but just an optimization that is not being
done, which may or may not lead to compile time warnings for the particular
case I was trying to improve; but the code would be correct in any case, as
long as __assume() is used correctly.

I'll rephrase the comment, and split / reorder patches differently so it is
(hopefully) more obvious what I try to achieve: allow for micro-optimizations
of inline assembly outputs.
Re: [PATCH 1/3] Compiler Attributes: Add __assume macro
Posted by Nathan Chancellor 4 months, 4 weeks ago
Hi Heiko,

On Wed, Sep 10, 2025 at 05:12:14PM +0200, Heiko Carstens wrote:
> Make the statement attribute "assume" with a new __assume macro available.
> 
> This allows compilers to generate better code, however code which makes use
> of __assume must be written as if the compiler ignores the hint. Otherwise
> this may lead to subtle bugs if code is compiled with compilers which do
> not support the attribute.
> 
> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
> ---
>  include/linux/compiler_attributes.h | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
> index c16d4199bf92..16c3d4a865e2 100644
> --- a/include/linux/compiler_attributes.h
> +++ b/include/linux/compiler_attributes.h
> @@ -54,6 +54,22 @@
>   */
>  #define __always_inline                 inline __attribute__((__always_inline__))
>  
> +/*
> + * Beware: Code which makes use of __assume must be written as if the compiler
> + * ignores the hint. Otherwise this may lead to subtle bugs if code is compiled
> + * with compilers which do not support the attribute.

It may be worth noting that careful analysis should be performed when
adding this attribute since clang's documentation [1] (more on that
below...) notes that it could hurt optimizations just as much as it
could help it.

> + *
> + * Optional: only supported since GCC >= 13.1, clang >= 12.0
> + *
> + *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#index-assume-statement-attribute
> + * clang: https://clang.llvm.org/docs/AttributeReference.html#assume

Looking at this link sent me down a bit of a rabbit hole :) Prior to
Clang 19.1.0 [2], assume was an OpenMP attribute, which has completely
different semantics and errors out when used in the way the series does:

  In file included from kernel/bounds.c:13:
  In file included from include/linux/log2.h:12:
  In file included from include/linux/bitops.h:67:
  arch/s390/include/asm/bitops.h:173:12: error: expected string literal as argument of '__assume__' attribute
    173 |                 __assume(bit <= 64);
        |                          ^

Unfortunately, I think __assume will need to be handled in the compiler
specific headers :/

[1]: https://clang.llvm.org/docs/AttributeReference.html#id13
[2]: https://github.com/llvm/llvm-project/commit/c44fa3e8a9a44c2e9a575768a3c185354b9f6c17

Cheers,
Nathan

> + */
> +#if __has_attribute(assume)
> +# define __assume(expr)                 __attribute__((__assume__(expr)))
> +#else
> +# define __assume(expr)
> +#endif
> +
>  /*
>   * The second argument is optional (default 0), so we use a variadic macro
>   * to make the shorthand.
> -- 
> 2.48.1
>
Re: [PATCH 1/3] Compiler Attributes: Add __assume macro
Posted by Miguel Ojeda 4 months, 4 weeks ago
On Thu, Sep 11, 2025 at 3:32 AM Nathan Chancellor <nathan@kernel.org> wrote:
>
> It may be worth noting that careful analysis should be performed when
> adding this attribute since clang's documentation [1] (more on that
> below...) notes that it could hurt optimizations just as much as it
> could help it.

Yeah, it can be tricky, and I assume it may depend on the compiler
version too, i.e. the result could change over time. At least for
"build asserts relying on optimizations" it is clear if it stops
working, but here I assume we may have new compiler versions getting
released that stop doing what the developer intended. But perhaps is
not a problem in practice for the cases we care? Does someone know?

> Looking at this link sent me down a bit of a rabbit hole :) Prior to
> Clang 19.1.0 [2], assume was an OpenMP attribute, which has completely
> different semantics and errors out when used in the way the series does:

Oh... :(

Cheers,
Miguel
Re: [PATCH 1/3] Compiler Attributes: Add __assume macro
Posted by Heiko Carstens 4 months, 4 weeks ago
On Wed, Sep 10, 2025 at 06:32:43PM -0700, Nathan Chancellor wrote:
> > + *
> > + * Optional: only supported since GCC >= 13.1, clang >= 12.0
> > + *
> > + *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#index-assume-statement-attribute
> > + * clang: https://clang.llvm.org/docs/AttributeReference.html#assume
> 
> Looking at this link sent me down a bit of a rabbit hole :) Prior to
> Clang 19.1.0 [2], assume was an OpenMP attribute, which has completely
> different semantics and errors out when used in the way the series does:
> 
>   In file included from kernel/bounds.c:13:
>   In file included from include/linux/log2.h:12:
>   In file included from include/linux/bitops.h:67:
>   arch/s390/include/asm/bitops.h:173:12: error: expected string literal as argument of '__assume__' attribute
>     173 |                 __assume(bit <= 64);
>         |                          ^
> 
> Unfortunately, I think __assume will need to be handled in the compiler
> specific headers :/
> 
> [1]: https://clang.llvm.org/docs/AttributeReference.html#id13
> [2]: https://github.com/llvm/llvm-project/commit/c44fa3e8a9a44c2e9a575768a3c185354b9f6c17

Thank you for having look. This is quite surprising. So after looking into the
various header files it might be acceptable to add this to compiler_types.h,
since there seem to be a few similar constructs.

Maybe something like this(?):

From d9d67807e6854666507e55d9ac0c7b4ec659aa99 Mon Sep 17 00:00:00 2001
From: Heiko Carstens <hca@linux.ibm.com>
Date: Wed, 10 Sep 2025 14:18:07 +0200
Subject: [PATCH] compiler_types: Add __assume macro

Make the statement attribute "assume" with a new __assume macro available.

This allows compilers to generate better code, however code which makes use
of __assume must be written as if the compiler ignores the hint. Otherwise
this may lead to subtle bugs if code is compiled with compilers which do
not support the attribute.

Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
---
 include/linux/compiler_types.h | 20 ++++++++++++++++++++
 init/Kconfig                   | 10 ++++++++++
 2 files changed, 30 insertions(+)

diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index 16755431fc11..38a52a792e48 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -329,6 +329,26 @@ struct ftrace_likely_data {
 #define __no_sanitize_or_inline __always_inline
 #endif
 
+/*
+ * Beware: Code which makes use of __assume must be written as if the compiler
+ * ignores the hint. Otherwise this may lead to subtle bugs if code is compiled
+ * with compilers which do not support the attribute.
+ * Using this attribute requires careful analysis, since in some cases it may
+ * generate worse code (see clang documentation).
+ *
+ * Optional: only supported since gcc >= 13
+ * Optional: only supported since clang >= 19
+ *
+ *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#index-assume-statement-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#id13
+ *
+ */
+#ifdef CONFIG_CC_HAS_ASSUME
+# define __assume(expr)			__attribute__((__assume__(expr)))
+#else
+# define __assume(expr)
+#endif
+
 /*
  * Optional: only supported since gcc >= 15
  * Optional: only supported since clang >= 18
diff --git a/init/Kconfig b/init/Kconfig
index e3eb63eadc87..5882c5e74047 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -112,6 +112,16 @@ config TOOLS_SUPPORT_RELR
 config CC_HAS_ASM_INLINE
 	def_bool $(success,echo 'void foo(void) { asm inline (""); }' | $(CC) -x c - -c -o /dev/null)
 
+config CC_HAS_ASSUME
+	bool
+	# clang needs to be at least 19.1.0 since the meaning of the assume
+	# attribute changed:
+	# https://github.com/llvm/llvm-project/commit/c44fa3e8a9a44c2e9a575768a3c185354b9f6c17
+	default y if CC_IS_CLANG && CLANG_VERSION >= 190100
+	# supported since gcc 13.1.0
+	# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106654
+	default y if CC_IS_GCC && GCC_VERSION >= 130100
+
 config CC_HAS_NO_PROFILE_FN_ATTR
 	def_bool $(success,echo '__attribute__((no_profile_instrument_function)) int x();' | $(CC) -x c - -c -o /dev/null -Werror)
 
-- 
2.48.1
Re: [PATCH 1/3] Compiler Attributes: Add __assume macro
Posted by Nathan Chancellor 4 months, 4 weeks ago
On Thu, Sep 11, 2025 at 04:56:59PM +0200, Heiko Carstens wrote:
> On Wed, Sep 10, 2025 at 06:32:43PM -0700, Nathan Chancellor wrote:
> > > + *
> > > + * Optional: only supported since GCC >= 13.1, clang >= 12.0
> > > + *
> > > + *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#index-assume-statement-attribute
> > > + * clang: https://clang.llvm.org/docs/AttributeReference.html#assume
> > 
> > Looking at this link sent me down a bit of a rabbit hole :) Prior to
> > Clang 19.1.0 [2], assume was an OpenMP attribute, which has completely
> > different semantics and errors out when used in the way the series does:
> > 
> >   In file included from kernel/bounds.c:13:
> >   In file included from include/linux/log2.h:12:
> >   In file included from include/linux/bitops.h:67:
> >   arch/s390/include/asm/bitops.h:173:12: error: expected string literal as argument of '__assume__' attribute
> >     173 |                 __assume(bit <= 64);
> >         |                          ^
> > 
> > Unfortunately, I think __assume will need to be handled in the compiler
> > specific headers :/
> > 
> > [1]: https://clang.llvm.org/docs/AttributeReference.html#id13
> > [2]: https://github.com/llvm/llvm-project/commit/c44fa3e8a9a44c2e9a575768a3c185354b9f6c17
> 
> Thank you for having look. This is quite surprising. So after looking into the
> various header files it might be acceptable to add this to compiler_types.h,
> since there seem to be a few similar constructs.
> 
> Maybe something like this(?):

Ah, yeah, that would work too. I had not considered compiler_types.h
since most of those tend to involve dynamic checks via cc-option but I
do like keeping the documentation attached to the attribute in a single
location, rather than duplicating it in the individual compiler files.
This will also make it easy to move this into compiler_attributes.h in
the (likely distant) future when both compilers support this
unconditionally (or clang 19.1.0 is the minimum supported version so
__has_attribute can be used).

> From d9d67807e6854666507e55d9ac0c7b4ec659aa99 Mon Sep 17 00:00:00 2001
> From: Heiko Carstens <hca@linux.ibm.com>
> Date: Wed, 10 Sep 2025 14:18:07 +0200
> Subject: [PATCH] compiler_types: Add __assume macro
> 
> Make the statement attribute "assume" with a new __assume macro available.
> 
> This allows compilers to generate better code, however code which makes use
> of __assume must be written as if the compiler ignores the hint. Otherwise
> this may lead to subtle bugs if code is compiled with compilers which do
> not support the attribute.
> 
> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>

Reviewed-by: Nathan Chancellor <nathan@kernel.org>

I do not think anyone really owns compiler_types.h so unless Miguel has
any objections from the compiler attributes perspective, I think you can
just take this via the s390 tree with the other two changes.

> ---
>  include/linux/compiler_types.h | 20 ++++++++++++++++++++
>  init/Kconfig                   | 10 ++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
> index 16755431fc11..38a52a792e48 100644
> --- a/include/linux/compiler_types.h
> +++ b/include/linux/compiler_types.h
> @@ -329,6 +329,26 @@ struct ftrace_likely_data {
>  #define __no_sanitize_or_inline __always_inline
>  #endif
>  
> +/*
> + * Beware: Code which makes use of __assume must be written as if the compiler
> + * ignores the hint. Otherwise this may lead to subtle bugs if code is compiled
> + * with compilers which do not support the attribute.
> + * Using this attribute requires careful analysis, since in some cases it may
> + * generate worse code (see clang documentation).
> + *
> + * Optional: only supported since gcc >= 13
> + * Optional: only supported since clang >= 19
> + *
> + *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#index-assume-statement-attribute
> + * clang: https://clang.llvm.org/docs/AttributeReference.html#id13
> + *
> + */
> +#ifdef CONFIG_CC_HAS_ASSUME
> +# define __assume(expr)			__attribute__((__assume__(expr)))
> +#else
> +# define __assume(expr)
> +#endif
> +
>  /*
>   * Optional: only supported since gcc >= 15
>   * Optional: only supported since clang >= 18
> diff --git a/init/Kconfig b/init/Kconfig
> index e3eb63eadc87..5882c5e74047 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -112,6 +112,16 @@ config TOOLS_SUPPORT_RELR
>  config CC_HAS_ASM_INLINE
>  	def_bool $(success,echo 'void foo(void) { asm inline (""); }' | $(CC) -x c - -c -o /dev/null)
>  
> +config CC_HAS_ASSUME
> +	bool
> +	# clang needs to be at least 19.1.0 since the meaning of the assume
> +	# attribute changed:
> +	# https://github.com/llvm/llvm-project/commit/c44fa3e8a9a44c2e9a575768a3c185354b9f6c17
> +	default y if CC_IS_CLANG && CLANG_VERSION >= 190100
> +	# supported since gcc 13.1.0
> +	# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106654
> +	default y if CC_IS_GCC && GCC_VERSION >= 130100
> +
>  config CC_HAS_NO_PROFILE_FN_ATTR
>  	def_bool $(success,echo '__attribute__((no_profile_instrument_function)) int x();' | $(CC) -x c - -c -o /dev/null -Werror)
>  
> -- 
> 2.48.1
Re: [PATCH 1/3] Compiler Attributes: Add __assume macro
Posted by Miguel Ojeda 4 months, 4 weeks ago
On Thu, Sep 11, 2025 at 8:44 PM Nathan Chancellor <nathan@kernel.org> wrote:
>
> I do not think anyone really owns compiler_types.h so unless Miguel has
> any objections from the compiler attributes perspective, I think you can
> just take this via the s390 tree with the other two changes.

No objections from me, and thanks for spotting the OpenMP thing above.

I would say, though, that this is a fairly general and subtle tool to
have around, so it would be nice to have others chime in. In other
words, do we want to start using `assume`s? Should we constrain its
use a bit, e.g. say its use should really be justified etc.? (In the
Rust side, a tool like this would require a SAFETY comment on top with
a justification, which may give a developer pause).

Thanks!

Cheers,
Miguel
Re: [PATCH 1/3] Compiler Attributes: Add __assume macro
Posted by Nathan Chancellor 4 months, 4 weeks ago
On Thu, Sep 11, 2025 at 09:04:36PM +0200, Miguel Ojeda wrote:
> On Thu, Sep 11, 2025 at 8:44 PM Nathan Chancellor <nathan@kernel.org> wrote:
> >
> > I do not think anyone really owns compiler_types.h so unless Miguel has
> > any objections from the compiler attributes perspective, I think you can
> > just take this via the s390 tree with the other two changes.
> 
> No objections from me, and thanks for spotting the OpenMP thing above.
> 
> I would say, though, that this is a fairly general and subtle tool to
> have around, so it would be nice to have others chime in. In other
> words, do we want to start using `assume`s? Should we constrain its
> use a bit, e.g. say its use should really be justified etc.? (In the
> Rust side, a tool like this would require a SAFETY comment on top with
> a justification, which may give a developer pause).

I do think justification at the source level (i.e., a comment) would be
a good baseline. I thought I remember a similar discussion around
likely() / unlikely() annotations since those should have some evidence
of benefit behind it. Applying the same policy to __assume() usage would
help ensure there is sufficient justification for adding and maintaining
such annotations, especially if they turn out to cause problems later.
Not sure if there should be a format standard like exists for SAFETY
comments but something is better than nothing.

Cheers,
Nathan