Add gfx950 mfma instructions to ROCDL dialect (#123361)
[llvm-project.git] / llvm / lib / Target / X86 / X86InstrShiftRotate.td
blob2a5488847e64890558f639748eda03d223de5cb1
1 //===-- X86InstrShiftRotate.td - Shift and Rotate Instrs ---*- tablegen -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file describes the shift and rotate instructions.
11 //===----------------------------------------------------------------------===//
13 //===----------------------------------------------------------------------===//
14 // Shift/Rotate instructions
15 //===----------------------------------------------------------------------===//
17 multiclass ShiftRotate<string m, Format RegMRM, Format MemMRM, SDPatternOperator node,
18                        SchedReadWrite rCL, SchedReadWrite ri, SchedReadWrite mCL,
19                        SchedReadWrite mi, list<Register> uses = []> {
21   let Uses = uses in {
22     let isConvertibleToThreeAddress = !if(!eq(m, "shl"), 1, 0) in {
23       let Predicates = [NoNDD] in {
24         def 8ri  : BinOpRI8U_R<m, RegMRM, Xi8, node>, Sched<[ri]>, DefEFLAGS;
25         def 16ri : BinOpRI8U_R<m, RegMRM, Xi16, node>, Sched<[ri]>, DefEFLAGS, OpSize16;
26         def 32ri : BinOpRI8U_R<m, RegMRM, Xi32, node>, Sched<[ri]>, DefEFLAGS, OpSize32;
27         def 64ri : BinOpRI8U_R<m, RegMRM, Xi64, node>, Sched<[ri]>, DefEFLAGS;
28       }
29       let Predicates = [HasNDD, In64BitMode] in {
30         def 8ri_ND  : BinOpRI8U_R<m, RegMRM, Xi8, node, 1>, Sched<[ri]>, DefEFLAGS;
31         def 16ri_ND : BinOpRI8U_R<m, RegMRM, Xi16, node, 1>, Sched<[ri]>, DefEFLAGS, PD;
32         def 32ri_ND : BinOpRI8U_R<m, RegMRM, Xi32, node, 1>, Sched<[ri]>, DefEFLAGS;
33         def 64ri_ND : BinOpRI8U_R<m, RegMRM, Xi64, node, 1>, Sched<[ri]>, DefEFLAGS;
34       }
35       let Predicates = [In64BitMode] in {
36         def 8ri_EVEX  : BinOpRI8U_R<m, RegMRM, Xi8>, Sched<[ri]>, DefEFLAGS, PL;
37         def 16ri_EVEX : BinOpRI8U_R<m, RegMRM, Xi16>, Sched<[ri]>, DefEFLAGS, PL, PD;
38         def 32ri_EVEX : BinOpRI8U_R<m, RegMRM, Xi32>, Sched<[ri]>, DefEFLAGS, PL;
39         def 64ri_EVEX : BinOpRI8U_R<m, RegMRM, Xi64>, Sched<[ri]>, DefEFLAGS, PL;
40       }
41     }
43     def 8mi  : BinOpMI8U_M<m, MemMRM, Xi8, node>, Sched<[mi, WriteRMW]>, DefEFLAGS;
44     def 16mi : BinOpMI8U_M<m, MemMRM, Xi16, node>, Sched<[mi, WriteRMW]>, DefEFLAGS, OpSize16;
45     def 32mi : BinOpMI8U_M<m, MemMRM, Xi32, node>, Sched<[mi, WriteRMW]>, DefEFLAGS, OpSize32;
46     def 64mi : BinOpMI8U_M<m, MemMRM, Xi64, node>, Sched<[mi, WriteRMW]>, DefEFLAGS, Requires<[In64BitMode]>;
47     let Predicates = [HasNDD, In64BitMode] in {
48       def 8mi_ND  : BinOpMI8U_R<m, MemMRM, Xi8, node>, Sched<[mi, ri]>, DefEFLAGS;
49       def 16mi_ND : BinOpMI8U_R<m, MemMRM, Xi16, node>, Sched<[mi, ri]>, DefEFLAGS, PD;
50       def 32mi_ND : BinOpMI8U_R<m, MemMRM, Xi32, node>, Sched<[mi, ri]>, DefEFLAGS;
51       def 64mi_ND : BinOpMI8U_R<m, MemMRM, Xi64, node>, Sched<[mi, ri]>, DefEFLAGS;
52     }
53     let Predicates = [In64BitMode] in {
54       def 8mi_EVEX  : BinOpMI8U_M<m, MemMRM, Xi8>, Sched<[mi, WriteRMW]>, DefEFLAGS, PL;
55       def 16mi_EVEX : BinOpMI8U_M<m, MemMRM, Xi16>, Sched<[mi, WriteRMW]>, DefEFLAGS, PL, PD;
56       def 32mi_EVEX : BinOpMI8U_M<m, MemMRM, Xi32>, Sched<[mi, WriteRMW]>, DefEFLAGS, PL;
57       def 64mi_EVEX : BinOpMI8U_M<m, MemMRM, Xi64>, Sched<[mi, WriteRMW]>, DefEFLAGS, PL;
58     }
60     let SchedRW = [ri] in {
61       def 8r1  : UnaryOpR_RF<0xD1, RegMRM, m, Xi8>;
62       def 16r1 : UnaryOpR_RF<0xD1, RegMRM, m, Xi16>, OpSize16;
63       def 32r1 : UnaryOpR_RF<0xD1, RegMRM, m, Xi32>, OpSize32;
64       def 64r1 : UnaryOpR_RF<0xD1, RegMRM, m, Xi64>;
66       // FIXME: Assembler can't tell whether it's 8r1_ND or 8rCL when the source register is cl, e.g.
67       //
68       //  shlb %cl, %al
69       //
70       // GNU binutils distinguish them by adding an explicit $1 to asm string of 8r1_ND. But we haven't support
71       // constant immediate in asm string for X86 in TD. So we add DisassembleOnly for 8r1_ND for the time being.
72       let Predicates = [In64BitMode] in {
73         def 8r1_ND  : UnaryOpR_RF<0xD1, RegMRM, m, Xi8, null_frag, 1>, DisassembleOnly;
74         def 16r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi16, null_frag, 1>, PD;
75         def 32r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi32, null_frag, 1>;
76         def 64r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi64, null_frag, 1>;
78         def 8r1_EVEX  : UnaryOpR_RF<0xD1, RegMRM, m, Xi8>, PL;
79         def 16r1_EVEX : UnaryOpR_RF<0xD1, RegMRM, m, Xi16>, PL, PD;
80         def 32r1_EVEX : UnaryOpR_RF<0xD1, RegMRM, m, Xi32>, PL;
81         def 64r1_EVEX : UnaryOpR_RF<0xD1, RegMRM, m, Xi64>, PL;
82       }
83     }
85     let SchedRW = [mi, WriteRMW] in {
86       def 8m1  : UnaryOpM_MF<0xD1, MemMRM, m, Xi8>;
87       def 16m1 : UnaryOpM_MF<0xD1, MemMRM, m, Xi16>, OpSize16;
88       def 32m1 : UnaryOpM_MF<0xD1, MemMRM, m, Xi32>, OpSize32;
89       def 64m1 : UnaryOpM_MF<0xD1, MemMRM, m, Xi64>, Requires<[In64BitMode]>;
91       let Predicates = [In64BitMode] in {
92         def 8m1_EVEX  : UnaryOpM_MF<0xD1, MemMRM, m, Xi8>, PL;
93         def 16m1_EVEX : UnaryOpM_MF<0xD1, MemMRM, m, Xi16>, PL, PD;
94         def 32m1_EVEX : UnaryOpM_MF<0xD1, MemMRM, m, Xi32>, PL;
95         def 64m1_EVEX : UnaryOpM_MF<0xD1, MemMRM, m, Xi64>, PL;
96       }
97     }
98     let SchedRW = [mi, ri], Predicates = [In64BitMode] in {
99       def 8m1_ND  : UnaryOpM_RF<0xD1, MemMRM, m, Xi8>;
100       def 16m1_ND : UnaryOpM_RF<0xD1, MemMRM, m, Xi16>, PD;
101       def 32m1_ND : UnaryOpM_RF<0xD1, MemMRM, m, Xi32>;
102       def 64m1_ND : UnaryOpM_RF<0xD1, MemMRM, m, Xi64>;
103     }
104   }
106   let Uses = !listconcat([CL], uses), Defs = [EFLAGS] in {
107     let Predicates = [NoNDD] in {
108       def 8rCL  : BinOpRC_R<m, RegMRM, Xi8, node>, Sched<[rCL]>;
109       def 16rCL : BinOpRC_R<m, RegMRM, Xi16, node>, Sched<[rCL]>, OpSize16;
110       def 32rCL : BinOpRC_R<m, RegMRM, Xi32, node>, Sched<[rCL]>, OpSize32;
111       def 64rCL : BinOpRC_R<m, RegMRM, Xi64, node>, Sched<[rCL]>;
112     }
113     let Predicates = [HasNDD, In64BitMode] in {
114       def 8rCL_ND  : BinOpRC_R<m, RegMRM, Xi8, node, 1>, Sched<[rCL]>;
115       def 16rCL_ND : BinOpRC_R<m, RegMRM, Xi16, node, 1>, Sched<[rCL]>, PD;
116       def 32rCL_ND : BinOpRC_R<m, RegMRM, Xi32, node, 1>, Sched<[rCL]>;
117       def 64rCL_ND : BinOpRC_R<m, RegMRM, Xi64, node, 1>, Sched<[rCL]>;
118     }
119     let Predicates = [In64BitMode] in {
120       def 8rCL_EVEX  : BinOpRC_R<m, RegMRM, Xi8>, Sched<[rCL]>, PL;
121       def 16rCL_EVEX : BinOpRC_R<m, RegMRM, Xi16>, Sched<[rCL]>, PL, PD;
122       def 32rCL_EVEX : BinOpRC_R<m, RegMRM, Xi32>, Sched<[rCL]>, PL;
123       def 64rCL_EVEX : BinOpRC_R<m, RegMRM, Xi64>, Sched<[rCL]>, PL;
124     }
126     def 8mCL  : BinOpMC_M<m, MemMRM, Xi8, node>, Sched<[mCL, WriteRMW]>;
127     def 16mCL : BinOpMC_M<m, MemMRM, Xi16, node>, Sched<[mCL, WriteRMW]>, OpSize16;
128     def 32mCL : BinOpMC_M<m, MemMRM, Xi32, node>, Sched<[mCL, WriteRMW]>, OpSize32;
129     def 64mCL : BinOpMC_M<m, MemMRM, Xi64, node>, Sched<[mCL, WriteRMW]>, Requires<[In64BitMode]>;
131     let Predicates = [HasNDD, In64BitMode] in {
132       def 8mCL_ND  : BinOpMC_R<m, MemMRM, Xi8, node>, Sched<[mCL, rCL]>;
133       def 16mCL_ND : BinOpMC_R<m, MemMRM, Xi16, node>, Sched<[mCL, rCL]>, PD;
134       def 32mCL_ND : BinOpMC_R<m, MemMRM, Xi32, node>, Sched<[mCL, rCL]>;
135       def 64mCL_ND : BinOpMC_R<m, MemMRM, Xi64, node>, Sched<[mCL, rCL]>;
136     }
138     let Predicates = [In64BitMode] in {
139       def 8mCL_EVEX  : BinOpMC_M<m, MemMRM, Xi8>, Sched<[mCL, WriteRMW]>, PL;
140       def 16mCL_EVEX : BinOpMC_M<m, MemMRM, Xi16>, Sched<[mCL, WriteRMW]>, PL, PD;
141       def 32mCL_EVEX : BinOpMC_M<m, MemMRM, Xi32>, Sched<[mCL, WriteRMW]>, PL;
142       def 64mCL_EVEX : BinOpMC_M<m, MemMRM, Xi64>, Sched<[mCL, WriteRMW]>, PL;
143     }
144   }
147 multiclass ShiftRotate_NF<string m, Format RegMRM, Format MemMRM, SchedReadWrite rCL,
148                           SchedReadWrite ri, SchedReadWrite mCL, SchedReadWrite mi> {
149   let Predicates = [In64BitMode] in {
150     let isConvertibleToThreeAddress = !if(!eq(m, "shl"), 1, 0) in {
151       def 8ri_NF  : BinOpRI8U_R<m, RegMRM, Xi8>, Sched<[ri]>, NF;
152       def 16ri_NF : BinOpRI8U_R<m, RegMRM, Xi16>, Sched<[ri]>, NF, PD;
153       def 32ri_NF : BinOpRI8U_R<m, RegMRM, Xi32>, Sched<[ri]>, NF;
154       def 64ri_NF : BinOpRI8U_R<m, RegMRM, Xi64>, Sched<[ri]>, NF;
156       def 8ri_NF_ND  : BinOpRI8U_R<m, RegMRM, Xi8, null_frag, 1>, Sched<[ri]>, EVEX_NF;
157       def 16ri_NF_ND : BinOpRI8U_R<m, RegMRM, Xi16, null_frag, 1>, Sched<[ri]>, EVEX_NF, PD;
158       def 32ri_NF_ND : BinOpRI8U_R<m, RegMRM, Xi32, null_frag, 1>, Sched<[ri]>, EVEX_NF;
159       def 64ri_NF_ND : BinOpRI8U_R<m, RegMRM, Xi64, null_frag, 1>, Sched<[ri]>, EVEX_NF;
160     }
162     def 8mi_NF  : BinOpMI8U_M<m, MemMRM, Xi8>, Sched<[mi, WriteRMW]>, NF;
163     def 16mi_NF : BinOpMI8U_M<m, MemMRM, Xi16>, Sched<[mi, WriteRMW]>, NF, PD;
164     def 32mi_NF : BinOpMI8U_M<m, MemMRM, Xi32>, Sched<[mi, WriteRMW]>, NF;
165     def 64mi_NF : BinOpMI8U_M<m, MemMRM, Xi64>, Sched<[mi, WriteRMW]>, NF;
167     def 8mi_NF_ND  : BinOpMI8U_R<m, MemMRM, Xi8>, Sched<[mi, ri]>, EVEX_NF;
168     def 16mi_NF_ND : BinOpMI8U_R<m, MemMRM, Xi16>, Sched<[mi, ri]>, EVEX_NF, PD;
169     def 32mi_NF_ND : BinOpMI8U_R<m, MemMRM, Xi32>, Sched<[mi, ri]>, EVEX_NF;
170     def 64mi_NF_ND : BinOpMI8U_R<m, MemMRM, Xi64>, Sched<[mi, ri]>, EVEX_NF;
172     let SchedRW = [ri] in {
173       // FIXME: Assembler can't tell whether it's 8r1_NF_ND or 8rCL_NF when the source register is cl, e.g.
174       //
175       //  {nf} shlb %cl, %al
176       //
177       // GNU binutils distinguish them by adding an explicit $1 to asm string of 8r1_NF_ND. But we haven't support
178       // constant immediate in asm string for X86 in TD. So we add DisassembleOnly for 8r1_NF_ND for the time being.
179       def 8r1_NF  : UnaryOpR_R<0xD1, RegMRM, m, Xi8>, NF;
180       def 16r1_NF : UnaryOpR_R<0xD1, RegMRM, m, Xi16>, NF, PD;
181       def 32r1_NF : UnaryOpR_R<0xD1, RegMRM, m, Xi32>, NF;
182       def 64r1_NF : UnaryOpR_R<0xD1, RegMRM, m, Xi64>, NF;
184       def 8r1_NF_ND  : UnaryOpR_R<0xD1, RegMRM, m, Xi8, null_frag, 1>, EVEX_NF, DisassembleOnly;
185       def 16r1_NF_ND : UnaryOpR_R<0xD1, RegMRM, m, Xi16, null_frag, 1>, EVEX_NF, PD;
186       def 32r1_NF_ND : UnaryOpR_R<0xD1, RegMRM, m, Xi32, null_frag, 1>, EVEX_NF;
187       def 64r1_NF_ND : UnaryOpR_R<0xD1, RegMRM, m, Xi64, null_frag, 1>, EVEX_NF;
188     }
190     let SchedRW = [mi, WriteRMW] in {
191       def 8m1_NF  : UnaryOpM_M<0xD1, MemMRM, m, Xi8>, NF;
192       def 16m1_NF : UnaryOpM_M<0xD1, MemMRM, m, Xi16>, NF, PD;
193       def 32m1_NF : UnaryOpM_M<0xD1, MemMRM, m, Xi32>, NF;
194       def 64m1_NF : UnaryOpM_M<0xD1, MemMRM, m, Xi64>, NF;
195     }
196     let SchedRW = [mi, ri] in {
197       def 8m1_NF_ND  : UnaryOpM_R<0xD1, MemMRM, m, Xi8>, EVEX_NF;
198       def 16m1_NF_ND : UnaryOpM_R<0xD1, MemMRM, m, Xi16>, EVEX_NF, PD;
199       def 32m1_NF_ND : UnaryOpM_R<0xD1, MemMRM, m, Xi32>, EVEX_NF;
200       def 64m1_NF_ND : UnaryOpM_R<0xD1, MemMRM, m, Xi64>, EVEX_NF;
201     }
203     let Uses = [CL] in {
204       def 8rCL_NF  : BinOpRC_R<m, RegMRM, Xi8>, Sched<[rCL]>, NF;
205       def 16rCL_NF : BinOpRC_R<m, RegMRM, Xi16>, Sched<[rCL]>, NF, PD;
206       def 32rCL_NF : BinOpRC_R<m, RegMRM, Xi32>, Sched<[rCL]>, NF;
207       def 64rCL_NF : BinOpRC_R<m, RegMRM, Xi64>, Sched<[rCL]>, NF;
209       def 8rCL_NF_ND  : BinOpRC_R<m, RegMRM, Xi8, null_frag, 1>, Sched<[rCL]>, EVEX_NF;
210       def 16rCL_NF_ND : BinOpRC_R<m, RegMRM, Xi16, null_frag, 1>, Sched<[rCL]>, EVEX_NF, PD;
211       def 32rCL_NF_ND : BinOpRC_R<m, RegMRM, Xi32, null_frag, 1>, Sched<[rCL]>, EVEX_NF;
212       def 64rCL_NF_ND : BinOpRC_R<m, RegMRM, Xi64, null_frag, 1>, Sched<[rCL]>, EVEX_NF;
214       def 8mCL_NF  : BinOpMC_M<m, MemMRM, Xi8>, Sched<[mCL, WriteRMW]>, NF;
215       def 16mCL_NF : BinOpMC_M<m, MemMRM, Xi16>, Sched<[mCL, WriteRMW]>, NF, PD;
216       def 32mCL_NF : BinOpMC_M<m, MemMRM, Xi32>, Sched<[mCL, WriteRMW]>, NF;
217       def 64mCL_NF : BinOpMC_M<m, MemMRM, Xi64>, Sched<[mCL, WriteRMW]>, NF;
219       def 8mCL_NF_ND  : BinOpMC_R<m, MemMRM, Xi8>, Sched<[mCL, rCL]>, EVEX_NF;
220       def 16mCL_NF_ND : BinOpMC_R<m, MemMRM, Xi16>, Sched<[mCL, rCL]>, EVEX_NF, PD;
221       def 32mCL_NF_ND : BinOpMC_R<m, MemMRM, Xi32>, Sched<[mCL, rCL]>, EVEX_NF;
222       def 64mCL_NF_ND : BinOpMC_R<m, MemMRM, Xi64>, Sched<[mCL, rCL]>, EVEX_NF;
223     }
224   }
226 defm SHL: ShiftRotate<"shl", MRM4r, MRM4m, shl, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
227 defm SHR: ShiftRotate<"shr", MRM5r, MRM5m, srl, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
228 defm SAR: ShiftRotate<"sar", MRM7r, MRM7m, sra, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
230 defm ROL: ShiftRotate<"rol", MRM0r, MRM0m, rotl, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd>;
231 defm ROR: ShiftRotate<"ror", MRM1r, MRM1m, rotr, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd>;
232 defm RCL: ShiftRotate<"rcl", MRM2r, MRM2m, null_frag, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd, [EFLAGS]>;
233 defm RCR: ShiftRotate<"rcr", MRM3r, MRM3m, null_frag, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd, [EFLAGS]>;
235 defm SHL: ShiftRotate_NF<"shl", MRM4r, MRM4m, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
236 defm SHR: ShiftRotate_NF<"shr", MRM5r, MRM5m, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
237 defm SAR: ShiftRotate_NF<"sar", MRM7r, MRM7m, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
239 defm ROL: ShiftRotate_NF<"rol", MRM0r, MRM0m, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd>;
240 defm ROR: ShiftRotate_NF<"ror", MRM1r, MRM1m, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd>;
242 // Use the opposite rotate if allows us to use the rotate by 1 instruction.
243 let Predicates = [NoNDD] in {
244   def : Pat<(rotl GR8:$src1,  (i8 7)),  (ROR8r1  GR8:$src1)>;
245   def : Pat<(rotl GR16:$src1, (i8 15)), (ROR16r1 GR16:$src1)>;
246   def : Pat<(rotl GR32:$src1, (i8 31)), (ROR32r1 GR32:$src1)>;
247   def : Pat<(rotl GR64:$src1, (i8 63)), (ROR64r1 GR64:$src1)>;
248   def : Pat<(rotr GR8:$src1,  (i8 7)),  (ROL8r1  GR8:$src1)>;
249   def : Pat<(rotr GR16:$src1, (i8 15)), (ROL16r1 GR16:$src1)>;
250   def : Pat<(rotr GR32:$src1, (i8 31)), (ROL32r1 GR32:$src1)>;
251   def : Pat<(rotr GR64:$src1, (i8 63)), (ROL64r1 GR64:$src1)>;
253 let Predicates = [HasNDD] in {
254   def : Pat<(rotl GR8:$src1,  (i8 7)),  (ROR8r1_ND  GR8:$src1)>;
255   def : Pat<(rotl GR16:$src1, (i8 15)), (ROR16r1_ND GR16:$src1)>;
256   def : Pat<(rotl GR32:$src1, (i8 31)), (ROR32r1_ND GR32:$src1)>;
257   def : Pat<(rotl GR64:$src1, (i8 63)), (ROR64r1_ND GR64:$src1)>;
258   def : Pat<(rotr GR8:$src1,  (i8 7)),  (ROL8r1_ND  GR8:$src1)>;
259   def : Pat<(rotr GR16:$src1, (i8 15)), (ROL16r1_ND GR16:$src1)>;
260   def : Pat<(rotr GR32:$src1, (i8 31)), (ROL32r1_ND GR32:$src1)>;
261   def : Pat<(rotr GR64:$src1, (i8 63)), (ROL64r1_ND GR64:$src1)>;
264 def : Pat<(store (rotl (loadi8 addr:$dst), (i8 7)), addr:$dst),
265           (ROR8m1 addr:$dst)>;
266 def : Pat<(store (rotl (loadi16 addr:$dst), (i8 15)), addr:$dst),
267           (ROR16m1 addr:$dst)>;
268 def : Pat<(store (rotl (loadi32 addr:$dst), (i8 31)), addr:$dst),
269           (ROR32m1 addr:$dst)>;
270 def : Pat<(store (rotl (loadi64 addr:$dst), (i8 63)), addr:$dst),
271           (ROR64m1 addr:$dst)>, Requires<[In64BitMode]>;
273 def : Pat<(store (rotr (loadi8 addr:$dst), (i8 7)), addr:$dst),
274           (ROL8m1 addr:$dst)>;
275 def : Pat<(store (rotr (loadi16 addr:$dst), (i8 15)), addr:$dst),
276           (ROL16m1 addr:$dst)>;
277 def : Pat<(store (rotr (loadi32 addr:$dst), (i8 31)), addr:$dst),
278           (ROL32m1 addr:$dst)>;
279 def : Pat<(store (rotr (loadi64 addr:$dst), (i8 63)), addr:$dst),
280           (ROL64m1 addr:$dst)>, Requires<[In64BitMode]>;
282 let Predicates = [HasNDD] in {
283 def : Pat<(rotl (loadi8 addr:$src), (i8 7)),
284           (ROR8m1_ND addr:$src)>;
285 def : Pat<(rotl (loadi16 addr:$src), (i8 15)),
286           (ROR16m1_ND addr:$src)>;
287 def : Pat<(rotl (loadi32 addr:$src), (i8 31)),
288           (ROR32m1_ND addr:$src)>;
289 def : Pat<(rotl (loadi64 addr:$src), (i8 63)),
290           (ROR64m1_ND addr:$src)>;
292 def : Pat<(rotr (loadi8 addr:$src), (i8 7)),
293           (ROL8m1_ND addr:$src)>;
294 def : Pat<(rotr (loadi16 addr:$src), (i8 15)),
295           (ROL16m1_ND addr:$src)>;
296 def : Pat<(rotr (loadi32 addr:$src), (i8 31)),
297           (ROL32m1_ND addr:$src)>;
298 def : Pat<(rotr (loadi64 addr:$src), (i8 63)),
299           (ROL64m1_ND addr:$src)>;
302 // Patterns for rotate with relocImm for the immediate field.
303 let Predicates = [NoNDD] in {
304   def : Pat<(rotl GR8:$src1, (i8 relocImm:$src2)),
305             (ROL8ri GR8:$src1, relocImm:$src2)>;
306   def : Pat<(rotl GR16:$src1, (i8 relocImm:$src2)),
307             (ROL16ri GR16:$src1, relocImm:$src2)>;
308   def : Pat<(rotl GR32:$src1, (i8 relocImm:$src2)),
309             (ROL32ri GR32:$src1, relocImm:$src2)>;
310   def : Pat<(rotl GR64:$src1, (i8 relocImm:$src2)),
311             (ROL64ri GR64:$src1, relocImm:$src2)>;
313   def : Pat<(rotr GR8:$src1, (i8 relocImm:$src2)),
314             (ROR8ri GR8:$src1, relocImm:$src2)>;
315   def : Pat<(rotr GR16:$src1, (i8 relocImm:$src2)),
316             (ROR16ri GR16:$src1, relocImm:$src2)>;
317   def : Pat<(rotr GR32:$src1, (i8 relocImm:$src2)),
318             (ROR32ri GR32:$src1, relocImm:$src2)>;
319   def : Pat<(rotr GR64:$src1, (i8 relocImm:$src2)),
320             (ROR64ri GR64:$src1, relocImm:$src2)>;
322 let Predicates = [HasNDD] in {
323   def : Pat<(rotl GR8:$src1, (i8 relocImm:$src2)),
324             (ROL8ri_ND GR8:$src1, relocImm:$src2)>;
325   def : Pat<(rotl GR16:$src1, (i8 relocImm:$src2)),
326             (ROL16ri_ND GR16:$src1, relocImm:$src2)>;
327   def : Pat<(rotl GR32:$src1, (i8 relocImm:$src2)),
328             (ROL32ri_ND GR32:$src1, relocImm:$src2)>;
329   def : Pat<(rotl GR64:$src1, (i8 relocImm:$src2)),
330             (ROL64ri_ND GR64:$src1, relocImm:$src2)>;
332   def : Pat<(rotr GR8:$src1, (i8 relocImm:$src2)),
333             (ROR8ri_ND GR8:$src1, relocImm:$src2)>;
334   def : Pat<(rotr GR16:$src1, (i8 relocImm:$src2)),
335             (ROR16ri_ND GR16:$src1, relocImm:$src2)>;
336   def : Pat<(rotr GR32:$src1, (i8 relocImm:$src2)),
337             (ROR32ri_ND GR32:$src1, relocImm:$src2)>;
338   def : Pat<(rotr GR64:$src1, (i8 relocImm:$src2)),
339             (ROR64ri_ND GR64:$src1, relocImm:$src2)>;
342 //===----------------------------------------------------------------------===//
343 // Double precision shift instructions (generalizations of rotate)
344 //===----------------------------------------------------------------------===//
346 class ShlrdOpRRI8U_R<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag, bit ndd = 0>
347   : ITy<o, MRMDestReg, t, (outs t.RegClass:$dst),
348         (ins t.RegClass:$src1, t.RegClass:$src2, u8imm:$src3), m, !if(!eq(ndd, 0), triop_args, triop_ndd_args),
349         []>, NDD<ndd> {
350   let isCommutable = 1;
351   let ImmT = Imm8;
352   let SchedRW = [WriteSHDrri];
353   let Pattern = !if(!eq(m, "shld"),
354                     [(set t.RegClass:$dst, (node t.RegClass:$src1, t.RegClass:$src2, (i8 imm:$src3)))],
355                     [(set t.RegClass:$dst, (node t.RegClass:$src2, t.RegClass:$src1, (i8 imm:$src3)))]);
358 class ShlrdOpRRC_R<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag, bit ndd = 0>
359   : BinOpRR<o, m, !if(!eq(ndd, 0), triop_cl_args, triop_cl_ndd_args), t, (outs t.RegClass:$dst), []>, NDD<ndd> {
360   let Uses = [CL];
361   let SchedRW = [WriteSHDrrcl];
362   let Pattern = !if(!eq(m, "shld"),
363                     [(set t.RegClass:$dst, (node t.RegClass:$src1, t.RegClass:$src2, CL))],
364                     [(set t.RegClass:$dst, (node t.RegClass:$src2, t.RegClass:$src1, CL))]);
367 class ShlrdOpMRI8U_M<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag>
368   : ITy<o, MRMDestMem, t, (outs), (ins t.MemOperand:$src1, t.RegClass:$src2, u8imm:$src3),
369         m, triop_args, []>, TB {
370   let ImmT = Imm8;
371   let SchedRW = [WriteSHDmri];
372   let mayLoad = 1;
373   let mayStore = 1;
374   let Pattern = !if(!eq(m, "shld"),
375                     [(store (node (t.LoadNode addr:$src1), t.RegClass:$src2, (i8 imm:$src3)), addr:$src1)],
376                     [(store (node t.RegClass:$src2, (t.LoadNode addr:$src1), (i8 imm:$src3)), addr:$src1)]);
379 class ShlrdOpMRC_M<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag>
380   : BinOpMR<o, m, triop_cl_args, t, (outs), []>, TB {
381   let Uses = [CL];
382   let SchedRW = [WriteSHDmrcl];
383   let mayStore = 1;
384   let Pattern = !if(!eq(m, "shld"),
385                     [(store (node (t.LoadNode addr:$src1), t.RegClass:$src2, CL), addr:$src1)],
386                     [(store (node t.RegClass:$src2, (t.LoadNode addr:$src1), CL), addr:$src1)]);
389 class ShlrdOpMRI8U_R<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag>
390   : ITy<o, MRMDestMem, t, (outs t.RegClass:$dst), (ins t.MemOperand:$src1, t.RegClass:$src2, u8imm:$src3),
391         m, triop_ndd_args, []>, NDD<1> {
392   let ImmT = Imm8;
393   let SchedRW = [WriteSHDmri];
394   let mayLoad = 1;
395   let Pattern = !if(!eq(m, "shld"),
396                     [(set t.RegClass:$dst, (node (t.LoadNode addr:$src1), t.RegClass:$src2, (i8 imm:$src3)))],
397                     [(set t.RegClass:$dst, (node t.RegClass:$src2, (t.LoadNode addr:$src1), (i8 imm:$src3)))]);
400 class ShlrdOpMRC_R<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag>
401   : BinOpMR<o, m, triop_cl_ndd_args, t, (outs t.RegClass:$dst), []>, NDD<1> {
402   let Uses = [CL];
403   let SchedRW = [WriteSHDmrcl];
404   let Pattern = !if(!eq(m, "shld"),
405                     [(set t.RegClass:$dst, (node (t.LoadNode addr:$src1), t.RegClass:$src2, CL))],
406                     [(set t.RegClass:$dst, (node t.RegClass:$src2, (t.LoadNode addr:$src1), CL))]);
409 multiclass Shlrd<bits<8> o1, bits<8> o2, bits<8> o3, string m, SDPatternOperator node, SDPatternOperator t_node> {
410   let Predicates = [NoNDD] in {
411     def 16rri8 : ShlrdOpRRI8U_R<o1, m, Xi16, t_node>, TB, DefEFLAGS, OpSize16;
412     def 32rri8 : ShlrdOpRRI8U_R<o1, m, Xi32, node>, TB, DefEFLAGS, OpSize32;
413     def 64rri8 : ShlrdOpRRI8U_R<o1, m, Xi64, node>, TB, DefEFLAGS;
415     def 16rrCL : ShlrdOpRRC_R<o2, m, Xi16, t_node>, TB, DefEFLAGS, OpSize16;
416     def 32rrCL : ShlrdOpRRC_R<o2, m, Xi32, node>, TB, DefEFLAGS, OpSize32;
417     def 64rrCL : ShlrdOpRRC_R<o2, m, Xi64, node>, TB, DefEFLAGS;
418   }
419   let Predicates = [HasNDD, In64BitMode] in {
420     def 16rri8_ND : ShlrdOpRRI8U_R<o3, m, Xi16, t_node, 1>, DefEFLAGS, PD;
421     def 32rri8_ND : ShlrdOpRRI8U_R<o3, m, Xi32, node, 1>, DefEFLAGS;
422     def 64rri8_ND : ShlrdOpRRI8U_R<o3, m, Xi64, node, 1>, DefEFLAGS;
424     def 16rrCL_ND : ShlrdOpRRC_R<o2, m, Xi16, t_node, 1>, DefEFLAGS, PD;
425     def 32rrCL_ND : ShlrdOpRRC_R<o2, m, Xi32, node, 1>, DefEFLAGS;
426     def 64rrCL_ND : ShlrdOpRRC_R<o2, m, Xi64, node, 1>, DefEFLAGS;
427   }
429   let Predicates = [In64BitMode] in {
430     def 16rri8_NF : ShlrdOpRRI8U_R<o3, m, Xi16>, NF, PD;
431     def 32rri8_NF : ShlrdOpRRI8U_R<o3, m, Xi32>, NF;
432     def 64rri8_NF : ShlrdOpRRI8U_R<o3, m, Xi64>, NF;
434     def 16rrCL_NF : ShlrdOpRRC_R<o2, m, Xi16>, NF, PD;
435     def 32rrCL_NF : ShlrdOpRRC_R<o2, m, Xi32>, NF;
436     def 64rrCL_NF : ShlrdOpRRC_R<o2, m, Xi64>, NF;
438     def 16rri8_NF_ND : ShlrdOpRRI8U_R<o3, m, Xi16, null_frag, 1>, EVEX_NF, PD;
439     def 32rri8_NF_ND : ShlrdOpRRI8U_R<o3, m, Xi32, null_frag, 1>, EVEX_NF;
440     def 64rri8_NF_ND : ShlrdOpRRI8U_R<o3, m, Xi64, null_frag, 1>, EVEX_NF;
442     def 16rrCL_NF_ND : ShlrdOpRRC_R<o2, m, Xi16, null_frag, 1>, EVEX_NF, PD;
443     def 32rrCL_NF_ND : ShlrdOpRRC_R<o2, m, Xi32, null_frag, 1>, EVEX_NF;
444     def 64rrCL_NF_ND : ShlrdOpRRC_R<o2, m, Xi64, null_frag, 1>, EVEX_NF;
446     def 16rri8_EVEX : ShlrdOpRRI8U_R<o3, m, Xi16>, DefEFLAGS, PL, PD;
447     def 32rri8_EVEX : ShlrdOpRRI8U_R<o3, m, Xi32>, DefEFLAGS, PL;
448     def 64rri8_EVEX : ShlrdOpRRI8U_R<o3, m, Xi64>, DefEFLAGS, PL;
450     def 16rrCL_EVEX : ShlrdOpRRC_R<o2, m, Xi16>, DefEFLAGS, PL, PD;
451     def 32rrCL_EVEX : ShlrdOpRRC_R<o2, m, Xi32>, DefEFLAGS, PL;
452     def 64rrCL_EVEX : ShlrdOpRRC_R<o2, m, Xi64>, DefEFLAGS, PL;
453   }
455   def 16mri8 : ShlrdOpMRI8U_M<o1, m, Xi16, t_node>, DefEFLAGS, OpSize16;
456   def 32mri8 : ShlrdOpMRI8U_M<o1, m, Xi32, node>, DefEFLAGS, OpSize32;
457   def 64mri8 : ShlrdOpMRI8U_M<o1, m, Xi64, node>, DefEFLAGS;
459   def 16mrCL : ShlrdOpMRC_M<o2, m, Xi16, t_node>, DefEFLAGS, OpSize16;
460   def 32mrCL : ShlrdOpMRC_M<o2, m, Xi32, node>, DefEFLAGS, OpSize32;
461   def 64mrCL : ShlrdOpMRC_M<o2, m, Xi64, node>, DefEFLAGS;
463   let Predicates = [HasNDD, In64BitMode] in {
464     def 16mri8_ND : ShlrdOpMRI8U_R<o3, m, Xi16, t_node>, DefEFLAGS, PD;
465     def 32mri8_ND : ShlrdOpMRI8U_R<o3, m, Xi32, node>, DefEFLAGS;
466     def 64mri8_ND : ShlrdOpMRI8U_R<o3, m, Xi64, node>, DefEFLAGS;
468     def 16mrCL_ND : ShlrdOpMRC_R<o2, m, Xi16, t_node>, DefEFLAGS, PD;
469     def 32mrCL_ND : ShlrdOpMRC_R<o2, m, Xi32, node>, DefEFLAGS;
470     def 64mrCL_ND : ShlrdOpMRC_R<o2, m, Xi64, node>, DefEFLAGS;
471   }
473   let Predicates = [In64BitMode] in {
474     def 16mri8_NF : ShlrdOpMRI8U_M<o3, m, Xi16>, NF, PD;
475     def 32mri8_NF : ShlrdOpMRI8U_M<o3, m, Xi32>, NF;
476     def 64mri8_NF : ShlrdOpMRI8U_M<o3, m, Xi64>, NF;
478     def 16mrCL_NF : ShlrdOpMRC_M<o2, m, Xi16>, NF, PD;
479     def 32mrCL_NF : ShlrdOpMRC_M<o2, m, Xi32>, NF;
480     def 64mrCL_NF : ShlrdOpMRC_M<o2, m, Xi64>, NF;
482     def 16mri8_NF_ND : ShlrdOpMRI8U_R<o3, m, Xi16>, EVEX_NF, PD;
483     def 32mri8_NF_ND : ShlrdOpMRI8U_R<o3, m, Xi32>, EVEX_NF;
484     def 64mri8_NF_ND : ShlrdOpMRI8U_R<o3, m, Xi64>, EVEX_NF;
486     def 16mrCL_NF_ND : ShlrdOpMRC_R<o2, m, Xi16>, EVEX_NF, PD;
487     def 32mrCL_NF_ND : ShlrdOpMRC_R<o2, m, Xi32>, EVEX_NF;
488     def 64mrCL_NF_ND : ShlrdOpMRC_R<o2, m, Xi64>, EVEX_NF;
490     def 16mri8_EVEX : ShlrdOpMRI8U_M<o3, m, Xi16>, DefEFLAGS, PL, PD;
491     def 32mri8_EVEX : ShlrdOpMRI8U_M<o3, m, Xi32>, DefEFLAGS, PL;
492     def 64mri8_EVEX : ShlrdOpMRI8U_M<o3, m, Xi64>, DefEFLAGS, PL;
494     def 16mrCL_EVEX : ShlrdOpMRC_M<o2, m, Xi16>, DefEFLAGS, PL, PD;
495     def 32mrCL_EVEX : ShlrdOpMRC_M<o2, m, Xi32>, DefEFLAGS, PL;
496     def 64mrCL_EVEX : ShlrdOpMRC_M<o2, m, Xi64>, DefEFLAGS, PL;
497   }
500 defm SHLD : Shlrd<0xA4, 0xA5, 0x24, "shld", fshl, X86fshl>;
501 defm SHRD : Shlrd<0xAC, 0xAD, 0x2C, "shrd", fshr, X86fshr>;
503 // Sandy Bridge and newer Intel processors support faster rotates using
504 // SHLD to avoid a partial flag update on the normal rotate instructions.
505 // Use a pseudo so that TwoInstructionPass and register allocation will see
506 // this as unary instruction.
507 let Predicates = [HasFastSHLDRotate], AddedComplexity = 5,
508     Defs = [EFLAGS], isPseudo = 1, SchedRW = [WriteSHDrri],
509     Constraints = "$src1 = $dst" in {
510   def SHLDROT32ri  : I<0, Pseudo, (outs GR32:$dst),
511                        (ins GR32:$src1, u8imm:$shamt), "",
512                      [(set GR32:$dst, (rotl GR32:$src1, (i8 imm:$shamt)))]>;
513   def SHLDROT64ri  : I<0, Pseudo, (outs GR64:$dst),
514                        (ins GR64:$src1, u8imm:$shamt), "",
515                      [(set GR64:$dst, (rotl GR64:$src1, (i8 imm:$shamt)))]>;
517   def SHRDROT32ri  : I<0, Pseudo, (outs GR32:$dst),
518                        (ins GR32:$src1, u8imm:$shamt), "",
519                      [(set GR32:$dst, (rotr GR32:$src1, (i8 imm:$shamt)))]>;
520   def SHRDROT64ri  : I<0, Pseudo, (outs GR64:$dst),
521                        (ins GR64:$src1, u8imm:$shamt), "",
522                      [(set GR64:$dst, (rotr GR64:$src1, (i8 imm:$shamt)))]>;
525 //===----------------------------------------------------------------------===//
526 // BMI Shift/Rotate instructions
527 //===----------------------------------------------------------------------===//
529 def ROT32L2R_imm8  : SDNodeXForm<imm, [{
530   // Convert a ROTL shamt to a ROTR shamt on 32-bit integer.
531   return getI8Imm(32 - N->getZExtValue(), SDLoc(N));
532 }]>;
534 def ROT64L2R_imm8  : SDNodeXForm<imm, [{
535   // Convert a ROTL shamt to a ROTR shamt on 64-bit integer.
536   return getI8Imm(64 - N->getZExtValue(), SDLoc(N));
537 }]>;
539 // NOTE: We use WriteShift for these rotates as they avoid the stalls
540 // of many of the older x86 rotate instructions.
541 class RorXri<X86TypeInfo t>
542   : ITy<0xF0, MRMSrcReg, t, (outs t.RegClass:$dst), (ins t.RegClass:$src1, u8imm:$src2),
543         "rorx", binop_ndd_args, []>, TA, XD, Sched<[WriteShift]> {
544   let ImmT = Imm8;
546 class RorXmi<X86TypeInfo t>
547   : ITy<0xF0, MRMSrcMem, t, (outs t.RegClass:$dst), (ins t.MemOperand:$src1, u8imm:$src2),
548         "rorx", binop_ndd_args, []>, TA, XD, Sched<[WriteShiftLd]> {
549   let ImmT = Imm8;
550   let mayLoad = 1;
553 multiclass RorX<X86TypeInfo t> {
554   let Predicates = [HasBMI2, NoEGPR] in {
555     def ri : RorXri<t>, VEX;
556     def mi : RorXmi<t>, VEX;
557   }
558   let Predicates = [HasBMI2, HasEGPR, In64BitMode] in {
559     def ri_EVEX : RorXri<t>, EVEX;
560     def mi_EVEX : RorXmi<t>, EVEX;
561   }
564 defm RORX32: RorX<Xi32>;
565 defm RORX64: RorX<Xi64>;
567 class ShiftXrr<string m, X86TypeInfo t>
568   : ITy<0xF7, MRMSrcReg4VOp3, t, (outs t.RegClass:$dst), (ins t.RegClass:$src1, t.RegClass:$src2),
569         m, binop_ndd_args, []>, T8, Sched<[WriteShift]>;
571 class ShiftXrm<string m, X86TypeInfo t>
572   : ITy<0xF7, MRMSrcMem4VOp3, t, (outs t.RegClass:$dst), (ins t.MemOperand:$src1, t.RegClass:$src2),
573         m, binop_ndd_args, []>, T8,
574     Sched<[WriteShift.Folded,
575            // x86memop:$src1
576            ReadDefault, ReadDefault, ReadDefault, ReadDefault,
577            ReadDefault,
578            // RC:$src2
579            WriteShift.ReadAfterFold]> {
580   let mayLoad = 1;
584 multiclass ShiftX<string m, X86TypeInfo t> {
585   let Predicates = [HasBMI2, NoEGPR] in {
586     def rr : ShiftXrr<m, t>, VEX;
587     def rm : ShiftXrm<m, t>, VEX;
588   }
589   let Predicates = [HasBMI2, HasEGPR, In64BitMode] in {
590     def rr_EVEX : ShiftXrr<m, t>, EVEX;
591     def rm_EVEX : ShiftXrm<m, t>, EVEX;
592   }
595 defm SARX32: ShiftX<"sarx", Xi32>, XS;
596 defm SARX64: ShiftX<"sarx", Xi64>, XS;
597 defm SHRX32: ShiftX<"shrx", Xi32>, XD;
598 defm SHRX64: ShiftX<"shrx", Xi64>, XD;
599 defm SHLX32: ShiftX<"shlx", Xi32>, PD;
600 defm SHLX64: ShiftX<"shlx", Xi64>, PD;
602 multiclass RORX_Pats<string suffix> {
603   // Prefer RORX which is non-destructive and doesn't update EFLAGS.
604   let AddedComplexity = 10 in {
605     def : Pat<(rotr GR32:$src, (i8 imm:$shamt)),
606               (!cast<Instruction>(RORX32ri#suffix) GR32:$src, imm:$shamt)>;
607     def : Pat<(rotr GR64:$src, (i8 imm:$shamt)),
608               (!cast<Instruction>(RORX64ri#suffix) GR64:$src, imm:$shamt)>;
610     def : Pat<(rotl GR32:$src, (i8 imm:$shamt)),
611               (!cast<Instruction>(RORX32ri#suffix) GR32:$src, (ROT32L2R_imm8 imm:$shamt))>;
612     def : Pat<(rotl GR64:$src, (i8 imm:$shamt)),
613               (!cast<Instruction>(RORX64ri#suffix) GR64:$src, (ROT64L2R_imm8 imm:$shamt))>;
614   }
616   def : Pat<(rotr (loadi32 addr:$src), (i8 imm:$shamt)),
617             (!cast<Instruction>(RORX32mi#suffix) addr:$src, imm:$shamt)>;
618   def : Pat<(rotr (loadi64 addr:$src), (i8 imm:$shamt)),
619             (!cast<Instruction>(RORX64mi#suffix) addr:$src, imm:$shamt)>;
621   def : Pat<(rotl (loadi32 addr:$src), (i8 imm:$shamt)),
622             (!cast<Instruction>(RORX32mi#suffix) addr:$src, (ROT32L2R_imm8 imm:$shamt))>;
623   def : Pat<(rotl (loadi64 addr:$src), (i8 imm:$shamt)),
624             (!cast<Instruction>(RORX64mi#suffix) addr:$src, (ROT64L2R_imm8 imm:$shamt))>;
627 multiclass ShiftX_Pats<SDNode op, string suffix = ""> {
628   // Prefer SARX/SHRX/SHLX over SAR/SHR/SHL with variable shift BUT not
629   // immediate shift, i.e. the following code is considered better
630   //
631   //  mov %edi, %esi
632   //  shl $imm, %esi
633   //  ... %edi, ...
634   //
635   // than
636   //
637   //  movb $imm, %sil
638   //  shlx %sil, %edi, %esi
639   //  ... %edi, ...
640   //
641   let AddedComplexity = 1 in {
642    def : Pat<(op GR32:$src1, GR8:$src2),
643               (!cast<Instruction>(NAME#"32rr"#suffix) GR32:$src1,
644                (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
645    def : Pat<(op GR64:$src1, GR8:$src2),
646               (!cast<Instruction>(NAME#"64rr"#suffix) GR64:$src1,
647                (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
648    def : Pat<(op GR32:$src1, (shiftMask32 GR8:$src2)),
649               (!cast<Instruction>(NAME#"32rr"#suffix) GR32:$src1,
650                (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
651    def : Pat<(op GR64:$src1, (shiftMask64 GR8:$src2)),
652               (!cast<Instruction>(NAME#"64rr"#suffix) GR64:$src1,
653                (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
654   }
655   // We prefer to use
656   //  mov (%ecx), %esi
657   //  shl $imm, $esi
658   //
659   // over
660   //
661   //  movb $imm, %al
662   //  shlx %al, (%ecx), %esi
663   //
664   // This priority is enforced by IsProfitableToFoldLoad.
665   def : Pat<(op (loadi32 addr:$src1), GR8:$src2),
666              (!cast<Instruction>(NAME#"32rm"#suffix) addr:$src1,
667               (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
668   def : Pat<(op (loadi64 addr:$src1), GR8:$src2),
669              (!cast<Instruction>(NAME#"64rm"#suffix) addr:$src1,
670               (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
671   def : Pat<(op (loadi32 addr:$src1), (shiftMask32 GR8:$src2)),
672              (!cast<Instruction>(NAME#"32rm"#suffix) addr:$src1,
673               (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
674   def : Pat<(op (loadi64 addr:$src1), (shiftMask64 GR8:$src2)),
675              (!cast<Instruction>(NAME#"64rm"#suffix) addr:$src1,
676               (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
679 let Predicates = [HasBMI2, NoEGPR] in {
680   defm : RORX_Pats<"">;
681   defm SARX : ShiftX_Pats<sra>;
682   defm SHRX : ShiftX_Pats<srl>;
683   defm SHLX : ShiftX_Pats<shl>;
686 let Predicates = [HasBMI2, HasEGPR] in {
687   defm : RORX_Pats<"_EVEX">;
688   defm SARX : ShiftX_Pats<sra, "_EVEX">;
689   defm SHRX : ShiftX_Pats<srl, "_EVEX">;
690   defm SHLX : ShiftX_Pats<shl, "_EVEX">;