xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/X86/X86InstrShiftRotate.td (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
10b57cec5SDimitry Andric//===-- X86InstrShiftRotate.td - Shift and Rotate Instrs ---*- tablegen -*-===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric//
90b57cec5SDimitry Andric// This file describes the shift and rotate instructions.
100b57cec5SDimitry Andric//
110b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
14*7a6dacacSDimitry Andric// Shift/Rotate instructions
150b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
160b57cec5SDimitry Andric
17*7a6dacacSDimitry Andricmulticlass ShiftRotate<string m, Format RegMRM, Format MemMRM, SDPatternOperator node,
18*7a6dacacSDimitry Andric                       SchedReadWrite rCL, SchedReadWrite ri, SchedReadWrite mCL,
19*7a6dacacSDimitry Andric                       SchedReadWrite mi, list<Register> uses = []> {
200b57cec5SDimitry Andric
21*7a6dacacSDimitry Andric  let Uses = uses in {
22*7a6dacacSDimitry Andric    let isConvertibleToThreeAddress = !if(!eq(m, "shl"), 1, 0) in {
23*7a6dacacSDimitry Andric      let Predicates = [NoNDD] in {
24*7a6dacacSDimitry Andric        def 8ri  : BinOpRI8U_R<m, RegMRM, Xi8, node>, Sched<[ri]>, DefEFLAGS;
25*7a6dacacSDimitry Andric        def 16ri : BinOpRI8U_R<m, RegMRM, Xi16, node>, Sched<[ri]>, DefEFLAGS, OpSize16;
26*7a6dacacSDimitry Andric        def 32ri : BinOpRI8U_R<m, RegMRM, Xi32, node>, Sched<[ri]>, DefEFLAGS, OpSize32;
27*7a6dacacSDimitry Andric        def 64ri : BinOpRI8U_R<m, RegMRM, Xi64, node>, Sched<[ri]>, DefEFLAGS;
28*7a6dacacSDimitry Andric      }
29*7a6dacacSDimitry Andric      let Predicates = [HasNDD, In64BitMode] in {
30*7a6dacacSDimitry Andric        def 8ri_ND  : BinOpRI8U_R<m, RegMRM, Xi8, node, 1>, Sched<[ri]>, DefEFLAGS;
31*7a6dacacSDimitry Andric        def 16ri_ND : BinOpRI8U_R<m, RegMRM, Xi16, node, 1>, Sched<[ri]>, DefEFLAGS, PD;
32*7a6dacacSDimitry Andric        def 32ri_ND : BinOpRI8U_R<m, RegMRM, Xi32, node, 1>, Sched<[ri]>, DefEFLAGS;
33*7a6dacacSDimitry Andric        def 64ri_ND : BinOpRI8U_R<m, RegMRM, Xi64, node, 1>, Sched<[ri]>, DefEFLAGS;
34*7a6dacacSDimitry Andric      }
35*7a6dacacSDimitry Andric      let Predicates = [In64BitMode] in {
36*7a6dacacSDimitry Andric        def 8ri_EVEX  : BinOpRI8U_R<m, RegMRM, Xi8>, Sched<[ri]>, DefEFLAGS, PL;
37*7a6dacacSDimitry Andric        def 16ri_EVEX : BinOpRI8U_R<m, RegMRM, Xi16>, Sched<[ri]>, DefEFLAGS, PL, PD;
38*7a6dacacSDimitry Andric        def 32ri_EVEX : BinOpRI8U_R<m, RegMRM, Xi32>, Sched<[ri]>, DefEFLAGS, PL;
39*7a6dacacSDimitry Andric        def 64ri_EVEX : BinOpRI8U_R<m, RegMRM, Xi64>, Sched<[ri]>, DefEFLAGS, PL;
40*7a6dacacSDimitry Andric      }
410b57cec5SDimitry Andric    }
420b57cec5SDimitry Andric
43*7a6dacacSDimitry Andric    def 8mi  : BinOpMI8U_M<m, MemMRM, Xi8, node>, Sched<[mi, WriteRMW]>, DefEFLAGS;
44*7a6dacacSDimitry Andric    def 16mi : BinOpMI8U_M<m, MemMRM, Xi16, node>, Sched<[mi, WriteRMW]>, DefEFLAGS, OpSize16;
45*7a6dacacSDimitry Andric    def 32mi : BinOpMI8U_M<m, MemMRM, Xi32, node>, Sched<[mi, WriteRMW]>, DefEFLAGS, OpSize32;
46*7a6dacacSDimitry Andric    def 64mi : BinOpMI8U_M<m, MemMRM, Xi64, node>, Sched<[mi, WriteRMW]>, DefEFLAGS, Requires<[In64BitMode]>;
47*7a6dacacSDimitry Andric    let Predicates = [HasNDD, In64BitMode] in {
48*7a6dacacSDimitry Andric      def 8mi_ND  : BinOpMI8U_R<m, MemMRM, Xi8, node>, Sched<[mi, ri]>, DefEFLAGS;
49*7a6dacacSDimitry Andric      def 16mi_ND : BinOpMI8U_R<m, MemMRM, Xi16, node>, Sched<[mi, ri]>, DefEFLAGS, PD;
50*7a6dacacSDimitry Andric      def 32mi_ND : BinOpMI8U_R<m, MemMRM, Xi32, node>, Sched<[mi, ri]>, DefEFLAGS;
51*7a6dacacSDimitry Andric      def 64mi_ND : BinOpMI8U_R<m, MemMRM, Xi64, node>, Sched<[mi, ri]>, DefEFLAGS;
52*7a6dacacSDimitry Andric    }
53*7a6dacacSDimitry Andric    let Predicates = [In64BitMode] in {
54*7a6dacacSDimitry Andric      def 8mi_EVEX  : BinOpMI8U_M<m, MemMRM, Xi8>, Sched<[mi, WriteRMW]>, DefEFLAGS, PL;
55*7a6dacacSDimitry Andric      def 16mi_EVEX : BinOpMI8U_M<m, MemMRM, Xi16>, Sched<[mi, WriteRMW]>, DefEFLAGS, PL, PD;
56*7a6dacacSDimitry Andric      def 32mi_EVEX : BinOpMI8U_M<m, MemMRM, Xi32>, Sched<[mi, WriteRMW]>, DefEFLAGS, PL;
57*7a6dacacSDimitry Andric      def 64mi_EVEX : BinOpMI8U_M<m, MemMRM, Xi64>, Sched<[mi, WriteRMW]>, DefEFLAGS, PL;
58*7a6dacacSDimitry Andric    }
590b57cec5SDimitry Andric
60*7a6dacacSDimitry Andric    let SchedRW = [ri] in {
61*7a6dacacSDimitry Andric      def 8r1  : UnaryOpR_RF<0xD1, RegMRM, m, Xi8>;
62*7a6dacacSDimitry Andric      def 16r1 : UnaryOpR_RF<0xD1, RegMRM, m, Xi16>, OpSize16;
63*7a6dacacSDimitry Andric      def 32r1 : UnaryOpR_RF<0xD1, RegMRM, m, Xi32>, OpSize32;
64*7a6dacacSDimitry Andric      def 64r1 : UnaryOpR_RF<0xD1, RegMRM, m, Xi64>;
650b57cec5SDimitry Andric
66*7a6dacacSDimitry Andric      // FIXME: Assembler can't tell whether it's 8r1_ND or 8rCL when the source register is cl, e.g.
67*7a6dacacSDimitry Andric      //
68*7a6dacacSDimitry Andric      //  shlb %cl, %al
69*7a6dacacSDimitry Andric      //
70*7a6dacacSDimitry Andric      // GNU binutils distinguish them by adding an explicit $1 to asm string of 8r1_ND. But we haven't support
71*7a6dacacSDimitry Andric      // constant immediate in asm string for X86 in TD. So we add DisassembleOnly for 8r1_ND for the time being.
72*7a6dacacSDimitry Andric      let Predicates = [In64BitMode] in {
73*7a6dacacSDimitry Andric        def 8r1_ND  : UnaryOpR_RF<0xD1, RegMRM, m, Xi8, null_frag, 1>, DisassembleOnly;
74*7a6dacacSDimitry Andric        def 16r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi16, null_frag, 1>, PD;
75*7a6dacacSDimitry Andric        def 32r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi32, null_frag, 1>;
76*7a6dacacSDimitry Andric        def 64r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi64, null_frag, 1>;
770b57cec5SDimitry Andric
78*7a6dacacSDimitry Andric        def 8r1_EVEX  : UnaryOpR_RF<0xD1, RegMRM, m, Xi8>, PL;
79*7a6dacacSDimitry Andric        def 16r1_EVEX : UnaryOpR_RF<0xD1, RegMRM, m, Xi16>, PL, PD;
80*7a6dacacSDimitry Andric        def 32r1_EVEX : UnaryOpR_RF<0xD1, RegMRM, m, Xi32>, PL;
81*7a6dacacSDimitry Andric        def 64r1_EVEX : UnaryOpR_RF<0xD1, RegMRM, m, Xi64>, PL;
82*7a6dacacSDimitry Andric      }
83*7a6dacacSDimitry Andric    }
840b57cec5SDimitry Andric
85*7a6dacacSDimitry Andric    let SchedRW = [mi, WriteRMW] in {
86*7a6dacacSDimitry Andric      def 8m1  : UnaryOpM_MF<0xD1, MemMRM, m, Xi8>;
87*7a6dacacSDimitry Andric      def 16m1 : UnaryOpM_MF<0xD1, MemMRM, m, Xi16>, OpSize16;
88*7a6dacacSDimitry Andric      def 32m1 : UnaryOpM_MF<0xD1, MemMRM, m, Xi32>, OpSize32;
89*7a6dacacSDimitry Andric      def 64m1 : UnaryOpM_MF<0xD1, MemMRM, m, Xi64>, Requires<[In64BitMode]>;
900b57cec5SDimitry Andric
91*7a6dacacSDimitry Andric      let Predicates = [In64BitMode] in {
92*7a6dacacSDimitry Andric        def 8m1_EVEX  : UnaryOpM_MF<0xD1, MemMRM, m, Xi8>, PL;
93*7a6dacacSDimitry Andric        def 16m1_EVEX : UnaryOpM_MF<0xD1, MemMRM, m, Xi16>, PL, PD;
94*7a6dacacSDimitry Andric        def 32m1_EVEX : UnaryOpM_MF<0xD1, MemMRM, m, Xi32>, PL;
95*7a6dacacSDimitry Andric        def 64m1_EVEX : UnaryOpM_MF<0xD1, MemMRM, m, Xi64>, PL;
96*7a6dacacSDimitry Andric      }
97*7a6dacacSDimitry Andric    }
98*7a6dacacSDimitry Andric    let SchedRW = [mi, ri], Predicates = [In64BitMode] in {
99*7a6dacacSDimitry Andric      def 8m1_ND  : UnaryOpM_RF<0xD1, MemMRM, m, Xi8>;
100*7a6dacacSDimitry Andric      def 16m1_ND : UnaryOpM_RF<0xD1, MemMRM, m, Xi16>, PD;
101*7a6dacacSDimitry Andric      def 32m1_ND : UnaryOpM_RF<0xD1, MemMRM, m, Xi32>;
102*7a6dacacSDimitry Andric      def 64m1_ND : UnaryOpM_RF<0xD1, MemMRM, m, Xi64>;
103*7a6dacacSDimitry Andric    }
104*7a6dacacSDimitry Andric  }
1050b57cec5SDimitry Andric
106*7a6dacacSDimitry Andric  let Uses = !listconcat([CL], uses), Defs = [EFLAGS] in {
107*7a6dacacSDimitry Andric    let Predicates = [NoNDD] in {
108*7a6dacacSDimitry Andric      def 8rCL  : BinOpRC_R<m, RegMRM, Xi8, node>, Sched<[rCL]>;
109*7a6dacacSDimitry Andric      def 16rCL : BinOpRC_R<m, RegMRM, Xi16, node>, Sched<[rCL]>, OpSize16;
110*7a6dacacSDimitry Andric      def 32rCL : BinOpRC_R<m, RegMRM, Xi32, node>, Sched<[rCL]>, OpSize32;
111*7a6dacacSDimitry Andric      def 64rCL : BinOpRC_R<m, RegMRM, Xi64, node>, Sched<[rCL]>;
112*7a6dacacSDimitry Andric    }
113*7a6dacacSDimitry Andric    let Predicates = [HasNDD, In64BitMode] in {
114*7a6dacacSDimitry Andric      def 8rCL_ND  : BinOpRC_R<m, RegMRM, Xi8, node, 1>, Sched<[rCL]>;
115*7a6dacacSDimitry Andric      def 16rCL_ND : BinOpRC_R<m, RegMRM, Xi16, node, 1>, Sched<[rCL]>, PD;
116*7a6dacacSDimitry Andric      def 32rCL_ND : BinOpRC_R<m, RegMRM, Xi32, node, 1>, Sched<[rCL]>;
117*7a6dacacSDimitry Andric      def 64rCL_ND : BinOpRC_R<m, RegMRM, Xi64, node, 1>, Sched<[rCL]>;
118*7a6dacacSDimitry Andric    }
119*7a6dacacSDimitry Andric    let Predicates = [In64BitMode] in {
120*7a6dacacSDimitry Andric      def 8rCL_EVEX  : BinOpRC_R<m, RegMRM, Xi8>, Sched<[rCL]>, PL;
121*7a6dacacSDimitry Andric      def 16rCL_EVEX : BinOpRC_R<m, RegMRM, Xi16>, Sched<[rCL]>, PL, PD;
122*7a6dacacSDimitry Andric      def 32rCL_EVEX : BinOpRC_R<m, RegMRM, Xi32>, Sched<[rCL]>, PL;
123*7a6dacacSDimitry Andric      def 64rCL_EVEX : BinOpRC_R<m, RegMRM, Xi64>, Sched<[rCL]>, PL;
124*7a6dacacSDimitry Andric    }
1250b57cec5SDimitry Andric
126*7a6dacacSDimitry Andric    def 8mCL  : BinOpMC_M<m, MemMRM, Xi8, node>, Sched<[mCL, WriteRMW]>;
127*7a6dacacSDimitry Andric    def 16mCL : BinOpMC_M<m, MemMRM, Xi16, node>, Sched<[mCL, WriteRMW]>, OpSize16;
128*7a6dacacSDimitry Andric    def 32mCL : BinOpMC_M<m, MemMRM, Xi32, node>, Sched<[mCL, WriteRMW]>, OpSize32;
129*7a6dacacSDimitry Andric    def 64mCL : BinOpMC_M<m, MemMRM, Xi64, node>, Sched<[mCL, WriteRMW]>, Requires<[In64BitMode]>;
1300b57cec5SDimitry Andric
131*7a6dacacSDimitry Andric    let Predicates = [HasNDD, In64BitMode] in {
132*7a6dacacSDimitry Andric      def 8mCL_ND  : BinOpMC_R<m, MemMRM, Xi8, node>, Sched<[mCL, rCL]>;
133*7a6dacacSDimitry Andric      def 16mCL_ND : BinOpMC_R<m, MemMRM, Xi16, node>, Sched<[mCL, rCL]>, PD;
134*7a6dacacSDimitry Andric      def 32mCL_ND : BinOpMC_R<m, MemMRM, Xi32, node>, Sched<[mCL, rCL]>;
135*7a6dacacSDimitry Andric      def 64mCL_ND : BinOpMC_R<m, MemMRM, Xi64, node>, Sched<[mCL, rCL]>;
136*7a6dacacSDimitry Andric    }
1370b57cec5SDimitry Andric
138*7a6dacacSDimitry Andric    let Predicates = [In64BitMode] in {
139*7a6dacacSDimitry Andric      def 8mCL_EVEX  : BinOpMC_M<m, MemMRM, Xi8>, Sched<[mCL, WriteRMW]>, PL;
140*7a6dacacSDimitry Andric      def 16mCL_EVEX : BinOpMC_M<m, MemMRM, Xi16>, Sched<[mCL, WriteRMW]>, PL, PD;
141*7a6dacacSDimitry Andric      def 32mCL_EVEX : BinOpMC_M<m, MemMRM, Xi32>, Sched<[mCL, WriteRMW]>, PL;
142*7a6dacacSDimitry Andric      def 64mCL_EVEX : BinOpMC_M<m, MemMRM, Xi64>, Sched<[mCL, WriteRMW]>, PL;
143*7a6dacacSDimitry Andric    }
144*7a6dacacSDimitry Andric  }
145*7a6dacacSDimitry Andric}
1460b57cec5SDimitry Andric
147*7a6dacacSDimitry Andricmulticlass ShiftRotate_NF<string m, Format RegMRM, Format MemMRM, SchedReadWrite rCL,
148*7a6dacacSDimitry Andric                          SchedReadWrite ri, SchedReadWrite mCL, SchedReadWrite mi> {
149*7a6dacacSDimitry Andric  let Predicates = [In64BitMode] in {
150*7a6dacacSDimitry Andric    let isConvertibleToThreeAddress = !if(!eq(m, "shl"), 1, 0) in {
151*7a6dacacSDimitry Andric      def 8ri_NF  : BinOpRI8U_R<m, RegMRM, Xi8>, Sched<[ri]>, NF;
152*7a6dacacSDimitry Andric      def 16ri_NF : BinOpRI8U_R<m, RegMRM, Xi16>, Sched<[ri]>, NF, PD;
153*7a6dacacSDimitry Andric      def 32ri_NF : BinOpRI8U_R<m, RegMRM, Xi32>, Sched<[ri]>, NF;
154*7a6dacacSDimitry Andric      def 64ri_NF : BinOpRI8U_R<m, RegMRM, Xi64>, Sched<[ri]>, NF;
1550b57cec5SDimitry Andric
156*7a6dacacSDimitry Andric      def 8ri_NF_ND  : BinOpRI8U_R<m, RegMRM, Xi8, null_frag, 1>, Sched<[ri]>, EVEX_NF;
157*7a6dacacSDimitry Andric      def 16ri_NF_ND : BinOpRI8U_R<m, RegMRM, Xi16, null_frag, 1>, Sched<[ri]>, EVEX_NF, PD;
158*7a6dacacSDimitry Andric      def 32ri_NF_ND : BinOpRI8U_R<m, RegMRM, Xi32, null_frag, 1>, Sched<[ri]>, EVEX_NF;
159*7a6dacacSDimitry Andric      def 64ri_NF_ND : BinOpRI8U_R<m, RegMRM, Xi64, null_frag, 1>, Sched<[ri]>, EVEX_NF;
160*7a6dacacSDimitry Andric    }
1610b57cec5SDimitry Andric
162*7a6dacacSDimitry Andric    def 8mi_NF  : BinOpMI8U_M<m, MemMRM, Xi8>, Sched<[mi, WriteRMW]>, NF;
163*7a6dacacSDimitry Andric    def 16mi_NF : BinOpMI8U_M<m, MemMRM, Xi16>, Sched<[mi, WriteRMW]>, NF, PD;
164*7a6dacacSDimitry Andric    def 32mi_NF : BinOpMI8U_M<m, MemMRM, Xi32>, Sched<[mi, WriteRMW]>, NF;
165*7a6dacacSDimitry Andric    def 64mi_NF : BinOpMI8U_M<m, MemMRM, Xi64>, Sched<[mi, WriteRMW]>, NF;
1660b57cec5SDimitry Andric
167*7a6dacacSDimitry Andric    def 8mi_NF_ND  : BinOpMI8U_R<m, MemMRM, Xi8>, Sched<[mi, ri]>, EVEX_NF;
168*7a6dacacSDimitry Andric    def 16mi_NF_ND : BinOpMI8U_R<m, MemMRM, Xi16>, Sched<[mi, ri]>, EVEX_NF, PD;
169*7a6dacacSDimitry Andric    def 32mi_NF_ND : BinOpMI8U_R<m, MemMRM, Xi32>, Sched<[mi, ri]>, EVEX_NF;
170*7a6dacacSDimitry Andric    def 64mi_NF_ND : BinOpMI8U_R<m, MemMRM, Xi64>, Sched<[mi, ri]>, EVEX_NF;
1710b57cec5SDimitry Andric
172*7a6dacacSDimitry Andric    let SchedRW = [ri] in {
173*7a6dacacSDimitry Andric      // FIXME: Assembler can't tell whether it's 8r1_NF_ND or 8rCL_NF when the source register is cl, e.g.
174*7a6dacacSDimitry Andric      //
175*7a6dacacSDimitry Andric      //  {nf} shlb %cl, %al
176*7a6dacacSDimitry Andric      //
177*7a6dacacSDimitry Andric      // GNU binutils distinguish them by adding an explicit $1 to asm string of 8r1_NF_ND. But we haven't support
178*7a6dacacSDimitry Andric      // constant immediate in asm string for X86 in TD. So we add DisassembleOnly for 8r1_NF_ND for the time being.
179*7a6dacacSDimitry Andric      def 8r1_NF  : UnaryOpR_R<0xD1, RegMRM, m, Xi8>, NF;
180*7a6dacacSDimitry Andric      def 16r1_NF : UnaryOpR_R<0xD1, RegMRM, m, Xi16>, NF, PD;
181*7a6dacacSDimitry Andric      def 32r1_NF : UnaryOpR_R<0xD1, RegMRM, m, Xi32>, NF;
182*7a6dacacSDimitry Andric      def 64r1_NF : UnaryOpR_R<0xD1, RegMRM, m, Xi64>, NF;
1830b57cec5SDimitry Andric
184*7a6dacacSDimitry Andric      def 8r1_NF_ND  : UnaryOpR_R<0xD1, RegMRM, m, Xi8, null_frag, 1>, EVEX_NF, DisassembleOnly;
185*7a6dacacSDimitry Andric      def 16r1_NF_ND : UnaryOpR_R<0xD1, RegMRM, m, Xi16, null_frag, 1>, EVEX_NF, PD;
186*7a6dacacSDimitry Andric      def 32r1_NF_ND : UnaryOpR_R<0xD1, RegMRM, m, Xi32, null_frag, 1>, EVEX_NF;
187*7a6dacacSDimitry Andric      def 64r1_NF_ND : UnaryOpR_R<0xD1, RegMRM, m, Xi64, null_frag, 1>, EVEX_NF;
188*7a6dacacSDimitry Andric    }
1890b57cec5SDimitry Andric
190*7a6dacacSDimitry Andric    let SchedRW = [mi, WriteRMW] in {
191*7a6dacacSDimitry Andric      def 8m1_NF  : UnaryOpM_M<0xD1, MemMRM, m, Xi8>, NF;
192*7a6dacacSDimitry Andric      def 16m1_NF : UnaryOpM_M<0xD1, MemMRM, m, Xi16>, NF, PD;
193*7a6dacacSDimitry Andric      def 32m1_NF : UnaryOpM_M<0xD1, MemMRM, m, Xi32>, NF;
194*7a6dacacSDimitry Andric      def 64m1_NF : UnaryOpM_M<0xD1, MemMRM, m, Xi64>, NF;
195*7a6dacacSDimitry Andric    }
196*7a6dacacSDimitry Andric    let SchedRW = [mi, ri] in {
197*7a6dacacSDimitry Andric      def 8m1_NF_ND  : UnaryOpM_R<0xD1, MemMRM, m, Xi8>, EVEX_NF;
198*7a6dacacSDimitry Andric      def 16m1_NF_ND : UnaryOpM_R<0xD1, MemMRM, m, Xi16>, EVEX_NF, PD;
199*7a6dacacSDimitry Andric      def 32m1_NF_ND : UnaryOpM_R<0xD1, MemMRM, m, Xi32>, EVEX_NF;
200*7a6dacacSDimitry Andric      def 64m1_NF_ND : UnaryOpM_R<0xD1, MemMRM, m, Xi64>, EVEX_NF;
201*7a6dacacSDimitry Andric    }
202*7a6dacacSDimitry Andric
203*7a6dacacSDimitry Andric    let Uses = [CL] in {
204*7a6dacacSDimitry Andric      def 8rCL_NF  : BinOpRC_R<m, RegMRM, Xi8>, Sched<[rCL]>, NF;
205*7a6dacacSDimitry Andric      def 16rCL_NF : BinOpRC_R<m, RegMRM, Xi16>, Sched<[rCL]>, NF, PD;
206*7a6dacacSDimitry Andric      def 32rCL_NF : BinOpRC_R<m, RegMRM, Xi32>, Sched<[rCL]>, NF;
207*7a6dacacSDimitry Andric      def 64rCL_NF : BinOpRC_R<m, RegMRM, Xi64>, Sched<[rCL]>, NF;
208*7a6dacacSDimitry Andric
209*7a6dacacSDimitry Andric      def 8rCL_NF_ND  : BinOpRC_R<m, RegMRM, Xi8, null_frag, 1>, Sched<[rCL]>, EVEX_NF;
210*7a6dacacSDimitry Andric      def 16rCL_NF_ND : BinOpRC_R<m, RegMRM, Xi16, null_frag, 1>, Sched<[rCL]>, EVEX_NF, PD;
211*7a6dacacSDimitry Andric      def 32rCL_NF_ND : BinOpRC_R<m, RegMRM, Xi32, null_frag, 1>, Sched<[rCL]>, EVEX_NF;
212*7a6dacacSDimitry Andric      def 64rCL_NF_ND : BinOpRC_R<m, RegMRM, Xi64, null_frag, 1>, Sched<[rCL]>, EVEX_NF;
213*7a6dacacSDimitry Andric
214*7a6dacacSDimitry Andric      def 8mCL_NF  : BinOpMC_M<m, MemMRM, Xi8>, Sched<[mCL, WriteRMW]>, NF;
215*7a6dacacSDimitry Andric      def 16mCL_NF : BinOpMC_M<m, MemMRM, Xi16>, Sched<[mCL, WriteRMW]>, NF, PD;
216*7a6dacacSDimitry Andric      def 32mCL_NF : BinOpMC_M<m, MemMRM, Xi32>, Sched<[mCL, WriteRMW]>, NF;
217*7a6dacacSDimitry Andric      def 64mCL_NF : BinOpMC_M<m, MemMRM, Xi64>, Sched<[mCL, WriteRMW]>, NF;
218*7a6dacacSDimitry Andric
219*7a6dacacSDimitry Andric      def 8mCL_NF_ND  : BinOpMC_R<m, MemMRM, Xi8>, Sched<[mCL, rCL]>, EVEX_NF;
220*7a6dacacSDimitry Andric      def 16mCL_NF_ND : BinOpMC_R<m, MemMRM, Xi16>, Sched<[mCL, rCL]>, EVEX_NF, PD;
221*7a6dacacSDimitry Andric      def 32mCL_NF_ND : BinOpMC_R<m, MemMRM, Xi32>, Sched<[mCL, rCL]>, EVEX_NF;
222*7a6dacacSDimitry Andric      def 64mCL_NF_ND : BinOpMC_R<m, MemMRM, Xi64>, Sched<[mCL, rCL]>, EVEX_NF;
223*7a6dacacSDimitry Andric    }
224*7a6dacacSDimitry Andric  }
225*7a6dacacSDimitry Andric}
226*7a6dacacSDimitry Andricdefm SHL: ShiftRotate<"shl", MRM4r, MRM4m, shl, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
227*7a6dacacSDimitry Andricdefm SHR: ShiftRotate<"shr", MRM5r, MRM5m, srl, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
228*7a6dacacSDimitry Andricdefm SAR: ShiftRotate<"sar", MRM7r, MRM7m, sra, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
229*7a6dacacSDimitry Andric
230*7a6dacacSDimitry Andricdefm ROL: ShiftRotate<"rol", MRM0r, MRM0m, rotl, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd>;
231*7a6dacacSDimitry Andricdefm ROR: ShiftRotate<"ror", MRM1r, MRM1m, rotr, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd>;
232*7a6dacacSDimitry Andricdefm RCL: ShiftRotate<"rcl", MRM2r, MRM2m, null_frag, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd, [EFLAGS]>;
233*7a6dacacSDimitry Andricdefm RCR: ShiftRotate<"rcr", MRM3r, MRM3m, null_frag, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd, [EFLAGS]>;
234*7a6dacacSDimitry Andric
235*7a6dacacSDimitry Andricdefm SHL: ShiftRotate_NF<"shl", MRM4r, MRM4m, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
236*7a6dacacSDimitry Andricdefm SHR: ShiftRotate_NF<"shr", MRM5r, MRM5m, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
237*7a6dacacSDimitry Andricdefm SAR: ShiftRotate_NF<"sar", MRM7r, MRM7m, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
238*7a6dacacSDimitry Andric
239*7a6dacacSDimitry Andricdefm ROL: ShiftRotate_NF<"rol", MRM0r, MRM0m, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd>;
240*7a6dacacSDimitry Andricdefm ROR: ShiftRotate_NF<"ror", MRM1r, MRM1m, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd>;
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric// Use the opposite rotate if allows us to use the rotate by 1 instruction.
243*7a6dacacSDimitry Andriclet Predicates = [NoNDD] in {
2440b57cec5SDimitry Andric  def : Pat<(rotl GR8:$src1,  (i8 7)),  (ROR8r1  GR8:$src1)>;
2450b57cec5SDimitry Andric  def : Pat<(rotl GR16:$src1, (i8 15)), (ROR16r1 GR16:$src1)>;
2460b57cec5SDimitry Andric  def : Pat<(rotl GR32:$src1, (i8 31)), (ROR32r1 GR32:$src1)>;
2470b57cec5SDimitry Andric  def : Pat<(rotl GR64:$src1, (i8 63)), (ROR64r1 GR64:$src1)>;
2480b57cec5SDimitry Andric  def : Pat<(rotr GR8:$src1,  (i8 7)),  (ROL8r1  GR8:$src1)>;
2490b57cec5SDimitry Andric  def : Pat<(rotr GR16:$src1, (i8 15)), (ROL16r1 GR16:$src1)>;
2500b57cec5SDimitry Andric  def : Pat<(rotr GR32:$src1, (i8 31)), (ROL32r1 GR32:$src1)>;
2510b57cec5SDimitry Andric  def : Pat<(rotr GR64:$src1, (i8 63)), (ROL64r1 GR64:$src1)>;
252*7a6dacacSDimitry Andric}
253*7a6dacacSDimitry Andriclet Predicates = [HasNDD] in {
254*7a6dacacSDimitry Andric  def : Pat<(rotl GR8:$src1,  (i8 7)),  (ROR8r1_ND  GR8:$src1)>;
255*7a6dacacSDimitry Andric  def : Pat<(rotl GR16:$src1, (i8 15)), (ROR16r1_ND GR16:$src1)>;
256*7a6dacacSDimitry Andric  def : Pat<(rotl GR32:$src1, (i8 31)), (ROR32r1_ND GR32:$src1)>;
257*7a6dacacSDimitry Andric  def : Pat<(rotl GR64:$src1, (i8 63)), (ROR64r1_ND GR64:$src1)>;
258*7a6dacacSDimitry Andric  def : Pat<(rotr GR8:$src1,  (i8 7)),  (ROL8r1_ND  GR8:$src1)>;
259*7a6dacacSDimitry Andric  def : Pat<(rotr GR16:$src1, (i8 15)), (ROL16r1_ND GR16:$src1)>;
260*7a6dacacSDimitry Andric  def : Pat<(rotr GR32:$src1, (i8 31)), (ROL32r1_ND GR32:$src1)>;
261*7a6dacacSDimitry Andric  def : Pat<(rotr GR64:$src1, (i8 63)), (ROL64r1_ND GR64:$src1)>;
262*7a6dacacSDimitry Andric}
2630b57cec5SDimitry Andric
2640b57cec5SDimitry Andricdef : Pat<(store (rotl (loadi8 addr:$dst), (i8 7)), addr:$dst),
2650b57cec5SDimitry Andric          (ROR8m1 addr:$dst)>;
2660b57cec5SDimitry Andricdef : Pat<(store (rotl (loadi16 addr:$dst), (i8 15)), addr:$dst),
2670b57cec5SDimitry Andric          (ROR16m1 addr:$dst)>;
2680b57cec5SDimitry Andricdef : Pat<(store (rotl (loadi32 addr:$dst), (i8 31)), addr:$dst),
2690b57cec5SDimitry Andric          (ROR32m1 addr:$dst)>;
2700b57cec5SDimitry Andricdef : Pat<(store (rotl (loadi64 addr:$dst), (i8 63)), addr:$dst),
2710b57cec5SDimitry Andric          (ROR64m1 addr:$dst)>, Requires<[In64BitMode]>;
2720b57cec5SDimitry Andric
2730b57cec5SDimitry Andricdef : Pat<(store (rotr (loadi8 addr:$dst), (i8 7)), addr:$dst),
2740b57cec5SDimitry Andric          (ROL8m1 addr:$dst)>;
2750b57cec5SDimitry Andricdef : Pat<(store (rotr (loadi16 addr:$dst), (i8 15)), addr:$dst),
2760b57cec5SDimitry Andric          (ROL16m1 addr:$dst)>;
2770b57cec5SDimitry Andricdef : Pat<(store (rotr (loadi32 addr:$dst), (i8 31)), addr:$dst),
2780b57cec5SDimitry Andric          (ROL32m1 addr:$dst)>;
2790b57cec5SDimitry Andricdef : Pat<(store (rotr (loadi64 addr:$dst), (i8 63)), addr:$dst),
2800b57cec5SDimitry Andric          (ROL64m1 addr:$dst)>, Requires<[In64BitMode]>;
2810b57cec5SDimitry Andric
282*7a6dacacSDimitry Andriclet Predicates = [HasNDD] in {
283*7a6dacacSDimitry Andricdef : Pat<(rotl (loadi8 addr:$src), (i8 7)),
284*7a6dacacSDimitry Andric          (ROR8m1_ND addr:$src)>;
285*7a6dacacSDimitry Andricdef : Pat<(rotl (loadi16 addr:$src), (i8 15)),
286*7a6dacacSDimitry Andric          (ROR16m1_ND addr:$src)>;
287*7a6dacacSDimitry Andricdef : Pat<(rotl (loadi32 addr:$src), (i8 31)),
288*7a6dacacSDimitry Andric          (ROR32m1_ND addr:$src)>;
289*7a6dacacSDimitry Andricdef : Pat<(rotl (loadi64 addr:$src), (i8 63)),
290*7a6dacacSDimitry Andric          (ROR64m1_ND addr:$src)>;
291*7a6dacacSDimitry Andric
292*7a6dacacSDimitry Andricdef : Pat<(rotr (loadi8 addr:$src), (i8 7)),
293*7a6dacacSDimitry Andric          (ROL8m1_ND addr:$src)>;
294*7a6dacacSDimitry Andricdef : Pat<(rotr (loadi16 addr:$src), (i8 15)),
295*7a6dacacSDimitry Andric          (ROL16m1_ND addr:$src)>;
296*7a6dacacSDimitry Andricdef : Pat<(rotr (loadi32 addr:$src), (i8 31)),
297*7a6dacacSDimitry Andric          (ROL32m1_ND addr:$src)>;
298*7a6dacacSDimitry Andricdef : Pat<(rotr (loadi64 addr:$src), (i8 63)),
299*7a6dacacSDimitry Andric          (ROL64m1_ND addr:$src)>;
300*7a6dacacSDimitry Andric}
301*7a6dacacSDimitry Andric
302*7a6dacacSDimitry Andric// Patterns for rotate with relocImm for the immediate field.
303*7a6dacacSDimitry Andriclet Predicates = [NoNDD] in {
304*7a6dacacSDimitry Andric  def : Pat<(rotl GR8:$src1, (i8 relocImm:$src2)),
305*7a6dacacSDimitry Andric            (ROL8ri GR8:$src1, relocImm:$src2)>;
306*7a6dacacSDimitry Andric  def : Pat<(rotl GR16:$src1, (i8 relocImm:$src2)),
307*7a6dacacSDimitry Andric            (ROL16ri GR16:$src1, relocImm:$src2)>;
308*7a6dacacSDimitry Andric  def : Pat<(rotl GR32:$src1, (i8 relocImm:$src2)),
309*7a6dacacSDimitry Andric            (ROL32ri GR32:$src1, relocImm:$src2)>;
310*7a6dacacSDimitry Andric  def : Pat<(rotl GR64:$src1, (i8 relocImm:$src2)),
311*7a6dacacSDimitry Andric            (ROL64ri GR64:$src1, relocImm:$src2)>;
312*7a6dacacSDimitry Andric
313*7a6dacacSDimitry Andric  def : Pat<(rotr GR8:$src1, (i8 relocImm:$src2)),
314*7a6dacacSDimitry Andric            (ROR8ri GR8:$src1, relocImm:$src2)>;
315*7a6dacacSDimitry Andric  def : Pat<(rotr GR16:$src1, (i8 relocImm:$src2)),
316*7a6dacacSDimitry Andric            (ROR16ri GR16:$src1, relocImm:$src2)>;
317*7a6dacacSDimitry Andric  def : Pat<(rotr GR32:$src1, (i8 relocImm:$src2)),
318*7a6dacacSDimitry Andric            (ROR32ri GR32:$src1, relocImm:$src2)>;
319*7a6dacacSDimitry Andric  def : Pat<(rotr GR64:$src1, (i8 relocImm:$src2)),
320*7a6dacacSDimitry Andric            (ROR64ri GR64:$src1, relocImm:$src2)>;
321*7a6dacacSDimitry Andric}
322*7a6dacacSDimitry Andriclet Predicates = [HasNDD] in {
323*7a6dacacSDimitry Andric  def : Pat<(rotl GR8:$src1, (i8 relocImm:$src2)),
324*7a6dacacSDimitry Andric            (ROL8ri_ND GR8:$src1, relocImm:$src2)>;
325*7a6dacacSDimitry Andric  def : Pat<(rotl GR16:$src1, (i8 relocImm:$src2)),
326*7a6dacacSDimitry Andric            (ROL16ri_ND GR16:$src1, relocImm:$src2)>;
327*7a6dacacSDimitry Andric  def : Pat<(rotl GR32:$src1, (i8 relocImm:$src2)),
328*7a6dacacSDimitry Andric            (ROL32ri_ND GR32:$src1, relocImm:$src2)>;
329*7a6dacacSDimitry Andric  def : Pat<(rotl GR64:$src1, (i8 relocImm:$src2)),
330*7a6dacacSDimitry Andric            (ROL64ri_ND GR64:$src1, relocImm:$src2)>;
331*7a6dacacSDimitry Andric
332*7a6dacacSDimitry Andric  def : Pat<(rotr GR8:$src1, (i8 relocImm:$src2)),
333*7a6dacacSDimitry Andric            (ROR8ri_ND GR8:$src1, relocImm:$src2)>;
334*7a6dacacSDimitry Andric  def : Pat<(rotr GR16:$src1, (i8 relocImm:$src2)),
335*7a6dacacSDimitry Andric            (ROR16ri_ND GR16:$src1, relocImm:$src2)>;
336*7a6dacacSDimitry Andric  def : Pat<(rotr GR32:$src1, (i8 relocImm:$src2)),
337*7a6dacacSDimitry Andric            (ROR32ri_ND GR32:$src1, relocImm:$src2)>;
338*7a6dacacSDimitry Andric  def : Pat<(rotr GR64:$src1, (i8 relocImm:$src2)),
339*7a6dacacSDimitry Andric            (ROR64ri_ND GR64:$src1, relocImm:$src2)>;
340*7a6dacacSDimitry Andric}
341*7a6dacacSDimitry Andric
342*7a6dacacSDimitry Andric//===----------------------------------------------------------------------===//
343*7a6dacacSDimitry Andric// Double precision shift instructions (generalizations of rotate)
344*7a6dacacSDimitry Andric//===----------------------------------------------------------------------===//
345*7a6dacacSDimitry Andric
346*7a6dacacSDimitry Andricclass ShlrdOpRRI8U_R<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag, bit ndd = 0>
347*7a6dacacSDimitry Andric  : ITy<o, MRMDestReg, t, (outs t.RegClass:$dst),
348*7a6dacacSDimitry Andric        (ins t.RegClass:$src1, t.RegClass:$src2, u8imm:$src3), m, !if(!eq(ndd, 0), triop_args, triop_ndd_args),
349*7a6dacacSDimitry Andric        []>, NDD<ndd> {
350*7a6dacacSDimitry Andric  let isCommutable = 1;
351*7a6dacacSDimitry Andric  let ImmT = Imm8;
352*7a6dacacSDimitry Andric  let SchedRW = [WriteSHDrri];
353*7a6dacacSDimitry Andric  let Pattern = !if(!eq(m, "shld"),
354*7a6dacacSDimitry Andric                    [(set t.RegClass:$dst, (node t.RegClass:$src1, t.RegClass:$src2, (i8 imm:$src3)))],
355*7a6dacacSDimitry Andric                    [(set t.RegClass:$dst, (node t.RegClass:$src2, t.RegClass:$src1, (i8 imm:$src3)))]);
356*7a6dacacSDimitry Andric}
357*7a6dacacSDimitry Andric
358*7a6dacacSDimitry Andricclass ShlrdOpRRC_R<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag, bit ndd = 0>
359*7a6dacacSDimitry Andric  : BinOpRR<o, m, !if(!eq(ndd, 0), triop_cl_args, triop_cl_ndd_args), t, (outs t.RegClass:$dst), []>, NDD<ndd> {
360*7a6dacacSDimitry Andric  let Uses = [CL];
361*7a6dacacSDimitry Andric  let SchedRW = [WriteSHDrrcl];
362*7a6dacacSDimitry Andric  let Pattern = !if(!eq(m, "shld"),
363*7a6dacacSDimitry Andric                    [(set t.RegClass:$dst, (node t.RegClass:$src1, t.RegClass:$src2, CL))],
364*7a6dacacSDimitry Andric                    [(set t.RegClass:$dst, (node t.RegClass:$src2, t.RegClass:$src1, CL))]);
365*7a6dacacSDimitry Andric}
366*7a6dacacSDimitry Andric
367*7a6dacacSDimitry Andricclass ShlrdOpMRI8U_M<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag>
368*7a6dacacSDimitry Andric  : ITy<o, MRMDestMem, t, (outs), (ins t.MemOperand:$src1, t.RegClass:$src2, u8imm:$src3),
369*7a6dacacSDimitry Andric        m, triop_args, []>, TB {
370*7a6dacacSDimitry Andric  let ImmT = Imm8;
371*7a6dacacSDimitry Andric  let SchedRW = [WriteSHDmri];
372*7a6dacacSDimitry Andric  let mayLoad = 1;
373*7a6dacacSDimitry Andric  let mayStore = 1;
374*7a6dacacSDimitry Andric  let Pattern = !if(!eq(m, "shld"),
375*7a6dacacSDimitry Andric                    [(store (node (t.LoadNode addr:$src1), t.RegClass:$src2, (i8 imm:$src3)), addr:$src1)],
376*7a6dacacSDimitry Andric                    [(store (node t.RegClass:$src2, (t.LoadNode addr:$src1), (i8 imm:$src3)), addr:$src1)]);
377*7a6dacacSDimitry Andric}
378*7a6dacacSDimitry Andric
379*7a6dacacSDimitry Andricclass ShlrdOpMRC_M<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag>
380*7a6dacacSDimitry Andric  : BinOpMR<o, m, triop_cl_args, t, (outs), []>, TB {
381*7a6dacacSDimitry Andric  let Uses = [CL];
382*7a6dacacSDimitry Andric  let SchedRW = [WriteSHDmrcl];
383*7a6dacacSDimitry Andric  let mayStore = 1;
384*7a6dacacSDimitry Andric  let Pattern = !if(!eq(m, "shld"),
385*7a6dacacSDimitry Andric                    [(store (node (t.LoadNode addr:$src1), t.RegClass:$src2, CL), addr:$src1)],
386*7a6dacacSDimitry Andric                    [(store (node t.RegClass:$src2, (t.LoadNode addr:$src1), CL), addr:$src1)]);
387*7a6dacacSDimitry Andric}
388*7a6dacacSDimitry Andric
389*7a6dacacSDimitry Andricclass ShlrdOpMRI8U_R<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag>
390*7a6dacacSDimitry Andric  : ITy<o, MRMDestMem, t, (outs t.RegClass:$dst), (ins t.MemOperand:$src1, t.RegClass:$src2, u8imm:$src3),
391*7a6dacacSDimitry Andric        m, triop_ndd_args, []>, NDD<1> {
392*7a6dacacSDimitry Andric  let ImmT = Imm8;
393*7a6dacacSDimitry Andric  let SchedRW = [WriteSHDmri];
394*7a6dacacSDimitry Andric  let mayLoad = 1;
395*7a6dacacSDimitry Andric  let Pattern = !if(!eq(m, "shld"),
396*7a6dacacSDimitry Andric                    [(set t.RegClass:$dst, (node (t.LoadNode addr:$src1), t.RegClass:$src2, (i8 imm:$src3)))],
397*7a6dacacSDimitry Andric                    [(set t.RegClass:$dst, (node t.RegClass:$src2, (t.LoadNode addr:$src1), (i8 imm:$src3)))]);
398*7a6dacacSDimitry Andric}
399*7a6dacacSDimitry Andric
400*7a6dacacSDimitry Andricclass ShlrdOpMRC_R<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag>
401*7a6dacacSDimitry Andric  : BinOpMR<o, m, triop_cl_ndd_args, t, (outs t.RegClass:$dst), []>, NDD<1> {
402*7a6dacacSDimitry Andric  let Uses = [CL];
403*7a6dacacSDimitry Andric  let SchedRW = [WriteSHDmrcl];
404*7a6dacacSDimitry Andric  let Pattern = !if(!eq(m, "shld"),
405*7a6dacacSDimitry Andric                    [(set t.RegClass:$dst, (node (t.LoadNode addr:$src1), t.RegClass:$src2, CL))],
406*7a6dacacSDimitry Andric                    [(set t.RegClass:$dst, (node t.RegClass:$src2, (t.LoadNode addr:$src1), CL))]);
407*7a6dacacSDimitry Andric}
408*7a6dacacSDimitry Andric
409*7a6dacacSDimitry Andricmulticlass Shlrd<bits<8> o1, bits<8> o2, bits<8> o3, string m, SDPatternOperator node, SDPatternOperator t_node> {
410*7a6dacacSDimitry Andric  let Predicates = [NoNDD] in {
411*7a6dacacSDimitry Andric    def 16rri8 : ShlrdOpRRI8U_R<o1, m, Xi16, t_node>, TB, DefEFLAGS, OpSize16;
412*7a6dacacSDimitry Andric    def 32rri8 : ShlrdOpRRI8U_R<o1, m, Xi32, node>, TB, DefEFLAGS, OpSize32;
413*7a6dacacSDimitry Andric    def 64rri8 : ShlrdOpRRI8U_R<o1, m, Xi64, node>, TB, DefEFLAGS;
414*7a6dacacSDimitry Andric
415*7a6dacacSDimitry Andric    def 16rrCL : ShlrdOpRRC_R<o2, m, Xi16, t_node>, TB, DefEFLAGS, OpSize16;
416*7a6dacacSDimitry Andric    def 32rrCL : ShlrdOpRRC_R<o2, m, Xi32, node>, TB, DefEFLAGS, OpSize32;
417*7a6dacacSDimitry Andric    def 64rrCL : ShlrdOpRRC_R<o2, m, Xi64, node>, TB, DefEFLAGS;
418*7a6dacacSDimitry Andric  }
419*7a6dacacSDimitry Andric  let Predicates = [HasNDD, In64BitMode] in {
420*7a6dacacSDimitry Andric    def 16rri8_ND : ShlrdOpRRI8U_R<o3, m, Xi16, t_node, 1>, DefEFLAGS, PD;
421*7a6dacacSDimitry Andric    def 32rri8_ND : ShlrdOpRRI8U_R<o3, m, Xi32, node, 1>, DefEFLAGS;
422*7a6dacacSDimitry Andric    def 64rri8_ND : ShlrdOpRRI8U_R<o3, m, Xi64, node, 1>, DefEFLAGS;
423*7a6dacacSDimitry Andric
424*7a6dacacSDimitry Andric    def 16rrCL_ND : ShlrdOpRRC_R<o2, m, Xi16, t_node, 1>, DefEFLAGS, PD;
425*7a6dacacSDimitry Andric    def 32rrCL_ND : ShlrdOpRRC_R<o2, m, Xi32, node, 1>, DefEFLAGS;
426*7a6dacacSDimitry Andric    def 64rrCL_ND : ShlrdOpRRC_R<o2, m, Xi64, node, 1>, DefEFLAGS;
427*7a6dacacSDimitry Andric  }
428*7a6dacacSDimitry Andric
429*7a6dacacSDimitry Andric  let Predicates = [In64BitMode] in {
430*7a6dacacSDimitry Andric    def 16rri8_NF : ShlrdOpRRI8U_R<o3, m, Xi16>, NF, PD;
431*7a6dacacSDimitry Andric    def 32rri8_NF : ShlrdOpRRI8U_R<o3, m, Xi32>, NF;
432*7a6dacacSDimitry Andric    def 64rri8_NF : ShlrdOpRRI8U_R<o3, m, Xi64>, NF;
433*7a6dacacSDimitry Andric
434*7a6dacacSDimitry Andric    def 16rrCL_NF : ShlrdOpRRC_R<o2, m, Xi16>, NF, PD;
435*7a6dacacSDimitry Andric    def 32rrCL_NF : ShlrdOpRRC_R<o2, m, Xi32>, NF;
436*7a6dacacSDimitry Andric    def 64rrCL_NF : ShlrdOpRRC_R<o2, m, Xi64>, NF;
437*7a6dacacSDimitry Andric
438*7a6dacacSDimitry Andric    def 16rri8_NF_ND : ShlrdOpRRI8U_R<o3, m, Xi16, null_frag, 1>, EVEX_NF, PD;
439*7a6dacacSDimitry Andric    def 32rri8_NF_ND : ShlrdOpRRI8U_R<o3, m, Xi32, null_frag, 1>, EVEX_NF;
440*7a6dacacSDimitry Andric    def 64rri8_NF_ND : ShlrdOpRRI8U_R<o3, m, Xi64, null_frag, 1>, EVEX_NF;
441*7a6dacacSDimitry Andric
442*7a6dacacSDimitry Andric    def 16rrCL_NF_ND : ShlrdOpRRC_R<o2, m, Xi16, null_frag, 1>, EVEX_NF, PD;
443*7a6dacacSDimitry Andric    def 32rrCL_NF_ND : ShlrdOpRRC_R<o2, m, Xi32, null_frag, 1>, EVEX_NF;
444*7a6dacacSDimitry Andric    def 64rrCL_NF_ND : ShlrdOpRRC_R<o2, m, Xi64, null_frag, 1>, EVEX_NF;
445*7a6dacacSDimitry Andric
446*7a6dacacSDimitry Andric    def 16rri8_EVEX : ShlrdOpRRI8U_R<o3, m, Xi16>, DefEFLAGS, PL, PD;
447*7a6dacacSDimitry Andric    def 32rri8_EVEX : ShlrdOpRRI8U_R<o3, m, Xi32>, DefEFLAGS, PL;
448*7a6dacacSDimitry Andric    def 64rri8_EVEX : ShlrdOpRRI8U_R<o3, m, Xi64>, DefEFLAGS, PL;
449*7a6dacacSDimitry Andric
450*7a6dacacSDimitry Andric    def 16rrCL_EVEX : ShlrdOpRRC_R<o2, m, Xi16>, DefEFLAGS, PL, PD;
451*7a6dacacSDimitry Andric    def 32rrCL_EVEX : ShlrdOpRRC_R<o2, m, Xi32>, DefEFLAGS, PL;
452*7a6dacacSDimitry Andric    def 64rrCL_EVEX : ShlrdOpRRC_R<o2, m, Xi64>, DefEFLAGS, PL;
453*7a6dacacSDimitry Andric  }
454*7a6dacacSDimitry Andric
455*7a6dacacSDimitry Andric  def 16mri8 : ShlrdOpMRI8U_M<o1, m, Xi16, t_node>, DefEFLAGS, OpSize16;
456*7a6dacacSDimitry Andric  def 32mri8 : ShlrdOpMRI8U_M<o1, m, Xi32, node>, DefEFLAGS, OpSize32;
457*7a6dacacSDimitry Andric  def 64mri8 : ShlrdOpMRI8U_M<o1, m, Xi64, node>, DefEFLAGS;
458*7a6dacacSDimitry Andric
459*7a6dacacSDimitry Andric  def 16mrCL : ShlrdOpMRC_M<o2, m, Xi16, t_node>, DefEFLAGS, OpSize16;
460*7a6dacacSDimitry Andric  def 32mrCL : ShlrdOpMRC_M<o2, m, Xi32, node>, DefEFLAGS, OpSize32;
461*7a6dacacSDimitry Andric  def 64mrCL : ShlrdOpMRC_M<o2, m, Xi64, node>, DefEFLAGS;
462*7a6dacacSDimitry Andric
463*7a6dacacSDimitry Andric  let Predicates = [HasNDD, In64BitMode] in {
464*7a6dacacSDimitry Andric    def 16mri8_ND : ShlrdOpMRI8U_R<o3, m, Xi16, t_node>, DefEFLAGS, PD;
465*7a6dacacSDimitry Andric    def 32mri8_ND : ShlrdOpMRI8U_R<o3, m, Xi32, node>, DefEFLAGS;
466*7a6dacacSDimitry Andric    def 64mri8_ND : ShlrdOpMRI8U_R<o3, m, Xi64, node>, DefEFLAGS;
467*7a6dacacSDimitry Andric
468*7a6dacacSDimitry Andric    def 16mrCL_ND : ShlrdOpMRC_R<o2, m, Xi16, t_node>, DefEFLAGS, PD;
469*7a6dacacSDimitry Andric    def 32mrCL_ND : ShlrdOpMRC_R<o2, m, Xi32, node>, DefEFLAGS;
470*7a6dacacSDimitry Andric    def 64mrCL_ND : ShlrdOpMRC_R<o2, m, Xi64, node>, DefEFLAGS;
471*7a6dacacSDimitry Andric  }
472*7a6dacacSDimitry Andric
473*7a6dacacSDimitry Andric  let Predicates = [In64BitMode] in {
474*7a6dacacSDimitry Andric    def 16mri8_NF : ShlrdOpMRI8U_M<o3, m, Xi16>, NF, PD;
475*7a6dacacSDimitry Andric    def 32mri8_NF : ShlrdOpMRI8U_M<o3, m, Xi32>, NF;
476*7a6dacacSDimitry Andric    def 64mri8_NF : ShlrdOpMRI8U_M<o3, m, Xi64>, NF;
477*7a6dacacSDimitry Andric
478*7a6dacacSDimitry Andric    def 16mrCL_NF : ShlrdOpMRC_M<o2, m, Xi16>, NF, PD;
479*7a6dacacSDimitry Andric    def 32mrCL_NF : ShlrdOpMRC_M<o2, m, Xi32>, NF;
480*7a6dacacSDimitry Andric    def 64mrCL_NF : ShlrdOpMRC_M<o2, m, Xi64>, NF;
481*7a6dacacSDimitry Andric
482*7a6dacacSDimitry Andric    def 16mri8_NF_ND : ShlrdOpMRI8U_R<o3, m, Xi16>, EVEX_NF, PD;
483*7a6dacacSDimitry Andric    def 32mri8_NF_ND : ShlrdOpMRI8U_R<o3, m, Xi32>, EVEX_NF;
484*7a6dacacSDimitry Andric    def 64mri8_NF_ND : ShlrdOpMRI8U_R<o3, m, Xi64>, EVEX_NF;
485*7a6dacacSDimitry Andric
486*7a6dacacSDimitry Andric    def 16mrCL_NF_ND : ShlrdOpMRC_R<o2, m, Xi16>, EVEX_NF, PD;
487*7a6dacacSDimitry Andric    def 32mrCL_NF_ND : ShlrdOpMRC_R<o2, m, Xi32>, EVEX_NF;
488*7a6dacacSDimitry Andric    def 64mrCL_NF_ND : ShlrdOpMRC_R<o2, m, Xi64>, EVEX_NF;
489*7a6dacacSDimitry Andric
490*7a6dacacSDimitry Andric    def 16mri8_EVEX : ShlrdOpMRI8U_M<o3, m, Xi16>, DefEFLAGS, PL, PD;
491*7a6dacacSDimitry Andric    def 32mri8_EVEX : ShlrdOpMRI8U_M<o3, m, Xi32>, DefEFLAGS, PL;
492*7a6dacacSDimitry Andric    def 64mri8_EVEX : ShlrdOpMRI8U_M<o3, m, Xi64>, DefEFLAGS, PL;
493*7a6dacacSDimitry Andric
494*7a6dacacSDimitry Andric    def 16mrCL_EVEX : ShlrdOpMRC_M<o2, m, Xi16>, DefEFLAGS, PL, PD;
495*7a6dacacSDimitry Andric    def 32mrCL_EVEX : ShlrdOpMRC_M<o2, m, Xi32>, DefEFLAGS, PL;
496*7a6dacacSDimitry Andric    def 64mrCL_EVEX : ShlrdOpMRC_M<o2, m, Xi64>, DefEFLAGS, PL;
497*7a6dacacSDimitry Andric  }
498*7a6dacacSDimitry Andric}
499*7a6dacacSDimitry Andric
500*7a6dacacSDimitry Andricdefm SHLD : Shlrd<0xA4, 0xA5, 0x24, "shld", fshl, X86fshl>;
501*7a6dacacSDimitry Andricdefm SHRD : Shlrd<0xAC, 0xAD, 0x2C, "shrd", fshr, X86fshr>;
502*7a6dacacSDimitry Andric
5030b57cec5SDimitry Andric// Sandy Bridge and newer Intel processors support faster rotates using
5040b57cec5SDimitry Andric// SHLD to avoid a partial flag update on the normal rotate instructions.
5050b57cec5SDimitry Andric// Use a pseudo so that TwoInstructionPass and register allocation will see
5060b57cec5SDimitry Andric// this as unary instruction.
5070b57cec5SDimitry Andriclet Predicates = [HasFastSHLDRotate], AddedComplexity = 5,
5080b57cec5SDimitry Andric    Defs = [EFLAGS], isPseudo = 1, SchedRW = [WriteSHDrri],
5090b57cec5SDimitry Andric    Constraints = "$src1 = $dst" in {
5100b57cec5SDimitry Andric  def SHLDROT32ri  : I<0, Pseudo, (outs GR32:$dst),
5110b57cec5SDimitry Andric                       (ins GR32:$src1, u8imm:$shamt), "",
5120b57cec5SDimitry Andric                     [(set GR32:$dst, (rotl GR32:$src1, (i8 imm:$shamt)))]>;
5130b57cec5SDimitry Andric  def SHLDROT64ri  : I<0, Pseudo, (outs GR64:$dst),
5140b57cec5SDimitry Andric                       (ins GR64:$src1, u8imm:$shamt), "",
5150b57cec5SDimitry Andric                     [(set GR64:$dst, (rotl GR64:$src1, (i8 imm:$shamt)))]>;
5160b57cec5SDimitry Andric
5170b57cec5SDimitry Andric  def SHRDROT32ri  : I<0, Pseudo, (outs GR32:$dst),
5180b57cec5SDimitry Andric                       (ins GR32:$src1, u8imm:$shamt), "",
5190b57cec5SDimitry Andric                     [(set GR32:$dst, (rotr GR32:$src1, (i8 imm:$shamt)))]>;
5200b57cec5SDimitry Andric  def SHRDROT64ri  : I<0, Pseudo, (outs GR64:$dst),
5210b57cec5SDimitry Andric                       (ins GR64:$src1, u8imm:$shamt), "",
5220b57cec5SDimitry Andric                     [(set GR64:$dst, (rotr GR64:$src1, (i8 imm:$shamt)))]>;
5230b57cec5SDimitry Andric}
5240b57cec5SDimitry Andric
525*7a6dacacSDimitry Andric//===----------------------------------------------------------------------===//
526*7a6dacacSDimitry Andric// BMI Shift/Rotate instructions
527*7a6dacacSDimitry Andric//===----------------------------------------------------------------------===//
528*7a6dacacSDimitry Andric
5290b57cec5SDimitry Andricdef ROT32L2R_imm8  : SDNodeXForm<imm, [{
5300b57cec5SDimitry Andric  // Convert a ROTL shamt to a ROTR shamt on 32-bit integer.
5310b57cec5SDimitry Andric  return getI8Imm(32 - N->getZExtValue(), SDLoc(N));
5320b57cec5SDimitry Andric}]>;
5330b57cec5SDimitry Andric
5340b57cec5SDimitry Andricdef ROT64L2R_imm8  : SDNodeXForm<imm, [{
5350b57cec5SDimitry Andric  // Convert a ROTL shamt to a ROTR shamt on 64-bit integer.
5360b57cec5SDimitry Andric  return getI8Imm(64 - N->getZExtValue(), SDLoc(N));
5370b57cec5SDimitry Andric}]>;
5380b57cec5SDimitry Andric
5390b57cec5SDimitry Andric// NOTE: We use WriteShift for these rotates as they avoid the stalls
5400b57cec5SDimitry Andric// of many of the older x86 rotate instructions.
541*7a6dacacSDimitry Andricclass RorXri<X86TypeInfo t>
542*7a6dacacSDimitry Andric  : ITy<0xF0, MRMSrcReg, t, (outs t.RegClass:$dst), (ins t.RegClass:$src1, u8imm:$src2),
543*7a6dacacSDimitry Andric        "rorx", binop_ndd_args, []>, TA, XD, Sched<[WriteShift]> {
544*7a6dacacSDimitry Andric  let ImmT = Imm8;
545*7a6dacacSDimitry Andric}
546*7a6dacacSDimitry Andricclass RorXmi<X86TypeInfo t>
547*7a6dacacSDimitry Andric  : ITy<0xF0, MRMSrcMem, t, (outs t.RegClass:$dst), (ins t.MemOperand:$src1, u8imm:$src2),
548*7a6dacacSDimitry Andric        "rorx", binop_ndd_args, []>, TA, XD, Sched<[WriteShiftLd]> {
549*7a6dacacSDimitry Andric  let ImmT = Imm8;
550*7a6dacacSDimitry Andric  let mayLoad = 1;
551*7a6dacacSDimitry Andric}
552*7a6dacacSDimitry Andric
553*7a6dacacSDimitry Andricmulticlass RorX<X86TypeInfo t> {
554*7a6dacacSDimitry Andric  let Predicates = [HasBMI2, NoEGPR] in {
555*7a6dacacSDimitry Andric    def ri : RorXri<t>, VEX;
556*7a6dacacSDimitry Andric    def mi : RorXmi<t>, VEX;
557*7a6dacacSDimitry Andric  }
558*7a6dacacSDimitry Andric  let Predicates = [HasBMI2, HasEGPR, In64BitMode] in {
559*7a6dacacSDimitry Andric    def ri_EVEX : RorXri<t>, EVEX;
560*7a6dacacSDimitry Andric    def mi_EVEX : RorXmi<t>, EVEX;
5610b57cec5SDimitry Andric  }
5620b57cec5SDimitry Andric}
5630b57cec5SDimitry Andric
564*7a6dacacSDimitry Andricdefm RORX32: RorX<Xi32>;
565*7a6dacacSDimitry Andricdefm RORX64: RorX<Xi64>;
566*7a6dacacSDimitry Andric
567*7a6dacacSDimitry Andricclass ShiftXrr<string m, X86TypeInfo t>
568*7a6dacacSDimitry Andric  : ITy<0xF7, MRMSrcReg4VOp3, t, (outs t.RegClass:$dst), (ins t.RegClass:$src1, t.RegClass:$src2),
569*7a6dacacSDimitry Andric        m, binop_ndd_args, []>, T8, Sched<[WriteShift]>;
570*7a6dacacSDimitry Andric
571*7a6dacacSDimitry Andricclass ShiftXrm<string m, X86TypeInfo t>
572*7a6dacacSDimitry Andric  : ITy<0xF7, MRMSrcMem4VOp3, t, (outs t.RegClass:$dst), (ins t.MemOperand:$src1, t.RegClass:$src2),
573*7a6dacacSDimitry Andric        m, binop_ndd_args, []>, T8,
574*7a6dacacSDimitry Andric    Sched<[WriteShift.Folded,
5750b57cec5SDimitry Andric           // x86memop:$src1
5760b57cec5SDimitry Andric           ReadDefault, ReadDefault, ReadDefault, ReadDefault,
5770b57cec5SDimitry Andric           ReadDefault,
5780b57cec5SDimitry Andric           // RC:$src2
579*7a6dacacSDimitry Andric           WriteShift.ReadAfterFold]> {
580*7a6dacacSDimitry Andric  let mayLoad = 1;
5810b57cec5SDimitry Andric}
5820b57cec5SDimitry Andric
583*7a6dacacSDimitry Andric
584*7a6dacacSDimitry Andricmulticlass ShiftX<string m, X86TypeInfo t> {
5855f757f3fSDimitry Andric  let Predicates = [HasBMI2, NoEGPR] in {
586*7a6dacacSDimitry Andric    def rr : ShiftXrr<m, t>, VEX;
587*7a6dacacSDimitry Andric    def rm : ShiftXrm<m, t>, VEX;
5885f757f3fSDimitry Andric  }
5891db9f3b2SDimitry Andric  let Predicates = [HasBMI2, HasEGPR, In64BitMode] in {
590*7a6dacacSDimitry Andric    def rr_EVEX : ShiftXrr<m, t>, EVEX;
591*7a6dacacSDimitry Andric    def rm_EVEX : ShiftXrm<m, t>, EVEX;
592*7a6dacacSDimitry Andric  }
5935f757f3fSDimitry Andric}
5945f757f3fSDimitry Andric
595*7a6dacacSDimitry Andricdefm SARX32: ShiftX<"sarx", Xi32>, XS;
596*7a6dacacSDimitry Andricdefm SARX64: ShiftX<"sarx", Xi64>, XS;
597*7a6dacacSDimitry Andricdefm SHRX32: ShiftX<"shrx", Xi32>, XD;
598*7a6dacacSDimitry Andricdefm SHRX64: ShiftX<"shrx", Xi64>, XD;
599*7a6dacacSDimitry Andricdefm SHLX32: ShiftX<"shlx", Xi32>, PD;
600*7a6dacacSDimitry Andricdefm SHLX64: ShiftX<"shlx", Xi64>, PD;
601*7a6dacacSDimitry Andric
602*7a6dacacSDimitry Andricmulticlass RORX_Pats<string suffix> {
6030b57cec5SDimitry Andric  // Prefer RORX which is non-destructive and doesn't update EFLAGS.
6040b57cec5SDimitry Andric  let AddedComplexity = 10 in {
6050b57cec5SDimitry Andric    def : Pat<(rotr GR32:$src, (i8 imm:$shamt)),
606*7a6dacacSDimitry Andric              (!cast<Instruction>(RORX32ri#suffix) GR32:$src, imm:$shamt)>;
6070b57cec5SDimitry Andric    def : Pat<(rotr GR64:$src, (i8 imm:$shamt)),
608*7a6dacacSDimitry Andric              (!cast<Instruction>(RORX64ri#suffix) GR64:$src, imm:$shamt)>;
6090b57cec5SDimitry Andric
6100b57cec5SDimitry Andric    def : Pat<(rotl GR32:$src, (i8 imm:$shamt)),
611*7a6dacacSDimitry Andric              (!cast<Instruction>(RORX32ri#suffix) GR32:$src, (ROT32L2R_imm8 imm:$shamt))>;
6120b57cec5SDimitry Andric    def : Pat<(rotl GR64:$src, (i8 imm:$shamt)),
613*7a6dacacSDimitry Andric              (!cast<Instruction>(RORX64ri#suffix) GR64:$src, (ROT64L2R_imm8 imm:$shamt))>;
6140b57cec5SDimitry Andric  }
6150b57cec5SDimitry Andric
6160b57cec5SDimitry Andric  def : Pat<(rotr (loadi32 addr:$src), (i8 imm:$shamt)),
617*7a6dacacSDimitry Andric            (!cast<Instruction>(RORX32mi#suffix) addr:$src, imm:$shamt)>;
6180b57cec5SDimitry Andric  def : Pat<(rotr (loadi64 addr:$src), (i8 imm:$shamt)),
619*7a6dacacSDimitry Andric            (!cast<Instruction>(RORX64mi#suffix) addr:$src, imm:$shamt)>;
6200b57cec5SDimitry Andric
6210b57cec5SDimitry Andric  def : Pat<(rotl (loadi32 addr:$src), (i8 imm:$shamt)),
622*7a6dacacSDimitry Andric            (!cast<Instruction>(RORX32mi#suffix) addr:$src, (ROT32L2R_imm8 imm:$shamt))>;
6230b57cec5SDimitry Andric  def : Pat<(rotl (loadi64 addr:$src), (i8 imm:$shamt)),
624*7a6dacacSDimitry Andric            (!cast<Instruction>(RORX64mi#suffix) addr:$src, (ROT64L2R_imm8 imm:$shamt))>;
625*7a6dacacSDimitry Andric}
6260b57cec5SDimitry Andric
627*7a6dacacSDimitry Andricmulticlass ShiftX_Pats<SDNode op, string suffix = ""> {
6280b57cec5SDimitry Andric  // Prefer SARX/SHRX/SHLX over SAR/SHR/SHL with variable shift BUT not
6290b57cec5SDimitry Andric  // immediate shift, i.e. the following code is considered better
6300b57cec5SDimitry Andric  //
6310b57cec5SDimitry Andric  //  mov %edi, %esi
6320b57cec5SDimitry Andric  //  shl $imm, %esi
6330b57cec5SDimitry Andric  //  ... %edi, ...
6340b57cec5SDimitry Andric  //
6350b57cec5SDimitry Andric  // than
6360b57cec5SDimitry Andric  //
6370b57cec5SDimitry Andric  //  movb $imm, %sil
6380b57cec5SDimitry Andric  //  shlx %sil, %edi, %esi
6390b57cec5SDimitry Andric  //  ... %edi, ...
6400b57cec5SDimitry Andric  //
6410b57cec5SDimitry Andric  let AddedComplexity = 1 in {
642*7a6dacacSDimitry Andric   def : Pat<(op GR32:$src1, GR8:$src2),
643*7a6dacacSDimitry Andric              (!cast<Instruction>(NAME#"32rr"#suffix) GR32:$src1,
644*7a6dacacSDimitry Andric               (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
645*7a6dacacSDimitry Andric   def : Pat<(op GR64:$src1, GR8:$src2),
646*7a6dacacSDimitry Andric              (!cast<Instruction>(NAME#"64rr"#suffix) GR64:$src1,
647*7a6dacacSDimitry Andric               (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
648*7a6dacacSDimitry Andric   def : Pat<(op GR32:$src1, (shiftMask32 GR8:$src2)),
649*7a6dacacSDimitry Andric              (!cast<Instruction>(NAME#"32rr"#suffix) GR32:$src1,
650*7a6dacacSDimitry Andric               (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
651*7a6dacacSDimitry Andric   def : Pat<(op GR64:$src1, (shiftMask64 GR8:$src2)),
652*7a6dacacSDimitry Andric              (!cast<Instruction>(NAME#"64rr"#suffix) GR64:$src1,
653*7a6dacacSDimitry Andric               (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
6540b57cec5SDimitry Andric  }
6550b57cec5SDimitry Andric  // We prefer to use
6560b57cec5SDimitry Andric  //  mov (%ecx), %esi
6570b57cec5SDimitry Andric  //  shl $imm, $esi
6580b57cec5SDimitry Andric  //
6590b57cec5SDimitry Andric  // over
6600b57cec5SDimitry Andric  //
6610b57cec5SDimitry Andric  //  movb $imm, %al
6620b57cec5SDimitry Andric  //  shlx %al, (%ecx), %esi
6630b57cec5SDimitry Andric  //
6640b57cec5SDimitry Andric  // This priority is enforced by IsProfitableToFoldLoad.
665*7a6dacacSDimitry Andric  def : Pat<(op (loadi32 addr:$src1), GR8:$src2),
666*7a6dacacSDimitry Andric             (!cast<Instruction>(NAME#"32rm"#suffix) addr:$src1,
667*7a6dacacSDimitry Andric              (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
668*7a6dacacSDimitry Andric  def : Pat<(op (loadi64 addr:$src1), GR8:$src2),
669*7a6dacacSDimitry Andric             (!cast<Instruction>(NAME#"64rm"#suffix) addr:$src1,
670*7a6dacacSDimitry Andric              (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
671*7a6dacacSDimitry Andric  def : Pat<(op (loadi32 addr:$src1), (shiftMask32 GR8:$src2)),
672*7a6dacacSDimitry Andric             (!cast<Instruction>(NAME#"32rm"#suffix) addr:$src1,
673*7a6dacacSDimitry Andric              (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
674*7a6dacacSDimitry Andric  def : Pat<(op (loadi64 addr:$src1), (shiftMask64 GR8:$src2)),
675*7a6dacacSDimitry Andric             (!cast<Instruction>(NAME#"64rm"#suffix) addr:$src1,
676*7a6dacacSDimitry Andric              (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
6770b57cec5SDimitry Andric}
6785ffd83dbSDimitry Andric
679*7a6dacacSDimitry Andriclet Predicates = [HasBMI2, NoEGPR] in {
680*7a6dacacSDimitry Andric  defm : RORX_Pats<"">;
681*7a6dacacSDimitry Andric  defm SARX : ShiftX_Pats<sra>;
682*7a6dacacSDimitry Andric  defm SHRX : ShiftX_Pats<srl>;
683*7a6dacacSDimitry Andric  defm SHLX : ShiftX_Pats<shl>;
684*7a6dacacSDimitry Andric}
6855ffd83dbSDimitry Andric
686*7a6dacacSDimitry Andriclet Predicates = [HasBMI2, HasEGPR] in {
687*7a6dacacSDimitry Andric  defm : RORX_Pats<"_EVEX">;
688*7a6dacacSDimitry Andric  defm SARX : ShiftX_Pats<sra, "_EVEX">;
689*7a6dacacSDimitry Andric  defm SHRX : ShiftX_Pats<srl, "_EVEX">;
690*7a6dacacSDimitry Andric  defm SHLX : ShiftX_Pats<shl, "_EVEX">;
691*7a6dacacSDimitry Andric}
692