[PATCH 1/2] x86: optimize XCHG to MOV for same-register forms
Jan Beulich
jbeulich@suse.com
Fri Jun 5 09:34:27 GMT 2026
MOV requires far less execution resources.
---
Should we go further and optimize to NOP (unless of course it's a 32-bit
insn in 64-bit mode)? If so, obviously we'd then want to do this also for
MOV itself.
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -5176,6 +5176,17 @@ optimize_encoding (void)
i.seg[0] = NULL;
}
+ if (!optimize_for_space
+ && i.tm.mnem_off == MN_xchg
+ && i.reg_operands == 2
+ && i.op[0].regs == i.op[1].regs)
+ {
+ /* Optimize: -O:
+ xchg %rN, %rN -> mov %rN, %rN
+ */
+ i.tm.base_opcode = pp.dir_encoding == dir_encoding_load ? 0x8a : 0x88;
+ }
+
if (((i.tm.opcode_space == SPACE_0F
&& (i.tm.base_opcode | 1) == 0xbf
&& (i.types[0].bitfield.byte
--- a/gas/testsuite/gas/i386/optimize-2.d
+++ b/gas/testsuite/gas/i386/optimize-2.d
@@ -24,6 +24,9 @@ Disassembly of section .text:
+[a-f0-9]+: 09 f6 or %esi,%esi
+[a-f0-9]+: 87 0a xchg %ecx,\(%edx\)
+[a-f0-9]+: 87 11 xchg %edx,\(%ecx\)
+ +[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
--- a/gas/testsuite/gas/i386/optimize-2.s
+++ b/gas/testsuite/gas/i386/optimize-2.s
@@ -22,6 +22,10 @@ _start:
lock xchg %ecx, (%edx)
lock xchg (%ecx), %edx
+ xchg %cl, %cl
+ {load} xchg %dx, %dx
+ xchg %edi, %edi
+
movsb %al, %ax
movsbw %al, %ax
--- a/gas/testsuite/gas/i386/optimize-2b.d
+++ b/gas/testsuite/gas/i386/optimize-2b.d
@@ -25,6 +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]+: 66 98 cbtw
+[a-f0-9]+: 66 98 cbtw
+[a-f0-9]+: 98 cwtl
--- a/gas/testsuite/gas/i386/x86-64-optimize-3.d
+++ b/gas/testsuite/gas/i386/x86-64-optimize-3.d
@@ -80,6 +80,10 @@ Disassembly of section .text:
+[a-f0-9]+: 66 09 f6 or %si,%si
+[a-f0-9]+: 09 ff or %edi,%edi
+[a-f0-9]+: 4d 09 c0 or %r8,%r8
+ +[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
--- a/gas/testsuite/gas/i386/x86-64-optimize-3.s
+++ b/gas/testsuite/gas/i386/x86-64-optimize-3.s
@@ -39,6 +39,11 @@ _start:
or %edi, %edi
or %r8, %r8
+ xchg %r17b, %r17b
+ {load} xchg %r8w, %r8w
+ xchg %eax, %eax
+ xchg %r15, %r15
+
movsb %al, %ax
movsbw %al, %ax
--- a/gas/testsuite/gas/i386/x86-64-optimize-3b.d
+++ b/gas/testsuite/gas/i386/x86-64-optimize-3b.d
@@ -81,6 +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]+: 66 98 cbtw
+[a-f0-9]+: 66 98 cbtw
+[a-f0-9]+: 98 cwtl
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -269,7 +269,7 @@ popa, 0x61, i186&No64, ImplicitStackOp|D
// In the 64bit code, xchg rax, rax is reused for new nop instruction.
xchg, 0x90, 0, D|C|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64, Acc|Word|Dword|Qword }
-xchg, 0x86, 0, D|W|C|CheckOperandSize|Modrm|No_sSuf|HLEPrefixAny, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+xchg, 0x86, 0, D|W|C|CheckOperandSize|Modrm|No_sSuf|HLEPrefixAny|Optimize, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
// In/out from ports.
in, 0xe4, 0, W|No_sSuf|No_qSuf, { Imm8, Acc|Byte|Word|Dword }
More information about the Binutils
mailing list