[binutils-gdb] x86: optimize XADD to ADD for same-register forms

Jan Beulich via Binutils-cvs <[email protected]> Fri, 19 Jun 2026 07:49:31 +0000 (GMT)
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6780979d416b57cdd6f6b8f55645f808b5a72fec

commit 6780979d416b57cdd6f6b8f55645f808b5a72fec
Author: Jan Beulich <[email protected]>
Date:   Fri Jun 19 09:47:42 2026 +0200

    x86: optimize XADD to ADD for same-register forms
    
    ADD requires less execution resources and is shorter to encode.

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 d58c375c8d8..9b3f527d2c1 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -5187,6 +5187,17 @@ optimize_encoding (void)
       i.tm.base_opcode = pp.dir_encoding == dir_encoding_load ? 0x8a : 0x88;
     }
 
+  if (i.tm.mnem_off == MN_xadd
+      && i.reg_operands == 2
+      && i.op[0].regs == i.op[1].regs)
+    {
+      /* Optimize: -O:
+	   xadd %rN, %rN     -> add %rN, %rN
+       */
+      i.tm.opcode_space = SPACE_BASE;
+      i.tm.base_opcode = 0x00;
+    }
+
   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 51f117966be..48703a86cba 100644
--- a/gas/testsuite/gas/i386/optimize-2.d
+++ b/gas/testsuite/gas/i386/optimize-2.d
@@ -48,6 +48,9 @@ Disassembly of section .text:
  +[a-f0-9]+:	66 d1 e2             	shl    \$1,%dx
  +[a-f0-9]+:	d1 e2                	shl    \$1,%edx
  +[a-f0-9]+:	d1 e2                	shl    \$1,%edx
+ +[a-f0-9]+:	00 c9                	add    %cl,%cl
+ +[a-f0-9]+:	66 01 d2             	add    %dx,%dx
+ +[a-f0-9]+:	01 ff                	add    %edi,%edi
  +[a-f0-9]+:	c5 f1 55 e9          	vandnpd %xmm1,%xmm1,%xmm5
  +[a-f0-9]+:	c5 f9 6f d1          	vmovdqa %xmm1,%xmm2
  +[a-f0-9]+:	c5 f9 6f d1          	vmovdqa %xmm1,%xmm2
diff --git a/gas/testsuite/gas/i386/optimize-2.s b/gas/testsuite/gas/i386/optimize-2.s
index 102144592b1..68d9502dccb 100644
--- a/gas/testsuite/gas/i386/optimize-2.s
+++ b/gas/testsuite/gas/i386/optimize-2.s
@@ -59,6 +59,10 @@ _start:
 	sal	$1, %edx
 	sal	%edx
 
+	xadd	%cl, %cl
+	xadd	%dx, %dx
+	xadd	%edi, %edi
+
 	vandnpd	%zmm1, %zmm1, %zmm5
 
 	vmovdqa32	%xmm1, %xmm2
diff --git a/gas/testsuite/gas/i386/optimize-2b.d b/gas/testsuite/gas/i386/optimize-2b.d
index 359d4a097a0..5d270a07360 100644
--- a/gas/testsuite/gas/i386/optimize-2b.d
+++ b/gas/testsuite/gas/i386/optimize-2b.d
@@ -49,6 +49,9 @@ Disassembly of section .text:
  +[a-f0-9]+:	66 01 d2             	add    %dx,%dx
  +[a-f0-9]+:	01 d2                	add    %edx,%edx
  +[a-f0-9]+:	01 d2                	add    %edx,%edx
+ +[a-f0-9]+:	00 c9                	add    %cl,%cl
+ +[a-f0-9]+:	66 01 d2             	add    %dx,%dx
+ +[a-f0-9]+:	01 ff                	add    %edi,%edi
  +[a-f0-9]+:	c5 f1 55 e9          	vandnpd %xmm1,%xmm1,%xmm5
  +[a-f0-9]+:	c5 f9 6f d1          	vmovdqa %xmm1,%xmm2
  +[a-f0-9]+:	c5 f9 6f d1          	vmovdqa %xmm1,%xmm2
diff --git a/gas/testsuite/gas/i386/x86-64-optimize-3.d b/gas/testsuite/gas/i386/x86-64-optimize-3.d
index 20d3d550041..0cc4ba8f450 100644
--- a/gas/testsuite/gas/i386/x86-64-optimize-3.d
+++ b/gas/testsuite/gas/i386/x86-64-optimize-3.d
@@ -94,6 +94,10 @@ Disassembly of section .text:
  +[a-f0-9]+:	66 98                	cbtw
  +[a-f0-9]+:	98                   	cwtl
  +[a-f0-9]+:	48 98                	cltq
+ +[a-f0-9]+:	d5 50 00 c9          	add    %r17b,%r17b
+ +[a-f0-9]+:	66 45 01 c0          	add    %r8w,%r8w
+ +[a-f0-9]+:	01 c0                	add    %eax,%eax
+ +[a-f0-9]+:	4d 01 ff             	add    %r15,%r15
  +[a-f0-9]+:	c5 f1 55 e9          	vandnpd %xmm1,%xmm1,%xmm5
  +[a-f0-9]+:	c5 f9 6f d1          	vmovdqa %xmm1,%xmm2
  +[a-f0-9]+:	c5 f9 6f d1          	vmovdqa %xmm1,%xmm2
diff --git a/gas/testsuite/gas/i386/x86-64-optimize-3.s b/gas/testsuite/gas/i386/x86-64-optimize-3.s
index 1b61d017e7b..010ccfbfb85 100644
--- a/gas/testsuite/gas/i386/x86-64-optimize-3.s
+++ b/gas/testsuite/gas/i386/x86-64-optimize-3.s
@@ -60,6 +60,11 @@ _start:
 	movsx	rax, eax
 	.att_syntax prefix
 
+	xadd	%r17b, %r17b
+	xadd	%r8w, %r8w
+	xadd	%eax, %eax
+	xadd	%r15, %r15
+
 	vandnpd	%zmm1, %zmm1, %zmm5
 
 	vmovdqa32	%xmm1, %xmm2
diff --git a/gas/testsuite/gas/i386/x86-64-optimize-3b.d b/gas/testsuite/gas/i386/x86-64-optimize-3b.d
index e7d211ed74c..ef6fd27c03c 100644
--- a/gas/testsuite/gas/i386/x86-64-optimize-3b.d
+++ b/gas/testsuite/gas/i386/x86-64-optimize-3b.d
@@ -95,6 +95,10 @@ Disassembly of section .text:
  +[a-f0-9]+:	66 98                	cbtw
  +[a-f0-9]+:	98                   	cwtl
  +[a-f0-9]+:	48 98                	cltq
+ +[a-f0-9]+:	d5 50 00 c9          	add    %r17b,%r17b
+ +[a-f0-9]+:	66 45 01 c0          	add    %r8w,%r8w
+ +[a-f0-9]+:	01 c0                	add    %eax,%eax
+ +[a-f0-9]+:	4d 01 ff             	add    %r15,%r15
  +[a-f0-9]+:	c5 f1 55 e9          	vandnpd %xmm1,%xmm1,%xmm5
  +[a-f0-9]+:	c5 f9 6f d1          	vmovdqa %xmm1,%xmm2
  +[a-f0-9]+:	c5 f9 6f d1          	vmovdqa %xmm1,%xmm2
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index bb547bd2ee7..63c3b5275b8 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -957,7 +957,7 @@ rex.wrxb, 0x4f, x64, NoSuf|IsPrefix, {}
 
 // 486 extensions (BSWAP moved elsewhere).
 
-xadd, 0xfc0, i486, W|CheckOperandSize|Modrm|No_sSuf|HLEPrefixLock, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+xadd, 0xfc0, i486, W|CheckOperandSize|Modrm|No_sSuf|HLEPrefixLock|Optimize, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
 cmpxchg, 0xfb0, i486, W|CheckOperandSize|Modrm|No_sSuf|HLEPrefixLock, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
 invd, 0xf08, i486, NoSuf, {}
 wbinvd, 0xf09, i486, NoSuf, {}
diff --git a/opcodes/i386-tbl.h b/opcodes/i386-tbl.h
index f1ecc6498af..e4738c32b06 100644
--- a/opcodes/i386-tbl.h
+++ b/opcodes/i386-tbl.h
@@ -8798,7 +8798,7 @@ static const insn_template i386_optab[] =
 	  0, 0, 0, 0, 0, 0 } } } },
   { MN_xadd, 0xc0, 2, SPACE_0F, None,
     { 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 6,
-      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, 1, 0, 0, 0, 0,
       0, 0 },
     { { 4, 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 } },