Re: [PATCH] x86: Disable XCHG to MOV optimization

"H.J. Lu" <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Message-ID <CAMe9rOqBTPsZrq1S24uAaXhRPsCoVsPDwKPWyT_CHGh9j-xNUQ@mail.gmail.com>
On Mon, Jul 13, 2026 at 11:42 PM Jan Beulich <[email protected]> wrote:
>
> On 13.07.2026 17:31, H.J. Lu wrote:
> > On Mon, Jul 13, 2026 at 11:20 PM Jan Beulich <[email protected]> wrote:
> >>
> >> On 13.07.2026 17:10, H.J. Lu wrote:
> >>> On Mon, Jul 13, 2026 at 11:03 PM Jan Beulich <[email protected]> wrote:
> >>>>
> >>>> On 13.07.2026 14:08, H.J. Lu wrote:
> >>>>> I am going to check this patch into master as well as 2.47 branch.
> >>>>> I added optimize_for_unsafe, which is 0, and moved XCHG to MOV
> >>>>> optimization under it.  We can add something like -Ounsafe later.
> >>>>
> >>>> But this is wrong, the optimization itself isn't unsafe. Please can we
> >>>
> >>> You can change it to a different name.  But -O on master must work with
> >>> today's valgrind.
> >>
> >> That's your position. I continue to fail to see why -O needs to work on
> >> anything (valgrind or not) that depends on getting to see specific
> >> encodings for certain insns. Such uses of -O are simply wrong. Undoing
> >
> > You can add a different option.  -O should work for all applications today.
>
> Again - no. It simply can't. (Ftaod when I say -O in this discussion, I
> generally mean all its forms.)
>

My original design goal of -O is 100% safe for any applications.  It
is too bad we don't agree on it.  Here is the final patch I am checking
in.

-- 
H.J.
0001-x86-Disable-XCHG-to-MOV-optimization.patch (text/x-patch, 6.9 KB)
From dfe7933c4c0b3c7c2779d6bd6c0e3f6dda9330dd Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Sun, 12 Jul 2026 18:24:42 +0800
Subject: [PATCH] x86: Disable XCHG to MOV optimization

The -O option was added to x86 assembler by

commit b6f8c7c45229a8a5405079e586bfbaad396d2cbe
Author: H.J. Lu <[email protected]>
Date:   Tue Feb 27 07:36:33 2018 -0800

    x86: Add -O[2|s] assembler command-line options

On x86, some instructions have alternate shorter encodings:

1. When the upper 32 bits of destination registers of

andq $imm31, %r64
testq $imm31, %r64
xorq %r64, %r64
subq %r64, %r64

known to be zero, we can encode them without the REX_W bit:

andl $imm31, %r32
testl $imm31, %r32
xorl %r32, %r32
subl %r32, %r32

This optimization is enabled with -O, -O2 and -Os.
2. Since 0xb0 mov with 32-bit destination registers zero-extends 32-bit
immediate to 64-bit destination register, we can use it to encode 64-bit
mov with 32-bit immediates.  This optimization is enabled with -O, -O2
and -Os.
3. Since the upper bits of destination registers of VEX128 and EVEX128
instructions are extended to zero, if all bits of destination registers
of AVX256 or AVX512 instructions are zero, we can use VEX128 or EVEX128
encoding to encode AVX256 or AVX512 instructions.  When 2 source
registers are identical, AVX256 and AVX512 andn and xor instructions:

VOP %reg, %reg, %dest_reg

can be encoded with

VOP128 %reg, %reg, %dest_reg

This optimization is enabled with -O2 and -Os.
4. 16-bit, 32-bit and 64-bit register tests with immediate may be
encoded as 8-bit register test with immediate.  This optimization is
enabled with -Os.

These optimizations were intended for compiler generated assembly codes.
The optimization changes may take a long time to be put into GCC.  The
similar SSE move encoding optimization for GCC was first proposed in
Feb, 2019:

https://gcc.gnu.org/pipermail/gcc-patches/2019-February/516941.html

It finally went in Mar, 2020:

commit 5358e8f5800daa0012fc9d06705d64bbb21fa07b
Author: H.J. Lu <[email protected]>
Date:   Thu Mar 5 16:45:05 2020 -0800

    i386: Properly encode vector registers in vector move

Such optimizations are useful for compiler generated codes since they
work with released versions of GCC which don't have such optimized
encoding.  We assume that it is safe to use on compiler generated codes.
When we are informed that an assembler optimization introduces a
significant drawback, we will investigate its drawbacks and benefits.
If its drawbacks outweigh its benefits, such optimization should be
removed.

commit 1c3c3e4b3c2ac2eed9abcbce0b9cba1be10ed3f0
Author: Jan Beulich <[email protected]>
Date:   Fri Jun 19 09:47:21 2026 +0200

    x86: optimize XCHG to MOV for same-register forms

breaks valgrind:

https://bugs.kde.org/show_bug.cgi?id=522533

"xchgl %ecx,%ecx" in VALGRIND_GET_NR_CONTEXT, which is defined in
/usr/include/valgrind/valgrind.h:

 #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;                                   \
  }

has special meanings and shouldn't be changed by assembler even when
assembler optimization is enabled.  Since there are no any evidences
to show its benefits, we can't say that it is useful at all.  This
patch disables this optimization, which may be enabled with a different
option.

gas/

	PR gas/34343
	* config/tc-i386.c (optimize_for_disabled_optimizations): New.
	(optimize_encoding): Optimize "xchg %rN, %rN" to "mov %rN, %rN"
	only if optimize_for_disabled_optimizations isn't 0.
	* testsuite/gas/i386/optimize-2b.d: Updated.
	* testsuite/gas/i386/x86-64-optimize-3b.d: Likewise.

Signed-off-by: H.J. Lu <[email protected]>
---
 gas/config/tc-i386.c                        | 5 ++++-
 gas/testsuite/gas/i386/optimize-2b.d        | 6 +++---
 gas/testsuite/gas/i386/x86-64-optimize-3b.d | 8 ++++----
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 6e104ed2213..90971b4dbe2 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -848,6 +848,9 @@ static int optimize = 0;
  */
 static int optimize_for_space = 0;
 
+/* Disabled optimizations.  */
+static int optimize_for_disabled_optimizations = 0;
+
 /* Register prefix used for error message.  */
 static const char *register_prefix = "%";
 
@@ -5177,7 +5180,7 @@ optimize_encoding (void)
       i.seg[0] = NULL;
     }
 
-  if (!optimize_for_space
+  if (optimize_for_disabled_optimizations
       && i.tm.mnem_off == MN_xchg
       && i.reg_operands == 2
       && i.op[0].regs == i.op[1].regs)
diff --git a/gas/testsuite/gas/i386/optimize-2b.d b/gas/testsuite/gas/i386/optimize-2b.d
index 5d270a07360..6e058b433a0 100644
--- a/gas/testsuite/gas/i386/optimize-2b.d
+++ b/gas/testsuite/gas/i386/optimize-2b.d
@@ -25,9 +25,9 @@ Disassembly of section .text:
  +[a-f0-9]+:	85 f6                	test   %esi,%esi
  +[a-f0-9]+:	87 0a                	xchg   %ecx,\(%edx\)
  +[a-f0-9]+:	87 11                	xchg   %edx,\(%ecx\)
- +[a-f0-9]+:	88 c9                	mov    %cl,%cl
- +[a-f0-9]+:	66 8b d2             	mov    %dx,%dx
- +[a-f0-9]+:	89 ff                	mov    %edi,%edi
+ +[a-f0-9]+:	86 c9                	xchg   %cl,%cl
+ +[a-f0-9]+:	66 87 d2             	xchg   %dx,%dx
+ +[a-f0-9]+:	87 ff                	xchg   %edi,%edi
  +[a-f0-9]+:	66 98                	cbtw
  +[a-f0-9]+:	66 98                	cbtw
  +[a-f0-9]+:	98                   	cwtl
diff --git a/gas/testsuite/gas/i386/x86-64-optimize-3b.d b/gas/testsuite/gas/i386/x86-64-optimize-3b.d
index ef6fd27c03c..2a2593cdb90 100644
--- a/gas/testsuite/gas/i386/x86-64-optimize-3b.d
+++ b/gas/testsuite/gas/i386/x86-64-optimize-3b.d
@@ -81,10 +81,10 @@ Disassembly of section .text:
  +[a-f0-9]+:	66 85 f6             	test   %si,%si
  +[a-f0-9]+:	09 ff                	or     %edi,%edi
  +[a-f0-9]+:	4d 85 c0             	test   %r8,%r8
- +[a-f0-9]+:	d5 50 88 c9          	mov    %r17b,%r17b
- +[a-f0-9]+:	66 45 8b c0          	mov    %r8w,%r8w
- +[a-f0-9]+:	89 c0                	mov    %eax,%eax
- +[a-f0-9]+:	4d 89 ff             	mov    %r15,%r15
+ +[a-f0-9]+:	d5 50 86 c9          	xchg   %r17b,%r17b
+ +[a-f0-9]+:	66 45 87 c0          	xchg   %r8w,%r8w
+ +[a-f0-9]+:	87 c0                	xchg   %eax,%eax
+ +[a-f0-9]+:	4d 87 ff             	xchg   %r15,%r15
  +[a-f0-9]+:	66 98                	cbtw
  +[a-f0-9]+:	66 98                	cbtw
  +[a-f0-9]+:	98                   	cwtl
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.