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
>
next prev parent reply other threads:[~2026-10-20 19:27 UTC|newest]
Thread overview: 28+ 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
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-09-28 15:39 ` [Regression] " 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
2025-10-16 20:51 ` [PATCH v5 4/4] tools headers: Remove unneeded ignoring of warnings in unaligned.h 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