Re: [PATCH] x86/local: Remove trailing semicolon from _ASM_XADD in local_add_return()
From: Uros Bizjak
Date: Sun Feb 15 2026 - 11:43:41 EST
On Sun, Feb 15, 2026 at 1:55 AM H. Peter Anvin <hpa@xxxxxxxxx> wrote:
>
> On February 12, 2026 2:51:02 AM PST, Uros Bizjak <ubizjak@xxxxxxxxx> wrote:
> >Remove the trailing semicolon from the inline assembly statement in
> >local_add_return().
> >
> >The _ASM_XADD macro already expands to a complete instruction, making
> >the extra semicolon unnecessary. More importantly, the stray semicolon
> >causes GCC to treat the inline asm as containing multiple instructions,
> >which can skew its internal instruction count estimation and affect
> >optimization heuristics.
> >
> >No functional change intended.
> >
> >Signed-off-by: Uros Bizjak <ubizjak@xxxxxxxxx>
> >Cc: Thomas Gleixner <tglx@xxxxxxxxxx>
> >Cc: Ingo Molnar <mingo@xxxxxxxxxx>
> >Cc: Borislav Petkov <bp@xxxxxxxxx>
> >Cc: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx>
> >Cc: "H. Peter Anvin" <hpa@xxxxxxxxx>
> >---
> > arch/x86/include/asm/local.h | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> >diff --git a/arch/x86/include/asm/local.h b/arch/x86/include/asm/local.h
> >index 59aa966dc212..4957018fef3e 100644
> >--- a/arch/x86/include/asm/local.h
> >+++ b/arch/x86/include/asm/local.h
> >@@ -106,7 +106,7 @@ static inline bool local_add_negative(long i, local_t *l)
> > static inline long local_add_return(long i, local_t *l)
> > {
> > long __i = i;
> >- asm volatile(_ASM_XADD "%0, %1;"
> >+ asm volatile(_ASM_XADD "%0, %1"
> > : "+r" (i), "+m" (l->a.counter)
> > : : "memory");
> > return i + __i;
>
> Are you sure that gcc treats an empty statement or line as something that should be counted? It is awkward as heck if so, and really ought to be fixed in gcc.
Unfortunately, it is.
GCC does not parse asm template at all, and the insn estimator is very crude:
{
int count = 1;
if (!*templ)
return 0;
for (; *templ; templ++)
if (IS_ASM_LOGICAL_LINE_SEPARATOR (*templ, templ)
|| *templ == '\n')
count++;
return count;
}
with:
#define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) ((C) == ';')
The size (in bytes) of asm is determined as the number of insns * the
length of the longest instruction supported by that processor (defined
to 16 for x86) [1]. So, the estimated byte size difference between
"mnemonic" and "mnemonic;" is 16 bytes, which can and will affect
inlining decisions for small utility functions.
There was a long debate about this, and as a result, the compiler
implemented "asm inline" to mitigate the effects of pseudo
instructions in asm templates. For other asms, they should use line
separators with care, to keep the estimated size of the asm at least
somehow sane.
[1] https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html
Uros.