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.
10//
11//===----------------------------------------------------------------------===//
12
13//===----------------------------------------------------------------------===//
14// Shift/Rotate instructions
15//===----------------------------------------------------------------------===//
16
17multiclass ShiftRotate<string m, Format RegMRM, Format MemMRM, SDPatternOperator node,
18                       SchedReadWrite rCL, SchedReadWrite ri, SchedReadWrite mCL,
19                       SchedReadWrite mi, list<Register> uses = []> {
20
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    }
42
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    }
59
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>;
65
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>;
77
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    }
84
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]>;
90
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  }
105
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    }
125
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]>;
130
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    }
137
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  }
145}
146
147multiclass 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;
155
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    }
161
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;
166
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;
171
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;
183
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    }
189
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    }
202
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;
208
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;
213
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;
218
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  }
225}
226defm SHL: ShiftRotate<"shl", MRM4r, MRM4m, shl, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
227defm SHR: ShiftRotate<"shr", MRM5r, MRM5m, srl, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
228defm SAR: ShiftRotate<"sar", MRM7r, MRM7m, sra, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
229
230defm ROL: ShiftRotate<"rol", MRM0r, MRM0m, rotl, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd>;
231defm ROR: ShiftRotate<"ror", MRM1r, MRM1m, rotr, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd>;
232defm RCL: ShiftRotate<"rcl", MRM2r, MRM2m, null_frag, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd, [EFLAGS]>;
233defm RCR: ShiftRotate<"rcr", MRM3r, MRM3m, null_frag, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd, [EFLAGS]>;
234
235defm SHL: ShiftRotate_NF<"shl", MRM4r, MRM4m, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
236defm SHR: ShiftRotate_NF<"shr", MRM5r, MRM5m, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
237defm SAR: ShiftRotate_NF<"sar", MRM7r, MRM7m, WriteShiftCL, WriteShift, WriteShiftCLLd, WriteShiftLd>;
238
239defm ROL: ShiftRotate_NF<"rol", MRM0r, MRM0m, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd>;
240defm ROR: ShiftRotate_NF<"ror", MRM1r, MRM1m, WriteRotateCL, WriteRotate, WriteRotateCLLd, WriteRotateLd>;
241
242// Use the opposite rotate if allows us to use the rotate by 1 instruction.
243let 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)>;
252}
253let 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)>;
262}
263
264def : Pat<(store (rotl (loadi8 addr:$dst), (i8 7)), addr:$dst),
265          (ROR8m1 addr:$dst)>;
266def : Pat<(store (rotl (loadi16 addr:$dst), (i8 15)), addr:$dst),
267          (ROR16m1 addr:$dst)>;
268def : Pat<(store (rotl (loadi32 addr:$dst), (i8 31)), addr:$dst),
269          (ROR32m1 addr:$dst)>;
270def : Pat<(store (rotl (loadi64 addr:$dst), (i8 63)), addr:$dst),
271          (ROR64m1 addr:$dst)>, Requires<[In64BitMode]>;
272
273def : Pat<(store (rotr (loadi8 addr:$dst), (i8 7)), addr:$dst),
274          (ROL8m1 addr:$dst)>;
275def : Pat<(store (rotr (loadi16 addr:$dst), (i8 15)), addr:$dst),
276          (ROL16m1 addr:$dst)>;
277def : Pat<(store (rotr (loadi32 addr:$dst), (i8 31)), addr:$dst),
278          (ROL32m1 addr:$dst)>;
279def : Pat<(store (rotr (loadi64 addr:$dst), (i8 63)), addr:$dst),
280          (ROL64m1 addr:$dst)>, Requires<[In64BitMode]>;
281
282let Predicates = [HasNDD] in {
283def : Pat<(rotl (loadi8 addr:$src), (i8 7)),
284          (ROR8m1_ND addr:$src)>;
285def : Pat<(rotl (loadi16 addr:$src), (i8 15)),
286          (ROR16m1_ND addr:$src)>;
287def : Pat<(rotl (loadi32 addr:$src), (i8 31)),
288          (ROR32m1_ND addr:$src)>;
289def : Pat<(rotl (loadi64 addr:$src), (i8 63)),
290          (ROR64m1_ND addr:$src)>;
291
292def : Pat<(rotr (loadi8 addr:$src), (i8 7)),
293          (ROL8m1_ND addr:$src)>;
294def : Pat<(rotr (loadi16 addr:$src), (i8 15)),
295          (ROL16m1_ND addr:$src)>;
296def : Pat<(rotr (loadi32 addr:$src), (i8 31)),
297          (ROL32m1_ND addr:$src)>;
298def : Pat<(rotr (loadi64 addr:$src), (i8 63)),
299          (ROL64m1_ND addr:$src)>;
300}
301
302// Patterns for rotate with relocImm for the immediate field.
303let 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)>;
312
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)>;
321}
322let 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)>;
331
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)>;
340}
341
342//===----------------------------------------------------------------------===//
343// Double precision shift instructions (generalizations of rotate)
344//===----------------------------------------------------------------------===//
345
346class 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)))]);
356}
357
358class 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))]);
365}
366
367class 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)]);
377}
378
379class 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)]);
387}
388
389class 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)))]);
398}
399
400class 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))]);
407}
408
409multiclass 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;
414
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;
423
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  }
428
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;
433
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;
437
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;
441
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;
445
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;
449
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  }
454
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;
458
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;
462
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;
467
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  }
472
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;
477
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;
481
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;
485
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;
489
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;
493
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  }
498}
499
500defm SHLD : Shlrd<0xA4, 0xA5, 0x24, "shld", fshl, X86fshl>;
501defm SHRD : Shlrd<0xAC, 0xAD, 0x2C, "shrd", fshr, X86fshr>;
502
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.
507let 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)))]>;
516
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)))]>;
523}
524
525//===----------------------------------------------------------------------===//
526// BMI Shift/Rotate instructions
527//===----------------------------------------------------------------------===//
528
529def 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}]>;
533
534def 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}]>;
538
539// NOTE: We use WriteShift for these rotates as they avoid the stalls
540// of many of the older x86 rotate instructions.
541class 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;
545}
546class 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;
551}
552
553multiclass 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  }
562}
563
564defm RORX32: RorX<Xi32>;
565defm RORX64: RorX<Xi64>;
566
567class 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]>;
570
571class 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;
581}
582
583
584multiclass 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  }
593}
594
595defm SARX32: ShiftX<"sarx", Xi32>, XS;
596defm SARX64: ShiftX<"sarx", Xi64>, XS;
597defm SHRX32: ShiftX<"shrx", Xi32>, XD;
598defm SHRX64: ShiftX<"shrx", Xi64>, XD;
599defm SHLX32: ShiftX<"shlx", Xi32>, PD;
600defm SHLX64: ShiftX<"shlx", Xi64>, PD;
601
602multiclass 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)>;
609
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  }
615
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)>;
620
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))>;
625}
626
627multiclass 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))>;
677}
678
679let 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>;
684}
685
686let 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">;
691}
692