[llvm] [X86][MC] Support encoding/decoding for APX variant MUL/IMUL/DIV/IDIV instructions (PR #76919)

Shengchen Kan via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 4 22:44:07 PST 2024


================
@@ -100,87 +136,204 @@ multiclass Div<bits<8> o, string m, Format RegMRM, Format MemMRM> {
   defvar sched32 = !if(!eq(m, "div"), WriteDiv32, WriteIDiv32);
   defvar sched64 = !if(!eq(m, "div"), WriteDiv64, WriteIDiv64);
   let Defs = [AL,AH,EFLAGS], Uses = [AX] in
-  def 8r  : MulDivOpR<o, RegMRM, m, Xi8, sched8, []>;
+    def 8r  : MulDivOpR<o, RegMRM, m, Xi8, sched8, []>;
   let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
-  def 16r : MulDivOpR<o, RegMRM, m, Xi16, sched16, []>, OpSize16;
+    def 16r : MulDivOpR<o, RegMRM, m, Xi16, sched16, []>, OpSize16;
   let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
-  def 32r : MulDivOpR<o, RegMRM, m, Xi32, sched32, []>, OpSize32;
+    def 32r : MulDivOpR<o, RegMRM, m, Xi32, sched32, []>, OpSize32;
   let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
-  def 64r : MulDivOpR<o, RegMRM, m, Xi64, sched64, []>;
+    def 64r : MulDivOpR<o, RegMRM, m, Xi64, sched64, []>;
   let Defs = [AL,AH,EFLAGS], Uses = [AX] in
-  def 8m  : MulDivOpM<o, MemMRM, m, Xi8, sched8, []>;
+    def 8m  : MulDivOpM<o, MemMRM, m, Xi8, sched8, []>;
   let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
-  def 16m : MulDivOpM<o, MemMRM, m, Xi16, sched16, []>, OpSize16;
+    def 16m : MulDivOpM<o, MemMRM, m, Xi16, sched16, []>, OpSize16;
   let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
-  def 32m : MulDivOpM<o, MemMRM, m, Xi32, sched32, []>, OpSize32;
+    def 32m : MulDivOpM<o, MemMRM, m, Xi32, sched32, []>, OpSize32;
   let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
-  def 64m : MulDivOpM<o, MemMRM, m, Xi64, sched64, []>, Requires<[In64BitMode]>;
+    def 64m : MulDivOpM<o, MemMRM, m, Xi64, sched64, []>, Requires<[In64BitMode]>;
+
+  let Predicates = [In64BitMode] in {
+    let Defs = [AL,AH], Uses = [AX] in
+      def 8r_NF  : MulDivOpR<o, RegMRM, m, Xi8, sched8, []>, NF;
+    let Defs = [AX,DX], Uses = [AX,DX] in
+      def 16r_NF : MulDivOpR<o, RegMRM, m, Xi16, sched16, []>, NF, PD;
+    let Defs = [EAX,EDX], Uses = [EAX,EDX] in
+      def 32r_NF : MulDivOpR<o, RegMRM, m, Xi32, sched32, []>, NF;
+    let Defs = [RAX,RDX], Uses = [RAX,RDX] in
+      def 64r_NF : MulDivOpR<o, RegMRM, m, Xi64, sched64, []>, NF;
+    let Defs = [AL,AH], Uses = [AX] in
+      def 8m_NF  : MulDivOpM<o, MemMRM, m, Xi8, sched8, []>, NF;
+    let Defs = [AX,DX], Uses = [AX,DX] in
+      def 16m_NF : MulDivOpM<o, MemMRM, m, Xi16, sched16, []>, NF, PD;
+    let Defs = [EAX,EDX], Uses = [EAX,EDX] in
+      def 32m_NF : MulDivOpM<o, MemMRM, m, Xi32, sched32, []>, NF;
+    let Defs = [RAX,RDX], Uses = [RAX,RDX] in
+      def 64m_NF : MulDivOpM<o, MemMRM, m, Xi64, sched64, []>, NF;
+
+    let Defs = [AL,AH,EFLAGS], Uses = [AX] in
+      def 8r_EVEX  : MulDivOpR<o, RegMRM, m, Xi8, sched8, []>, PL;
+    let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
+      def 16r_EVEX : MulDivOpR<o, RegMRM, m, Xi16, sched16, []>, PL, PD;
+    let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
+      def 32r_EVEX : MulDivOpR<o, RegMRM, m, Xi32, sched32, []>, PL;
+    let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
+      def 64r_EVEX : MulDivOpR<o, RegMRM, m, Xi64, sched64, []>, PL;
+    let Defs = [AL,AH,EFLAGS], Uses = [AX] in
+      def 8m_EVEX  : MulDivOpM<o, MemMRM, m, Xi8, sched8, []>, PL;
+    let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in
+      def 16m_EVEX : MulDivOpM<o, MemMRM, m, Xi16, sched16, []>, PL, PD;
+    let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in
+      def 32m_EVEX : MulDivOpM<o, MemMRM, m, Xi32, sched32, []>, PL;
+    let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in
+      def 64m_EVEX : MulDivOpM<o, MemMRM, m, Xi64, sched64, []>, PL;
+  }
 }
+
 let hasSideEffects = 1 in { // so that we don't speculatively execute
-defm DIV: Div<0xF7, "div", MRM6r, MRM6m>;
-defm IDIV: Div<0xF7, "idiv", MRM7r, MRM7m>;
+  defm DIV: Div<0xF7, "div", MRM6r, MRM6m>;
+  defm IDIV: Div<0xF7, "idiv", MRM7r, MRM7m>;
 }
 
-class IMulOpRR<X86TypeInfo t, X86FoldableSchedWrite sched>
-  : BinOpRR_RF<0xAF, "imul", t, X86smul_flag>, TB {
+class IMulOpRR_R<X86TypeInfo t, X86FoldableSchedWrite sched, bit ndd = 0>
+  : BinOpRR_R<0xAF, "imul", t, ndd> {
   let Form = MRMSrcReg;
   let SchedRW = [sched];
   // X = IMUL Y, Z --> X = IMUL Z, Y
   let isCommutable = 1;
 }
-class IMulOpRM<X86TypeInfo t, X86FoldableSchedWrite sched>
-  : BinOpRM_RF<0xAF, "imul", t, X86smul_flag>, TB {
-let Form = MRMSrcMem;
-let SchedRW = [sched.Folded, sched.ReadAfterFold];
+class IMulOpRR_RF<X86TypeInfo t, X86FoldableSchedWrite sched, bit ndd = 0>
+  : BinOpRR_RF<0xAF, "imul", t, X86smul_flag, ndd> {
+  let Form = MRMSrcReg;
+  let SchedRW = [sched];
+  // X = IMUL Y, Z --> X = IMUL Z, Y
+  let isCommutable = 1;
+}
+class IMulOpRM_R<X86TypeInfo t, X86FoldableSchedWrite sched, bit ndd = 0>
+  : BinOpRM_R<0xAF, "imul", t, ndd> {
+  let Form = MRMSrcMem;
+  let SchedRW = [sched.Folded, sched.ReadAfterFold];
+}
+class IMulOpRM_RF<X86TypeInfo t, X86FoldableSchedWrite sched, bit ndd = 0>
+  : BinOpRM_RF<0xAF, "imul", t, X86smul_flag, ndd> {
+  let Form = MRMSrcMem;
+  let SchedRW = [sched.Folded, sched.ReadAfterFold];
 }
 
-def IMUL16rr : IMulOpRR<Xi16, WriteIMul16Reg>, OpSize16;
-def IMUL32rr : IMulOpRR<Xi32, WriteIMul32Reg>, OpSize32;
-def IMUL64rr : IMulOpRR<Xi64, WriteIMul64Reg>;
-def IMUL16rm : IMulOpRM<Xi16, WriteIMul16Reg>, OpSize16;
-def IMUL32rm : IMulOpRM<Xi32, WriteIMul32Reg>, OpSize32;
-def IMUL64rm : IMulOpRM<Xi64, WriteIMul64Reg>;
+let Predicates = [NoNDD] in {
+  def IMUL16rr : IMulOpRR_RF<Xi16, WriteIMul16Reg>, TB, OpSize16;
+  def IMUL32rr : IMulOpRR_RF<Xi32, WriteIMul32Reg>, TB, OpSize32;
+  def IMUL64rr : IMulOpRR_RF<Xi64, WriteIMul64Reg>, TB;
+  def IMUL16rm : IMulOpRM_RF<Xi16, WriteIMul16Reg>, TB, OpSize16;
+  def IMUL32rm : IMulOpRM_RF<Xi32, WriteIMul32Reg>, TB, OpSize32;
+  def IMUL64rm : IMulOpRM_RF<Xi64, WriteIMul64Reg>, TB;
+}
+let Predicates = [HasNDD, In64BitMode] in {
+  def IMUL16rr_ND : IMulOpRR_RF<Xi16, WriteIMul16Reg, 1>, PD;
+  def IMUL32rr_ND : IMulOpRR_RF<Xi32, WriteIMul32Reg, 1>;
+  def IMUL64rr_ND : IMulOpRR_RF<Xi64, WriteIMul64Reg, 1>;
+  def IMUL16rm_ND : IMulOpRM_RF<Xi16, WriteIMul16Reg, 1>, PD;
+  def IMUL32rm_ND : IMulOpRM_RF<Xi32, WriteIMul32Reg, 1>;
+  def IMUL64rm_ND : IMulOpRM_RF<Xi64, WriteIMul64Reg, 1>;
+}
 
-class IMulOpRI8_R<X86TypeInfo t, X86FoldableSchedWrite sched>
+let Predicates = [In64BitMode], Pattern = [(null_frag)] in {
+  def IMUL16rr_NF : IMulOpRR_R<Xi16, WriteIMul16Reg>, NF, PD;
+  def IMUL32rr_NF : IMulOpRR_R<Xi32, WriteIMul32Reg>, NF;
+  def IMUL64rr_NF : IMulOpRR_R<Xi64, WriteIMul64Reg>, NF;
+  def IMUL16rm_NF : IMulOpRM_R<Xi16, WriteIMul16Reg>, NF, PD;
+  def IMUL32rm_NF : IMulOpRM_R<Xi32, WriteIMul32Reg>, NF;
+  def IMUL64rm_NF : IMulOpRM_R<Xi64, WriteIMul64Reg>, NF;
+
+  def IMUL16rr_NF_ND : IMulOpRR_R<Xi16, WriteIMul16Reg, 1>, EVEX_NF, PD;
+  def IMUL32rr_NF_ND : IMulOpRR_R<Xi32, WriteIMul32Reg, 1>, EVEX_NF;
+  def IMUL64rr_NF_ND : IMulOpRR_R<Xi64, WriteIMul64Reg, 1>, EVEX_NF;
+  def IMUL16rm_NF_ND : IMulOpRM_R<Xi16, WriteIMul16Reg, 1>, EVEX_NF, PD;
+  def IMUL32rm_NF_ND : IMulOpRM_R<Xi32, WriteIMul32Reg, 1>, EVEX_NF;
+  def IMUL64rm_NF_ND : IMulOpRM_R<Xi64, WriteIMul64Reg, 1>, EVEX_NF;
+
+  def IMUL16rr_EVEX : IMulOpRR_RF<Xi16, WriteIMul16Reg>, PL, PD;
+  def IMUL32rr_EVEX : IMulOpRR_RF<Xi32, WriteIMul32Reg>, PL;
+  def IMUL64rr_EVEX : IMulOpRR_RF<Xi64, WriteIMul64Reg>, PL;
+  def IMUL16rm_EVEX : IMulOpRM_RF<Xi16, WriteIMul16Reg>, PL, PD;
+  def IMUL32rm_EVEX : IMulOpRM_RF<Xi32, WriteIMul32Reg>, PL;
+  def IMUL64rm_EVEX : IMulOpRM_RF<Xi64, WriteIMul64Reg>, PL;
+}
+
+class IMulOpRI8<X86TypeInfo t, X86FoldableSchedWrite sched>
   : BinOpRI8<0x6B, "imul", binop_ndd_args, t, MRMSrcReg,
-             (outs t.RegClass:$dst)>, DefEFLAGS {
+             (outs t.RegClass:$dst)> {
   let SchedRW = [sched];
 }
 class IMulOpRI_R<X86TypeInfo t, X86FoldableSchedWrite sched>
+  : BinOpRI<0x69, "imul", binop_ndd_args, t, MRMSrcReg,
+            (outs t.RegClass:$dst), []> {
+  let SchedRW = [sched];
+}
+class IMulOpRI_RF<X86TypeInfo t, X86FoldableSchedWrite sched>
   : BinOpRI<0x69, "imul", binop_ndd_args, t, MRMSrcReg,
             (outs t.RegClass:$dst),
             [(set t.RegClass:$dst, EFLAGS, (X86smul_flag t.RegClass:$src1,
              t.ImmNoSuOperator:$src2))]>, DefEFLAGS {
   let SchedRW = [sched];
 }
-class IMulOpMI8_R<X86TypeInfo t, X86FoldableSchedWrite sched>
-  : BinOpMI8<"imul", binop_ndd_args, t, MRMSrcMem, (outs t.RegClass:$dst)>,
-    DefEFLAGS {
+class IMulOpMI8<X86TypeInfo t, X86FoldableSchedWrite sched>
+  : BinOpMI8<"imul", binop_ndd_args, t, MRMSrcMem, (outs t.RegClass:$dst)> {
   let Opcode = 0x6B;
   let SchedRW = [sched.Folded];
 }
 class IMulOpMI_R<X86TypeInfo t, X86FoldableSchedWrite sched>
+  : BinOpMI<0x69, "imul", binop_ndd_args, t, MRMSrcMem,
+            (outs t.RegClass:$dst), []> {
+  let SchedRW = [sched.Folded];
+}
+class IMulOpMI_RF<X86TypeInfo t, X86FoldableSchedWrite sched>
   : BinOpMI<0x69, "imul", binop_ndd_args, t, MRMSrcMem,
             (outs t.RegClass:$dst),
             [(set t.RegClass:$dst, EFLAGS, (X86smul_flag (t.LoadNode addr:$src1),
              t.ImmNoSuOperator:$src2))]>,
     DefEFLAGS {
   let SchedRW = [sched.Folded];
 }
-def IMUL16rri8 : IMulOpRI8_R<Xi16, WriteIMul16Imm>, OpSize16;
-def IMUL32rri8 : IMulOpRI8_R<Xi32, WriteIMul32Imm>, OpSize32;
-def IMUL64rri8 : IMulOpRI8_R<Xi64, WriteIMul64Imm>;
-def IMUL16rri  : IMulOpRI_R<Xi16, WriteIMul16Imm>, OpSize16;
-def IMUL32rri  : IMulOpRI_R<Xi32, WriteIMul32Imm>, OpSize32;
-def IMUL64rri32 : IMulOpRI_R<Xi64, WriteIMul64Imm>;
-
-def IMUL16rmi8 : IMulOpMI8_R<Xi16, WriteIMul16Imm>, OpSize16;
-def IMUL32rmi8 : IMulOpMI8_R<Xi32, WriteIMul32Imm>, OpSize32;
-def IMUL64rmi8 : IMulOpMI8_R<Xi64, WriteIMul64Imm>;
-def IMUL16rmi  : IMulOpMI_R<Xi16, WriteIMul16Imm>, OpSize16;
-def IMUL32rmi  : IMulOpMI_R<Xi32, WriteIMul32Imm>, OpSize32;
-def IMUL64rmi32 : IMulOpMI_R<Xi64, WriteIMul64Imm>;
-
+def IMUL16rri8 : IMulOpRI8<Xi16, WriteIMul16Imm>, DefEFLAGS, OpSize16;
----------------
KanRobert wrote:

We share the same class  `IMulOpRI8` for `IMUL16rri8_NF` and `IMUL16rri8`. That's why I don't add `_R`.

https://github.com/llvm/llvm-project/pull/76919


More information about the llvm-commits mailing list