[llvm] [X86] Support encoding/decoding and lowering for APX variant SHL/SHR/SAR/SHLD/SHRD (PR #78853)

Shengchen Kan via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 21 22:28:09 PST 2024


================
@@ -20,45 +20,209 @@ multiclass ShiftRotate<string m, Format RegMRM, Format MemMRM, SDPatternOperator
 
   let Uses = uses in {
     let isConvertibleToThreeAddress = !if(!eq(m, "shl"), 1, 0) in {
-      def 8ri  : BinOpRI8U_R<m, RegMRM, Xi8, node>, Sched<[ri]>, DefEFLAGS;
-      def 16ri : BinOpRI8U_R<m, RegMRM, Xi16, node>, Sched<[ri]>, DefEFLAGS, OpSize16;
-      def 32ri : BinOpRI8U_R<m, RegMRM, Xi32, node>, Sched<[ri]>, DefEFLAGS, OpSize32;
-      def 64ri : BinOpRI8U_R<m, RegMRM, Xi64, node>, Sched<[ri]>, DefEFLAGS;
+      let Predicates = [NoNDD] in {
+        def 8ri  : BinOpRI8U_R<m, RegMRM, Xi8, node>, Sched<[ri]>, DefEFLAGS;
+        def 16ri : BinOpRI8U_R<m, RegMRM, Xi16, node>, Sched<[ri]>, DefEFLAGS, OpSize16;
+        def 32ri : BinOpRI8U_R<m, RegMRM, Xi32, node>, Sched<[ri]>, DefEFLAGS, OpSize32;
+        def 64ri : BinOpRI8U_R<m, RegMRM, Xi64, node>, Sched<[ri]>, DefEFLAGS;
+      }
+      let Predicates = [HasNDD, In64BitMode] in {
+        def 8ri_ND  : BinOpRI8U_R<m, RegMRM, Xi8, node, 1>, Sched<[ri]>, DefEFLAGS;
+        def 16ri_ND : BinOpRI8U_R<m, RegMRM, Xi16, node, 1>, Sched<[ri]>, DefEFLAGS, PD;
+        def 32ri_ND : BinOpRI8U_R<m, RegMRM, Xi32, node, 1>, Sched<[ri]>, DefEFLAGS;
+        def 64ri_ND : BinOpRI8U_R<m, RegMRM, Xi64, node, 1>, Sched<[ri]>, DefEFLAGS;
+      }
+      let Predicates = [In64BitMode] in {
+        def 8ri_EVEX  : BinOpRI8U_R<m, RegMRM, Xi8, null_frag>, Sched<[ri]>, DefEFLAGS, PL;
+        def 16ri_EVEX : BinOpRI8U_R<m, RegMRM, Xi16, null_frag>, Sched<[ri]>, DefEFLAGS, PL, PD;
+        def 32ri_EVEX : BinOpRI8U_R<m, RegMRM, Xi32, null_frag>, Sched<[ri]>, DefEFLAGS, PL;
+        def 64ri_EVEX : BinOpRI8U_R<m, RegMRM, Xi64, null_frag>, Sched<[ri]>, DefEFLAGS, PL;
+      }
     }
 
     def 8mi  : BinOpMI8U_M<m, MemMRM, Xi8, node>, Sched<[mi, WriteRMW]>, DefEFLAGS;
     def 16mi : BinOpMI8U_M<m, MemMRM, Xi16, node>, Sched<[mi, WriteRMW]>, DefEFLAGS, OpSize16;
     def 32mi : BinOpMI8U_M<m, MemMRM, Xi32, node>, Sched<[mi, WriteRMW]>, DefEFLAGS, OpSize32;
     def 64mi : BinOpMI8U_M<m, MemMRM, Xi64, node>, Sched<[mi, WriteRMW]>, DefEFLAGS, Requires<[In64BitMode]>;
+    let Predicates = [HasNDD, In64BitMode] in {
+      def 8mi_ND  : BinOpMI8U_R<m, MemMRM, Xi8, node>, Sched<[mi, ri]>, DefEFLAGS;
+      def 16mi_ND : BinOpMI8U_R<m, MemMRM, Xi16, node>, Sched<[mi, ri]>, DefEFLAGS, PD;
+      def 32mi_ND : BinOpMI8U_R<m, MemMRM, Xi32, node>, Sched<[mi, ri]>, DefEFLAGS;
+      def 64mi_ND : BinOpMI8U_R<m, MemMRM, Xi64, node>, Sched<[mi, ri]>, DefEFLAGS;
+    }
+    let Predicates = [In64BitMode] in {
+      def 8mi_EVEX  : BinOpMI8U_M<m, MemMRM, Xi8, null_frag>, Sched<[mi, WriteRMW]>, DefEFLAGS, PL;
+      def 16mi_EVEX : BinOpMI8U_M<m, MemMRM, Xi16, null_frag>, Sched<[mi, WriteRMW]>, DefEFLAGS, PL, PD;
+      def 32mi_EVEX : BinOpMI8U_M<m, MemMRM, Xi32, null_frag>, Sched<[mi, WriteRMW]>, DefEFLAGS, PL;
+      def 64mi_EVEX : BinOpMI8U_M<m, MemMRM, Xi64, null_frag>, Sched<[mi, WriteRMW]>, DefEFLAGS, PL;
+    }
 
     let SchedRW = [ri] in {
       def 8r1  : UnaryOpR_RF<0xD1, RegMRM, m, Xi8, null_frag>;
       def 16r1 : UnaryOpR_RF<0xD1, RegMRM, m, Xi16, null_frag>, OpSize16;
       def 32r1 : UnaryOpR_RF<0xD1, RegMRM, m, Xi32, null_frag>, OpSize32;
       def 64r1 : UnaryOpR_RF<0xD1, RegMRM, m, Xi64, null_frag>;
+
+      // FIXME: Assembler can't tell whether it's 8r1_ND or 8rCL when the source register is cl, e.g.
+      //
+      //  shlb %cl, %al
+      //
+      // GNU binutils distinguish them by adding an explicit $1 to asm string of 8r1_ND. But we haven't support
+      // constant immediate in ams string for X86 in TD. So we add DisassembleOnly for 8r1_ND for the time being.
+      let Predicates = [In64BitMode] in {
+        def 8r1_ND  : UnaryOpR_RF<0xD1, RegMRM, m, Xi8, null_frag, 1>, DisassembleOnly;
+        def 16r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi16, null_frag, 1>, PD;
+        def 32r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi32, null_frag, 1>;
+        def 64r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi64, null_frag, 1>;
+
+        def 8r1_EVEX  : UnaryOpR_RF<0xD1, RegMRM, m, Xi8, null_frag>, PL;
+        def 16r1_EVEX : UnaryOpR_RF<0xD1, RegMRM, m, Xi16, null_frag>, PL, PD;
+        def 32r1_EVEX : UnaryOpR_RF<0xD1, RegMRM, m, Xi32, null_frag>, PL;
+        def 64r1_EVEX : UnaryOpR_RF<0xD1, RegMRM, m, Xi64, null_frag>, PL;
+      }
     }
 
     let SchedRW = [mi, WriteRMW] in {
       def 8m1  : UnaryOpM_MF<0xD1, MemMRM, m, Xi8, null_frag>;
       def 16m1 : UnaryOpM_MF<0xD1, MemMRM, m, Xi16, null_frag>, OpSize16;
       def 32m1 : UnaryOpM_MF<0xD1, MemMRM, m, Xi32, null_frag>, OpSize32;
       def 64m1 : UnaryOpM_MF<0xD1, MemMRM, m, Xi64, null_frag>, Requires<[In64BitMode]>;
+
+      let Predicates = [In64BitMode] in {
+        def 8m1_EVEX  : UnaryOpM_MF<0xD1, MemMRM, m, Xi8, null_frag>, PL;
+        def 16m1_EVEX : UnaryOpM_MF<0xD1, MemMRM, m, Xi16, null_frag>, PL, PD;
+        def 32m1_EVEX : UnaryOpM_MF<0xD1, MemMRM, m, Xi32, null_frag>, PL;
+        def 64m1_EVEX : UnaryOpM_MF<0xD1, MemMRM, m, Xi64, null_frag>, PL;
+      }
+    }
+    let SchedRW = [mi, ri], Predicates = [In64BitMode] in {
+      def 8m1_ND  : UnaryOpM_RF<0xD1, MemMRM, m, Xi8, null_frag>;
+      def 16m1_ND : UnaryOpM_RF<0xD1, MemMRM, m, Xi16, null_frag>, PD;
+      def 32m1_ND : UnaryOpM_RF<0xD1, MemMRM, m, Xi32, null_frag>;
+      def 64m1_ND : UnaryOpM_RF<0xD1, MemMRM, m, Xi64, null_frag>;
     }
   }
 
   let Uses = !listconcat([CL], uses) in {
-    def 8rCL  : BinOpRC_R<m, RegMRM, Xi8, node>, Sched<[rCL]>, DefEFLAGS;
-    def 16rCL : BinOpRC_R<m, RegMRM, Xi16, node>, Sched<[rCL]>, DefEFLAGS, OpSize16;
-    def 32rCL : BinOpRC_R<m, RegMRM, Xi32, node>, Sched<[rCL]>, DefEFLAGS, OpSize32;
-    def 64rCL : BinOpRC_R<m, RegMRM, Xi64, node>, Sched<[rCL]>, DefEFLAGS;
+    let Predicates = [NoNDD] in {
+      def 8rCL  : BinOpRC_R<m, RegMRM, Xi8, node>, Sched<[rCL]>, DefEFLAGS;
+      def 16rCL : BinOpRC_R<m, RegMRM, Xi16, node>, Sched<[rCL]>, DefEFLAGS, OpSize16;
+      def 32rCL : BinOpRC_R<m, RegMRM, Xi32, node>, Sched<[rCL]>, DefEFLAGS, OpSize32;
+      def 64rCL : BinOpRC_R<m, RegMRM, Xi64, node>, Sched<[rCL]>, DefEFLAGS;
+    }
+    let Predicates = [HasNDD, In64BitMode] in {
+      def 8rCL_ND  : BinOpRC_R<m, RegMRM, Xi8, node, 1>, Sched<[rCL]>, DefEFLAGS;
+      def 16rCL_ND : BinOpRC_R<m, RegMRM, Xi16, node, 1>, Sched<[rCL]>, DefEFLAGS, PD;
+      def 32rCL_ND : BinOpRC_R<m, RegMRM, Xi32, node, 1>, Sched<[rCL]>, DefEFLAGS;
+      def 64rCL_ND : BinOpRC_R<m, RegMRM, Xi64, node, 1>, Sched<[rCL]>, DefEFLAGS;
+    }
+    let Predicates = [In64BitMode] in {
+      def 8rCL_EVEX  : BinOpRC_R<m, RegMRM, Xi8, null_frag>, Sched<[rCL]>, DefEFLAGS, PL;
+      def 16rCL_EVEX : BinOpRC_R<m, RegMRM, Xi16, null_frag>, Sched<[rCL]>, DefEFLAGS, PL, PD;
+      def 32rCL_EVEX : BinOpRC_R<m, RegMRM, Xi32, null_frag>, Sched<[rCL]>, DefEFLAGS, PL;
+      def 64rCL_EVEX : BinOpRC_R<m, RegMRM, Xi64, null_frag>, Sched<[rCL]>, DefEFLAGS, PL;
+    }
 
     def 8mCL  : BinOpMC_M<m, MemMRM, Xi8, node>, Sched<[mCL, WriteRMW]>, DefEFLAGS;
     def 16mCL : BinOpMC_M<m, MemMRM, Xi16, node>, Sched<[mCL, WriteRMW]>, DefEFLAGS, OpSize16;
     def 32mCL : BinOpMC_M<m, MemMRM, Xi32, node>, Sched<[mCL, WriteRMW]>, DefEFLAGS, OpSize32;
     def 64mCL : BinOpMC_M<m, MemMRM, Xi64, node>, Sched<[mCL, WriteRMW]>, DefEFLAGS, Requires<[In64BitMode]>;
+
+    let Predicates = [HasNDD, In64BitMode] in {
+      def 8mCL_ND  : BinOpMC_R<m, MemMRM, Xi8, node>, Sched<[mCL, rCL]>, DefEFLAGS;
+      def 16mCL_ND : BinOpMC_R<m, MemMRM, Xi16, node>, Sched<[mCL, rCL]>, DefEFLAGS, PD;
+      def 32mCL_ND : BinOpMC_R<m, MemMRM, Xi32, node>, Sched<[mCL, rCL]>, DefEFLAGS;
+      def 64mCL_ND : BinOpMC_R<m, MemMRM, Xi64, node>, Sched<[mCL, rCL]>, DefEFLAGS;
+    }
+
+    let Predicates = [In64BitMode] in {
+      def 8mCL_EVEX  : BinOpMC_M<m, MemMRM, Xi8, null_frag>, Sched<[mCL, WriteRMW]>, DefEFLAGS, PL;
+      def 16mCL_EVEX : BinOpMC_M<m, MemMRM, Xi16, null_frag>, Sched<[mCL, WriteRMW]>, DefEFLAGS, PL, PD;
+      def 32mCL_EVEX : BinOpMC_M<m, MemMRM, Xi32, null_frag>, Sched<[mCL, WriteRMW]>, DefEFLAGS, PL;
+      def 64mCL_EVEX : BinOpMC_M<m, MemMRM, Xi64, null_frag>, Sched<[mCL, WriteRMW]>, DefEFLAGS, PL;
+    }
   }
 }
 
+multiclass ShiftRotate_NF<string m, Format RegMRM, Format MemMRM, SchedReadWrite rCL,
+                          SchedReadWrite ri, SchedReadWrite mCL, SchedReadWrite mi> {
+  let Predicates = [In64BitMode] in {
----------------
KanRobert wrote:

I think you meant default `null_frag`? If yes, done.

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


More information about the llvm-commits mailing list