[PATCH 1/2] x86: optimize XCHG to MOV for same-register forms

Sam James sam@gentoo.org
Thu Jul 2 06:45:11 GMT 2026


Jan Beulich <jbeulich@suse.com> writes:

> On 02.07.2026 08:06, Sam James wrote:
>> Jan Beulich <jbeulich@suse.com> writes:
>> 
>>> MOV requires far less execution resources.
>> 
>> In case anyone ends up stumbling upon this and wonders why Valgrind
>> stopped working, it needs adjusting for this change:
>> https://bugs.kde.org/522533.
>
> So the instruction bytes quoted there:
>
> IR: unhandled instruction bytes: 0x48 0xC1 0xC7 0x3 0x48 0xC1 0xC7 0xD 0x48 0xC1
>
> are really unrelated to the issue? That's the earlier ROLs afaict ...
>

AFAICT yes! I found this surprising too but it's the only difference
in the object.

> What is that code doing anyway?

Mark explained it to me yesterday as (any errors mine in paraphrasing)..

We die in vg_preloaded.c:129 which is:

void * VG_NOTIFY_ON_LOAD(ifunc_wrapper) (void)
...
    /* Call the original indirect function and get it's result */
    VALGRIND_GET_ORIG_FN(fn); /* <-- */
    CALL_FN_W_v(result, fn);

which is VALGRIND_GET_NR_CONTEXT:

#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
    volatile unsigned int __addr;                                 \
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
                     /* %EAX = guest_NRADDR */                    \
                     "xchgl %%ecx,%%ecx"                          \
                     : "=a" (__addr)                              \
                     :                                            \
                     : "cc", "memory"                             \
                    );                                            \
    _zzq_orig->nraddr = __addr;                                   \
  }

and the rols are the _S_I_P macro:

#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
                     "roll $3,  %%edi ; roll $13, %%edi\n\t"      \
                     "roll $29, %%edi ; roll $19, %%edi\n\t"

but what I don't understand is why it ends up seeing that. I think when
it sees _S_I_P, it is supposed to rewrite it (?), but I am not an expert on
valgrind's VEX interpreter at all.

> And why is -O passed to gas there, when specific
> insn selection matters?

That's just because it's one of the things I test in some runs. I'll
filter it out for Valgrind as I agree it makes no sense there, but
another problem  happens when Valgrind itself is built without it, but
e.g. systemd has -Wa,-O2:

vex amd64->IR: unhandled instruction bytes: 0x48 0xC1 0xC7 0x3 0x48 0xC1 0xC7 0xD 0x48 0xC1
vex amd64->IR:   REX=0 REX.W=0 REX.R=0 REX.X=0 REX.B=0
vex amd64->IR:   VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=NONE
vex amd64->IR:   PFX.66=0 PFX.F2=0 PFX.F3=0
==720097== valgrind: Unrecognised instruction at address 0x491cf5b.
==720097==    at 0x491CF5B: cleanup_pools (in /usr/lib64/libsystemd.so.0.44.0)
==720097==    by 0x400C061: _dl_call_fini (dl-call_fini.c:43)
==720097==    by 0x401098F: _dl_fini (dl-fini.c:120)
==720097==    by 0x4B8E7CF: __run_exit_handlers (exit.c:118)
==720097==    by 0x4B8E8BB: exit (exit.c:148)
==720097==    by 0x4B6F290: (below main) (libc_start_call_main.h:83)
==720097== Your program just tried to execute an instruction that Valgrind
==720097== did not recognise.  There are two possible reasons for this.
==720097== 1. Your program has a bug and erroneously jumped to a non-code
==720097==    location.  If you are running Memcheck and you just saw a
==720097==    warning about a bad jump, it's probably your program's fault.
==720097== 2. The instruction is legitimate but Valgrind doesn't handle it,
==720097==    i.e. it's Valgrind's fault.  If you think this is the case or
==720097==    you are not sure, please let us know and we'll try to fix it.
==720097== Either way, Valgrind will now raise a SIGILL signal which will
==720097== probably kill your program.
==720097==
==720097== Process terminating with default action of signal 4 (SIGILL): dumping core
==720097==  Illegal opcode at address 0x491CF5B
==720097==    at 0x491CF5B: cleanup_pools (in /usr/lib64/libsystemd.so.0.44.0)
==720097==    by 0x400C061: _dl_call_fini (dl-call_fini.c:43)
==720097==    by 0x401098F: _dl_fini (dl-fini.c:120)
==720097==    by 0x4B8E7CF: __run_exit_handlers (exit.c:118)
==720097==    by 0x4B8E8BB: exit (exit.c:148)
==720097==    by 0x4B6F290: (below main) (libc_start_call_main.h:83)

so Valgrind still needs to be able to interpret the pattern anyway.

>
> Jan

sam
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 418 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/binutils/attachments/20260702/50ee793c/attachment-0001.sig>


More information about the Binutils mailing list