mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: David Laight <david.laight.linux@gmail.com>
To: Ian Rogers <irogers@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>,
	Marc Kleine-Budde <mkl@pengutronix.de>,
	Thomas Gleixner <tglx@linutronix.de>,
	Stefan Kerkmann <s.kerkmann@pengutronix.de>,
	"James E . J . Bottomley" <James.Bottomley@hansenpartnership.com>,
	Helge Deller <deller@gmx.de>, Andy Lutomirski <luto@kernel.org>,
	Vincenzo Frascino <vincenzo.frascino@arm.com>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	linux-parisc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Eric Biggers <ebiggers@google.com>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	Christophe Leroy <christophe.leroy@csgroup.eu>,
	"Jason A . Donenfeld" <Jason@zx2c4.com>
Subject: Re: [Regression] [PATCH v5 2/4] vdso: Switch get/put unaligned from packed struct to memcpy
Date: Tue, 20 Oct 2026 20:27:44 +0100	[thread overview]
Message-ID: <20261020202744.55c52a49@pumpkin> (raw)
In-Reply-To: <CAP-5=fXQxGBYnCKbGpxvtaQxxhju2UXgzn1vy-8rcoNVOvSqyw@mail.gmail.com>

On Tue, 20 Oct 2026 09:21:47 -0700
Ian Rogers <irogers@google.com> wrote:

> On Mon, Oct 19, 2026 at 3:05 PM Arnd Bergmann <arnd@arndb.de> wrote:
> >
> > On Mon, Oct 19, 2026, at 23:14, Ian Rogers wrote:  
> > > On Mon, Oct 19, 2026 at 2:00 PM Arnd Bergmann <arnd@arndb.de> wrote:  
> > >> On Mon, Oct 19, 2026, at 19:04, Ian Rogers wrote:  
> > >
> > > Is there a reason that the compiler's instruction selection can't make
> > > the same decision for the memcpy case as the __packed case? We can
> > > work around the compiler bug with a config option.
> > > The intent with using __builtin_memcpy, as opposed to memcpy, is to
> > > avoid a library call.  
> >
> > As far as I understand, the only difference between calling
> > __builtin_memcpy() and memcpy() is the need for a prototype
> > for the latter, I would expect the compiler to behave the exact
> > same for for both otherwise. Whether any of the string.h functions
> > are replaced by an inline alternative is a complex optimizer
> > decision, not something you can enforce by calling the function
> > by one name rather than the other.  
> 
> So to repeat, relying on __packed and assuming __packed won't be
> lowered to a memcpy(), memset(), etc. call by the compiler is false.
> Both GCC and Clang lower __packed accesses and assignments to
> out-of-line memcpy()/memset() calls in a variety of cases on
> -mno-unaligned-access targets:
> 
> https://godbolt.org/z/qKWv6Gdav
> 
> Using the __packed definitions of get_unaligned() and put_unaligned():
> 
>     #define __get_unaligned_t(type, ptr) ({                        \
>         const struct { type x; } __packed *__get_pptr =
> (typeof(__get_pptr))(ptr); \
>         __get_pptr->x;                                \
>     })
> 
>     #define __put_unaligned_t(type, val, ptr) do {                    \
>         struct { type x; } __packed *__put_pptr =
> (typeof(__put_pptr))(ptr);    \
>         __put_pptr->x = (val);                            \
>     } while (0)
> 
> 1. 4-byte aggregate with __packed put_unaligned():
> 
>     struct s4 { short a, b; };
>     void put_s4(struct s4 *p, struct s4 v)
>     {
>         put_unaligned(v, p);
>     }
> 
> Even though struct s4 is 4 bytes and passed in a single register (r1),
> GCC with -O2 -mno-unaligned-access spills r1 to the stack and calls
> memcpy() for 4 bytes:
> 
>     put_s4:
>         str    lr, [sp, #-4]!
>         mov    r2, #4
>         sub    sp, sp, #12
>         str    r1, [sp, #4]
>         add    r1, sp, r2
>         bl    memcpy
>         add    sp, sp, #12
>         ldr    pc, [sp], #4
> 
> 2. Copying a 4-byte __packed struct containing a single int:
> 
>     struct packed_int { int x; } __packed;
>     void copy_packed_int(struct packed_int *dst, const struct packed_int *src)
>     {
>         *dst = *src;
>     }
> 
> Clang's frontend lowers *dst = *src directly to @llvm.memcpy(...,
> align 1), and GCC with -O2 -mno-unaligned-access emits an out-of-line
> call to memcpy(..., 4) (as does riscv64-linux-gnu-gcc -Os).
> 
> 3. struct debug_entry __packed (from tools/perf/util/jitdump.h):
> 
>     struct debug_entry {
>         unsigned long long addr;
>         int lineno;
>         int discrim;
>     } __packed;
> 
>     struct debug_entry get_entry(const void *p)
>     {
>         return get_unaligned((const struct debug_entry *)p);
>     }
> 
>     void copy_entry(struct debug_entry *dst, const struct debug_entry *src)
>     {
>         *dst = *src;
>     }
> 
> Whether accessed via the __packed get_unaligned() macro or via direct
> assignment on a __packed struct, both GCC and Clang emit memcpy()
> calls. In fact, with the __packed statement-expression macro, GCC
> emits two back-to-back memcpy() calls in get_entry() (one into the
> statement expression temporary on the stack, and a second from the
> stack into the return slot).
> 
> 4. Loops of scalar int __packed get_unaligned() / put_unaligned():
> 
>     void copy_8_ints(int * restrict dst, const int * restrict src)
>     {
>         for (int i = 0; i < 8; i++)
>             put_unaligned(get_unaligned(&src[i]), &dst[i]);
>     }
> 
> Even for a scalar int, loop idiom recognition in both GCC and Clang at
> -O2 turns the __packed loads/stores into a call to memcpy(dst, src,
> 32).
> 
> 5. Adjacent scalar __packed zero stores promoted to memset():
> 
>     void zero_2_u64(long long *dst)
>     {
>         put_unaligned(0LL, &dst[0]);
>         put_unaligned(0LL, &dst[1]);
>     }
> 
> Even in straight-line code without a loop, Clang's MemCpyOpt merges
> two adjacent 64-bit (or four 32-bit) __packed zero stores into
> @llvm.memset(..., align 1), which lowers under -O2
> -mno-unaligned-access to an out-of-line memset() call:
> 
>     zero_2_u64:
>         mov    r1, #0
>         mov    r2, #16
>         b    memset
> 
> On the Kconfig patch, I have updated v2 so
> CONFIG_VDSO_UNALIGNED_PACKED defaults to
> !HAVE_EFFICIENT_UNALIGNED_ACCESS to cover all strict-alignment targets
> rather than just CPU_32v5.
> 
> I continue to think that:
> 
> 1) given __packed implicitly can be turned into a memcpy, it is no
> better than a memcpy;

I suspect it happens less often with __packed.
You can probably add volatile to stop the other merging.

It really might be necessary to give up on the C versions and use asm()
(at least for the unaligned access case).

David

> 2) the __builtin_memcpy for efficient unaligned targets avoids type
> punning, is more intention revealing, is clearer for compiler writers,
> and is what compiler writers tell me they want.
> 
> That said, the code with a __packed or with a memcpy can be made to
> work, optimized, etc. I'd like to be pragmatic and address Stefan and
> Marc's problem so a revert works, I just think we can try to do a
> little better.
> 
> Thanks,
> Ian
> 


  reply	other threads:[~2026-10-20 19:27 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-16 20:51 [PATCH v5 0/4] Switch get/put unaligned to use memcpy Ian Rogers
2025-10-16 20:51 ` [PATCH v5 1/4] parisc: Inline a type punning version of get_unaligned_le32 Ian Rogers
2026-01-13 13:47   ` [tip: timers/vdso] parisc: Inline a type punning version of get_unaligned_le32() tip-bot2 for Ian Rogers
2026-01-14  8:01   ` tip-bot2 for Ian Rogers
2025-10-16 20:51 ` [PATCH v5 2/4] vdso: Switch get/put unaligned from packed struct to memcpy Ian Rogers
2025-10-19 17:24   ` David Laight
2026-01-13 13:47   ` [tip: timers/vdso] vdso: Switch get/put_unaligned() from packed struct to memcpy() tip-bot2 for Ian Rogers
2026-01-14  8:01   ` tip-bot2 for Ian Rogers
2026-09-28 15:39   ` [Regression] [PATCH v5 2/4] vdso: Switch get/put unaligned from packed struct to memcpy Stefan Kerkmann
2026-09-28 15:58     ` Ian Rogers
2026-10-06 12:31     ` Marc Kleine-Budde
2026-10-07 10:59       ` Arnd Bergmann
2026-10-09 21:28         ` Ian Rogers
2026-10-10 10:26           ` Christophe Leroy (CS GROUP)
2026-10-10 12:20             ` Ian Rogers
2026-10-10 14:06           ` Arnd Bergmann
2026-10-10 15:04             ` Ian Rogers
2026-10-19 12:37               ` Marc Kleine-Budde
2026-10-19 15:10                 ` Ian Rogers
2026-10-19 16:27                   ` Arnd Bergmann
2026-10-19 17:04                     ` Ian Rogers
2026-10-19 21:00                       ` Arnd Bergmann
2026-10-19 21:14                         ` Ian Rogers
2026-10-19 22:05                           ` Arnd Bergmann
2026-10-20 16:21                             ` Ian Rogers
2026-10-20 19:27                               ` David Laight [this message]
2026-10-20 21:20                                 ` David Laight
2026-10-20  8:36                     ` David Laight
2026-10-20  8:41                       ` Arnd Bergmann
2026-10-20 10:01                         ` David Laight
2025-10-16 20:51 ` [PATCH v5 3/4] tools headers: Update the linux/unaligned.h copy with the kernel sources Ian Rogers
2026-01-13 13:47   ` [tip: timers/vdso] " tip-bot2 for Ian Rogers
2026-01-14  8:01   ` tip-bot2 for Ian Rogers
2025-10-16 20:51 ` [PATCH v5 4/4] tools headers: Remove unneeded ignoring of warnings in unaligned.h Ian Rogers
2026-01-13 13:47   ` [tip: timers/vdso] " tip-bot2 for Ian Rogers
2026-01-14  8:01   ` tip-bot2 for Ian Rogers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261020202744.55c52a49@pumpkin \
    --to=david.laight.linux@gmail.com \
    --cc=James.Bottomley@hansenpartnership.com \
    --cc=Jason@zx2c4.com \
    --cc=acme@redhat.com \
    --cc=arnd@arndb.de \
    --cc=christophe.leroy@csgroup.eu \
    --cc=deller@gmx.de \
    --cc=ebiggers@google.com \
    --cc=irogers@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-parisc@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mkl@pengutronix.de \
    --cc=s.kerkmann@pengutronix.de \
    --cc=tglx@linutronix.de \
    --cc=vincenzo.frascino@arm.com \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®