1 //===- X86InstrCompiler.td - Compiler Pseudos and Patterns -*- tablegen -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file describes the various pseudo instructions used by the compiler,
10 // as well as Pat patterns used during instruction selection.
12 //===----------------------------------------------------------------------===//
14 //===----------------------------------------------------------------------===//
15 // Pattern Matching Support
17 def GetLo32XForm : SDNodeXForm<imm, [{
18 // Transformation function: get the low 32 bits.
19 return getI32Imm((uint32_t)N->getZExtValue(), SDLoc(N));
22 def GetLo8XForm : SDNodeXForm<imm, [{
23 // Transformation function: get the low 8 bits.
24 return getI8Imm((uint8_t)N->getZExtValue(), SDLoc(N));
28 //===----------------------------------------------------------------------===//
29 // Random Pseudo Instructions.
31 // PIC base construction. This expands to code that looks like this:
34 let hasSideEffects = 0, isNotDuplicable = 1, Uses = [ESP, SSP],
35 SchedRW = [WriteJump] in
36 def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins i32imm:$label),
39 // ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into
40 // a stack adjustment and the codegen must know that they may modify the stack
41 // pointer before prolog-epilog rewriting occurs.
42 // Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
43 // sub / add which can clobber EFLAGS.
44 let Defs = [ESP, EFLAGS, SSP], Uses = [ESP, SSP], SchedRW = [WriteALU] in {
45 def ADJCALLSTACKDOWN32 : I<0, Pseudo, (outs),
46 (ins i32imm:$amt1, i32imm:$amt2, i32imm:$amt3),
47 "#ADJCALLSTACKDOWN", []>, Requires<[NotLP64]>;
48 def ADJCALLSTACKUP32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
50 [(X86callseq_end timm:$amt1, timm:$amt2)]>,
53 def : Pat<(X86callseq_start timm:$amt1, timm:$amt2),
54 (ADJCALLSTACKDOWN32 i32imm:$amt1, i32imm:$amt2, 0)>, Requires<[NotLP64]>;
57 // ADJCALLSTACKDOWN/UP implicitly use/def RSP because they may be expanded into
58 // a stack adjustment and the codegen must know that they may modify the stack
59 // pointer before prolog-epilog rewriting occurs.
60 // Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
61 // sub / add which can clobber EFLAGS.
62 let Defs = [RSP, EFLAGS, SSP], Uses = [RSP, SSP], SchedRW = [WriteALU] in {
63 def ADJCALLSTACKDOWN64 : I<0, Pseudo, (outs),
64 (ins i32imm:$amt1, i32imm:$amt2, i32imm:$amt3),
65 "#ADJCALLSTACKDOWN", []>, Requires<[IsLP64]>;
66 def ADJCALLSTACKUP64 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
68 [(X86callseq_end timm:$amt1, timm:$amt2)]>,
71 def : Pat<(X86callseq_start timm:$amt1, timm:$amt2),
72 (ADJCALLSTACKDOWN64 i32imm:$amt1, i32imm:$amt2, 0)>, Requires<[IsLP64]>;
74 let SchedRW = [WriteSystem] in {
76 // x86-64 va_start lowering magic.
77 let usesCustomInserter = 1, Defs = [EFLAGS] in {
78 def VASTART_SAVE_XMM_REGS : I<0, Pseudo,
81 i64imm:$regsavefi, i64imm:$offset,
83 "#VASTART_SAVE_XMM_REGS $al, $regsavefi, $offset",
84 [(X86vastart_save_xmm_regs GR8:$al,
89 // The VAARG_64 pseudo-instruction takes the address of the va_list,
90 // and places the address of the next argument into a register.
91 let Defs = [EFLAGS] in
92 def VAARG_64 : I<0, Pseudo,
94 (ins i8mem:$ap, i32imm:$size, i8imm:$mode, i32imm:$align),
95 "#VAARG_64 $dst, $ap, $size, $mode, $align",
97 (X86vaarg64 addr:$ap, imm:$size, imm:$mode, imm:$align)),
101 // When using segmented stacks these are lowered into instructions which first
102 // check if the current stacklet has enough free memory. If it does, memory is
103 // allocated by bumping the stack pointer. Otherwise memory is allocated from
106 let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in
107 def SEG_ALLOCA_32 : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$size),
108 "# variable sized alloca for segmented stacks",
110 (X86SegAlloca GR32:$size))]>,
113 let Defs = [RAX, RSP, EFLAGS], Uses = [RSP] in
114 def SEG_ALLOCA_64 : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$size),
115 "# variable sized alloca for segmented stacks",
117 (X86SegAlloca GR64:$size))]>,
118 Requires<[In64BitMode]>;
121 // Dynamic stack allocation yields a _chkstk or _alloca call for all Windows
122 // targets. These calls are needed to probe the stack when allocating more than
123 // 4k bytes in one go. Touching the stack at 4K increments is necessary to
124 // ensure that the guard pages used by the OS virtual memory manager are
125 // allocated in correct sequence.
126 // The main point of having separate instruction are extra unmodelled effects
127 // (compared to ordinary calls) like stack pointer change.
129 let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in
130 def WIN_ALLOCA_32 : I<0, Pseudo, (outs), (ins GR32:$size),
131 "# dynamic stack allocation",
132 [(X86WinAlloca GR32:$size)]>,
135 let Defs = [RAX, RSP, EFLAGS], Uses = [RSP] in
136 def WIN_ALLOCA_64 : I<0, Pseudo, (outs), (ins GR64:$size),
137 "# dynamic stack allocation",
138 [(X86WinAlloca GR64:$size)]>,
139 Requires<[In64BitMode]>;
142 // These instructions XOR the frame pointer into a GPR. They are used in some
143 // stack protection schemes. These are post-RA pseudos because we only know the
144 // frame register after register allocation.
145 let Constraints = "$src = $dst", isMoveImm = 1, isPseudo = 1, Defs = [EFLAGS] in {
146 def XOR32_FP : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src),
147 "xorl\t$$FP, $src", []>,
148 Requires<[NotLP64]>, Sched<[WriteALU]>;
149 def XOR64_FP : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$src),
150 "xorq\t$$FP $src", []>,
151 Requires<[In64BitMode]>, Sched<[WriteALU]>;
154 //===----------------------------------------------------------------------===//
155 // EH Pseudo Instructions
157 let SchedRW = [WriteSystem] in {
158 let isTerminator = 1, isReturn = 1, isBarrier = 1,
159 hasCtrlDep = 1, isCodeGenOnly = 1 in {
160 def EH_RETURN : I<0xC3, RawFrm, (outs), (ins GR32:$addr),
161 "ret\t#eh_return, addr: $addr",
162 [(X86ehret GR32:$addr)]>, Sched<[WriteJumpLd]>;
166 let isTerminator = 1, isReturn = 1, isBarrier = 1,
167 hasCtrlDep = 1, isCodeGenOnly = 1 in {
168 def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr),
169 "ret\t#eh_return, addr: $addr",
170 [(X86ehret GR64:$addr)]>, Sched<[WriteJumpLd]>;
174 let isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1,
175 isCodeGenOnly = 1, isReturn = 1, isEHScopeReturn = 1 in {
176 def CLEANUPRET : I<0, Pseudo, (outs), (ins), "# CLEANUPRET", [(cleanupret)]>;
178 // CATCHRET needs a custom inserter for SEH.
179 let usesCustomInserter = 1 in
180 def CATCHRET : I<0, Pseudo, (outs), (ins brtarget32:$dst, brtarget32:$from),
182 [(catchret bb:$dst, bb:$from)]>;
185 let hasSideEffects = 1, hasCtrlDep = 1, isCodeGenOnly = 1,
186 usesCustomInserter = 1 in
187 def CATCHPAD : I<0, Pseudo, (outs), (ins), "# CATCHPAD", [(catchpad)]>;
189 // This instruction is responsible for re-establishing stack pointers after an
190 // exception has been caught and we are rejoining normal control flow in the
191 // parent function or funclet. It generally sets ESP and EBP, and optionally
192 // ESI. It is only needed for 32-bit WinEH, as the runtime restores CSRs for us
194 let hasSideEffects = 1, hasCtrlDep = 1, isCodeGenOnly = 1 in
195 def EH_RESTORE : I<0, Pseudo, (outs), (ins), "# EH_RESTORE", []>;
197 let hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1,
198 usesCustomInserter = 1 in {
199 def EH_SjLj_SetJmp32 : I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$buf),
201 [(set GR32:$dst, (X86eh_sjlj_setjmp addr:$buf))]>,
202 Requires<[Not64BitMode]>;
203 def EH_SjLj_SetJmp64 : I<0, Pseudo, (outs GR32:$dst), (ins i64mem:$buf),
205 [(set GR32:$dst, (X86eh_sjlj_setjmp addr:$buf))]>,
206 Requires<[In64BitMode]>;
207 let isTerminator = 1 in {
208 def EH_SjLj_LongJmp32 : I<0, Pseudo, (outs), (ins i32mem:$buf),
209 "#EH_SJLJ_LONGJMP32",
210 [(X86eh_sjlj_longjmp addr:$buf)]>,
211 Requires<[Not64BitMode]>;
212 def EH_SjLj_LongJmp64 : I<0, Pseudo, (outs), (ins i64mem:$buf),
213 "#EH_SJLJ_LONGJMP64",
214 [(X86eh_sjlj_longjmp addr:$buf)]>,
215 Requires<[In64BitMode]>;
219 let isBranch = 1, isTerminator = 1, isCodeGenOnly = 1 in {
220 def EH_SjLj_Setup : I<0, Pseudo, (outs), (ins brtarget:$dst),
221 "#EH_SjLj_Setup\t$dst", []>;
225 //===----------------------------------------------------------------------===//
226 // Pseudo instructions used by unwind info.
228 let isPseudo = 1, SchedRW = [WriteSystem] in {
229 def SEH_PushReg : I<0, Pseudo, (outs), (ins i32imm:$reg),
230 "#SEH_PushReg $reg", []>;
231 def SEH_SaveReg : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$dst),
232 "#SEH_SaveReg $reg, $dst", []>;
233 def SEH_SaveXMM : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$dst),
234 "#SEH_SaveXMM $reg, $dst", []>;
235 def SEH_StackAlloc : I<0, Pseudo, (outs), (ins i32imm:$size),
236 "#SEH_StackAlloc $size", []>;
237 def SEH_StackAlign : I<0, Pseudo, (outs), (ins i32imm:$align),
238 "#SEH_StackAlign $align", []>;
239 def SEH_SetFrame : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$offset),
240 "#SEH_SetFrame $reg, $offset", []>;
241 def SEH_PushFrame : I<0, Pseudo, (outs), (ins i1imm:$mode),
242 "#SEH_PushFrame $mode", []>;
243 def SEH_EndPrologue : I<0, Pseudo, (outs), (ins),
244 "#SEH_EndPrologue", []>;
245 def SEH_Epilogue : I<0, Pseudo, (outs), (ins),
246 "#SEH_Epilogue", []>;
249 //===----------------------------------------------------------------------===//
250 // Pseudo instructions used by segmented stacks.
253 // This is lowered into a RET instruction by MCInstLower. We need
254 // this so that we don't have to have a MachineBasicBlock which ends
255 // with a RET and also has successors.
256 let isPseudo = 1, SchedRW = [WriteJumpLd] in {
257 def MORESTACK_RET: I<0, Pseudo, (outs), (ins), "", []>;
259 // This instruction is lowered to a RET followed by a MOV. The two
260 // instructions are not generated on a higher level since then the
261 // verifier sees a MachineBasicBlock ending with a non-terminator.
262 def MORESTACK_RET_RESTORE_R10 : I<0, Pseudo, (outs), (ins), "", []>;
265 //===----------------------------------------------------------------------===//
266 // Alias Instructions
267 //===----------------------------------------------------------------------===//
269 // Alias instruction mapping movr0 to xor.
270 // FIXME: remove when we can teach regalloc that xor reg, reg is ok.
271 let Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1,
272 isPseudo = 1, isMoveImm = 1, AddedComplexity = 10 in
273 def MOV32r0 : I<0, Pseudo, (outs GR32:$dst), (ins), "",
274 [(set GR32:$dst, 0)]>, Sched<[WriteZero]>;
276 // Other widths can also make use of the 32-bit xor, which may have a smaller
277 // encoding and avoid partial register updates.
278 let AddedComplexity = 10 in {
279 def : Pat<(i8 0), (EXTRACT_SUBREG (MOV32r0), sub_8bit)>;
280 def : Pat<(i16 0), (EXTRACT_SUBREG (MOV32r0), sub_16bit)>;
281 def : Pat<(i64 0), (SUBREG_TO_REG (i64 0), (MOV32r0), sub_32bit)>;
284 let Predicates = [OptForSize, Not64BitMode],
285 AddedComplexity = 10 in {
286 let SchedRW = [WriteALU] in {
287 // Pseudo instructions for materializing 1 and -1 using XOR+INC/DEC,
288 // which only require 3 bytes compared to MOV32ri which requires 5.
289 let Defs = [EFLAGS], isReMaterializable = 1, isPseudo = 1 in {
290 def MOV32r1 : I<0, Pseudo, (outs GR32:$dst), (ins), "",
291 [(set GR32:$dst, 1)]>;
292 def MOV32r_1 : I<0, Pseudo, (outs GR32:$dst), (ins), "",
293 [(set GR32:$dst, -1)]>;
297 // MOV16ri is 4 bytes, so the instructions above are smaller.
298 def : Pat<(i16 1), (EXTRACT_SUBREG (MOV32r1), sub_16bit)>;
299 def : Pat<(i16 -1), (EXTRACT_SUBREG (MOV32r_1), sub_16bit)>;
302 let isReMaterializable = 1, isPseudo = 1, AddedComplexity = 5,
303 SchedRW = [WriteALU] in {
304 // AddedComplexity higher than MOV64ri but lower than MOV32r0 and MOV32r1.
305 def MOV32ImmSExti8 : I<0, Pseudo, (outs GR32:$dst), (ins i32i8imm:$src), "",
306 [(set GR32:$dst, i32immSExt8:$src)]>,
307 Requires<[OptForMinSize, NotWin64WithoutFP]>;
308 def MOV64ImmSExti8 : I<0, Pseudo, (outs GR64:$dst), (ins i64i8imm:$src), "",
309 [(set GR64:$dst, i64immSExt8:$src)]>,
310 Requires<[OptForMinSize, NotWin64WithoutFP]>;
313 // Materialize i64 constant where top 32-bits are zero. This could theoretically
314 // use MOV32ri with a SUBREG_TO_REG to represent the zero-extension, however
315 // that would make it more difficult to rematerialize.
316 let isReMaterializable = 1, isAsCheapAsAMove = 1,
317 isPseudo = 1, hasSideEffects = 0, SchedRW = [WriteMove] in
318 def MOV32ri64 : I<0, Pseudo, (outs GR64:$dst), (ins i64i32imm:$src), "", []>;
320 // This 64-bit pseudo-move can be used for both a 64-bit constant that is
321 // actually the zero-extension of a 32-bit constant and for labels in the
322 // x86-64 small code model.
323 def mov64imm32 : ComplexPattern<i64, 1, "selectMOV64Imm32", [imm, X86Wrapper]>;
325 def : Pat<(i64 mov64imm32:$src), (MOV32ri64 mov64imm32:$src)>;
327 // Use sbb to materialize carry bit.
328 let Uses = [EFLAGS], Defs = [EFLAGS], isPseudo = 1, SchedRW = [WriteALU] in {
329 // FIXME: These are pseudo ops that should be replaced with Pat<> patterns.
330 // However, Pat<> can't replicate the destination reg into the inputs of the
332 def SETB_C8r : I<0, Pseudo, (outs GR8:$dst), (ins), "",
333 [(set GR8:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>;
334 def SETB_C16r : I<0, Pseudo, (outs GR16:$dst), (ins), "",
335 [(set GR16:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>;
336 def SETB_C32r : I<0, Pseudo, (outs GR32:$dst), (ins), "",
337 [(set GR32:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>;
338 def SETB_C64r : I<0, Pseudo, (outs GR64:$dst), (ins), "",
339 [(set GR64:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>;
343 def : Pat<(i16 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))),
345 def : Pat<(i32 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))),
347 def : Pat<(i64 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))),
350 def : Pat<(i16 (sext (i8 (X86setcc_c X86_COND_B, EFLAGS)))),
352 def : Pat<(i32 (sext (i8 (X86setcc_c X86_COND_B, EFLAGS)))),
354 def : Pat<(i64 (sext (i8 (X86setcc_c X86_COND_B, EFLAGS)))),
357 // We canonicalize 'setb' to "(and (sbb reg,reg), 1)" on the hope that the and
358 // will be eliminated and that the sbb can be extended up to a wider type. When
359 // this happens, it is great. However, if we are left with an 8-bit sbb and an
360 // and, we might as well just match it as a setb.
361 def : Pat<(and (i8 (X86setcc_c X86_COND_B, EFLAGS)), 1),
364 // Patterns to give priority when both inputs are zero so that we don't use
365 // an immediate for the RHS.
366 // TODO: Should we use a 32-bit sbb for 8/16 to push the extract_subreg out?
367 def : Pat<(X86sbb_flag (i8 0), (i8 0), EFLAGS),
368 (SBB8rr (EXTRACT_SUBREG (MOV32r0), sub_8bit),
369 (EXTRACT_SUBREG (MOV32r0), sub_8bit))>;
370 def : Pat<(X86sbb_flag (i16 0), (i16 0), EFLAGS),
371 (SBB16rr (EXTRACT_SUBREG (MOV32r0), sub_16bit),
372 (EXTRACT_SUBREG (MOV32r0), sub_16bit))>;
373 def : Pat<(X86sbb_flag (i32 0), (i32 0), EFLAGS),
374 (SBB32rr (MOV32r0), (MOV32r0))>;
375 def : Pat<(X86sbb_flag (i64 0), (i64 0), EFLAGS),
376 (SBB64rr (SUBREG_TO_REG (i64 0), (MOV32r0), sub_32bit),
377 (SUBREG_TO_REG (i64 0), (MOV32r0), sub_32bit))>;
379 //===----------------------------------------------------------------------===//
380 // String Pseudo Instructions
382 let SchedRW = [WriteMicrocoded] in {
383 let Defs = [ECX,EDI,ESI], Uses = [ECX,EDI,ESI], isCodeGenOnly = 1 in {
384 def REP_MOVSB_32 : I<0xA4, RawFrm, (outs), (ins),
385 "{rep;movsb (%esi), %es:(%edi)|rep movsb es:[edi], [esi]}",
386 [(X86rep_movs i8)]>, REP, AdSize32,
388 def REP_MOVSW_32 : I<0xA5, RawFrm, (outs), (ins),
389 "{rep;movsw (%esi), %es:(%edi)|rep movsw es:[edi], [esi]}",
390 [(X86rep_movs i16)]>, REP, AdSize32, OpSize16,
392 def REP_MOVSD_32 : I<0xA5, RawFrm, (outs), (ins),
393 "{rep;movsl (%esi), %es:(%edi)|rep movsd es:[edi], [esi]}",
394 [(X86rep_movs i32)]>, REP, AdSize32, OpSize32,
396 def REP_MOVSQ_32 : RI<0xA5, RawFrm, (outs), (ins),
397 "{rep;movsq (%esi), %es:(%edi)|rep movsq es:[edi], [esi]}",
398 [(X86rep_movs i64)]>, REP, AdSize32,
399 Requires<[NotLP64, In64BitMode]>;
402 let Defs = [RCX,RDI,RSI], Uses = [RCX,RDI,RSI], isCodeGenOnly = 1 in {
403 def REP_MOVSB_64 : I<0xA4, RawFrm, (outs), (ins),
404 "{rep;movsb (%rsi), %es:(%rdi)|rep movsb es:[rdi], [rsi]}",
405 [(X86rep_movs i8)]>, REP, AdSize64,
407 def REP_MOVSW_64 : I<0xA5, RawFrm, (outs), (ins),
408 "{rep;movsw (%rsi), %es:(%rdi)|rep movsw es:[rdi], [rsi]}",
409 [(X86rep_movs i16)]>, REP, AdSize64, OpSize16,
411 def REP_MOVSD_64 : I<0xA5, RawFrm, (outs), (ins),
412 "{rep;movsl (%rsi), %es:(%rdi)|rep movsdi es:[rdi], [rsi]}",
413 [(X86rep_movs i32)]>, REP, AdSize64, OpSize32,
415 def REP_MOVSQ_64 : RI<0xA5, RawFrm, (outs), (ins),
416 "{rep;movsq (%rsi), %es:(%rdi)|rep movsq es:[rdi], [rsi]}",
417 [(X86rep_movs i64)]>, REP, AdSize64,
421 // FIXME: Should use "(X86rep_stos AL)" as the pattern.
422 let Defs = [ECX,EDI], isCodeGenOnly = 1 in {
423 let Uses = [AL,ECX,EDI] in
424 def REP_STOSB_32 : I<0xAA, RawFrm, (outs), (ins),
425 "{rep;stosb %al, %es:(%edi)|rep stosb es:[edi], al}",
426 [(X86rep_stos i8)]>, REP, AdSize32,
428 let Uses = [AX,ECX,EDI] in
429 def REP_STOSW_32 : I<0xAB, RawFrm, (outs), (ins),
430 "{rep;stosw %ax, %es:(%edi)|rep stosw es:[edi], ax}",
431 [(X86rep_stos i16)]>, REP, AdSize32, OpSize16,
433 let Uses = [EAX,ECX,EDI] in
434 def REP_STOSD_32 : I<0xAB, RawFrm, (outs), (ins),
435 "{rep;stosl %eax, %es:(%edi)|rep stosd es:[edi], eax}",
436 [(X86rep_stos i32)]>, REP, AdSize32, OpSize32,
438 let Uses = [RAX,RCX,RDI] in
439 def REP_STOSQ_32 : RI<0xAB, RawFrm, (outs), (ins),
440 "{rep;stosq %rax, %es:(%edi)|rep stosq es:[edi], rax}",
441 [(X86rep_stos i64)]>, REP, AdSize32,
442 Requires<[NotLP64, In64BitMode]>;
445 let Defs = [RCX,RDI], isCodeGenOnly = 1 in {
446 let Uses = [AL,RCX,RDI] in
447 def REP_STOSB_64 : I<0xAA, RawFrm, (outs), (ins),
448 "{rep;stosb %al, %es:(%rdi)|rep stosb es:[rdi], al}",
449 [(X86rep_stos i8)]>, REP, AdSize64,
451 let Uses = [AX,RCX,RDI] in
452 def REP_STOSW_64 : I<0xAB, RawFrm, (outs), (ins),
453 "{rep;stosw %ax, %es:(%rdi)|rep stosw es:[rdi], ax}",
454 [(X86rep_stos i16)]>, REP, AdSize64, OpSize16,
456 let Uses = [RAX,RCX,RDI] in
457 def REP_STOSD_64 : I<0xAB, RawFrm, (outs), (ins),
458 "{rep;stosl %eax, %es:(%rdi)|rep stosd es:[rdi], eax}",
459 [(X86rep_stos i32)]>, REP, AdSize64, OpSize32,
462 let Uses = [RAX,RCX,RDI] in
463 def REP_STOSQ_64 : RI<0xAB, RawFrm, (outs), (ins),
464 "{rep;stosq %rax, %es:(%rdi)|rep stosq es:[rdi], rax}",
465 [(X86rep_stos i64)]>, REP, AdSize64,
470 //===----------------------------------------------------------------------===//
471 // Thread Local Storage Instructions
473 let SchedRW = [WriteSystem] in {
476 // All calls clobber the non-callee saved registers. ESP is marked as
477 // a use to prevent stack-pointer assignments that appear immediately
478 // before calls from potentially appearing dead.
479 let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7,
480 ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7,
481 MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
482 XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
483 XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS, DF],
484 usesCustomInserter = 1, Uses = [ESP, SSP] in {
485 def TLS_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
487 [(X86tlsaddr tls32addr:$sym)]>,
488 Requires<[Not64BitMode]>;
489 def TLS_base_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
491 [(X86tlsbaseaddr tls32baseaddr:$sym)]>,
492 Requires<[Not64BitMode]>;
495 // All calls clobber the non-callee saved registers. RSP is marked as
496 // a use to prevent stack-pointer assignments that appear immediately
497 // before calls from potentially appearing dead.
498 let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11,
499 FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7,
500 ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7,
501 MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
502 XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
503 XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS, DF],
504 usesCustomInserter = 1, Uses = [RSP, SSP] in {
505 def TLS_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
507 [(X86tlsaddr tls64addr:$sym)]>,
508 Requires<[In64BitMode]>;
509 def TLS_base_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
511 [(X86tlsbaseaddr tls64baseaddr:$sym)]>,
512 Requires<[In64BitMode]>;
515 // Darwin TLS Support
516 // For i386, the address of the thunk is passed on the stack, on return the
517 // address of the variable is in %eax. %ecx is trashed during the function
518 // call. All other registers are preserved.
519 let Defs = [EAX, ECX, EFLAGS, DF],
521 usesCustomInserter = 1 in
522 def TLSCall_32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
524 [(X86TLSCall addr:$sym)]>,
525 Requires<[Not64BitMode]>;
527 // For x86_64, the address of the thunk is passed in %rdi, but the
528 // pseudo directly use the symbol, so do not add an implicit use of
529 // %rdi. The lowering will do the right thing with RDI.
530 // On return the address of the variable is in %rax. All other
531 // registers are preserved.
532 let Defs = [RAX, EFLAGS, DF],
534 usesCustomInserter = 1 in
535 def TLSCall_64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
537 [(X86TLSCall addr:$sym)]>,
538 Requires<[In64BitMode]>;
541 //===----------------------------------------------------------------------===//
542 // Conditional Move Pseudo Instructions
544 // CMOV* - Used to implement the SELECT DAG operation. Expanded after
545 // instruction selection into a branch sequence.
546 multiclass CMOVrr_PSEUDO<RegisterClass RC, ValueType VT> {
547 def CMOV#NAME : I<0, Pseudo,
548 (outs RC:$dst), (ins RC:$t, RC:$f, i8imm:$cond),
549 "#CMOV_"#NAME#" PSEUDO!",
550 [(set RC:$dst, (VT (X86cmov RC:$t, RC:$f, imm:$cond,
554 let usesCustomInserter = 1, hasNoSchedulingInfo = 1, Uses = [EFLAGS] in {
555 // X86 doesn't have 8-bit conditional moves. Use a customInserter to
556 // emit control flow. An alternative to this is to mark i8 SELECT as Promote,
557 // however that requires promoting the operands, and can induce additional
558 // i8 register pressure.
559 defm _GR8 : CMOVrr_PSEUDO<GR8, i8>;
561 let Predicates = [NoCMov] in {
562 defm _GR32 : CMOVrr_PSEUDO<GR32, i32>;
563 defm _GR16 : CMOVrr_PSEUDO<GR16, i16>;
564 } // Predicates = [NoCMov]
566 // fcmov doesn't handle all possible EFLAGS, provide a fallback if there is no
568 let Predicates = [FPStackf32] in
569 defm _RFP32 : CMOVrr_PSEUDO<RFP32, f32>;
571 let Predicates = [FPStackf64] in
572 defm _RFP64 : CMOVrr_PSEUDO<RFP64, f64>;
574 defm _RFP80 : CMOVrr_PSEUDO<RFP80, f80>;
576 defm _FR32 : CMOVrr_PSEUDO<FR32, f32>;
577 defm _FR64 : CMOVrr_PSEUDO<FR64, f64>;
578 let Predicates = [NoVLX] in {
579 defm _VR128 : CMOVrr_PSEUDO<VR128, v2i64>;
580 defm _VR256 : CMOVrr_PSEUDO<VR256, v4i64>;
582 let Predicates = [HasVLX] in {
583 defm _VR128X : CMOVrr_PSEUDO<VR128X, v2i64>;
584 defm _VR256X : CMOVrr_PSEUDO<VR256X, v4i64>;
586 defm _VR512 : CMOVrr_PSEUDO<VR512, v8i64>;
587 defm _VK2 : CMOVrr_PSEUDO<VK2, v2i1>;
588 defm _VK4 : CMOVrr_PSEUDO<VK4, v4i1>;
589 defm _VK8 : CMOVrr_PSEUDO<VK8, v8i1>;
590 defm _VK16 : CMOVrr_PSEUDO<VK16, v16i1>;
591 defm _VK32 : CMOVrr_PSEUDO<VK32, v32i1>;
592 defm _VK64 : CMOVrr_PSEUDO<VK64, v64i1>;
593 } // usesCustomInserter = 1, hasNoSchedulingInfo = 1, Uses = [EFLAGS]
595 def : Pat<(f128 (X86cmov VR128:$t, VR128:$f, imm:$cond, EFLAGS)),
596 (CMOV_VR128 VR128:$t, VR128:$f, imm:$cond)>;
598 let Predicates = [NoVLX] in {
599 def : Pat<(v16i8 (X86cmov VR128:$t, VR128:$f, imm:$cond, EFLAGS)),
600 (CMOV_VR128 VR128:$t, VR128:$f, imm:$cond)>;
601 def : Pat<(v8i16 (X86cmov VR128:$t, VR128:$f, imm:$cond, EFLAGS)),
602 (CMOV_VR128 VR128:$t, VR128:$f, imm:$cond)>;
603 def : Pat<(v4i32 (X86cmov VR128:$t, VR128:$f, imm:$cond, EFLAGS)),
604 (CMOV_VR128 VR128:$t, VR128:$f, imm:$cond)>;
605 def : Pat<(v4f32 (X86cmov VR128:$t, VR128:$f, imm:$cond, EFLAGS)),
606 (CMOV_VR128 VR128:$t, VR128:$f, imm:$cond)>;
607 def : Pat<(v2f64 (X86cmov VR128:$t, VR128:$f, imm:$cond, EFLAGS)),
608 (CMOV_VR128 VR128:$t, VR128:$f, imm:$cond)>;
610 def : Pat<(v32i8 (X86cmov VR256:$t, VR256:$f, imm:$cond, EFLAGS)),
611 (CMOV_VR256 VR256:$t, VR256:$f, imm:$cond)>;
612 def : Pat<(v16i16 (X86cmov VR256:$t, VR256:$f, imm:$cond, EFLAGS)),
613 (CMOV_VR256 VR256:$t, VR256:$f, imm:$cond)>;
614 def : Pat<(v8i32 (X86cmov VR256:$t, VR256:$f, imm:$cond, EFLAGS)),
615 (CMOV_VR256 VR256:$t, VR256:$f, imm:$cond)>;
616 def : Pat<(v8f32 (X86cmov VR256:$t, VR256:$f, imm:$cond, EFLAGS)),
617 (CMOV_VR256 VR256:$t, VR256:$f, imm:$cond)>;
618 def : Pat<(v4f64 (X86cmov VR256:$t, VR256:$f, imm:$cond, EFLAGS)),
619 (CMOV_VR256 VR256:$t, VR256:$f, imm:$cond)>;
621 let Predicates = [HasVLX] in {
622 def : Pat<(v16i8 (X86cmov VR128X:$t, VR128X:$f, imm:$cond, EFLAGS)),
623 (CMOV_VR128X VR128X:$t, VR128X:$f, imm:$cond)>;
624 def : Pat<(v8i16 (X86cmov VR128X:$t, VR128X:$f, imm:$cond, EFLAGS)),
625 (CMOV_VR128X VR128X:$t, VR128X:$f, imm:$cond)>;
626 def : Pat<(v4i32 (X86cmov VR128X:$t, VR128X:$f, imm:$cond, EFLAGS)),
627 (CMOV_VR128X VR128X:$t, VR128X:$f, imm:$cond)>;
628 def : Pat<(v4f32 (X86cmov VR128X:$t, VR128X:$f, imm:$cond, EFLAGS)),
629 (CMOV_VR128X VR128X:$t, VR128X:$f, imm:$cond)>;
630 def : Pat<(v2f64 (X86cmov VR128X:$t, VR128X:$f, imm:$cond, EFLAGS)),
631 (CMOV_VR128X VR128X:$t, VR128X:$f, imm:$cond)>;
633 def : Pat<(v32i8 (X86cmov VR256X:$t, VR256X:$f, imm:$cond, EFLAGS)),
634 (CMOV_VR256X VR256X:$t, VR256X:$f, imm:$cond)>;
635 def : Pat<(v16i16 (X86cmov VR256X:$t, VR256X:$f, imm:$cond, EFLAGS)),
636 (CMOV_VR256X VR256X:$t, VR256X:$f, imm:$cond)>;
637 def : Pat<(v8i32 (X86cmov VR256X:$t, VR256X:$f, imm:$cond, EFLAGS)),
638 (CMOV_VR256X VR256X:$t, VR256X:$f, imm:$cond)>;
639 def : Pat<(v8f32 (X86cmov VR256X:$t, VR256X:$f, imm:$cond, EFLAGS)),
640 (CMOV_VR256X VR256X:$t, VR256X:$f, imm:$cond)>;
641 def : Pat<(v4f64 (X86cmov VR256X:$t, VR256X:$f, imm:$cond, EFLAGS)),
642 (CMOV_VR256X VR256X:$t, VR256X:$f, imm:$cond)>;
645 def : Pat<(v64i8 (X86cmov VR512:$t, VR512:$f, imm:$cond, EFLAGS)),
646 (CMOV_VR512 VR512:$t, VR512:$f, imm:$cond)>;
647 def : Pat<(v32i16 (X86cmov VR512:$t, VR512:$f, imm:$cond, EFLAGS)),
648 (CMOV_VR512 VR512:$t, VR512:$f, imm:$cond)>;
649 def : Pat<(v16i32 (X86cmov VR512:$t, VR512:$f, imm:$cond, EFLAGS)),
650 (CMOV_VR512 VR512:$t, VR512:$f, imm:$cond)>;
651 def : Pat<(v16f32 (X86cmov VR512:$t, VR512:$f, imm:$cond, EFLAGS)),
652 (CMOV_VR512 VR512:$t, VR512:$f, imm:$cond)>;
653 def : Pat<(v8f64 (X86cmov VR512:$t, VR512:$f, imm:$cond, EFLAGS)),
654 (CMOV_VR512 VR512:$t, VR512:$f, imm:$cond)>;
656 //===----------------------------------------------------------------------===//
657 // Normal-Instructions-With-Lock-Prefix Pseudo Instructions
658 //===----------------------------------------------------------------------===//
660 // FIXME: Use normal instructions and add lock prefix dynamically.
664 let isCodeGenOnly = 1, Defs = [EFLAGS] in
665 def OR32mi8Locked : Ii8<0x83, MRM1m, (outs), (ins i32mem:$dst, i32i8imm:$zero),
666 "or{l}\t{$zero, $dst|$dst, $zero}", []>,
667 Requires<[Not64BitMode]>, OpSize32, LOCK,
668 Sched<[WriteALURMW]>;
670 let hasSideEffects = 1 in
671 def Int_MemBarrier : I<0, Pseudo, (outs), (ins),
673 [(X86MemBarrier)]>, Sched<[WriteLoad]>;
675 // RegOpc corresponds to the mr version of the instruction
676 // ImmOpc corresponds to the mi version of the instruction
677 // ImmOpc8 corresponds to the mi8 version of the instruction
678 // ImmMod corresponds to the instruction format of the mi and mi8 versions
679 multiclass LOCK_ArithBinOp<bits<8> RegOpc, bits<8> ImmOpc, bits<8> ImmOpc8,
680 Format ImmMod, SDNode Op, string mnemonic> {
681 let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1,
682 SchedRW = [WriteALURMW] in {
684 def NAME#8mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4},
685 RegOpc{3}, RegOpc{2}, RegOpc{1}, 0 },
686 MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src2),
687 !strconcat(mnemonic, "{b}\t",
688 "{$src2, $dst|$dst, $src2}"),
689 [(set EFLAGS, (Op addr:$dst, GR8:$src2))]>, LOCK;
691 def NAME#16mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4},
692 RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 },
693 MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2),
694 !strconcat(mnemonic, "{w}\t",
695 "{$src2, $dst|$dst, $src2}"),
696 [(set EFLAGS, (Op addr:$dst, GR16:$src2))]>,
699 def NAME#32mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4},
700 RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 },
701 MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2),
702 !strconcat(mnemonic, "{l}\t",
703 "{$src2, $dst|$dst, $src2}"),
704 [(set EFLAGS, (Op addr:$dst, GR32:$src2))]>,
707 def NAME#64mr : RI<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4},
708 RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 },
709 MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2),
710 !strconcat(mnemonic, "{q}\t",
711 "{$src2, $dst|$dst, $src2}"),
712 [(set EFLAGS, (Op addr:$dst, GR64:$src2))]>, LOCK;
714 def NAME#8mi : Ii8<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4},
715 ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 0 },
716 ImmMod, (outs), (ins i8mem :$dst, i8imm :$src2),
717 !strconcat(mnemonic, "{b}\t",
718 "{$src2, $dst|$dst, $src2}"),
719 [(set EFLAGS, (Op addr:$dst, (i8 imm:$src2)))]>, LOCK;
721 def NAME#16mi : Ii16<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4},
722 ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 },
723 ImmMod, (outs), (ins i16mem :$dst, i16imm :$src2),
724 !strconcat(mnemonic, "{w}\t",
725 "{$src2, $dst|$dst, $src2}"),
726 [(set EFLAGS, (Op addr:$dst, (i16 imm:$src2)))]>,
729 def NAME#32mi : Ii32<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4},
730 ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 },
731 ImmMod, (outs), (ins i32mem :$dst, i32imm :$src2),
732 !strconcat(mnemonic, "{l}\t",
733 "{$src2, $dst|$dst, $src2}"),
734 [(set EFLAGS, (Op addr:$dst, (i32 imm:$src2)))]>,
737 def NAME#64mi32 : RIi32S<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4},
738 ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 },
739 ImmMod, (outs), (ins i64mem :$dst, i64i32imm :$src2),
740 !strconcat(mnemonic, "{q}\t",
741 "{$src2, $dst|$dst, $src2}"),
742 [(set EFLAGS, (Op addr:$dst, i64immSExt32:$src2))]>,
745 def NAME#16mi8 : Ii8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4},
746 ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 },
747 ImmMod, (outs), (ins i16mem :$dst, i16i8imm :$src2),
748 !strconcat(mnemonic, "{w}\t",
749 "{$src2, $dst|$dst, $src2}"),
750 [(set EFLAGS, (Op addr:$dst, i16immSExt8:$src2))]>,
753 def NAME#32mi8 : Ii8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4},
754 ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 },
755 ImmMod, (outs), (ins i32mem :$dst, i32i8imm :$src2),
756 !strconcat(mnemonic, "{l}\t",
757 "{$src2, $dst|$dst, $src2}"),
758 [(set EFLAGS, (Op addr:$dst, i32immSExt8:$src2))]>,
761 def NAME#64mi8 : RIi8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4},
762 ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 },
763 ImmMod, (outs), (ins i64mem :$dst, i64i8imm :$src2),
764 !strconcat(mnemonic, "{q}\t",
765 "{$src2, $dst|$dst, $src2}"),
766 [(set EFLAGS, (Op addr:$dst, i64immSExt8:$src2))]>,
772 defm LOCK_ADD : LOCK_ArithBinOp<0x00, 0x80, 0x83, MRM0m, X86lock_add, "add">;
773 defm LOCK_SUB : LOCK_ArithBinOp<0x28, 0x80, 0x83, MRM5m, X86lock_sub, "sub">;
774 defm LOCK_OR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM1m, X86lock_or , "or">;
775 defm LOCK_AND : LOCK_ArithBinOp<0x20, 0x80, 0x83, MRM4m, X86lock_and, "and">;
776 defm LOCK_XOR : LOCK_ArithBinOp<0x30, 0x80, 0x83, MRM6m, X86lock_xor, "xor">;
778 def X86lock_add_nocf : PatFrag<(ops node:$lhs, node:$rhs),
779 (X86lock_add node:$lhs, node:$rhs), [{
780 return hasNoCarryFlagUses(SDValue(N, 0));
783 def X86lock_sub_nocf : PatFrag<(ops node:$lhs, node:$rhs),
784 (X86lock_sub node:$lhs, node:$rhs), [{
785 return hasNoCarryFlagUses(SDValue(N, 0));
788 let Predicates = [UseIncDec] in {
789 let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1,
790 SchedRW = [WriteALURMW] in {
791 def LOCK_INC8m : I<0xFE, MRM0m, (outs), (ins i8mem :$dst),
793 [(set EFLAGS, (X86lock_add_nocf addr:$dst, (i8 1)))]>,
795 def LOCK_INC16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst),
797 [(set EFLAGS, (X86lock_add_nocf addr:$dst, (i16 1)))]>,
799 def LOCK_INC32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst),
801 [(set EFLAGS, (X86lock_add_nocf addr:$dst, (i32 1)))]>,
803 def LOCK_INC64m : RI<0xFF, MRM0m, (outs), (ins i64mem:$dst),
805 [(set EFLAGS, (X86lock_add_nocf addr:$dst, (i64 1)))]>,
808 def LOCK_DEC8m : I<0xFE, MRM1m, (outs), (ins i8mem :$dst),
810 [(set EFLAGS, (X86lock_sub_nocf addr:$dst, (i8 1)))]>,
812 def LOCK_DEC16m : I<0xFF, MRM1m, (outs), (ins i16mem:$dst),
814 [(set EFLAGS, (X86lock_sub_nocf addr:$dst, (i16 1)))]>,
816 def LOCK_DEC32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst),
818 [(set EFLAGS, (X86lock_sub_nocf addr:$dst, (i32 1)))]>,
820 def LOCK_DEC64m : RI<0xFF, MRM1m, (outs), (ins i64mem:$dst),
822 [(set EFLAGS, (X86lock_sub_nocf addr:$dst, (i64 1)))]>,
826 // Additional patterns for -1 constant.
827 def : Pat<(X86lock_add addr:$dst, (i8 -1)), (LOCK_DEC8m addr:$dst)>;
828 def : Pat<(X86lock_add addr:$dst, (i16 -1)), (LOCK_DEC16m addr:$dst)>;
829 def : Pat<(X86lock_add addr:$dst, (i32 -1)), (LOCK_DEC32m addr:$dst)>;
830 def : Pat<(X86lock_add addr:$dst, (i64 -1)), (LOCK_DEC64m addr:$dst)>;
831 def : Pat<(X86lock_sub addr:$dst, (i8 -1)), (LOCK_INC8m addr:$dst)>;
832 def : Pat<(X86lock_sub addr:$dst, (i16 -1)), (LOCK_INC16m addr:$dst)>;
833 def : Pat<(X86lock_sub addr:$dst, (i32 -1)), (LOCK_INC32m addr:$dst)>;
834 def : Pat<(X86lock_sub addr:$dst, (i64 -1)), (LOCK_INC64m addr:$dst)>;
837 // Atomic compare and swap.
838 multiclass LCMPXCHG_UnOp<bits<8> Opc, Format Form, string mnemonic,
839 SDPatternOperator frag, X86MemOperand x86memop> {
840 let isCodeGenOnly = 1, usesCustomInserter = 1 in {
841 def NAME : I<Opc, Form, (outs), (ins x86memop:$ptr),
842 !strconcat(mnemonic, "\t$ptr"),
843 [(frag addr:$ptr)]>, TB, LOCK;
847 multiclass LCMPXCHG_BinOp<bits<8> Opc8, bits<8> Opc, Format Form,
848 string mnemonic, SDPatternOperator frag> {
849 let isCodeGenOnly = 1, SchedRW = [WriteCMPXCHGRMW] in {
850 let Defs = [AL, EFLAGS], Uses = [AL] in
851 def NAME#8 : I<Opc8, Form, (outs), (ins i8mem:$ptr, GR8:$swap),
852 !strconcat(mnemonic, "{b}\t{$swap, $ptr|$ptr, $swap}"),
853 [(frag addr:$ptr, GR8:$swap, 1)]>, TB, LOCK;
854 let Defs = [AX, EFLAGS], Uses = [AX] in
855 def NAME#16 : I<Opc, Form, (outs), (ins i16mem:$ptr, GR16:$swap),
856 !strconcat(mnemonic, "{w}\t{$swap, $ptr|$ptr, $swap}"),
857 [(frag addr:$ptr, GR16:$swap, 2)]>, TB, OpSize16, LOCK;
858 let Defs = [EAX, EFLAGS], Uses = [EAX] in
859 def NAME#32 : I<Opc, Form, (outs), (ins i32mem:$ptr, GR32:$swap),
860 !strconcat(mnemonic, "{l}\t{$swap, $ptr|$ptr, $swap}"),
861 [(frag addr:$ptr, GR32:$swap, 4)]>, TB, OpSize32, LOCK;
862 let Defs = [RAX, EFLAGS], Uses = [RAX] in
863 def NAME#64 : RI<Opc, Form, (outs), (ins i64mem:$ptr, GR64:$swap),
864 !strconcat(mnemonic, "{q}\t{$swap, $ptr|$ptr, $swap}"),
865 [(frag addr:$ptr, GR64:$swap, 8)]>, TB, LOCK;
869 let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EBX, ECX, EDX],
870 SchedRW = [WriteCMPXCHGRMW] in {
871 defm LCMPXCHG8B : LCMPXCHG_UnOp<0xC7, MRM1m, "cmpxchg8b", X86cas8, i64mem>;
874 // This pseudo must be used when the frame uses RBX as
875 // the base pointer. Indeed, in such situation RBX is a reserved
876 // register and the register allocator will ignore any use/def of
877 // it. In other words, the register will not fix the clobbering of
878 // RBX that will happen when setting the arguments for the instrucion.
880 // Unlike the actual related instuction, we mark that this one
881 // defines EBX (instead of using EBX).
882 // The rationale is that we will define RBX during the expansion of
883 // the pseudo. The argument feeding EBX is ebx_input.
885 // The additional argument, $ebx_save, is a temporary register used to
886 // save the value of RBX across the actual instruction.
888 // To make sure the register assigned to $ebx_save does not interfere with
889 // the definition of the actual instruction, we use a definition $dst which
890 // is tied to $rbx_save. That way, the live-range of $rbx_save spans across
891 // the instruction and we are sure we will have a valid register to restore
893 let Defs = [EAX, EDX, EBX, EFLAGS], Uses = [EAX, ECX, EDX],
894 SchedRW = [WriteCMPXCHGRMW], isCodeGenOnly = 1, isPseudo = 1,
895 Constraints = "$ebx_save = $dst", usesCustomInserter = 1 in {
896 def LCMPXCHG8B_SAVE_EBX :
897 I<0, Pseudo, (outs GR32:$dst),
898 (ins i64mem:$ptr, GR32:$ebx_input, GR32:$ebx_save),
899 !strconcat("cmpxchg8b", "\t$ptr"),
900 [(set GR32:$dst, (X86cas8save_ebx addr:$ptr, GR32:$ebx_input,
905 let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RBX, RCX, RDX],
906 Predicates = [HasCmpxchg16b], SchedRW = [WriteCMPXCHGRMW] in {
907 defm LCMPXCHG16B : LCMPXCHG_UnOp<0xC7, MRM1m, "cmpxchg16b",
908 X86cas16, i128mem>, REX_W;
911 // Same as LCMPXCHG8B_SAVE_RBX but for the 16 Bytes variant.
912 let Defs = [RAX, RDX, RBX, EFLAGS], Uses = [RAX, RCX, RDX],
913 Predicates = [HasCmpxchg16b], SchedRW = [WriteCMPXCHGRMW],
914 isCodeGenOnly = 1, isPseudo = 1, Constraints = "$rbx_save = $dst",
915 usesCustomInserter = 1 in {
916 def LCMPXCHG16B_SAVE_RBX :
917 I<0, Pseudo, (outs GR64:$dst),
918 (ins i128mem:$ptr, GR64:$rbx_input, GR64:$rbx_save),
919 !strconcat("cmpxchg16b", "\t$ptr"),
920 [(set GR64:$dst, (X86cas16save_rbx addr:$ptr, GR64:$rbx_input,
924 defm LCMPXCHG : LCMPXCHG_BinOp<0xB0, 0xB1, MRMDestMem, "cmpxchg", X86cas>;
926 // Atomic exchange and add
927 multiclass ATOMIC_LOAD_BINOP<bits<8> opc8, bits<8> opc, string mnemonic,
929 let Constraints = "$val = $dst", Defs = [EFLAGS], isCodeGenOnly = 1,
930 SchedRW = [WriteALURMW] in {
931 def NAME#8 : I<opc8, MRMSrcMem, (outs GR8:$dst),
932 (ins GR8:$val, i8mem:$ptr),
933 !strconcat(mnemonic, "{b}\t{$val, $ptr|$ptr, $val}"),
935 (!cast<PatFrag>(frag # "_8") addr:$ptr, GR8:$val))]>;
936 def NAME#16 : I<opc, MRMSrcMem, (outs GR16:$dst),
937 (ins GR16:$val, i16mem:$ptr),
938 !strconcat(mnemonic, "{w}\t{$val, $ptr|$ptr, $val}"),
941 (!cast<PatFrag>(frag # "_16") addr:$ptr, GR16:$val))]>,
943 def NAME#32 : I<opc, MRMSrcMem, (outs GR32:$dst),
944 (ins GR32:$val, i32mem:$ptr),
945 !strconcat(mnemonic, "{l}\t{$val, $ptr|$ptr, $val}"),
948 (!cast<PatFrag>(frag # "_32") addr:$ptr, GR32:$val))]>,
950 def NAME#64 : RI<opc, MRMSrcMem, (outs GR64:$dst),
951 (ins GR64:$val, i64mem:$ptr),
952 !strconcat(mnemonic, "{q}\t{$val, $ptr|$ptr, $val}"),
955 (!cast<PatFrag>(frag # "_64") addr:$ptr, GR64:$val))]>;
959 defm LXADD : ATOMIC_LOAD_BINOP<0xc0, 0xc1, "xadd", "atomic_load_add">, TB, LOCK;
961 /* The following multiclass tries to make sure that in code like
962 * x.store (immediate op x.load(acquire), release)
964 * x.store (register op x.load(acquire), release)
965 * an operation directly on memory is generated instead of wasting a register.
966 * It is not automatic as atomic_store/load are only lowered to MOV instructions
967 * extremely late to prevent them from being accidentally reordered in the backend
968 * (see below the RELEASE_MOV* / ACQUIRE_MOV* pseudo-instructions)
970 multiclass RELEASE_BINOP_MI<string Name, SDNode op> {
971 def : Pat<(atomic_store_8 addr:$dst,
972 (op (atomic_load_8 addr:$dst), (i8 imm:$src))),
973 (!cast<Instruction>(Name#"8mi") addr:$dst, imm:$src)>;
974 def : Pat<(atomic_store_16 addr:$dst,
975 (op (atomic_load_16 addr:$dst), (i16 imm:$src))),
976 (!cast<Instruction>(Name#"16mi") addr:$dst, imm:$src)>;
977 def : Pat<(atomic_store_32 addr:$dst,
978 (op (atomic_load_32 addr:$dst), (i32 imm:$src))),
979 (!cast<Instruction>(Name#"32mi") addr:$dst, imm:$src)>;
980 def : Pat<(atomic_store_64 addr:$dst,
981 (op (atomic_load_64 addr:$dst), (i64immSExt32:$src))),
982 (!cast<Instruction>(Name#"64mi32") addr:$dst, (i64immSExt32:$src))>;
984 def : Pat<(atomic_store_8 addr:$dst,
985 (op (atomic_load_8 addr:$dst), (i8 GR8:$src))),
986 (!cast<Instruction>(Name#"8mr") addr:$dst, GR8:$src)>;
987 def : Pat<(atomic_store_16 addr:$dst,
988 (op (atomic_load_16 addr:$dst), (i16 GR16:$src))),
989 (!cast<Instruction>(Name#"16mr") addr:$dst, GR16:$src)>;
990 def : Pat<(atomic_store_32 addr:$dst,
991 (op (atomic_load_32 addr:$dst), (i32 GR32:$src))),
992 (!cast<Instruction>(Name#"32mr") addr:$dst, GR32:$src)>;
993 def : Pat<(atomic_store_64 addr:$dst,
994 (op (atomic_load_64 addr:$dst), (i64 GR64:$src))),
995 (!cast<Instruction>(Name#"64mr") addr:$dst, GR64:$src)>;
997 defm : RELEASE_BINOP_MI<"ADD", add>;
998 defm : RELEASE_BINOP_MI<"AND", and>;
999 defm : RELEASE_BINOP_MI<"OR", or>;
1000 defm : RELEASE_BINOP_MI<"XOR", xor>;
1001 defm : RELEASE_BINOP_MI<"SUB", sub>;
1003 // Same as above, but for floating-point.
1004 // FIXME: imm version.
1005 // FIXME: Version that doesn't clobber $src, using AVX's VADDSS.
1006 // FIXME: This could also handle SIMD operations with *ps and *pd instructions.
1007 let usesCustomInserter = 1, SchedRW = [WriteMicrocoded] in {
1008 multiclass RELEASE_FP_BINOP_MI<SDNode op> {
1009 def NAME#32mr : I<0, Pseudo, (outs), (ins i32mem:$dst, FR32:$src),
1010 "#BINOP "#NAME#"32mr PSEUDO!",
1011 [(atomic_store_32 addr:$dst,
1012 (i32 (bitconvert (op
1013 (f32 (bitconvert (i32 (atomic_load_32 addr:$dst)))),
1014 FR32:$src))))]>, Requires<[HasSSE1]>;
1015 def NAME#64mr : I<0, Pseudo, (outs), (ins i64mem:$dst, FR64:$src),
1016 "#BINOP "#NAME#"64mr PSEUDO!",
1017 [(atomic_store_64 addr:$dst,
1018 (i64 (bitconvert (op
1019 (f64 (bitconvert (i64 (atomic_load_64 addr:$dst)))),
1020 FR64:$src))))]>, Requires<[HasSSE2]>;
1022 defm RELEASE_FADD : RELEASE_FP_BINOP_MI<fadd>;
1023 // FIXME: Add fsub, fmul, fdiv, ...
1026 multiclass RELEASE_UNOP<string Name, dag dag8, dag dag16, dag dag32,
1028 def : Pat<(atomic_store_8 addr:$dst, dag8),
1029 (!cast<Instruction>(Name#8m) addr:$dst)>;
1030 def : Pat<(atomic_store_16 addr:$dst, dag16),
1031 (!cast<Instruction>(Name#16m) addr:$dst)>;
1032 def : Pat<(atomic_store_32 addr:$dst, dag32),
1033 (!cast<Instruction>(Name#32m) addr:$dst)>;
1034 def : Pat<(atomic_store_64 addr:$dst, dag64),
1035 (!cast<Instruction>(Name#64m) addr:$dst)>;
1038 let Predicates = [UseIncDec] in {
1039 defm : RELEASE_UNOP<"INC",
1040 (add (atomic_load_8 addr:$dst), (i8 1)),
1041 (add (atomic_load_16 addr:$dst), (i16 1)),
1042 (add (atomic_load_32 addr:$dst), (i32 1)),
1043 (add (atomic_load_64 addr:$dst), (i64 1))>;
1044 defm : RELEASE_UNOP<"DEC",
1045 (add (atomic_load_8 addr:$dst), (i8 -1)),
1046 (add (atomic_load_16 addr:$dst), (i16 -1)),
1047 (add (atomic_load_32 addr:$dst), (i32 -1)),
1048 (add (atomic_load_64 addr:$dst), (i64 -1))>;
1051 defm : RELEASE_UNOP<"NEG",
1052 (ineg (i8 (atomic_load_8 addr:$dst))),
1053 (ineg (i16 (atomic_load_16 addr:$dst))),
1054 (ineg (i32 (atomic_load_32 addr:$dst))),
1055 (ineg (i64 (atomic_load_64 addr:$dst)))>;
1056 defm : RELEASE_UNOP<"NOT",
1057 (not (i8 (atomic_load_8 addr:$dst))),
1058 (not (i16 (atomic_load_16 addr:$dst))),
1059 (not (i32 (atomic_load_32 addr:$dst))),
1060 (not (i64 (atomic_load_64 addr:$dst)))>;
1062 def : Pat<(atomic_store_8 addr:$dst, (i8 imm:$src)),
1063 (MOV8mi addr:$dst, imm:$src)>;
1064 def : Pat<(atomic_store_16 addr:$dst, (i16 imm:$src)),
1065 (MOV16mi addr:$dst, imm:$src)>;
1066 def : Pat<(atomic_store_32 addr:$dst, (i32 imm:$src)),
1067 (MOV32mi addr:$dst, imm:$src)>;
1068 def : Pat<(atomic_store_64 addr:$dst, (i64immSExt32:$src)),
1069 (MOV64mi32 addr:$dst, i64immSExt32:$src)>;
1071 def : Pat<(atomic_store_8 addr:$dst, GR8:$src),
1072 (MOV8mr addr:$dst, GR8:$src)>;
1073 def : Pat<(atomic_store_16 addr:$dst, GR16:$src),
1074 (MOV16mr addr:$dst, GR16:$src)>;
1075 def : Pat<(atomic_store_32 addr:$dst, GR32:$src),
1076 (MOV32mr addr:$dst, GR32:$src)>;
1077 def : Pat<(atomic_store_64 addr:$dst, GR64:$src),
1078 (MOV64mr addr:$dst, GR64:$src)>;
1080 def : Pat<(i8 (atomic_load_8 addr:$src)), (MOV8rm addr:$src)>;
1081 def : Pat<(i16 (atomic_load_16 addr:$src)), (MOV16rm addr:$src)>;
1082 def : Pat<(i32 (atomic_load_32 addr:$src)), (MOV32rm addr:$src)>;
1083 def : Pat<(i64 (atomic_load_64 addr:$src)), (MOV64rm addr:$src)>;
1085 //===----------------------------------------------------------------------===//
1086 // DAG Pattern Matching Rules
1087 //===----------------------------------------------------------------------===//
1089 // Use AND/OR to store 0/-1 in memory when optimizing for minsize. This saves
1090 // binary size compared to a regular MOV, but it introduces an unnecessary
1091 // load, so is not suitable for regular or optsize functions.
1092 let Predicates = [OptForMinSize] in {
1093 def : Pat<(nonvolatile_store (i16 0), addr:$dst), (AND16mi8 addr:$dst, 0)>;
1094 def : Pat<(nonvolatile_store (i32 0), addr:$dst), (AND32mi8 addr:$dst, 0)>;
1095 def : Pat<(nonvolatile_store (i64 0), addr:$dst), (AND64mi8 addr:$dst, 0)>;
1096 def : Pat<(nonvolatile_store (i16 -1), addr:$dst), (OR16mi8 addr:$dst, -1)>;
1097 def : Pat<(nonvolatile_store (i32 -1), addr:$dst), (OR32mi8 addr:$dst, -1)>;
1098 def : Pat<(nonvolatile_store (i64 -1), addr:$dst), (OR64mi8 addr:$dst, -1)>;
1101 // In kernel code model, we can get the address of a label
1102 // into a register with 'movq'. FIXME: This is a hack, the 'imm' predicate of
1103 // the MOV64ri32 should accept these.
1104 def : Pat<(i64 (X86Wrapper tconstpool :$dst)),
1105 (MOV64ri32 tconstpool :$dst)>, Requires<[KernelCode]>;
1106 def : Pat<(i64 (X86Wrapper tjumptable :$dst)),
1107 (MOV64ri32 tjumptable :$dst)>, Requires<[KernelCode]>;
1108 def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)),
1109 (MOV64ri32 tglobaladdr :$dst)>, Requires<[KernelCode]>;
1110 def : Pat<(i64 (X86Wrapper texternalsym:$dst)),
1111 (MOV64ri32 texternalsym:$dst)>, Requires<[KernelCode]>;
1112 def : Pat<(i64 (X86Wrapper mcsym:$dst)),
1113 (MOV64ri32 mcsym:$dst)>, Requires<[KernelCode]>;
1114 def : Pat<(i64 (X86Wrapper tblockaddress:$dst)),
1115 (MOV64ri32 tblockaddress:$dst)>, Requires<[KernelCode]>;
1117 // If we have small model and -static mode, it is safe to store global addresses
1118 // directly as immediates. FIXME: This is really a hack, the 'imm' predicate
1119 // for MOV64mi32 should handle this sort of thing.
1120 def : Pat<(store (i64 (X86Wrapper tconstpool:$src)), addr:$dst),
1121 (MOV64mi32 addr:$dst, tconstpool:$src)>,
1122 Requires<[NearData, IsNotPIC]>;
1123 def : Pat<(store (i64 (X86Wrapper tjumptable:$src)), addr:$dst),
1124 (MOV64mi32 addr:$dst, tjumptable:$src)>,
1125 Requires<[NearData, IsNotPIC]>;
1126 def : Pat<(store (i64 (X86Wrapper tglobaladdr:$src)), addr:$dst),
1127 (MOV64mi32 addr:$dst, tglobaladdr:$src)>,
1128 Requires<[NearData, IsNotPIC]>;
1129 def : Pat<(store (i64 (X86Wrapper texternalsym:$src)), addr:$dst),
1130 (MOV64mi32 addr:$dst, texternalsym:$src)>,
1131 Requires<[NearData, IsNotPIC]>;
1132 def : Pat<(store (i64 (X86Wrapper mcsym:$src)), addr:$dst),
1133 (MOV64mi32 addr:$dst, mcsym:$src)>,
1134 Requires<[NearData, IsNotPIC]>;
1135 def : Pat<(store (i64 (X86Wrapper tblockaddress:$src)), addr:$dst),
1136 (MOV64mi32 addr:$dst, tblockaddress:$src)>,
1137 Requires<[NearData, IsNotPIC]>;
1139 def : Pat<(i32 (X86RecoverFrameAlloc mcsym:$dst)), (MOV32ri mcsym:$dst)>;
1140 def : Pat<(i64 (X86RecoverFrameAlloc mcsym:$dst)), (MOV64ri mcsym:$dst)>;
1144 // tls has some funny stuff here...
1145 // This corresponds to movabs $foo@tpoff, %rax
1146 def : Pat<(i64 (X86Wrapper tglobaltlsaddr :$dst)),
1147 (MOV64ri32 tglobaltlsaddr :$dst)>;
1148 // This corresponds to add $foo@tpoff, %rax
1149 def : Pat<(add GR64:$src1, (X86Wrapper tglobaltlsaddr :$dst)),
1150 (ADD64ri32 GR64:$src1, tglobaltlsaddr :$dst)>;
1153 // Direct PC relative function call for small code model. 32-bit displacement
1154 // sign extended to 64-bit.
1155 def : Pat<(X86call (i64 tglobaladdr:$dst)),
1156 (CALL64pcrel32 tglobaladdr:$dst)>;
1157 def : Pat<(X86call (i64 texternalsym:$dst)),
1158 (CALL64pcrel32 texternalsym:$dst)>;
1160 // Tailcall stuff. The TCRETURN instructions execute after the epilog, so they
1161 // can never use callee-saved registers. That is the purpose of the GR64_TC
1162 // register classes.
1164 // The only volatile register that is never used by the calling convention is
1165 // %r11. This happens when calling a vararg function with 6 arguments.
1167 // Match an X86tcret that uses less than 7 volatile registers.
1168 def X86tcret_6regs : PatFrag<(ops node:$ptr, node:$off),
1169 (X86tcret node:$ptr, node:$off), [{
1170 // X86tcret args: (*chain, ptr, imm, regs..., glue)
1171 unsigned NumRegs = 0;
1172 for (unsigned i = 3, e = N->getNumOperands(); i != e; ++i)
1173 if (isa<RegisterSDNode>(N->getOperand(i)) && ++NumRegs > 6)
1178 def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off),
1179 (TCRETURNri ptr_rc_tailcall:$dst, imm:$off)>,
1180 Requires<[Not64BitMode, NotUseRetpolineIndirectCalls]>;
1182 // FIXME: This is disabled for 32-bit PIC mode because the global base
1183 // register which is part of the address mode may be assigned a
1184 // callee-saved register.
1185 def : Pat<(X86tcret (load addr:$dst), imm:$off),
1186 (TCRETURNmi addr:$dst, imm:$off)>,
1187 Requires<[Not64BitMode, IsNotPIC, NotUseRetpolineIndirectCalls]>;
1189 def : Pat<(X86tcret (i32 tglobaladdr:$dst), imm:$off),
1190 (TCRETURNdi tglobaladdr:$dst, imm:$off)>,
1191 Requires<[NotLP64]>;
1193 def : Pat<(X86tcret (i32 texternalsym:$dst), imm:$off),
1194 (TCRETURNdi texternalsym:$dst, imm:$off)>,
1195 Requires<[NotLP64]>;
1197 def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off),
1198 (TCRETURNri64 ptr_rc_tailcall:$dst, imm:$off)>,
1199 Requires<[In64BitMode, NotUseRetpolineIndirectCalls]>;
1201 // Don't fold loads into X86tcret requiring more than 6 regs.
1202 // There wouldn't be enough scratch registers for base+index.
1203 def : Pat<(X86tcret_6regs (load addr:$dst), imm:$off),
1204 (TCRETURNmi64 addr:$dst, imm:$off)>,
1205 Requires<[In64BitMode, NotUseRetpolineIndirectCalls]>;
1207 def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off),
1208 (RETPOLINE_TCRETURN64 ptr_rc_tailcall:$dst, imm:$off)>,
1209 Requires<[In64BitMode, UseRetpolineIndirectCalls]>;
1211 def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off),
1212 (RETPOLINE_TCRETURN32 ptr_rc_tailcall:$dst, imm:$off)>,
1213 Requires<[Not64BitMode, UseRetpolineIndirectCalls]>;
1215 def : Pat<(X86tcret (i64 tglobaladdr:$dst), imm:$off),
1216 (TCRETURNdi64 tglobaladdr:$dst, imm:$off)>,
1219 def : Pat<(X86tcret (i64 texternalsym:$dst), imm:$off),
1220 (TCRETURNdi64 texternalsym:$dst, imm:$off)>,
1223 // Normal calls, with various flavors of addresses.
1224 def : Pat<(X86call (i32 tglobaladdr:$dst)),
1225 (CALLpcrel32 tglobaladdr:$dst)>;
1226 def : Pat<(X86call (i32 texternalsym:$dst)),
1227 (CALLpcrel32 texternalsym:$dst)>;
1228 def : Pat<(X86call (i32 imm:$dst)),
1229 (CALLpcrel32 imm:$dst)>, Requires<[CallImmAddr]>;
1233 // TEST R,R is smaller than CMP R,0
1234 def : Pat<(X86cmp GR8:$src1, 0),
1235 (TEST8rr GR8:$src1, GR8:$src1)>;
1236 def : Pat<(X86cmp GR16:$src1, 0),
1237 (TEST16rr GR16:$src1, GR16:$src1)>;
1238 def : Pat<(X86cmp GR32:$src1, 0),
1239 (TEST32rr GR32:$src1, GR32:$src1)>;
1240 def : Pat<(X86cmp GR64:$src1, 0),
1241 (TEST64rr GR64:$src1, GR64:$src1)>;
1243 // Conditional moves with folded loads with operands swapped and conditions
1245 multiclass CMOVmr<PatLeaf InvertedCond, Instruction Inst16, Instruction Inst32,
1246 Instruction Inst64> {
1247 let Predicates = [HasCMov] in {
1248 def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, InvertedCond, EFLAGS),
1249 (Inst16 GR16:$src2, addr:$src1)>;
1250 def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, InvertedCond, EFLAGS),
1251 (Inst32 GR32:$src2, addr:$src1)>;
1252 def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, InvertedCond, EFLAGS),
1253 (Inst64 GR64:$src2, addr:$src1)>;
1257 defm : CMOVmr<X86_COND_B , CMOVAE16rm, CMOVAE32rm, CMOVAE64rm>;
1258 defm : CMOVmr<X86_COND_AE, CMOVB16rm , CMOVB32rm , CMOVB64rm>;
1259 defm : CMOVmr<X86_COND_E , CMOVNE16rm, CMOVNE32rm, CMOVNE64rm>;
1260 defm : CMOVmr<X86_COND_NE, CMOVE16rm , CMOVE32rm , CMOVE64rm>;
1261 defm : CMOVmr<X86_COND_BE, CMOVA16rm , CMOVA32rm , CMOVA64rm>;
1262 defm : CMOVmr<X86_COND_A , CMOVBE16rm, CMOVBE32rm, CMOVBE64rm>;
1263 defm : CMOVmr<X86_COND_L , CMOVGE16rm, CMOVGE32rm, CMOVGE64rm>;
1264 defm : CMOVmr<X86_COND_GE, CMOVL16rm , CMOVL32rm , CMOVL64rm>;
1265 defm : CMOVmr<X86_COND_LE, CMOVG16rm , CMOVG32rm , CMOVG64rm>;
1266 defm : CMOVmr<X86_COND_G , CMOVLE16rm, CMOVLE32rm, CMOVLE64rm>;
1267 defm : CMOVmr<X86_COND_P , CMOVNP16rm, CMOVNP32rm, CMOVNP64rm>;
1268 defm : CMOVmr<X86_COND_NP, CMOVP16rm , CMOVP32rm , CMOVP64rm>;
1269 defm : CMOVmr<X86_COND_S , CMOVNS16rm, CMOVNS32rm, CMOVNS64rm>;
1270 defm : CMOVmr<X86_COND_NS, CMOVS16rm , CMOVS32rm , CMOVS64rm>;
1271 defm : CMOVmr<X86_COND_O , CMOVNO16rm, CMOVNO32rm, CMOVNO64rm>;
1272 defm : CMOVmr<X86_COND_NO, CMOVO16rm , CMOVO32rm , CMOVO64rm>;
1274 // zextload bool -> zextload byte
1275 // i1 stored in one byte in zero-extended form.
1276 // Upper bits cleanup should be executed before Store.
1277 def : Pat<(zextloadi8i1 addr:$src), (MOV8rm addr:$src)>;
1278 def : Pat<(zextloadi16i1 addr:$src),
1279 (EXTRACT_SUBREG (MOVZX32rm8 addr:$src), sub_16bit)>;
1280 def : Pat<(zextloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>;
1281 def : Pat<(zextloadi64i1 addr:$src),
1282 (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>;
1284 // extload bool -> extload byte
1285 // When extloading from 16-bit and smaller memory locations into 64-bit
1286 // registers, use zero-extending loads so that the entire 64-bit register is
1287 // defined, avoiding partial-register updates.
1289 def : Pat<(extloadi8i1 addr:$src), (MOV8rm addr:$src)>;
1290 def : Pat<(extloadi16i1 addr:$src),
1291 (EXTRACT_SUBREG (MOVZX32rm8 addr:$src), sub_16bit)>;
1292 def : Pat<(extloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>;
1293 def : Pat<(extloadi16i8 addr:$src),
1294 (EXTRACT_SUBREG (MOVZX32rm8 addr:$src), sub_16bit)>;
1295 def : Pat<(extloadi32i8 addr:$src), (MOVZX32rm8 addr:$src)>;
1296 def : Pat<(extloadi32i16 addr:$src), (MOVZX32rm16 addr:$src)>;
1298 // For other extloads, use subregs, since the high contents of the register are
1299 // defined after an extload.
1300 def : Pat<(extloadi64i1 addr:$src),
1301 (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>;
1302 def : Pat<(extloadi64i8 addr:$src),
1303 (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>;
1304 def : Pat<(extloadi64i16 addr:$src),
1305 (SUBREG_TO_REG (i64 0), (MOVZX32rm16 addr:$src), sub_32bit)>;
1306 def : Pat<(extloadi64i32 addr:$src),
1307 (SUBREG_TO_REG (i64 0), (MOV32rm addr:$src), sub_32bit)>;
1309 // anyext. Define these to do an explicit zero-extend to
1310 // avoid partial-register updates.
1311 def : Pat<(i16 (anyext GR8 :$src)), (EXTRACT_SUBREG
1312 (MOVZX32rr8 GR8 :$src), sub_16bit)>;
1313 def : Pat<(i32 (anyext GR8 :$src)), (MOVZX32rr8 GR8 :$src)>;
1315 // Except for i16 -> i32 since isel expect i16 ops to be promoted to i32.
1316 def : Pat<(i32 (anyext GR16:$src)),
1317 (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR16:$src, sub_16bit)>;
1319 def : Pat<(i64 (anyext GR8 :$src)),
1320 (SUBREG_TO_REG (i64 0), (MOVZX32rr8 GR8 :$src), sub_32bit)>;
1321 def : Pat<(i64 (anyext GR16:$src)),
1322 (SUBREG_TO_REG (i64 0), (MOVZX32rr16 GR16 :$src), sub_32bit)>;
1323 def : Pat<(i64 (anyext GR32:$src)),
1324 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src, sub_32bit)>;
1326 // If this is an anyext of the remainder of an 8-bit sdivrem, use a MOVSX
1327 // instead of a MOVZX. The sdivrem lowering will emit emit a MOVSX to move
1328 // %ah to the lower byte of a register. By using a MOVSX here we allow a
1329 // post-isel peephole to merge the two MOVSX instructions into one.
1330 def anyext_sdiv : PatFrag<(ops node:$lhs), (anyext node:$lhs),[{
1331 return (N->getOperand(0).getOpcode() == ISD::SDIVREM &&
1332 N->getOperand(0).getResNo() == 1);
1334 def : Pat<(i32 (anyext_sdiv GR8:$src)), (MOVSX32rr8 GR8:$src)>;
1336 // Any instruction that defines a 32-bit result leaves the high half of the
1337 // register. Truncate can be lowered to EXTRACT_SUBREG. CopyFromReg may
1338 // be copying from a truncate. Any other 32-bit operation will zero-extend
1339 // up to 64 bits. AssertSext/AssertZext aren't saying anything about the upper
1340 // 32 bits, they're probably just qualifying a CopyFromReg.
1341 def def32 : PatLeaf<(i32 GR32:$src), [{
1342 return N->getOpcode() != ISD::TRUNCATE &&
1343 N->getOpcode() != TargetOpcode::EXTRACT_SUBREG &&
1344 N->getOpcode() != ISD::CopyFromReg &&
1345 N->getOpcode() != ISD::AssertSext &&
1346 N->getOpcode() != ISD::AssertZext;
1349 // In the case of a 32-bit def that is known to implicitly zero-extend,
1350 // we can use a SUBREG_TO_REG.
1351 def : Pat<(i64 (zext def32:$src)),
1352 (SUBREG_TO_REG (i64 0), GR32:$src, sub_32bit)>;
1353 def : Pat<(i64 (and (anyext def32:$src), 0x00000000FFFFFFFF)),
1354 (SUBREG_TO_REG (i64 0), GR32:$src, sub_32bit)>;
1356 //===----------------------------------------------------------------------===//
1357 // Pattern match OR as ADD
1358 //===----------------------------------------------------------------------===//
1360 // If safe, we prefer to pattern match OR as ADD at isel time. ADD can be
1361 // 3-addressified into an LEA instruction to avoid copies. However, we also
1362 // want to finally emit these instructions as an or at the end of the code
1363 // generator to make the generated code easier to read. To do this, we select
1364 // into "disjoint bits" pseudo ops.
1366 // Treat an 'or' node is as an 'add' if the or'ed bits are known to be zero.
1367 def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
1368 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
1369 return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue());
1371 KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
1372 KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
1373 return (~Known0.Zero & ~Known1.Zero) == 0;
1377 // (or x1, x2) -> (add x1, x2) if two operands are known not to share bits.
1378 // Try this before the selecting to OR.
1379 let SchedRW = [WriteALU] in {
1381 let isConvertibleToThreeAddress = 1,
1382 Constraints = "$src1 = $dst", Defs = [EFLAGS] in {
1383 let isCommutable = 1 in {
1384 def ADD16rr_DB : I<0, Pseudo, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
1385 "", // orw/addw REG, REG
1386 [(set GR16:$dst, (or_is_add GR16:$src1, GR16:$src2))]>;
1387 def ADD32rr_DB : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
1388 "", // orl/addl REG, REG
1389 [(set GR32:$dst, (or_is_add GR32:$src1, GR32:$src2))]>;
1390 def ADD64rr_DB : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
1391 "", // orq/addq REG, REG
1392 [(set GR64:$dst, (or_is_add GR64:$src1, GR64:$src2))]>;
1395 // NOTE: These are order specific, we want the ri8 forms to be listed
1396 // first so that they are slightly preferred to the ri forms.
1398 def ADD16ri8_DB : I<0, Pseudo,
1399 (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2),
1400 "", // orw/addw REG, imm8
1401 [(set GR16:$dst,(or_is_add GR16:$src1,i16immSExt8:$src2))]>;
1402 def ADD16ri_DB : I<0, Pseudo, (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
1403 "", // orw/addw REG, imm
1404 [(set GR16:$dst, (or_is_add GR16:$src1, imm:$src2))]>;
1406 def ADD32ri8_DB : I<0, Pseudo,
1407 (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2),
1408 "", // orl/addl REG, imm8
1409 [(set GR32:$dst,(or_is_add GR32:$src1,i32immSExt8:$src2))]>;
1410 def ADD32ri_DB : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
1411 "", // orl/addl REG, imm
1412 [(set GR32:$dst, (or_is_add GR32:$src1, imm:$src2))]>;
1415 def ADD64ri8_DB : I<0, Pseudo,
1416 (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2),
1417 "", // orq/addq REG, imm8
1418 [(set GR64:$dst, (or_is_add GR64:$src1,
1419 i64immSExt8:$src2))]>;
1420 def ADD64ri32_DB : I<0, Pseudo,
1421 (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2),
1422 "", // orq/addq REG, imm
1423 [(set GR64:$dst, (or_is_add GR64:$src1,
1424 i64immSExt32:$src2))]>;
1426 } // AddedComplexity, SchedRW
1428 //===----------------------------------------------------------------------===//
1429 // Pattern match SUB as XOR
1430 //===----------------------------------------------------------------------===//
1432 // An immediate in the LHS of a subtract can't be encoded in the instruction.
1433 // If there is no possibility of a borrow we can use an XOR instead of a SUB
1434 // to enable the immediate to be folded.
1435 // TODO: Move this to a DAG combine?
1437 def sub_is_xor : PatFrag<(ops node:$lhs, node:$rhs), (sub node:$lhs, node:$rhs),[{
1438 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(0))) {
1439 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(1));
1441 // If all possible ones in the RHS are set in the LHS then there can't be
1442 // a borrow and we can use xor.
1443 return (~Known.Zero).isSubsetOf(CN->getAPIntValue());
1449 let AddedComplexity = 5 in {
1450 def : Pat<(sub_is_xor imm:$src2, GR8:$src1),
1451 (XOR8ri GR8:$src1, imm:$src2)>;
1452 def : Pat<(sub_is_xor i16immSExt8:$src2, GR16:$src1),
1453 (XOR16ri8 GR16:$src1, i16immSExt8:$src2)>;
1454 def : Pat<(sub_is_xor imm:$src2, GR16:$src1),
1455 (XOR16ri GR16:$src1, imm:$src2)>;
1456 def : Pat<(sub_is_xor i32immSExt8:$src2, GR32:$src1),
1457 (XOR32ri8 GR32:$src1, i32immSExt8:$src2)>;
1458 def : Pat<(sub_is_xor imm:$src2, GR32:$src1),
1459 (XOR32ri GR32:$src1, imm:$src2)>;
1460 def : Pat<(sub_is_xor i64immSExt8:$src2, GR64:$src1),
1461 (XOR64ri8 GR64:$src1, i64immSExt8:$src2)>;
1462 def : Pat<(sub_is_xor i64immSExt32:$src2, GR64:$src1),
1463 (XOR64ri32 GR64:$src1, i64immSExt32:$src2)>;
1466 //===----------------------------------------------------------------------===//
1468 //===----------------------------------------------------------------------===//
1470 // Odd encoding trick: -128 fits into an 8-bit immediate field while
1471 // +128 doesn't, so in this special case use a sub instead of an add.
1472 def : Pat<(add GR16:$src1, 128),
1473 (SUB16ri8 GR16:$src1, -128)>;
1474 def : Pat<(store (add (loadi16 addr:$dst), 128), addr:$dst),
1475 (SUB16mi8 addr:$dst, -128)>;
1477 def : Pat<(add GR32:$src1, 128),
1478 (SUB32ri8 GR32:$src1, -128)>;
1479 def : Pat<(store (add (loadi32 addr:$dst), 128), addr:$dst),
1480 (SUB32mi8 addr:$dst, -128)>;
1482 def : Pat<(add GR64:$src1, 128),
1483 (SUB64ri8 GR64:$src1, -128)>;
1484 def : Pat<(store (add (loadi64 addr:$dst), 128), addr:$dst),
1485 (SUB64mi8 addr:$dst, -128)>;
1487 // The same trick applies for 32-bit immediate fields in 64-bit
1489 def : Pat<(add GR64:$src1, 0x0000000080000000),
1490 (SUB64ri32 GR64:$src1, 0xffffffff80000000)>;
1491 def : Pat<(store (add (loadi64 addr:$dst), 0x0000000080000000), addr:$dst),
1492 (SUB64mi32 addr:$dst, 0xffffffff80000000)>;
1494 // To avoid needing to materialize an immediate in a register, use a 32-bit and
1495 // with implicit zero-extension instead of a 64-bit and if the immediate has at
1496 // least 32 bits of leading zeros. If in addition the last 32 bits can be
1497 // represented with a sign extension of a 8 bit constant, use that.
1498 // This can also reduce instruction size by eliminating the need for the REX
1501 // AddedComplexity is needed to give priority over i64immSExt8 and i64immSExt32.
1502 let AddedComplexity = 1 in {
1503 def : Pat<(and GR64:$src, i64immZExt32SExt8:$imm),
1507 (EXTRACT_SUBREG GR64:$src, sub_32bit),
1508 (i32 (GetLo8XForm imm:$imm))),
1511 def : Pat<(and GR64:$src, i64immZExt32:$imm),
1515 (EXTRACT_SUBREG GR64:$src, sub_32bit),
1516 (i32 (GetLo32XForm imm:$imm))),
1518 } // AddedComplexity = 1
1521 // AddedComplexity is needed due to the increased complexity on the
1522 // i64immZExt32SExt8 and i64immZExt32 patterns above. Applying this to all
1523 // the MOVZX patterns keeps thems together in DAGIsel tables.
1524 let AddedComplexity = 1 in {
1525 // r & (2^16-1) ==> movz
1526 def : Pat<(and GR32:$src1, 0xffff),
1527 (MOVZX32rr16 (EXTRACT_SUBREG GR32:$src1, sub_16bit))>;
1528 // r & (2^8-1) ==> movz
1529 def : Pat<(and GR32:$src1, 0xff),
1530 (MOVZX32rr8 (EXTRACT_SUBREG GR32:$src1, sub_8bit))>;
1531 // r & (2^8-1) ==> movz
1532 def : Pat<(and GR16:$src1, 0xff),
1533 (EXTRACT_SUBREG (MOVZX32rr8 (EXTRACT_SUBREG GR16:$src1, sub_8bit)),
1536 // r & (2^32-1) ==> movz
1537 def : Pat<(and GR64:$src, 0x00000000FFFFFFFF),
1538 (SUBREG_TO_REG (i64 0),
1539 (MOV32rr (EXTRACT_SUBREG GR64:$src, sub_32bit)),
1541 // r & (2^16-1) ==> movz
1542 def : Pat<(and GR64:$src, 0xffff),
1543 (SUBREG_TO_REG (i64 0),
1544 (MOVZX32rr16 (i16 (EXTRACT_SUBREG GR64:$src, sub_16bit))),
1546 // r & (2^8-1) ==> movz
1547 def : Pat<(and GR64:$src, 0xff),
1548 (SUBREG_TO_REG (i64 0),
1549 (MOVZX32rr8 (i8 (EXTRACT_SUBREG GR64:$src, sub_8bit))),
1551 } // AddedComplexity = 1
1554 // Try to use BTS/BTR/BTC for single bit operations on the upper 32-bits.
1556 def BTRXForm : SDNodeXForm<imm, [{
1557 // Transformation function: Find the lowest 0.
1558 return getI64Imm((uint8_t)N->getAPIntValue().countTrailingOnes(), SDLoc(N));
1561 def BTCBTSXForm : SDNodeXForm<imm, [{
1562 // Transformation function: Find the lowest 1.
1563 return getI64Imm((uint8_t)N->getAPIntValue().countTrailingZeros(), SDLoc(N));
1566 def BTRMask64 : ImmLeaf<i64, [{
1567 return !isUInt<32>(Imm) && !isInt<32>(Imm) && isPowerOf2_64(~Imm);
1570 def BTCBTSMask64 : ImmLeaf<i64, [{
1571 return !isInt<32>(Imm) && isPowerOf2_64(Imm);
1574 // For now only do this for optsize.
1575 let AddedComplexity = 1, Predicates=[OptForSize] in {
1576 def : Pat<(and GR64:$src1, BTRMask64:$mask),
1577 (BTR64ri8 GR64:$src1, (BTRXForm imm:$mask))>;
1578 def : Pat<(or GR64:$src1, BTCBTSMask64:$mask),
1579 (BTS64ri8 GR64:$src1, (BTCBTSXForm imm:$mask))>;
1580 def : Pat<(xor GR64:$src1, BTCBTSMask64:$mask),
1581 (BTC64ri8 GR64:$src1, (BTCBTSXForm imm:$mask))>;
1585 // sext_inreg patterns
1586 def : Pat<(sext_inreg GR32:$src, i16),
1587 (MOVSX32rr16 (EXTRACT_SUBREG GR32:$src, sub_16bit))>;
1588 def : Pat<(sext_inreg GR32:$src, i8),
1589 (MOVSX32rr8 (EXTRACT_SUBREG GR32:$src, sub_8bit))>;
1591 def : Pat<(sext_inreg GR16:$src, i8),
1592 (EXTRACT_SUBREG (MOVSX32rr8 (EXTRACT_SUBREG GR16:$src, sub_8bit)),
1595 def : Pat<(sext_inreg GR64:$src, i32),
1596 (MOVSX64rr32 (EXTRACT_SUBREG GR64:$src, sub_32bit))>;
1597 def : Pat<(sext_inreg GR64:$src, i16),
1598 (MOVSX64rr16 (EXTRACT_SUBREG GR64:$src, sub_16bit))>;
1599 def : Pat<(sext_inreg GR64:$src, i8),
1600 (MOVSX64rr8 (EXTRACT_SUBREG GR64:$src, sub_8bit))>;
1602 // sext, sext_load, zext, zext_load
1603 def: Pat<(i16 (sext GR8:$src)),
1604 (EXTRACT_SUBREG (MOVSX32rr8 GR8:$src), sub_16bit)>;
1605 def: Pat<(sextloadi16i8 addr:$src),
1606 (EXTRACT_SUBREG (MOVSX32rm8 addr:$src), sub_16bit)>;
1607 def: Pat<(i16 (zext GR8:$src)),
1608 (EXTRACT_SUBREG (MOVZX32rr8 GR8:$src), sub_16bit)>;
1609 def: Pat<(zextloadi16i8 addr:$src),
1610 (EXTRACT_SUBREG (MOVZX32rm8 addr:$src), sub_16bit)>;
1613 def : Pat<(i16 (trunc GR32:$src)),
1614 (EXTRACT_SUBREG GR32:$src, sub_16bit)>;
1615 def : Pat<(i8 (trunc GR32:$src)),
1616 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)),
1618 Requires<[Not64BitMode]>;
1619 def : Pat<(i8 (trunc GR16:$src)),
1620 (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)),
1622 Requires<[Not64BitMode]>;
1623 def : Pat<(i32 (trunc GR64:$src)),
1624 (EXTRACT_SUBREG GR64:$src, sub_32bit)>;
1625 def : Pat<(i16 (trunc GR64:$src)),
1626 (EXTRACT_SUBREG GR64:$src, sub_16bit)>;
1627 def : Pat<(i8 (trunc GR64:$src)),
1628 (EXTRACT_SUBREG GR64:$src, sub_8bit)>;
1629 def : Pat<(i8 (trunc GR32:$src)),
1630 (EXTRACT_SUBREG GR32:$src, sub_8bit)>,
1631 Requires<[In64BitMode]>;
1632 def : Pat<(i8 (trunc GR16:$src)),
1633 (EXTRACT_SUBREG GR16:$src, sub_8bit)>,
1634 Requires<[In64BitMode]>;
1636 def immff00_ffff : ImmLeaf<i32, [{
1637 return Imm >= 0xff00 && Imm <= 0xffff;
1640 // h-register tricks
1641 def : Pat<(i8 (trunc (srl_su GR16:$src, (i8 8)))),
1642 (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)>,
1643 Requires<[Not64BitMode]>;
1644 def : Pat<(i8 (trunc (srl_su (i32 (anyext GR16:$src)), (i8 8)))),
1645 (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)>,
1646 Requires<[Not64BitMode]>;
1647 def : Pat<(i8 (trunc (srl_su GR32:$src, (i8 8)))),
1648 (EXTRACT_SUBREG GR32:$src, sub_8bit_hi)>,
1649 Requires<[Not64BitMode]>;
1650 def : Pat<(srl GR16:$src, (i8 8)),
1652 (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)),
1654 def : Pat<(i32 (zext (srl_su GR16:$src, (i8 8)))),
1655 (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>;
1656 def : Pat<(i32 (anyext (srl_su GR16:$src, (i8 8)))),
1657 (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>;
1658 def : Pat<(and (srl_su GR32:$src, (i8 8)), (i32 255)),
1659 (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>;
1660 def : Pat<(srl (and_su GR32:$src, immff00_ffff), (i8 8)),
1661 (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>;
1663 // h-register tricks.
1664 // For now, be conservative on x86-64 and use an h-register extract only if the
1665 // value is immediately zero-extended or stored, which are somewhat common
1666 // cases. This uses a bunch of code to prevent a register requiring a REX prefix
1667 // from being allocated in the same instruction as the h register, as there's
1668 // currently no way to describe this requirement to the register allocator.
1670 // h-register extract and zero-extend.
1671 def : Pat<(and (srl_su GR64:$src, (i8 8)), (i64 255)),
1675 (EXTRACT_SUBREG GR64:$src, sub_8bit_hi)),
1677 def : Pat<(i64 (zext (srl_su GR16:$src, (i8 8)))),
1681 (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)),
1683 def : Pat<(i64 (anyext (srl_su GR16:$src, (i8 8)))),
1687 (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)),
1690 // h-register extract and store.
1691 def : Pat<(store (i8 (trunc_su (srl_su GR64:$src, (i8 8)))), addr:$dst),
1694 (EXTRACT_SUBREG GR64:$src, sub_8bit_hi))>;
1695 def : Pat<(store (i8 (trunc_su (srl_su GR32:$src, (i8 8)))), addr:$dst),
1698 (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>,
1699 Requires<[In64BitMode]>;
1700 def : Pat<(store (i8 (trunc_su (srl_su GR16:$src, (i8 8)))), addr:$dst),
1703 (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>,
1704 Requires<[In64BitMode]>;
1707 // (shl x, 1) ==> (add x, x)
1708 // Note that if x is undef (immediate or otherwise), we could theoretically
1709 // end up with the two uses of x getting different values, producing a result
1710 // where the least significant bit is not 0. However, the probability of this
1711 // happening is considered low enough that this is officially not a
1713 def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr GR8 :$src1, GR8 :$src1)>;
1714 def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>;
1715 def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>;
1716 def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>;
1718 // Helper imms to check if a mask doesn't change significant shift/rotate bits.
1719 def immShift8 : ImmLeaf<i8, [{
1720 return countTrailingOnes<uint64_t>(Imm) >= 3;
1722 def immShift16 : ImmLeaf<i8, [{
1723 return countTrailingOnes<uint64_t>(Imm) >= 4;
1725 def immShift32 : ImmLeaf<i8, [{
1726 return countTrailingOnes<uint64_t>(Imm) >= 5;
1728 def immShift64 : ImmLeaf<i8, [{
1729 return countTrailingOnes<uint64_t>(Imm) >= 6;
1732 // Shift amount is implicitly masked.
1733 multiclass MaskedShiftAmountPats<SDNode frag, string name> {
1734 // (shift x (and y, 31)) ==> (shift x, y)
1735 def : Pat<(frag GR8:$src1, (and CL, immShift32)),
1736 (!cast<Instruction>(name # "8rCL") GR8:$src1)>;
1737 def : Pat<(frag GR16:$src1, (and CL, immShift32)),
1738 (!cast<Instruction>(name # "16rCL") GR16:$src1)>;
1739 def : Pat<(frag GR32:$src1, (and CL, immShift32)),
1740 (!cast<Instruction>(name # "32rCL") GR32:$src1)>;
1741 def : Pat<(store (frag (loadi8 addr:$dst), (and CL, immShift32)), addr:$dst),
1742 (!cast<Instruction>(name # "8mCL") addr:$dst)>;
1743 def : Pat<(store (frag (loadi16 addr:$dst), (and CL, immShift32)), addr:$dst),
1744 (!cast<Instruction>(name # "16mCL") addr:$dst)>;
1745 def : Pat<(store (frag (loadi32 addr:$dst), (and CL, immShift32)), addr:$dst),
1746 (!cast<Instruction>(name # "32mCL") addr:$dst)>;
1748 // (shift x (and y, 63)) ==> (shift x, y)
1749 def : Pat<(frag GR64:$src1, (and CL, immShift64)),
1750 (!cast<Instruction>(name # "64rCL") GR64:$src1)>;
1751 def : Pat<(store (frag (loadi64 addr:$dst), (and CL, immShift64)), addr:$dst),
1752 (!cast<Instruction>(name # "64mCL") addr:$dst)>;
1755 defm : MaskedShiftAmountPats<shl, "SHL">;
1756 defm : MaskedShiftAmountPats<srl, "SHR">;
1757 defm : MaskedShiftAmountPats<sra, "SAR">;
1759 // ROL/ROR instructions allow a stronger mask optimization than shift for 8- and
1760 // 16-bit. We can remove a mask of any (bitwidth - 1) on the rotation amount
1761 // because over-rotating produces the same result. This is noted in the Intel
1762 // docs with: "tempCOUNT <- (COUNT & COUNTMASK) MOD SIZE". Masking the rotation
1763 // amount could affect EFLAGS results, but that does not matter because we are
1764 // not tracking flags for these nodes.
1765 multiclass MaskedRotateAmountPats<SDNode frag, string name> {
1766 // (rot x (and y, BitWidth - 1)) ==> (rot x, y)
1767 def : Pat<(frag GR8:$src1, (and CL, immShift8)),
1768 (!cast<Instruction>(name # "8rCL") GR8:$src1)>;
1769 def : Pat<(frag GR16:$src1, (and CL, immShift16)),
1770 (!cast<Instruction>(name # "16rCL") GR16:$src1)>;
1771 def : Pat<(frag GR32:$src1, (and CL, immShift32)),
1772 (!cast<Instruction>(name # "32rCL") GR32:$src1)>;
1773 def : Pat<(store (frag (loadi8 addr:$dst), (and CL, immShift8)), addr:$dst),
1774 (!cast<Instruction>(name # "8mCL") addr:$dst)>;
1775 def : Pat<(store (frag (loadi16 addr:$dst), (and CL, immShift16)), addr:$dst),
1776 (!cast<Instruction>(name # "16mCL") addr:$dst)>;
1777 def : Pat<(store (frag (loadi32 addr:$dst), (and CL, immShift32)), addr:$dst),
1778 (!cast<Instruction>(name # "32mCL") addr:$dst)>;
1780 // (rot x (and y, 63)) ==> (rot x, y)
1781 def : Pat<(frag GR64:$src1, (and CL, immShift64)),
1782 (!cast<Instruction>(name # "64rCL") GR64:$src1)>;
1783 def : Pat<(store (frag (loadi64 addr:$dst), (and CL, immShift64)), addr:$dst),
1784 (!cast<Instruction>(name # "64mCL") addr:$dst)>;
1788 defm : MaskedRotateAmountPats<rotl, "ROL">;
1789 defm : MaskedRotateAmountPats<rotr, "ROR">;
1791 // Double shift amount is implicitly masked.
1792 multiclass MaskedDoubleShiftAmountPats<SDNode frag, string name> {
1793 // (shift x (and y, 31)) ==> (shift x, y)
1794 def : Pat<(frag GR16:$src1, GR16:$src2, (and CL, immShift32)),
1795 (!cast<Instruction>(name # "16rrCL") GR16:$src1, GR16:$src2)>;
1796 def : Pat<(frag GR32:$src1, GR32:$src2, (and CL, immShift32)),
1797 (!cast<Instruction>(name # "32rrCL") GR32:$src1, GR32:$src2)>;
1799 // (shift x (and y, 63)) ==> (shift x, y)
1800 def : Pat<(frag GR64:$src1, GR64:$src2, (and CL, immShift64)),
1801 (!cast<Instruction>(name # "64rrCL") GR64:$src1, GR64:$src2)>;
1804 defm : MaskedDoubleShiftAmountPats<X86shld, "SHLD">;
1805 defm : MaskedDoubleShiftAmountPats<X86shrd, "SHRD">;
1807 let Predicates = [HasBMI2] in {
1808 let AddedComplexity = 1 in {
1809 def : Pat<(sra GR32:$src1, (and GR8:$src2, immShift32)),
1810 (SARX32rr GR32:$src1,
1812 (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1813 def : Pat<(sra GR64:$src1, (and GR8:$src2, immShift64)),
1814 (SARX64rr GR64:$src1,
1816 (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1818 def : Pat<(srl GR32:$src1, (and GR8:$src2, immShift32)),
1819 (SHRX32rr GR32:$src1,
1821 (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1822 def : Pat<(srl GR64:$src1, (and GR8:$src2, immShift64)),
1823 (SHRX64rr GR64:$src1,
1825 (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1827 def : Pat<(shl GR32:$src1, (and GR8:$src2, immShift32)),
1828 (SHLX32rr GR32:$src1,
1830 (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1831 def : Pat<(shl GR64:$src1, (and GR8:$src2, immShift64)),
1832 (SHLX64rr GR64:$src1,
1834 (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1837 def : Pat<(sra (loadi32 addr:$src1), (and GR8:$src2, immShift32)),
1838 (SARX32rm addr:$src1,
1840 (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1841 def : Pat<(sra (loadi64 addr:$src1), (and GR8:$src2, immShift64)),
1842 (SARX64rm addr:$src1,
1844 (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1846 def : Pat<(srl (loadi32 addr:$src1), (and GR8:$src2, immShift32)),
1847 (SHRX32rm addr:$src1,
1849 (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1850 def : Pat<(srl (loadi64 addr:$src1), (and GR8:$src2, immShift64)),
1851 (SHRX64rm addr:$src1,
1853 (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1855 def : Pat<(shl (loadi32 addr:$src1), (and GR8:$src2, immShift32)),
1856 (SHLX32rm addr:$src1,
1858 (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1859 def : Pat<(shl (loadi64 addr:$src1), (and GR8:$src2, immShift64)),
1860 (SHLX64rm addr:$src1,
1862 (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1865 // Use BTR/BTS/BTC for clearing/setting/toggling a bit in a variable location.
1866 multiclass one_bit_patterns<RegisterClass RC, ValueType VT, Instruction BTR,
1867 Instruction BTS, Instruction BTC,
1869 def : Pat<(and RC:$src1, (rotl -2, GR8:$src2)),
1871 (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1872 def : Pat<(or RC:$src1, (shl 1, GR8:$src2)),
1874 (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1875 def : Pat<(xor RC:$src1, (shl 1, GR8:$src2)),
1877 (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1879 // Similar to above, but removing unneeded masking of the shift amount.
1880 def : Pat<(and RC:$src1, (rotl -2, (and GR8:$src2, ImmShift))),
1882 (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1883 def : Pat<(or RC:$src1, (shl 1, (and GR8:$src2, ImmShift))),
1885 (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1886 def : Pat<(xor RC:$src1, (shl 1, (and GR8:$src2, ImmShift))),
1888 (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1891 defm : one_bit_patterns<GR16, i16, BTR16rr, BTS16rr, BTC16rr, immShift16>;
1892 defm : one_bit_patterns<GR32, i32, BTR32rr, BTS32rr, BTC32rr, immShift32>;
1893 defm : one_bit_patterns<GR64, i64, BTR64rr, BTS64rr, BTC64rr, immShift64>;
1896 // (anyext (setcc_carry)) -> (setcc_carry)
1897 def : Pat<(i16 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))),
1899 def : Pat<(i32 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))),
1901 def : Pat<(i32 (anyext (i16 (X86setcc_c X86_COND_B, EFLAGS)))),
1904 //===----------------------------------------------------------------------===//
1905 // EFLAGS-defining Patterns
1906 //===----------------------------------------------------------------------===//
1909 def : Pat<(add GR8 :$src1, GR8 :$src2), (ADD8rr GR8 :$src1, GR8 :$src2)>;
1910 def : Pat<(add GR16:$src1, GR16:$src2), (ADD16rr GR16:$src1, GR16:$src2)>;
1911 def : Pat<(add GR32:$src1, GR32:$src2), (ADD32rr GR32:$src1, GR32:$src2)>;
1912 def : Pat<(add GR64:$src1, GR64:$src2), (ADD64rr GR64:$src1, GR64:$src2)>;
1915 def : Pat<(add GR8:$src1, (loadi8 addr:$src2)),
1916 (ADD8rm GR8:$src1, addr:$src2)>;
1917 def : Pat<(add GR16:$src1, (loadi16 addr:$src2)),
1918 (ADD16rm GR16:$src1, addr:$src2)>;
1919 def : Pat<(add GR32:$src1, (loadi32 addr:$src2)),
1920 (ADD32rm GR32:$src1, addr:$src2)>;
1921 def : Pat<(add GR64:$src1, (loadi64 addr:$src2)),
1922 (ADD64rm GR64:$src1, addr:$src2)>;
1925 def : Pat<(add GR8 :$src1, imm:$src2), (ADD8ri GR8:$src1 , imm:$src2)>;
1926 def : Pat<(add GR16:$src1, imm:$src2), (ADD16ri GR16:$src1, imm:$src2)>;
1927 def : Pat<(add GR32:$src1, imm:$src2), (ADD32ri GR32:$src1, imm:$src2)>;
1928 def : Pat<(add GR16:$src1, i16immSExt8:$src2),
1929 (ADD16ri8 GR16:$src1, i16immSExt8:$src2)>;
1930 def : Pat<(add GR32:$src1, i32immSExt8:$src2),
1931 (ADD32ri8 GR32:$src1, i32immSExt8:$src2)>;
1932 def : Pat<(add GR64:$src1, i64immSExt8:$src2),
1933 (ADD64ri8 GR64:$src1, i64immSExt8:$src2)>;
1934 def : Pat<(add GR64:$src1, i64immSExt32:$src2),
1935 (ADD64ri32 GR64:$src1, i64immSExt32:$src2)>;
1938 def : Pat<(sub GR8 :$src1, GR8 :$src2), (SUB8rr GR8 :$src1, GR8 :$src2)>;
1939 def : Pat<(sub GR16:$src1, GR16:$src2), (SUB16rr GR16:$src1, GR16:$src2)>;
1940 def : Pat<(sub GR32:$src1, GR32:$src2), (SUB32rr GR32:$src1, GR32:$src2)>;
1941 def : Pat<(sub GR64:$src1, GR64:$src2), (SUB64rr GR64:$src1, GR64:$src2)>;
1944 def : Pat<(sub GR8:$src1, (loadi8 addr:$src2)),
1945 (SUB8rm GR8:$src1, addr:$src2)>;
1946 def : Pat<(sub GR16:$src1, (loadi16 addr:$src2)),
1947 (SUB16rm GR16:$src1, addr:$src2)>;
1948 def : Pat<(sub GR32:$src1, (loadi32 addr:$src2)),
1949 (SUB32rm GR32:$src1, addr:$src2)>;
1950 def : Pat<(sub GR64:$src1, (loadi64 addr:$src2)),
1951 (SUB64rm GR64:$src1, addr:$src2)>;
1954 def : Pat<(sub GR8:$src1, imm:$src2),
1955 (SUB8ri GR8:$src1, imm:$src2)>;
1956 def : Pat<(sub GR16:$src1, imm:$src2),
1957 (SUB16ri GR16:$src1, imm:$src2)>;
1958 def : Pat<(sub GR32:$src1, imm:$src2),
1959 (SUB32ri GR32:$src1, imm:$src2)>;
1960 def : Pat<(sub GR16:$src1, i16immSExt8:$src2),
1961 (SUB16ri8 GR16:$src1, i16immSExt8:$src2)>;
1962 def : Pat<(sub GR32:$src1, i32immSExt8:$src2),
1963 (SUB32ri8 GR32:$src1, i32immSExt8:$src2)>;
1964 def : Pat<(sub GR64:$src1, i64immSExt8:$src2),
1965 (SUB64ri8 GR64:$src1, i64immSExt8:$src2)>;
1966 def : Pat<(sub GR64:$src1, i64immSExt32:$src2),
1967 (SUB64ri32 GR64:$src1, i64immSExt32:$src2)>;
1970 def : Pat<(X86sub_flag 0, GR8 :$src), (NEG8r GR8 :$src)>;
1971 def : Pat<(X86sub_flag 0, GR16:$src), (NEG16r GR16:$src)>;
1972 def : Pat<(X86sub_flag 0, GR32:$src), (NEG32r GR32:$src)>;
1973 def : Pat<(X86sub_flag 0, GR64:$src), (NEG64r GR64:$src)>;
1975 // sub reg, relocImm
1976 def : Pat<(X86sub_flag GR64:$src1, i64relocImmSExt8_su:$src2),
1977 (SUB64ri8 GR64:$src1, i64relocImmSExt8_su:$src2)>;
1978 def : Pat<(X86sub_flag GR64:$src1, i64relocImmSExt32_su:$src2),
1979 (SUB64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>;
1982 def : Pat<(mul GR16:$src1, GR16:$src2),
1983 (IMUL16rr GR16:$src1, GR16:$src2)>;
1984 def : Pat<(mul GR32:$src1, GR32:$src2),
1985 (IMUL32rr GR32:$src1, GR32:$src2)>;
1986 def : Pat<(mul GR64:$src1, GR64:$src2),
1987 (IMUL64rr GR64:$src1, GR64:$src2)>;
1990 def : Pat<(mul GR16:$src1, (loadi16 addr:$src2)),
1991 (IMUL16rm GR16:$src1, addr:$src2)>;
1992 def : Pat<(mul GR32:$src1, (loadi32 addr:$src2)),
1993 (IMUL32rm GR32:$src1, addr:$src2)>;
1994 def : Pat<(mul GR64:$src1, (loadi64 addr:$src2)),
1995 (IMUL64rm GR64:$src1, addr:$src2)>;
1998 def : Pat<(mul GR16:$src1, imm:$src2),
1999 (IMUL16rri GR16:$src1, imm:$src2)>;
2000 def : Pat<(mul GR32:$src1, imm:$src2),
2001 (IMUL32rri GR32:$src1, imm:$src2)>;
2002 def : Pat<(mul GR16:$src1, i16immSExt8:$src2),
2003 (IMUL16rri8 GR16:$src1, i16immSExt8:$src2)>;
2004 def : Pat<(mul GR32:$src1, i32immSExt8:$src2),
2005 (IMUL32rri8 GR32:$src1, i32immSExt8:$src2)>;
2006 def : Pat<(mul GR64:$src1, i64immSExt8:$src2),
2007 (IMUL64rri8 GR64:$src1, i64immSExt8:$src2)>;
2008 def : Pat<(mul GR64:$src1, i64immSExt32:$src2),
2009 (IMUL64rri32 GR64:$src1, i64immSExt32:$src2)>;
2011 // reg = mul mem, imm
2012 def : Pat<(mul (loadi16 addr:$src1), imm:$src2),
2013 (IMUL16rmi addr:$src1, imm:$src2)>;
2014 def : Pat<(mul (loadi32 addr:$src1), imm:$src2),
2015 (IMUL32rmi addr:$src1, imm:$src2)>;
2016 def : Pat<(mul (loadi16 addr:$src1), i16immSExt8:$src2),
2017 (IMUL16rmi8 addr:$src1, i16immSExt8:$src2)>;
2018 def : Pat<(mul (loadi32 addr:$src1), i32immSExt8:$src2),
2019 (IMUL32rmi8 addr:$src1, i32immSExt8:$src2)>;
2020 def : Pat<(mul (loadi64 addr:$src1), i64immSExt8:$src2),
2021 (IMUL64rmi8 addr:$src1, i64immSExt8:$src2)>;
2022 def : Pat<(mul (loadi64 addr:$src1), i64immSExt32:$src2),
2023 (IMUL64rmi32 addr:$src1, i64immSExt32:$src2)>;
2025 // Increment/Decrement reg.
2026 // Do not make INC/DEC if it is slow
2027 let Predicates = [UseIncDec] in {
2028 def : Pat<(add GR8:$src, 1), (INC8r GR8:$src)>;
2029 def : Pat<(add GR16:$src, 1), (INC16r GR16:$src)>;
2030 def : Pat<(add GR32:$src, 1), (INC32r GR32:$src)>;
2031 def : Pat<(add GR64:$src, 1), (INC64r GR64:$src)>;
2032 def : Pat<(add GR8:$src, -1), (DEC8r GR8:$src)>;
2033 def : Pat<(add GR16:$src, -1), (DEC16r GR16:$src)>;
2034 def : Pat<(add GR32:$src, -1), (DEC32r GR32:$src)>;
2035 def : Pat<(add GR64:$src, -1), (DEC64r GR64:$src)>;
2037 def : Pat<(X86add_flag_nocf GR8:$src, -1), (DEC8r GR8:$src)>;
2038 def : Pat<(X86add_flag_nocf GR16:$src, -1), (DEC16r GR16:$src)>;
2039 def : Pat<(X86add_flag_nocf GR32:$src, -1), (DEC32r GR32:$src)>;
2040 def : Pat<(X86add_flag_nocf GR64:$src, -1), (DEC64r GR64:$src)>;
2041 def : Pat<(X86sub_flag_nocf GR8:$src, -1), (INC8r GR8:$src)>;
2042 def : Pat<(X86sub_flag_nocf GR16:$src, -1), (INC16r GR16:$src)>;
2043 def : Pat<(X86sub_flag_nocf GR32:$src, -1), (INC32r GR32:$src)>;
2044 def : Pat<(X86sub_flag_nocf GR64:$src, -1), (INC64r GR64:$src)>;
2048 def : Pat<(or GR8 :$src1, GR8 :$src2), (OR8rr GR8 :$src1, GR8 :$src2)>;
2049 def : Pat<(or GR16:$src1, GR16:$src2), (OR16rr GR16:$src1, GR16:$src2)>;
2050 def : Pat<(or GR32:$src1, GR32:$src2), (OR32rr GR32:$src1, GR32:$src2)>;
2051 def : Pat<(or GR64:$src1, GR64:$src2), (OR64rr GR64:$src1, GR64:$src2)>;
2054 def : Pat<(or GR8:$src1, (loadi8 addr:$src2)),
2055 (OR8rm GR8:$src1, addr:$src2)>;
2056 def : Pat<(or GR16:$src1, (loadi16 addr:$src2)),
2057 (OR16rm GR16:$src1, addr:$src2)>;
2058 def : Pat<(or GR32:$src1, (loadi32 addr:$src2)),
2059 (OR32rm GR32:$src1, addr:$src2)>;
2060 def : Pat<(or GR64:$src1, (loadi64 addr:$src2)),
2061 (OR64rm GR64:$src1, addr:$src2)>;
2064 def : Pat<(or GR8:$src1 , imm:$src2), (OR8ri GR8 :$src1, imm:$src2)>;
2065 def : Pat<(or GR16:$src1, imm:$src2), (OR16ri GR16:$src1, imm:$src2)>;
2066 def : Pat<(or GR32:$src1, imm:$src2), (OR32ri GR32:$src1, imm:$src2)>;
2067 def : Pat<(or GR16:$src1, i16immSExt8:$src2),
2068 (OR16ri8 GR16:$src1, i16immSExt8:$src2)>;
2069 def : Pat<(or GR32:$src1, i32immSExt8:$src2),
2070 (OR32ri8 GR32:$src1, i32immSExt8:$src2)>;
2071 def : Pat<(or GR64:$src1, i64immSExt8:$src2),
2072 (OR64ri8 GR64:$src1, i64immSExt8:$src2)>;
2073 def : Pat<(or GR64:$src1, i64immSExt32:$src2),
2074 (OR64ri32 GR64:$src1, i64immSExt32:$src2)>;
2077 def : Pat<(xor GR8 :$src1, GR8 :$src2), (XOR8rr GR8 :$src1, GR8 :$src2)>;
2078 def : Pat<(xor GR16:$src1, GR16:$src2), (XOR16rr GR16:$src1, GR16:$src2)>;
2079 def : Pat<(xor GR32:$src1, GR32:$src2), (XOR32rr GR32:$src1, GR32:$src2)>;
2080 def : Pat<(xor GR64:$src1, GR64:$src2), (XOR64rr GR64:$src1, GR64:$src2)>;
2083 def : Pat<(xor GR8:$src1, (loadi8 addr:$src2)),
2084 (XOR8rm GR8:$src1, addr:$src2)>;
2085 def : Pat<(xor GR16:$src1, (loadi16 addr:$src2)),
2086 (XOR16rm GR16:$src1, addr:$src2)>;
2087 def : Pat<(xor GR32:$src1, (loadi32 addr:$src2)),
2088 (XOR32rm GR32:$src1, addr:$src2)>;
2089 def : Pat<(xor GR64:$src1, (loadi64 addr:$src2)),
2090 (XOR64rm GR64:$src1, addr:$src2)>;
2093 def : Pat<(xor GR8:$src1, imm:$src2),
2094 (XOR8ri GR8:$src1, imm:$src2)>;
2095 def : Pat<(xor GR16:$src1, imm:$src2),
2096 (XOR16ri GR16:$src1, imm:$src2)>;
2097 def : Pat<(xor GR32:$src1, imm:$src2),
2098 (XOR32ri GR32:$src1, imm:$src2)>;
2099 def : Pat<(xor GR16:$src1, i16immSExt8:$src2),
2100 (XOR16ri8 GR16:$src1, i16immSExt8:$src2)>;
2101 def : Pat<(xor GR32:$src1, i32immSExt8:$src2),
2102 (XOR32ri8 GR32:$src1, i32immSExt8:$src2)>;
2103 def : Pat<(xor GR64:$src1, i64immSExt8:$src2),
2104 (XOR64ri8 GR64:$src1, i64immSExt8:$src2)>;
2105 def : Pat<(xor GR64:$src1, i64immSExt32:$src2),
2106 (XOR64ri32 GR64:$src1, i64immSExt32:$src2)>;
2109 def : Pat<(and GR8 :$src1, GR8 :$src2), (AND8rr GR8 :$src1, GR8 :$src2)>;
2110 def : Pat<(and GR16:$src1, GR16:$src2), (AND16rr GR16:$src1, GR16:$src2)>;
2111 def : Pat<(and GR32:$src1, GR32:$src2), (AND32rr GR32:$src1, GR32:$src2)>;
2112 def : Pat<(and GR64:$src1, GR64:$src2), (AND64rr GR64:$src1, GR64:$src2)>;
2115 def : Pat<(and GR8:$src1, (loadi8 addr:$src2)),
2116 (AND8rm GR8:$src1, addr:$src2)>;
2117 def : Pat<(and GR16:$src1, (loadi16 addr:$src2)),
2118 (AND16rm GR16:$src1, addr:$src2)>;
2119 def : Pat<(and GR32:$src1, (loadi32 addr:$src2)),
2120 (AND32rm GR32:$src1, addr:$src2)>;
2121 def : Pat<(and GR64:$src1, (loadi64 addr:$src2)),
2122 (AND64rm GR64:$src1, addr:$src2)>;
2125 def : Pat<(and GR8:$src1, imm:$src2),
2126 (AND8ri GR8:$src1, imm:$src2)>;
2127 def : Pat<(and GR16:$src1, imm:$src2),
2128 (AND16ri GR16:$src1, imm:$src2)>;
2129 def : Pat<(and GR32:$src1, imm:$src2),
2130 (AND32ri GR32:$src1, imm:$src2)>;
2131 def : Pat<(and GR16:$src1, i16immSExt8:$src2),
2132 (AND16ri8 GR16:$src1, i16immSExt8:$src2)>;
2133 def : Pat<(and GR32:$src1, i32immSExt8:$src2),
2134 (AND32ri8 GR32:$src1, i32immSExt8:$src2)>;
2135 def : Pat<(and GR64:$src1, i64immSExt8:$src2),
2136 (AND64ri8 GR64:$src1, i64immSExt8:$src2)>;
2137 def : Pat<(and GR64:$src1, i64immSExt32:$src2),
2138 (AND64ri32 GR64:$src1, i64immSExt32:$src2)>;
2140 // Bit scan instruction patterns to match explicit zero-undef behavior.
2141 def : Pat<(cttz_zero_undef GR16:$src), (BSF16rr GR16:$src)>;
2142 def : Pat<(cttz_zero_undef GR32:$src), (BSF32rr GR32:$src)>;
2143 def : Pat<(cttz_zero_undef GR64:$src), (BSF64rr GR64:$src)>;
2144 def : Pat<(cttz_zero_undef (loadi16 addr:$src)), (BSF16rm addr:$src)>;
2145 def : Pat<(cttz_zero_undef (loadi32 addr:$src)), (BSF32rm addr:$src)>;
2146 def : Pat<(cttz_zero_undef (loadi64 addr:$src)), (BSF64rm addr:$src)>;
2148 // When HasMOVBE is enabled it is possible to get a non-legalized
2149 // register-register 16 bit bswap. This maps it to a ROL instruction.
2150 let Predicates = [HasMOVBE] in {
2151 def : Pat<(bswap GR16:$src), (ROL16ri GR16:$src, (i8 8))>;