[binutils-gdb] x86: optimize XCHG to MOV for same-register forms
Jan Beulich via Binutils-cvs <[email protected]> Fri, 19 Jun 2026 07:49:26 +0000 (GMT)
| Newsgroups | gmane.comp.gnu.binutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1c3c3e4b3c2ac2eed9abcbce0b9cba1be10ed3f0 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 MOV requires far less execution resources. Diff: --- gas/config/tc-i386.c | 11 +++++++++++ gas/testsuite/gas/i386/optimize-2.d | 3 +++ gas/testsuite/gas/i386/optimize-2.s | 4 ++++ gas/testsuite/gas/i386/optimize-2b.d | 3 +++ gas/testsuite/gas/i386/x86-64-optimize-3.d | 4 ++++ gas/testsuite/gas/i386/x86-64-optimize-3.s | 5 +++++ gas/testsuite/gas/i386/x86-64-optimize-3b.d | 4 ++++ opcodes/i386-opc.tbl | 2 +- opcodes/i386-tbl.h | 2 +- 9 files changed, 36 insertions(+), 2 deletions(-) diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 365c2ee95f5..d58c375c8d8 100644 --- 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 diff --git a/gas/testsuite/gas/i386/optimize-2.d b/gas/testsuite/gas/i386/optimize-2.d index 3c90cc9b178..51f117966be 100644 --- 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 diff --git a/gas/testsuite/gas/i386/optimize-2.s b/gas/testsuite/gas/i386/optimize-2.s index 80a46eab485..102144592b1 100644 --- 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 diff --git a/gas/testsuite/gas/i386/optimize-2b.d b/gas/testsuite/gas/i386/optimize-2b.d index 3e92acfd869..359d4a097a0 100644 --- 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 diff --git a/gas/testsuite/gas/i386/x86-64-optimize-3.d b/gas/testsuite/gas/i386/x86-64-optimize-3.d index c91503aa8f9..20d3d550041 100644 --- 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 diff --git a/gas/testsuite/gas/i386/x86-64-optimize-3.s b/gas/testsuite/gas/i386/x86-64-optimize-3.s index 4fd29aeec98..1b61d017e7b 100644 --- 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 diff --git a/gas/testsuite/gas/i386/x86-64-optimize-3b.d b/gas/testsuite/gas/i386/x86-64-optimize-3b.d index 2a8fd3a0f41..e7d211ed74c 100644 --- 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 diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl index 5797a634de3..bb547bd2ee7 100644 --- a/opcodes/i386-opc.tbl +++ b/opcodes/i386-opc.tbl @@ -269,7 +269,7 @@ popa, 0x61, i186&No64, ImplicitStackOp|DefaultSize|No_bSuf|No_sSuf|No_qSuf|Intel // 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 } diff --git a/opcodes/i386-tbl.h b/opcodes/i386-tbl.h index da96efc6fda..f1ecc6498af 100644 --- a/opcodes/i386-tbl.h +++ b/opcodes/i386-tbl.h @@ -494,7 +494,7 @@ static const insn_template i386_optab[] = 0, 0, 0, 0, 0, 0 } } } }, { MN_xchg, 0x86, 2, SPACE_BASE, None, { 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },