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