Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[X86][MC] Support encoding/decoding for APX variant INC/DEC/ADCX/ADOX instructions #76721

Merged
merged 3 commits into from
Jan 4, 2024

Conversation

KanRobert
Copy link
Contributor

@KanRobert KanRobert commented Jan 2, 2024

Four variants: promoted legacy, ND (new data destination), NF (no flags update) and NF_ND (NF + ND).

The syntax of NF instructions is aligned with GNU binutils.
https://sourceware.org/pipermail/binutils/2023-September/129545.html

@llvmbot llvmbot added backend:X86 mc Machine (object) code labels Jan 2, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 2, 2024

@llvm/pr-subscribers-mc

@llvm/pr-subscribers-backend-x86

Author: Shengchen Kan (KanRobert)

Changes

Patch is 42.91 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/76721.diff

11 Files Affected:

  • (modified) llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp (+3)
  • (modified) llvm/lib/Target/X86/X86InstrArithmetic.td (+139-32)
  • (added) llvm/test/MC/Disassembler/X86/apx/adx.txt (+66)
  • (added) llvm/test/MC/Disassembler/X86/apx/dec.txt (+130)
  • (added) llvm/test/MC/Disassembler/X86/apx/inc.txt (+130)
  • (added) llvm/test/MC/X86/apx/adx-att.s (+53)
  • (added) llvm/test/MC/X86/apx/adx-intel.s (+50)
  • (added) llvm/test/MC/X86/apx/dec-att.s (+101)
  • (added) llvm/test/MC/X86/apx/dec-intel.s (+98)
  • (added) llvm/test/MC/X86/apx/inc-att.s (+101)
  • (added) llvm/test/MC/X86/apx/inc-intel.s (+98)
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 924956295e7c60..d152c85da9393c 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -1650,6 +1650,9 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI,
     if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV)
       ++SrcRegNum;
 
+    if (IsND)
+      ++CurOp;
+
     emitRegModRMByte(MI.getOperand(SrcRegNum),
                      getX86RegNum(MI.getOperand(CurOp)), CB);
     CurOp = SrcRegNum + 1;
diff --git a/llvm/lib/Target/X86/X86InstrArithmetic.td b/llvm/lib/Target/X86/X86InstrArithmetic.td
index 6b0c1b8c28c950..1fda4f2993211f 100644
--- a/llvm/lib/Target/X86/X86InstrArithmetic.td
+++ b/llvm/lib/Target/X86/X86InstrArithmetic.td
@@ -184,52 +184,139 @@ def IMUL64rmi32 : IMulOpMI_R<Xi64, WriteIMul64Imm>;
 //===----------------------------------------------------------------------===//
 // INC and DEC Instructions
 //
-class IncOpR_RF<X86TypeInfo t> : UnaryOpR_RF<0xFF, MRM0r, "inc", t, null_frag> {
+class IncOpR_RF<X86TypeInfo t, bit ndd = 0> : UnaryOpR_RF<0xFF, MRM0r, "inc", t, null_frag, ndd> {
   let Pattern = [(set t.RegClass:$dst, EFLAGS,
                  (X86add_flag_nocf t.RegClass:$src1, 1))];
 }
-class DecOpR_RF<X86TypeInfo t> : UnaryOpR_RF<0xFF, MRM1r, "dec", t, null_frag> {
+class DecOpR_RF<X86TypeInfo t, bit ndd = 0> : UnaryOpR_RF<0xFF, MRM1r, "dec", t, null_frag, ndd> {
   let Pattern = [(set t.RegClass:$dst, EFLAGS,
                  (X86sub_flag_nocf t.RegClass:$src1, 1))];
 }
-class IncOpM_M<X86TypeInfo t> : UnaryOpM_MF<0xFF, MRM0m, "inc", t, null_frag> {
+class IncOpR_R<X86TypeInfo t, bit ndd = 0> : UnaryOpR_R<0xFF, MRM0r, "inc", t, null_frag, ndd>;
+class DecOpR_R<X86TypeInfo t, bit ndd = 0> : UnaryOpR_R<0xFF, MRM1r, "dec", t, null_frag, ndd>;
+class IncOpM_MF<X86TypeInfo t> : UnaryOpM_MF<0xFF, MRM0m, "inc", t, null_frag> {
   let Pattern = [(store (add (t.LoadNode addr:$src1), 1), addr:$src1),
                  (implicit EFLAGS)];
 }
-class DecOpM_M<X86TypeInfo t> : UnaryOpM_MF<0xFF, MRM1m, "dec", t, null_frag> {
+class DecOpM_MF<X86TypeInfo t> : UnaryOpM_MF<0xFF, MRM1m, "dec", t, null_frag> {
   let Pattern = [(store (add (t.LoadNode addr:$src1), -1), addr:$src1),
                  (implicit EFLAGS)];
 }
+class IncOpM_RF<X86TypeInfo t> : UnaryOpM_RF<0xFF, MRM0m, "inc", t, null_frag> {
+  let Pattern = [(set t.RegClass:$dst, EFLAGS, (add (t.LoadNode addr:$src1), 1))];
+}
+class DecOpM_RF<X86TypeInfo t> : UnaryOpM_RF<0xFF, MRM1m, "dec", t, null_frag> {
+  let Pattern = [(set t.RegClass:$dst, EFLAGS, (add (t.LoadNode addr:$src1), -1))];
+}
+class IncOpM_M<X86TypeInfo t> : UnaryOpM_M<0xFF, MRM0m, "inc", t, null_frag>;
+class DecOpM_M<X86TypeInfo t> : UnaryOpM_M<0xFF, MRM1m, "dec", t, null_frag>;
+class IncOpM_R<X86TypeInfo t> : UnaryOpM_R<0xFF, MRM0m, "inc", t, null_frag>;
+class DecOpM_R<X86TypeInfo t> : UnaryOpM_R<0xFF, MRM1m, "dec", t, null_frag>;
+
 // IncDec_Alt - Instructions like "inc reg" short forms.
 // Short forms only valid in 32-bit mode. Selected during MCInst lowering.
 class IncDec_Alt<bits<8> o, string m, X86TypeInfo t>
   : UnaryOpR_RF<o, AddRegFrm, m, t, null_frag>, Requires<[Not64BitMode]>;
 
 let isConvertibleToThreeAddress = 1 in {
-def INC16r_alt : IncDec_Alt<0x40, "inc", Xi16>, OpSize16;
-def INC32r_alt : IncDec_Alt<0x40, "inc", Xi32>, OpSize32;
-def DEC16r_alt : IncDec_Alt<0x48, "dec", Xi16>, OpSize16;
-def DEC32r_alt : IncDec_Alt<0x48, "dec", Xi32>, OpSize32;
-def INC8r  : IncOpR_RF<Xi8>;
-def INC16r : IncOpR_RF<Xi16>, OpSize16;
-def INC32r : IncOpR_RF<Xi32>, OpSize32;
-def INC64r : IncOpR_RF<Xi64>;
-def DEC8r  : DecOpR_RF<Xi8>;
-def DEC16r : DecOpR_RF<Xi16>, OpSize16;
-def DEC32r : DecOpR_RF<Xi32>, OpSize32;
-def DEC64r : DecOpR_RF<Xi64>;
+  def INC16r_alt : IncDec_Alt<0x40, "inc", Xi16>, OpSize16;
+  def INC32r_alt : IncDec_Alt<0x40, "inc", Xi32>, OpSize32;
+  def DEC16r_alt : IncDec_Alt<0x48, "dec", Xi16>, OpSize16;
+  def DEC32r_alt : IncDec_Alt<0x48, "dec", Xi32>, OpSize32;
+  let Predicates = [NoNDD] in {
+    def INC8r  : IncOpR_RF<Xi8>;
+    def INC16r : IncOpR_RF<Xi16>, OpSize16;
+    def INC32r : IncOpR_RF<Xi32>, OpSize32;
+    def INC64r : IncOpR_RF<Xi64>;
+    def DEC8r  : DecOpR_RF<Xi8>;
+    def DEC16r : DecOpR_RF<Xi16>, OpSize16;
+    def DEC32r : DecOpR_RF<Xi32>, OpSize32;
+    def DEC64r : DecOpR_RF<Xi64>;
+  }
+  let Predicates = [HasNDD, In64BitMode] in {
+    def INC8r_ND  : IncOpR_RF<Xi8, 1>;
+    def INC16r_ND : IncOpR_RF<Xi16, 1>, PD;
+    def INC32r_ND : IncOpR_RF<Xi32, 1>;
+    def INC64r_ND : IncOpR_RF<Xi64, 1>;
+    def DEC8r_ND  : DecOpR_RF<Xi8, 1>;
+    def DEC16r_ND : DecOpR_RF<Xi16, 1>, PD;
+    def DEC32r_ND : DecOpR_RF<Xi32, 1>;
+    def DEC64r_ND : DecOpR_RF<Xi64, 1>;
+  }
+  let Predicates = [In64BitMode], Pattern = [(null_frag)] in {
+    def INC8r_NF  : IncOpR_R<Xi8>, NF;
+    def INC16r_NF : IncOpR_R<Xi16>, NF, PD;
+    def INC32r_NF : IncOpR_R<Xi32>, NF;
+    def INC64r_NF : IncOpR_R<Xi64>, NF;
+    def DEC8r_NF  : DecOpR_R<Xi8>, NF;
+    def DEC16r_NF : DecOpR_R<Xi16>, NF, PD;
+    def DEC32r_NF : DecOpR_R<Xi32>, NF;
+    def DEC64r_NF : DecOpR_R<Xi64>, NF;
+    def INC8r_NF_ND  : IncOpR_R<Xi8, 1>, NF;
+    def INC16r_NF_ND : IncOpR_R<Xi16, 1>, NF, PD;
+    def INC32r_NF_ND : IncOpR_R<Xi32, 1>, NF;
+    def INC64r_NF_ND : IncOpR_R<Xi64, 1>, NF;
+    def DEC8r_NF_ND  : DecOpR_R<Xi8, 1>, NF;
+    def DEC16r_NF_ND : DecOpR_R<Xi16, 1>, NF, PD;
+    def DEC32r_NF_ND : DecOpR_R<Xi32, 1>, NF;
+    def DEC64r_NF_ND : DecOpR_R<Xi64, 1>, NF;
+    def INC8r_EVEX  : IncOpR_RF<Xi8>, PL;
+    def INC16r_EVEX : IncOpR_RF<Xi16>, PL, PD;
+    def INC32r_EVEX : IncOpR_RF<Xi32>, PL;
+    def INC64r_EVEX : IncOpR_RF<Xi64>, PL;
+    def DEC8r_EVEX  : DecOpR_RF<Xi8>, PL;
+    def DEC16r_EVEX : DecOpR_RF<Xi16>, PL, PD;
+    def DEC32r_EVEX : DecOpR_RF<Xi32>, PL;
+    def DEC64r_EVEX : DecOpR_RF<Xi64>, PL;
+  }
 }
 let Predicates = [UseIncDec] in {
-def INC8m  : IncOpM_M<Xi8>;
-def INC16m : IncOpM_M<Xi16>, OpSize16;
-def INC32m : IncOpM_M<Xi32>, OpSize32;
-def DEC8m  : DecOpM_M<Xi8>;
-def DEC16m : DecOpM_M<Xi16>, OpSize16;
-def DEC32m : DecOpM_M<Xi32>, OpSize32;
+  def INC8m  : IncOpM_MF<Xi8>;
+  def INC16m : IncOpM_MF<Xi16>, OpSize16;
+  def INC32m : IncOpM_MF<Xi32>, OpSize32;
+  def DEC8m  : DecOpM_MF<Xi8>;
+  def DEC16m : DecOpM_MF<Xi16>, OpSize16;
+  def DEC32m : DecOpM_MF<Xi32>, OpSize32;
 }
 let Predicates = [UseIncDec, In64BitMode] in {
-def INC64m : IncOpM_M<Xi64>;
-def DEC64m : DecOpM_M<Xi64>;
+  def INC64m : IncOpM_MF<Xi64>;
+  def DEC64m : DecOpM_MF<Xi64>;
+}
+let Predicates = [HasNDD, In64BitMode, UseIncDec] in {
+  def INC8m_ND  : IncOpM_RF<Xi8>;
+  def INC16m_ND : IncOpM_RF<Xi16>, PD;
+  def INC32m_ND : IncOpM_RF<Xi32>;
+  def DEC8m_ND  : DecOpM_RF<Xi8>;
+  def DEC16m_ND : DecOpM_RF<Xi16>, PD;
+  def DEC32m_ND : DecOpM_RF<Xi32>;
+  def INC64m_ND : IncOpM_RF<Xi64>;
+  def DEC64m_ND : DecOpM_RF<Xi64>;
+}
+let Predicates = [In64BitMode], Pattern = [(null_frag)] in {
+  def INC8m_NF  : IncOpM_M<Xi8>, NF;
+  def INC16m_NF : IncOpM_M<Xi16>, NF, PD;
+  def INC32m_NF : IncOpM_M<Xi32>, NF;
+  def INC64m_NF : IncOpM_M<Xi64>, NF;
+  def DEC8m_NF  : DecOpM_M<Xi8>, NF;
+  def DEC16m_NF : DecOpM_M<Xi16>, NF, PD;
+  def DEC32m_NF : DecOpM_M<Xi32>, NF;
+  def DEC64m_NF : DecOpM_M<Xi64>, NF;
+  def INC8m_NF_ND  : IncOpM_R<Xi8>, NF;
+  def INC16m_NF_ND : IncOpM_R<Xi16>, NF, PD;
+  def INC32m_NF_ND : IncOpM_R<Xi32>, NF;
+  def INC64m_NF_ND : IncOpM_R<Xi64>, NF;
+  def DEC8m_NF_ND  : DecOpM_R<Xi8>, NF;
+  def DEC16m_NF_ND : DecOpM_R<Xi16>, NF, PD;
+  def DEC32m_NF_ND : DecOpM_R<Xi32>, NF;
+  def DEC64m_NF_ND : DecOpM_R<Xi64>, NF;
+  def INC8m_EVEX  : IncOpM_MF<Xi8>, PL;
+  def INC16m_EVEX : IncOpM_MF<Xi16>, PL, PD;
+  def INC32m_EVEX : IncOpM_MF<Xi32>, PL;
+  def INC64m_EVEX : IncOpM_MF<Xi64>, PL;
+  def DEC8m_EVEX  : DecOpM_MF<Xi8>, PL;
+  def DEC16m_EVEX : DecOpM_MF<Xi16>, PL, PD;
+  def DEC32m_EVEX : DecOpM_MF<Xi32>, PL;
+  def DEC64m_EVEX : DecOpM_MF<Xi64>, PL;
 }
 
 //===----------------------------------------------------------------------===//
@@ -1119,14 +1206,34 @@ defm MULX64 : MulX<Xi64, WriteMULX64>, REX_W;
 // We don't have patterns for these as there is no advantage over ADC for
 // most code.
 let Form = MRMSrcReg in {
-def ADCX32rr : BinOpRRF_RF<0xF6, "adcx", Xi32, null_frag>, T8, PD;
-def ADCX64rr : BinOpRRF_RF<0xF6, "adcx", Xi64, null_frag>, T8, PD;
-def ADOX32rr : BinOpRRF_RF<0xF6, "adox", Xi32, null_frag>, T8, XS;
-def ADOX64rr : BinOpRRF_RF<0xF6, "adox", Xi64, null_frag>, T8, XS;
+  def ADCX32rr : BinOpRRF_RF<0xF6, "adcx", Xi32, null_frag>, T8, PD;
+  def ADCX64rr : BinOpRRF_RF<0xF6, "adcx", Xi64, null_frag>, T8, PD;
+  def ADOX32rr : BinOpRRF_RF<0xF6, "adox", Xi32, null_frag>, T8, XS;
+  def ADOX64rr : BinOpRRF_RF<0xF6, "adox", Xi64, null_frag>, T8, XS;
+  let Predicates =[In64BitMode] in {
+    def ADCX32rr_EVEX : BinOpRRF_RF<0x66, "adcx", Xi32, null_frag>, EVEX, T_MAP4, PD;
+    def ADCX64rr_EVEX : BinOpRRF_RF<0x66, "adcx", Xi64, null_frag>, EVEX, T_MAP4, PD;
+    def ADOX32rr_EVEX : BinOpRRF_RF<0x66, "adox", Xi32, null_frag>, EVEX, T_MAP4, XS;
+    def ADOX64rr_EVEX : BinOpRRF_RF<0x66, "adox", Xi64, null_frag>, EVEX, T_MAP4, XS;
+    def ADCX32rr_ND : BinOpRRF_RF<0x66, "adcx", Xi32, null_frag, 1>, PD;
+    def ADCX64rr_ND : BinOpRRF_RF<0x66, "adcx", Xi64, null_frag, 1>, PD;
+    def ADOX32rr_ND : BinOpRRF_RF<0x66, "adox", Xi32, null_frag, 1>, XS;
+    def ADOX64rr_ND : BinOpRRF_RF<0x66, "adox", Xi64, null_frag, 1>, XS;
+  }
 }
 let Form = MRMSrcMem in {
-def ADCX32rm : BinOpRMF_RF<0xF6, "adcx", Xi32, null_frag>, T8, PD;
-def ADCX64rm : BinOpRMF_RF<0xF6, "adcx", Xi64, null_frag>, T8, PD;
-def ADOX32rm : BinOpRMF_RF<0xF6, "adox", Xi32, null_frag>, T8, XS;
-def ADOX64rm : BinOpRMF_RF<0xF6, "adox", Xi64, null_frag>, T8, XS;
+  def ADCX32rm : BinOpRMF_RF<0xF6, "adcx", Xi32, null_frag>, T8, PD;
+  def ADCX64rm : BinOpRMF_RF<0xF6, "adcx", Xi64, null_frag>, T8, PD;
+  def ADOX32rm : BinOpRMF_RF<0xF6, "adox", Xi32, null_frag>, T8, XS;
+  def ADOX64rm : BinOpRMF_RF<0xF6, "adox", Xi64, null_frag>, T8, XS;
+  let Predicates =[In64BitMode] in {
+    def ADCX32rm_EVEX : BinOpRMF_RF<0x66, "adcx", Xi32, null_frag>, EVEX, T_MAP4, PD;
+    def ADCX64rm_EVEX : BinOpRMF_RF<0x66, "adcx", Xi64, null_frag>, EVEX, T_MAP4, PD;
+    def ADOX32rm_EVEX : BinOpRMF_RF<0x66, "adox", Xi32, null_frag>, EVEX, T_MAP4, XS;
+    def ADOX64rm_EVEX : BinOpRMF_RF<0x66, "adox", Xi64, null_frag>, EVEX, T_MAP4, XS;
+    def ADCX32rm_ND : BinOpRMF_RF<0x66, "adcx", Xi32, null_frag, 1>, PD;
+    def ADCX64rm_ND : BinOpRMF_RF<0x66, "adcx", Xi64, null_frag, 1>, PD;
+    def ADOX32rm_ND : BinOpRMF_RF<0x66, "adox", Xi32, null_frag, 1>, XS;
+    def ADOX64rm_ND : BinOpRMF_RF<0x66, "adox", Xi64, null_frag, 1>, XS;
+  }
 }
diff --git a/llvm/test/MC/Disassembler/X86/apx/adx.txt b/llvm/test/MC/Disassembler/X86/apx/adx.txt
new file mode 100644
index 00000000000000..926cd14bef1100
--- /dev/null
+++ b/llvm/test/MC/Disassembler/X86/apx/adx.txt
@@ -0,0 +1,66 @@
+# RUN: llvm-mc -triple x86_64 -disassemble %s | FileCheck %s --check-prefix=ATT
+# RUN: llvm-mc -triple x86_64 -disassemble -output-asm-variant=1 %s | FileCheck %s --check-prefix=INTEL
+
+# ATT:   adcxl	%r16d, %r17d
+# INTEL: adcx	r17d, r16d
+0x62,0xec,0x7d,0x08,0x66,0xc8
+
+# ATT:   adcxl	%r16d, %r17d, %r18d
+# INTEL: adcx	r18d, r17d, r16d
+0x62,0xec,0x6d,0x10,0x66,0xc8
+
+# ATT:   adcxq	%r16, %r17
+# INTEL: adcx	r17, r16
+0x62,0xec,0xfd,0x08,0x66,0xc8
+
+# ATT:   adcxq	%r16, %r17, %r18
+# INTEL: adcx	r18, r17, r16
+0x62,0xec,0xed,0x10,0x66,0xc8
+
+# ATT:   adcxl	(%r16), %r17d
+# INTEL: adcx	r17d, dword ptr [r16]
+0x62,0xec,0x7d,0x08,0x66,0x08
+
+# ATT:   adcxl	(%r16), %r17d, %r18d
+# INTEL: adcx	r18d, r17d, dword ptr [r16]
+0x62,0xec,0x6d,0x10,0x66,0x08
+
+# ATT:   adcxq	(%r16), %r17
+# INTEL: adcx	r17, qword ptr [r16]
+0x62,0xec,0xfd,0x08,0x66,0x08
+
+# ATT:   adcxq	(%r16), %r17, %r18
+# INTEL: adcx	r18, r17, qword ptr [r16]
+0x62,0xec,0xed,0x10,0x66,0x08
+
+# ATT:   adoxl	%r16d, %r17d
+# INTEL: adox	r17d, r16d
+0x62,0xec,0x7e,0x08,0x66,0xc8
+
+# ATT:   adoxl	%r16d, %r17d, %r18d
+# INTEL: adox	r18d, r17d, r16d
+0x62,0xec,0x6e,0x10,0x66,0xc8
+
+# ATT:   adoxq	%r16, %r17
+# INTEL: adox	r17, r16
+0x62,0xec,0xfe,0x08,0x66,0xc8
+
+# ATT:   adoxq	%r16, %r17, %r18
+# INTEL: adox	r18, r17, r16
+0x62,0xec,0xee,0x10,0x66,0xc8
+
+# ATT:   adoxl	(%r16), %r17d
+# INTEL: adox	r17d, dword ptr [r16]
+0x62,0xec,0x7e,0x08,0x66,0x08
+
+# ATT:   adoxl	(%r16), %r17d, %r18d
+# INTEL: adox	r18d, r17d, dword ptr [r16]
+0x62,0xec,0x6e,0x10,0x66,0x08
+
+# ATT:   adoxq	(%r16), %r17
+# INTEL: adox	r17, qword ptr [r16]
+0x62,0xec,0xfe,0x08,0x66,0x08
+
+# ATT:   adoxq	(%r16), %r17, %r18
+# INTEL: adox	r18, r17, qword ptr [r16]
+0x62,0xec,0xee,0x10,0x66,0x08
diff --git a/llvm/test/MC/Disassembler/X86/apx/dec.txt b/llvm/test/MC/Disassembler/X86/apx/dec.txt
new file mode 100644
index 00000000000000..029cf192558573
--- /dev/null
+++ b/llvm/test/MC/Disassembler/X86/apx/dec.txt
@@ -0,0 +1,130 @@
+# RUN: llvm-mc -triple x86_64 -disassemble %s | FileCheck %s --check-prefix=ATT
+# RUN: llvm-mc -triple x86_64 -disassemble -output-asm-variant=1 %s | FileCheck %s --check-prefix=INTEL
+
+# ATT:   {evex}	decb	%bl
+# INTEL: {evex}	dec	bl
+0x62,0xf4,0x7c,0x08,0xfe,0xcb
+
+# ATT:   {nf}	decb	%bl
+# INTEL: {nf}	dec	bl
+0x62,0xf4,0x7c,0x0c,0xfe,0xcb
+
+# ATT:   decb	%bl, %bl
+# INTEL: dec	bl, bl
+0x62,0xf4,0x64,0x18,0xfe,0xcb
+
+# ATT:   {nf}	decb	%bl, %bl
+# INTEL: {nf}	dec	bl, bl
+0x62,0xf4,0x64,0x1c,0xfe,0xcb
+
+# ATT:   {evex}	decw	%dx
+# INTEL: {evex}	dec	dx
+0x62,0xf4,0x7d,0x08,0xff,0xca
+
+# ATT:   {nf}	decw	%dx
+# INTEL: {nf}	dec	dx
+0x62,0xf4,0x7d,0x0c,0xff,0xca
+
+# ATT:   decw	%dx, %dx
+# INTEL: dec	dx, dx
+0x62,0xf4,0x6d,0x18,0xff,0xca
+
+# ATT:   {nf}	decw	%dx, %dx
+# INTEL: {nf}	dec	dx, dx
+0x62,0xf4,0x6d,0x1c,0xff,0xca
+
+# ATT:   {evex}	decl	%ecx
+# INTEL: {evex}	dec	ecx
+0x62,0xf4,0x7c,0x08,0xff,0xc9
+
+# ATT:   {nf}	decl	%ecx
+# INTEL: {nf}	dec	ecx
+0x62,0xf4,0x7c,0x0c,0xff,0xc9
+
+# ATT:   decl	%ecx, %ecx
+# INTEL: dec	ecx, ecx
+0x62,0xf4,0x74,0x18,0xff,0xc9
+
+# ATT:   {nf}	decl	%ecx, %ecx
+# INTEL: {nf}	dec	ecx, ecx
+0x62,0xf4,0x74,0x1c,0xff,0xc9
+
+# ATT:   {evex}	decq	%r9
+# INTEL: {evex}	dec	r9
+0x62,0xd4,0xfc,0x08,0xff,0xc9
+
+# ATT:   {nf}	decq	%r9
+# INTEL: {nf}	dec	r9
+0x62,0xd4,0xfc,0x0c,0xff,0xc9
+
+# ATT:   decq	%r9, %r9
+# INTEL: dec	r9, r9
+0x62,0xd4,0xb4,0x18,0xff,0xc9
+
+# ATT:   {nf}	decq	%r9, %r9
+# INTEL: {nf}	dec	r9, r9
+0x62,0xd4,0xb4,0x1c,0xff,0xc9
+
+# ATT:   {evex}	decb	291(%r8,%rax,4)
+# INTEL: {evex}	dec	byte ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x7c,0x08,0xfe,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	decb	291(%r8,%rax,4)
+# INTEL: {nf}	dec	byte ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x7c,0x0c,0xfe,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   decb	291(%r8,%rax,4), %bl
+# INTEL: dec	bl, byte ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x64,0x18,0xfe,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	decb	291(%r8,%rax,4), %bl
+# INTEL: {nf}	dec	bl, byte ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x64,0x1c,0xfe,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {evex}	decw	291(%r8,%rax,4)
+# INTEL: {evex}	dec	word ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x7d,0x08,0xff,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	decw	291(%r8,%rax,4)
+# INTEL: {nf}	dec	word ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x7d,0x0c,0xff,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   decw	291(%r8,%rax,4), %dx
+# INTEL: dec	dx, word ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x6d,0x18,0xff,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	decw	291(%r8,%rax,4), %dx
+# INTEL: {nf}	dec	dx, word ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x6d,0x1c,0xff,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {evex}	decl	291(%r8,%rax,4)
+# INTEL: {evex}	dec	dword ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x7c,0x08,0xff,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	decl	291(%r8,%rax,4)
+# INTEL: {nf}	dec	dword ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x7c,0x0c,0xff,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   decl	291(%r8,%rax,4), %ecx
+# INTEL: dec	ecx, dword ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x74,0x18,0xff,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	decl	291(%r8,%rax,4), %ecx
+# INTEL: {nf}	dec	ecx, dword ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x74,0x1c,0xff,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {evex}	decq	291(%r8,%rax,4)
+# INTEL: {evex}	dec	qword ptr [r8 + 4*rax + 291]
+0x62,0xd4,0xfc,0x08,0xff,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	decq	291(%r8,%rax,4)
+# INTEL: {nf}	dec	qword ptr [r8 + 4*rax + 291]
+0x62,0xd4,0xfc,0x0c,0xff,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   decq	291(%r8,%rax,4), %r9
+# INTEL: dec	r9, qword ptr [r8 + 4*rax + 291]
+0x62,0xd4,0xb4,0x18,0xff,0x8c,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	decq	291(%r8,%rax,4), %r9
+# INTEL: {nf}	dec	r9, qword ptr [r8 + 4*rax + 291]
+0x62,0xd4,0xb4,0x1c,0xff,0x8c,0x80,0x23,0x01,0x00,0x00
diff --git a/llvm/test/MC/Disassembler/X86/apx/inc.txt b/llvm/test/MC/Disassembler/X86/apx/inc.txt
new file mode 100644
index 00000000000000..0470319b4f6cdd
--- /dev/null
+++ b/llvm/test/MC/Disassembler/X86/apx/inc.txt
@@ -0,0 +1,130 @@
+# RUN: llvm-mc -triple x86_64 -disassemble %s | FileCheck %s --check-prefix=ATT
+# RUN: llvm-mc -triple x86_64 -disassemble -output-asm-variant=1 %s | FileCheck %s --check-prefix=INTEL
+
+# ATT:   {evex}	incb	%bl
+# INTEL: {evex}	inc	bl
+0x62,0xf4,0x7c,0x08,0xfe,0xc3
+
+# ATT:   {nf}	incb	%bl
+# INTEL: {nf}	inc	bl
+0x62,0xf4,0x7c,0x0c,0xfe,0xc3
+
+# ATT:   incb	%bl, %bl
+# INTEL: inc	bl, bl
+0x62,0xf4,0x64,0x18,0xfe,0xc3
+
+# ATT:   {nf}	incb	%bl, %bl
+# INTEL: {nf}	inc	bl, bl
+0x62,0xf4,0x64,0x1c,0xfe,0xc3
+
+# ATT:   {evex}	incw	%dx
+# INTEL: {evex}	inc	dx
+0x62,0xf4,0x7d,0x08,0xff,0xc2
+
+# ATT:   {nf}	incw	%dx
+# INTEL: {nf}	inc	dx
+0x62,0xf4,0x7d,0x0c,0xff,0xc2
+
+# ATT:   incw	%dx, %dx
+# INTEL: inc	dx, dx
+0x62,0xf4,0x6d,0x18,0xff,0xc2
+
+# ATT:   {nf}	incw	%dx, %dx
+# INTEL: {nf}	inc	dx, dx
+0x62,0xf4,0x6d,0x1c,0xff,0xc2
+
+# ATT:   {evex}	incl	%ecx
+# INTEL: {evex}	inc	ecx
+0x62,0xf4,0x7c,0x08,0xff,0xc1
+
+# ATT:   {nf}	incl	%ecx
+# INTEL: {nf}	inc	ecx
+0x62,0xf4,0x7c,0x0c,0xff,0xc1
+
+# ATT:   incl	%ecx, %ecx
+# INTEL: inc	ecx, ecx
+0x62,0xf4,0x74,0x18,0xff,0xc1
+
+# ATT:   {nf}	incl	%ecx, %ecx
+# INTEL: {nf}	inc	ecx, ecx
+0x62,0xf4,0x74,0x1c,0xff,0xc1
+
+# ATT:   {evex}	incq	%r9
+# INTEL: {evex}	inc	r9
+0x62,0xd4,0xfc,0x08,0xff,0xc1
+
+# ATT:   {nf}	incq	%r9
+# INTEL: {nf}	inc	r9
+0x62,0xd4,0xfc,0x0c,0xff,0xc1
+
+# ATT:   incq	%r9, %r9
+# INTEL: inc	r9, r9
+0x62,0xd4,0xb4,0x18,0xff,0xc1
+
+# ATT:   {nf}	incq	%r9, %r9
+# INTEL: {nf}	inc	r9, r9
+0x62,0xd4,0xb4,0x1c,0xff,0xc1
+
+# ATT:   {evex}	incb	291(%r8,%rax,4)
+# INTEL: {evex}	inc	byte ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x7c,0x08,0xfe,0x84,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	incb	291(%r8,%rax,4)
+# INTEL: {nf}	inc	byte ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x7c,0x0c,0xfe,0x84,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   incb	291(%r8,%rax,4), %bl
+# INTEL: inc	bl, byte ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x64,0x18,0xfe,0x84,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	incb	291(%r8,%rax,4), %bl
+# INTEL: {nf}	inc	bl, byte ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x64,0x1c,0xfe,0x84,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {evex}	incw	291(%r8,%rax,4)
+# INTEL: {evex}	inc	word ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x7d,0x08,0xff,0x84,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	incw	291(%r8,%rax,4)
+# INTEL: {nf}	inc	word ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x7d,0x0c,0xff,0x84,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   incw	291(%r8,%rax,4), %dx
+# INTEL: inc	dx, word ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x6d,0x18,0xff,0x84,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	incw	291(%r8,%rax,4), %dx
+# INTEL: {nf}	inc	dx, word ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x6d,0x1c,0xff,0x84,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {evex}	incl	291(%r8,%rax,4)
+# INTEL: {evex}	inc	dword ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x7c,0x08,0xff,0x84,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	incl	291(%r8,%rax,4)
+# INTEL: {nf}	inc	dword ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x7c,0x0c,0xff,0x84,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   incl	291(%r8,%rax,4), %ecx
+# INTEL: inc	ecx, dword ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x74,0x18,0xff,0x84,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {nf}	incl	291(%r8,%rax,4), %ecx
+# INTEL: {nf}	inc	ecx, dword ptr [r8 + 4*rax + 291]
+0x62,0xd4,0x74,0x1c,0xff,0x84,0x80,0x23,0x01,0x00,0x00
+
+# ATT:   {evex}	incq	291(%r8,%rax,4)
+# INTEL: {evex}...
[truncated]

llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp Outdated Show resolved Hide resolved
def DEC32r_ND : DecOpR_RF<Xi32, 1>;
def DEC64r_ND : DecOpR_RF<Xi64, 1>;
}
let Predicates = [In64BitMode], Pattern = [(null_frag)] in {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why set Pattern = [(null_frag)] here given both IncOpR_R and IncOpR_RF already pass null_frag by default?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only need to set Pattern = [(null_frag)] for INC/DEC*_EVEX. I put the setting in a wider range just to reduce nested let statements. Otherwise, the code would look like

 let Predicates = [In64BitMode] in {
    def INC8r_NF
    let Pattern = [(null_frag)] in {
       def INC8r_EVEX
    }
 }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about move INC8r_EVEX INC8m_EVEX together with let Predicates = [In64BitMode], Pattern = [(null_frag)]?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not save anything b/c we can not move INC8r_NF, which needs isConvertibleToThreeAddress = 1

llvm/lib/Target/X86/X86InstrArithmetic.td Show resolved Hide resolved
llvm/lib/Target/X86/X86InstrArithmetic.td Outdated Show resolved Hide resolved
llvm/lib/Target/X86/X86InstrArithmetic.td Outdated Show resolved Hide resolved
Comment on lines +1214 to +1217
def ADCX32rr_EVEX : BinOpRRF_RF<0x66, "adcx", Xi32>, EVEX, T_MAP4, PD;
def ADCX64rr_EVEX : BinOpRRF_RF<0x66, "adcx", Xi64>, EVEX, T_MAP4, PD;
def ADOX32rr_EVEX : BinOpRRF_RF<0x66, "adox", Xi32>, EVEX, T_MAP4, XS;
def ADOX64rr_EVEX : BinOpRRF_RF<0x66, "adox", Xi64>, EVEX, T_MAP4, XS;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't set Pattern = [(null_frag)] for these?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You suggested "make null_frag a default value for BinOpRRF_RF" and I made the change. Now the Pattern is equivalent to [(null_frag)], we don't need to set it explicitly here.

Copy link
Contributor

@phoebewang phoebewang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@KanRobert KanRobert merged commit dd9681f into llvm:main Jan 4, 2024
4 checks passed
KanRobert added a commit that referenced this pull request Jan 11, 2024
…T/INC/DEC/IMUL (#77564)

We supported encoding/decoding for these instructions in

#76319
#76721
#76919
justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this pull request Jan 28, 2024
…T/INC/DEC/IMUL (llvm#77564)

We supported encoding/decoding for these instructions in

llvm#76319
llvm#76721
llvm#76919
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:X86 mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants