[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