xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86InstrCompiler.td (revision 415efcecd8b80f68e76376ef2b854cb6f5c84b5a)
10b57cec5SDimitry Andric//===- X86InstrCompiler.td - Compiler Pseudos and Patterns -*- tablegen -*-===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric//
90b57cec5SDimitry Andric// This file describes the various pseudo instructions used by the compiler,
100b57cec5SDimitry Andric// as well as Pat patterns used during instruction selection.
110b57cec5SDimitry Andric//
120b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric// Pattern Matching Support
160b57cec5SDimitry Andric
170b57cec5SDimitry Andricdef GetLo32XForm : SDNodeXForm<imm, [{
180b57cec5SDimitry Andric  // Transformation function: get the low 32 bits.
190b57cec5SDimitry Andric  return getI32Imm((uint32_t)N->getZExtValue(), SDLoc(N));
200b57cec5SDimitry Andric}]>;
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
240b57cec5SDimitry Andric// Random Pseudo Instructions.
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric// PIC base construction.  This expands to code that looks like this:
270b57cec5SDimitry Andric//     call  $next_inst
280b57cec5SDimitry Andric//     popl %destreg"
290b57cec5SDimitry Andriclet hasSideEffects = 0, isNotDuplicable = 1, Uses = [ESP, SSP],
300b57cec5SDimitry Andric    SchedRW = [WriteJump] in
310b57cec5SDimitry Andric  def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins i32imm:$label),
320b57cec5SDimitry Andric                      "", []>;
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric// ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into
350b57cec5SDimitry Andric// a stack adjustment and the codegen must know that they may modify the stack
360b57cec5SDimitry Andric// pointer before prolog-epilog rewriting occurs.
370b57cec5SDimitry Andric// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
380b57cec5SDimitry Andric// sub / add which can clobber EFLAGS.
390b57cec5SDimitry Andriclet Defs = [ESP, EFLAGS, SSP], Uses = [ESP, SSP], SchedRW = [WriteALU] in {
400b57cec5SDimitry Andricdef ADJCALLSTACKDOWN32 : I<0, Pseudo, (outs),
410b57cec5SDimitry Andric                           (ins i32imm:$amt1, i32imm:$amt2, i32imm:$amt3),
420b57cec5SDimitry Andric                           "#ADJCALLSTACKDOWN", []>, Requires<[NotLP64]>;
430b57cec5SDimitry Andricdef ADJCALLSTACKUP32   : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
440b57cec5SDimitry Andric                           "#ADJCALLSTACKUP",
450b57cec5SDimitry Andric                           [(X86callseq_end timm:$amt1, timm:$amt2)]>,
460b57cec5SDimitry Andric                           Requires<[NotLP64]>;
470b57cec5SDimitry Andric}
480b57cec5SDimitry Andricdef : Pat<(X86callseq_start timm:$amt1, timm:$amt2),
490b57cec5SDimitry Andric       (ADJCALLSTACKDOWN32 i32imm:$amt1, i32imm:$amt2, 0)>, Requires<[NotLP64]>;
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric// ADJCALLSTACKDOWN/UP implicitly use/def RSP because they may be expanded into
530b57cec5SDimitry Andric// a stack adjustment and the codegen must know that they may modify the stack
540b57cec5SDimitry Andric// pointer before prolog-epilog rewriting occurs.
550b57cec5SDimitry Andric// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
560b57cec5SDimitry Andric// sub / add which can clobber EFLAGS.
570b57cec5SDimitry Andriclet Defs = [RSP, EFLAGS, SSP], Uses = [RSP, SSP], SchedRW = [WriteALU] in {
580b57cec5SDimitry Andricdef ADJCALLSTACKDOWN64 : I<0, Pseudo, (outs),
590b57cec5SDimitry Andric                           (ins i32imm:$amt1, i32imm:$amt2, i32imm:$amt3),
600b57cec5SDimitry Andric                           "#ADJCALLSTACKDOWN", []>, Requires<[IsLP64]>;
610b57cec5SDimitry Andricdef ADJCALLSTACKUP64   : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
620b57cec5SDimitry Andric                           "#ADJCALLSTACKUP",
630b57cec5SDimitry Andric                           [(X86callseq_end timm:$amt1, timm:$amt2)]>,
640b57cec5SDimitry Andric                           Requires<[IsLP64]>;
650b57cec5SDimitry Andric}
660b57cec5SDimitry Andricdef : Pat<(X86callseq_start timm:$amt1, timm:$amt2),
670b57cec5SDimitry Andric        (ADJCALLSTACKDOWN64 i32imm:$amt1, i32imm:$amt2, 0)>, Requires<[IsLP64]>;
680b57cec5SDimitry Andric
690b57cec5SDimitry Andriclet SchedRW = [WriteSystem] in {
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric// x86-64 va_start lowering magic.
72349cc55cSDimitry Andriclet hasSideEffects = 1, mayStore = 1, Defs = [EFLAGS] in {
730b57cec5SDimitry Andricdef VASTART_SAVE_XMM_REGS : I<0, Pseudo,
740b57cec5SDimitry Andric                              (outs),
75349cc55cSDimitry Andric                              (ins GR8:$al, i8mem:$regsavefi, variable_ops),
76349cc55cSDimitry Andric                              "#VASTART_SAVE_XMM_REGS $al, $regsavefi",
77349cc55cSDimitry Andric                              [(X86vastart_save_xmm_regs GR8:$al, addr:$regsavefi),
780b57cec5SDimitry Andric                               (implicit EFLAGS)]>;
79fe6060f1SDimitry Andric}
800b57cec5SDimitry Andric
81fe6060f1SDimitry Andriclet usesCustomInserter = 1, Defs = [EFLAGS] in {
82e8d8bef9SDimitry Andric// The VAARG_64 and VAARG_X32 pseudo-instructions take the address of the
83e8d8bef9SDimitry Andric// va_list, and place the address of the next argument into a register.
84e8d8bef9SDimitry Andriclet Defs = [EFLAGS] in {
850b57cec5SDimitry Andricdef VAARG_64 : I<0, Pseudo,
860b57cec5SDimitry Andric                 (outs GR64:$dst),
870b57cec5SDimitry Andric                 (ins i8mem:$ap, i32imm:$size, i8imm:$mode, i32imm:$align),
880b57cec5SDimitry Andric                 "#VAARG_64 $dst, $ap, $size, $mode, $align",
890b57cec5SDimitry Andric                 [(set GR64:$dst,
90e8d8bef9SDimitry Andric                    (X86vaarg64 addr:$ap, timm:$size, timm:$mode, timm:$align)),
91e8d8bef9SDimitry Andric                  (implicit EFLAGS)]>, Requires<[In64BitMode, IsLP64]>;
92e8d8bef9SDimitry Andricdef VAARG_X32 : I<0, Pseudo,
93e8d8bef9SDimitry Andric                 (outs GR32:$dst),
94e8d8bef9SDimitry Andric                 (ins i8mem:$ap, i32imm:$size, i8imm:$mode, i32imm:$align),
95e8d8bef9SDimitry Andric                 "#VAARG_X32 $dst, $ap, $size, $mode, $align",
96e8d8bef9SDimitry Andric                 [(set GR32:$dst,
97e8d8bef9SDimitry Andric                    (X86vaargx32 addr:$ap, timm:$size, timm:$mode, timm:$align)),
98e8d8bef9SDimitry Andric                  (implicit EFLAGS)]>, Requires<[In64BitMode, NotLP64]>;
99e8d8bef9SDimitry Andric}
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric// When using segmented stacks these are lowered into instructions which first
1020b57cec5SDimitry Andric// check if the current stacklet has enough free memory. If it does, memory is
1030b57cec5SDimitry Andric// allocated by bumping the stack pointer. Otherwise memory is allocated from
1040b57cec5SDimitry Andric// the heap.
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andriclet Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in
1070b57cec5SDimitry Andricdef SEG_ALLOCA_32 : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$size),
1080b57cec5SDimitry Andric                      "# variable sized alloca for segmented stacks",
1090b57cec5SDimitry Andric                      [(set GR32:$dst,
1100b57cec5SDimitry Andric                         (X86SegAlloca GR32:$size))]>,
1110b57cec5SDimitry Andric                    Requires<[NotLP64]>;
1120b57cec5SDimitry Andric
1130b57cec5SDimitry Andriclet Defs = [RAX, RSP, EFLAGS], Uses = [RSP] in
1140b57cec5SDimitry Andricdef SEG_ALLOCA_64 : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$size),
1150b57cec5SDimitry Andric                      "# variable sized alloca for segmented stacks",
1160b57cec5SDimitry Andric                      [(set GR64:$dst,
1170b57cec5SDimitry Andric                         (X86SegAlloca GR64:$size))]>,
1180b57cec5SDimitry Andric                    Requires<[In64BitMode]>;
1195ffd83dbSDimitry Andric
1205ffd83dbSDimitry Andric// To protect against stack clash, dynamic allocation should perform a memory
1215ffd83dbSDimitry Andric// probe at each page.
1225ffd83dbSDimitry Andric
1235ffd83dbSDimitry Andriclet Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in
1245ffd83dbSDimitry Andricdef PROBED_ALLOCA_32 : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$size),
1255ffd83dbSDimitry Andric                      "# variable sized alloca with probing",
1265ffd83dbSDimitry Andric                      [(set GR32:$dst,
1275ffd83dbSDimitry Andric                         (X86ProbedAlloca GR32:$size))]>,
1285ffd83dbSDimitry Andric                    Requires<[NotLP64]>;
1295ffd83dbSDimitry Andric
1305ffd83dbSDimitry Andriclet Defs = [RAX, RSP, EFLAGS], Uses = [RSP] in
1315ffd83dbSDimitry Andricdef PROBED_ALLOCA_64 : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$size),
1325ffd83dbSDimitry Andric                      "# variable sized alloca with probing",
1335ffd83dbSDimitry Andric                      [(set GR64:$dst,
1345ffd83dbSDimitry Andric                         (X86ProbedAlloca GR64:$size))]>,
1355ffd83dbSDimitry Andric                    Requires<[In64BitMode]>;
1360b57cec5SDimitry Andric}
1370b57cec5SDimitry Andric
1385ffd83dbSDimitry Andriclet hasNoSchedulingInfo = 1 in
1395ffd83dbSDimitry Andricdef STACKALLOC_W_PROBING : I<0, Pseudo, (outs), (ins i64imm:$stacksize),
1405ffd83dbSDimitry Andric                             "# fixed size alloca with probing",
1415ffd83dbSDimitry Andric                             []>;
1425ffd83dbSDimitry Andric
1430b57cec5SDimitry Andric// Dynamic stack allocation yields a _chkstk or _alloca call for all Windows
1440b57cec5SDimitry Andric// targets.  These calls are needed to probe the stack when allocating more than
1450b57cec5SDimitry Andric// 4k bytes in one go. Touching the stack at 4K increments is necessary to
1460b57cec5SDimitry Andric// ensure that the guard pages used by the OS virtual memory manager are
1470b57cec5SDimitry Andric// allocated in correct sequence.
1480b57cec5SDimitry Andric// The main point of having separate instruction are extra unmodelled effects
1490b57cec5SDimitry Andric// (compared to ordinary calls) like stack pointer change.
1500b57cec5SDimitry Andric
1510b57cec5SDimitry Andriclet Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in
152349cc55cSDimitry Andricdef DYN_ALLOCA_32 : I<0, Pseudo, (outs), (ins GR32:$size),
1530b57cec5SDimitry Andric                     "# dynamic stack allocation",
154349cc55cSDimitry Andric                     [(X86DynAlloca GR32:$size)]>,
1550b57cec5SDimitry Andric                     Requires<[NotLP64]>;
1560b57cec5SDimitry Andric
1570b57cec5SDimitry Andriclet Defs = [RAX, RSP, EFLAGS], Uses = [RSP] in
158349cc55cSDimitry Andricdef DYN_ALLOCA_64 : I<0, Pseudo, (outs), (ins GR64:$size),
1590b57cec5SDimitry Andric                     "# dynamic stack allocation",
160349cc55cSDimitry Andric                     [(X86DynAlloca GR64:$size)]>,
1610b57cec5SDimitry Andric                     Requires<[In64BitMode]>;
1620b57cec5SDimitry Andric} // SchedRW
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andric// These instructions XOR the frame pointer into a GPR. They are used in some
1650b57cec5SDimitry Andric// stack protection schemes. These are post-RA pseudos because we only know the
1660b57cec5SDimitry Andric// frame register after register allocation.
1670b57cec5SDimitry Andriclet Constraints = "$src = $dst", isMoveImm = 1, isPseudo = 1, Defs = [EFLAGS] in {
1680b57cec5SDimitry Andric  def XOR32_FP : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src),
1690b57cec5SDimitry Andric                  "xorl\t$$FP, $src", []>,
1700b57cec5SDimitry Andric                  Requires<[NotLP64]>, Sched<[WriteALU]>;
1710b57cec5SDimitry Andric  def XOR64_FP : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$src),
1720b57cec5SDimitry Andric                  "xorq\t$$FP $src", []>,
1730b57cec5SDimitry Andric                  Requires<[In64BitMode]>, Sched<[WriteALU]>;
1740b57cec5SDimitry Andric}
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1770b57cec5SDimitry Andric// EH Pseudo Instructions
1780b57cec5SDimitry Andric//
1790b57cec5SDimitry Andriclet SchedRW = [WriteSystem] in {
1800b57cec5SDimitry Andriclet isTerminator = 1, isReturn = 1, isBarrier = 1,
1810b57cec5SDimitry Andric    hasCtrlDep = 1, isCodeGenOnly = 1 in {
1820b57cec5SDimitry Andricdef EH_RETURN   : I<0xC3, RawFrm, (outs), (ins GR32:$addr),
1830b57cec5SDimitry Andric                    "ret\t#eh_return, addr: $addr",
1840b57cec5SDimitry Andric                    [(X86ehret GR32:$addr)]>, Sched<[WriteJumpLd]>;
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andric}
1870b57cec5SDimitry Andric
1880b57cec5SDimitry Andriclet isTerminator = 1, isReturn = 1, isBarrier = 1,
1890b57cec5SDimitry Andric    hasCtrlDep = 1, isCodeGenOnly = 1 in {
1900b57cec5SDimitry Andricdef EH_RETURN64   : I<0xC3, RawFrm, (outs), (ins GR64:$addr),
1910b57cec5SDimitry Andric                     "ret\t#eh_return, addr: $addr",
1920b57cec5SDimitry Andric                     [(X86ehret GR64:$addr)]>, Sched<[WriteJumpLd]>;
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andric}
1950b57cec5SDimitry Andric
1960b57cec5SDimitry Andriclet isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1,
1970b57cec5SDimitry Andric    isCodeGenOnly = 1, isReturn = 1, isEHScopeReturn = 1 in {
198*415efcecSDimitry Andric  def CLEANUPRET : I<0, Pseudo, (outs), (ins), "# CLEANUPRET",
199*415efcecSDimitry Andric                     [(cleanupret bb)]>;
2000b57cec5SDimitry Andric
2010b57cec5SDimitry Andric  // CATCHRET needs a custom inserter for SEH.
2020b57cec5SDimitry Andric  let usesCustomInserter = 1 in
2030b57cec5SDimitry Andric    def CATCHRET : I<0, Pseudo, (outs), (ins brtarget32:$dst, brtarget32:$from),
2040b57cec5SDimitry Andric                     "# CATCHRET",
2050b57cec5SDimitry Andric                     [(catchret bb:$dst, bb:$from)]>;
2060b57cec5SDimitry Andric}
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andriclet hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1,
2090b57cec5SDimitry Andric    usesCustomInserter = 1 in {
2100b57cec5SDimitry Andric  def EH_SjLj_SetJmp32  : I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$buf),
2110b57cec5SDimitry Andric                            "#EH_SJLJ_SETJMP32",
2120b57cec5SDimitry Andric                            [(set GR32:$dst, (X86eh_sjlj_setjmp addr:$buf))]>,
2130b57cec5SDimitry Andric                          Requires<[Not64BitMode]>;
2140b57cec5SDimitry Andric  def EH_SjLj_SetJmp64  : I<0, Pseudo, (outs GR32:$dst), (ins i64mem:$buf),
2150b57cec5SDimitry Andric                            "#EH_SJLJ_SETJMP64",
2160b57cec5SDimitry Andric                            [(set GR32:$dst, (X86eh_sjlj_setjmp addr:$buf))]>,
2170b57cec5SDimitry Andric                          Requires<[In64BitMode]>;
2180b57cec5SDimitry Andric  let isTerminator = 1 in {
2190b57cec5SDimitry Andric  def EH_SjLj_LongJmp32 : I<0, Pseudo, (outs), (ins i32mem:$buf),
2200b57cec5SDimitry Andric                            "#EH_SJLJ_LONGJMP32",
2210b57cec5SDimitry Andric                            [(X86eh_sjlj_longjmp addr:$buf)]>,
2220b57cec5SDimitry Andric                          Requires<[Not64BitMode]>;
2230b57cec5SDimitry Andric  def EH_SjLj_LongJmp64 : I<0, Pseudo, (outs), (ins i64mem:$buf),
2240b57cec5SDimitry Andric                            "#EH_SJLJ_LONGJMP64",
2250b57cec5SDimitry Andric                            [(X86eh_sjlj_longjmp addr:$buf)]>,
2260b57cec5SDimitry Andric                          Requires<[In64BitMode]>;
2270b57cec5SDimitry Andric  }
2280b57cec5SDimitry Andric}
2290b57cec5SDimitry Andric
2300b57cec5SDimitry Andriclet isBranch = 1, isTerminator = 1, isCodeGenOnly = 1 in {
2310b57cec5SDimitry Andric  def EH_SjLj_Setup : I<0, Pseudo, (outs), (ins brtarget:$dst),
2320b57cec5SDimitry Andric                        "#EH_SjLj_Setup\t$dst", []>;
2330b57cec5SDimitry Andric}
2340b57cec5SDimitry Andric} // SchedRW
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2370b57cec5SDimitry Andric// Pseudo instructions used by unwind info.
2380b57cec5SDimitry Andric//
2390b57cec5SDimitry Andriclet isPseudo = 1, SchedRW = [WriteSystem] in {
2400b57cec5SDimitry Andric  def SEH_PushReg : I<0, Pseudo, (outs), (ins i32imm:$reg),
2410b57cec5SDimitry Andric                            "#SEH_PushReg $reg", []>;
2420b57cec5SDimitry Andric  def SEH_SaveReg : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$dst),
2430b57cec5SDimitry Andric                            "#SEH_SaveReg $reg, $dst", []>;
2440b57cec5SDimitry Andric  def SEH_SaveXMM : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$dst),
2450b57cec5SDimitry Andric                            "#SEH_SaveXMM $reg, $dst", []>;
2460b57cec5SDimitry Andric  def SEH_StackAlloc : I<0, Pseudo, (outs), (ins i32imm:$size),
2470b57cec5SDimitry Andric                            "#SEH_StackAlloc $size", []>;
2480b57cec5SDimitry Andric  def SEH_StackAlign : I<0, Pseudo, (outs), (ins i32imm:$align),
2490b57cec5SDimitry Andric                            "#SEH_StackAlign $align", []>;
2500b57cec5SDimitry Andric  def SEH_SetFrame : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$offset),
2510b57cec5SDimitry Andric                            "#SEH_SetFrame $reg, $offset", []>;
2520b57cec5SDimitry Andric  def SEH_PushFrame : I<0, Pseudo, (outs), (ins i1imm:$mode),
2530b57cec5SDimitry Andric                            "#SEH_PushFrame $mode", []>;
2540b57cec5SDimitry Andric  def SEH_EndPrologue : I<0, Pseudo, (outs), (ins),
2550b57cec5SDimitry Andric                            "#SEH_EndPrologue", []>;
2560b57cec5SDimitry Andric  def SEH_Epilogue : I<0, Pseudo, (outs), (ins),
2570b57cec5SDimitry Andric                            "#SEH_Epilogue", []>;
2580b57cec5SDimitry Andric}
2590b57cec5SDimitry Andric
2600b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
261bdd1243dSDimitry Andric// Pseudo instructions used by KCFI.
262bdd1243dSDimitry Andric//===----------------------------------------------------------------------===//
263bdd1243dSDimitry Andriclet
264bdd1243dSDimitry Andric  Defs = [R10, R11, EFLAGS] in {
265bdd1243dSDimitry Andricdef KCFI_CHECK : PseudoI<
266bdd1243dSDimitry Andric  (outs), (ins GR64:$ptr, i32imm:$type), []>, Sched<[]>;
267bdd1243dSDimitry Andric}
268bdd1243dSDimitry Andric
269bdd1243dSDimitry Andric//===----------------------------------------------------------------------===//
270349cc55cSDimitry Andric// Pseudo instructions used by address sanitizer.
271349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
272349cc55cSDimitry Andriclet
2730eae32dcSDimitry Andric  Defs = [R10, R11, EFLAGS] in {
274349cc55cSDimitry Andricdef ASAN_CHECK_MEMACCESS : PseudoI<
2750eae32dcSDimitry Andric  (outs), (ins GR64PLTSafe:$addr, i32imm:$accessinfo),
2760eae32dcSDimitry Andric  [(int_asan_check_memaccess GR64PLTSafe:$addr, (i32 timm:$accessinfo))]>,
277349cc55cSDimitry Andric  Sched<[]>;
278349cc55cSDimitry Andric}
279349cc55cSDimitry Andric
280349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
2810b57cec5SDimitry Andric// Pseudo instructions used by segmented stacks.
2820b57cec5SDimitry Andric//
2830b57cec5SDimitry Andric
2840b57cec5SDimitry Andric// This is lowered into a RET instruction by MCInstLower.  We need
2850b57cec5SDimitry Andric// this so that we don't have to have a MachineBasicBlock which ends
2860b57cec5SDimitry Andric// with a RET and also has successors.
2870b57cec5SDimitry Andriclet isPseudo = 1, SchedRW = [WriteJumpLd] in {
2880b57cec5SDimitry Andricdef MORESTACK_RET: I<0, Pseudo, (outs), (ins), "", []>;
2890b57cec5SDimitry Andric
2900b57cec5SDimitry Andric// This instruction is lowered to a RET followed by a MOV.  The two
2910b57cec5SDimitry Andric// instructions are not generated on a higher level since then the
2920b57cec5SDimitry Andric// verifier sees a MachineBasicBlock ending with a non-terminator.
2930b57cec5SDimitry Andricdef MORESTACK_RET_RESTORE_R10 : I<0, Pseudo, (outs), (ins), "", []>;
2940b57cec5SDimitry Andric}
2950b57cec5SDimitry Andric
2960b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2970b57cec5SDimitry Andric// Alias Instructions
2980b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2990b57cec5SDimitry Andric
3000b57cec5SDimitry Andric// Alias instruction mapping movr0 to xor.
3010b57cec5SDimitry Andric// FIXME: remove when we can teach regalloc that xor reg, reg is ok.
3020b57cec5SDimitry Andriclet Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1,
3030b57cec5SDimitry Andric    isPseudo = 1, isMoveImm = 1, AddedComplexity = 10 in
3040b57cec5SDimitry Andricdef MOV32r0  : I<0, Pseudo, (outs GR32:$dst), (ins), "",
3050b57cec5SDimitry Andric                 [(set GR32:$dst, 0)]>, Sched<[WriteZero]>;
3060b57cec5SDimitry Andric
3070b57cec5SDimitry Andric// Other widths can also make use of the 32-bit xor, which may have a smaller
3080b57cec5SDimitry Andric// encoding and avoid partial register updates.
3090b57cec5SDimitry Andriclet AddedComplexity = 10 in {
3100b57cec5SDimitry Andricdef : Pat<(i8 0), (EXTRACT_SUBREG (MOV32r0), sub_8bit)>;
3110b57cec5SDimitry Andricdef : Pat<(i16 0), (EXTRACT_SUBREG (MOV32r0), sub_16bit)>;
3120b57cec5SDimitry Andricdef : Pat<(i64 0), (SUBREG_TO_REG (i64 0), (MOV32r0), sub_32bit)>;
3130b57cec5SDimitry Andric}
3140b57cec5SDimitry Andric
3150b57cec5SDimitry Andriclet Predicates = [OptForSize, Not64BitMode],
3160b57cec5SDimitry Andric    AddedComplexity = 10 in {
3170b57cec5SDimitry Andric  let SchedRW = [WriteALU] in {
3180b57cec5SDimitry Andric  // Pseudo instructions for materializing 1 and -1 using XOR+INC/DEC,
3190b57cec5SDimitry Andric  // which only require 3 bytes compared to MOV32ri which requires 5.
3200b57cec5SDimitry Andric  let Defs = [EFLAGS], isReMaterializable = 1, isPseudo = 1 in {
3210b57cec5SDimitry Andric    def MOV32r1 : I<0, Pseudo, (outs GR32:$dst), (ins), "",
3220b57cec5SDimitry Andric                        [(set GR32:$dst, 1)]>;
3230b57cec5SDimitry Andric    def MOV32r_1 : I<0, Pseudo, (outs GR32:$dst), (ins), "",
3240b57cec5SDimitry Andric                        [(set GR32:$dst, -1)]>;
3250b57cec5SDimitry Andric  }
3260b57cec5SDimitry Andric  } // SchedRW
3270b57cec5SDimitry Andric
3280b57cec5SDimitry Andric  // MOV16ri is 4 bytes, so the instructions above are smaller.
3290b57cec5SDimitry Andric  def : Pat<(i16 1), (EXTRACT_SUBREG (MOV32r1), sub_16bit)>;
3300b57cec5SDimitry Andric  def : Pat<(i16 -1), (EXTRACT_SUBREG (MOV32r_1), sub_16bit)>;
3310b57cec5SDimitry Andric}
3320b57cec5SDimitry Andric
3330b57cec5SDimitry Andriclet isReMaterializable = 1, isPseudo = 1, AddedComplexity = 5,
3340b57cec5SDimitry Andric    SchedRW = [WriteALU] in {
3350b57cec5SDimitry Andric// AddedComplexity higher than MOV64ri but lower than MOV32r0 and MOV32r1.
3360b57cec5SDimitry Andricdef MOV32ImmSExti8 : I<0, Pseudo, (outs GR32:$dst), (ins i32i8imm:$src), "",
3370b57cec5SDimitry Andric                       [(set GR32:$dst, i32immSExt8:$src)]>,
3380b57cec5SDimitry Andric                       Requires<[OptForMinSize, NotWin64WithoutFP]>;
3390b57cec5SDimitry Andricdef MOV64ImmSExti8 : I<0, Pseudo, (outs GR64:$dst), (ins i64i8imm:$src), "",
3400b57cec5SDimitry Andric                       [(set GR64:$dst, i64immSExt8:$src)]>,
3410b57cec5SDimitry Andric                       Requires<[OptForMinSize, NotWin64WithoutFP]>;
3420b57cec5SDimitry Andric}
3430b57cec5SDimitry Andric
3440b57cec5SDimitry Andric// Materialize i64 constant where top 32-bits are zero. This could theoretically
3450b57cec5SDimitry Andric// use MOV32ri with a SUBREG_TO_REG to represent the zero-extension, however
3460b57cec5SDimitry Andric// that would make it more difficult to rematerialize.
3475ffd83dbSDimitry Andriclet AddedComplexity = 1, isReMaterializable = 1, isAsCheapAsAMove = 1,
3485ffd83dbSDimitry Andric    isPseudo = 1, SchedRW = [WriteMove] in
3495ffd83dbSDimitry Andricdef MOV32ri64 : I<0, Pseudo, (outs GR64:$dst), (ins i64i32imm:$src), "",
3505ffd83dbSDimitry Andric                  [(set GR64:$dst, i64immZExt32:$src)]>;
3510b57cec5SDimitry Andric
3525ffd83dbSDimitry Andric// This 64-bit pseudo-move can also be used for labels in the x86-64 small code
3535ffd83dbSDimitry Andric// model.
3545ffd83dbSDimitry Andricdef mov64imm32 : ComplexPattern<i64, 1, "selectMOV64Imm32", [X86Wrapper]>;
3550b57cec5SDimitry Andricdef : Pat<(i64 mov64imm32:$src), (MOV32ri64 mov64imm32:$src)>;
3560b57cec5SDimitry Andric
3570b57cec5SDimitry Andric// Use sbb to materialize carry bit.
3585ffd83dbSDimitry Andriclet Uses = [EFLAGS], Defs = [EFLAGS], isPseudo = 1, SchedRW = [WriteADC],
3595ffd83dbSDimitry Andric    hasSideEffects = 0 in {
3600b57cec5SDimitry Andric// FIXME: These are pseudo ops that should be replaced with Pat<> patterns.
3610b57cec5SDimitry Andric// However, Pat<> can't replicate the destination reg into the inputs of the
3620b57cec5SDimitry Andric// result.
3635ffd83dbSDimitry Andricdef SETB_C32r : I<0, Pseudo, (outs GR32:$dst), (ins), "", []>;
3645ffd83dbSDimitry Andricdef SETB_C64r : I<0, Pseudo, (outs GR64:$dst), (ins), "", []>;
3650b57cec5SDimitry Andric} // isCodeGenOnly
3660b57cec5SDimitry Andric
3670b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
3680b57cec5SDimitry Andric// String Pseudo Instructions
3690b57cec5SDimitry Andric//
3700b57cec5SDimitry Andriclet SchedRW = [WriteMicrocoded] in {
3710b57cec5SDimitry Andriclet Defs = [ECX,EDI,ESI], Uses = [ECX,EDI,ESI], isCodeGenOnly = 1 in {
3720b57cec5SDimitry Andricdef REP_MOVSB_32 : I<0xA4, RawFrm, (outs), (ins),
3730b57cec5SDimitry Andric                    "{rep;movsb (%esi), %es:(%edi)|rep movsb es:[edi], [esi]}",
3740b57cec5SDimitry Andric                    [(X86rep_movs i8)]>, REP, AdSize32,
3750b57cec5SDimitry Andric                   Requires<[NotLP64]>;
3760b57cec5SDimitry Andricdef REP_MOVSW_32 : I<0xA5, RawFrm, (outs), (ins),
3770b57cec5SDimitry Andric                    "{rep;movsw (%esi), %es:(%edi)|rep movsw es:[edi], [esi]}",
3780b57cec5SDimitry Andric                    [(X86rep_movs i16)]>, REP, AdSize32, OpSize16,
3790b57cec5SDimitry Andric                   Requires<[NotLP64]>;
3800b57cec5SDimitry Andricdef REP_MOVSD_32 : I<0xA5, RawFrm, (outs), (ins),
3810b57cec5SDimitry Andric                    "{rep;movsl (%esi), %es:(%edi)|rep movsd es:[edi], [esi]}",
3820b57cec5SDimitry Andric                    [(X86rep_movs i32)]>, REP, AdSize32, OpSize32,
3830b57cec5SDimitry Andric                   Requires<[NotLP64]>;
3840b57cec5SDimitry Andricdef REP_MOVSQ_32 : RI<0xA5, RawFrm, (outs), (ins),
3850b57cec5SDimitry Andric                    "{rep;movsq (%esi), %es:(%edi)|rep movsq es:[edi], [esi]}",
3860b57cec5SDimitry Andric                    [(X86rep_movs i64)]>, REP, AdSize32,
3870b57cec5SDimitry Andric                   Requires<[NotLP64, In64BitMode]>;
3880b57cec5SDimitry Andric}
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andriclet Defs = [RCX,RDI,RSI], Uses = [RCX,RDI,RSI], isCodeGenOnly = 1 in {
3910b57cec5SDimitry Andricdef REP_MOVSB_64 : I<0xA4, RawFrm, (outs), (ins),
3920b57cec5SDimitry Andric                    "{rep;movsb (%rsi), %es:(%rdi)|rep movsb es:[rdi], [rsi]}",
3930b57cec5SDimitry Andric                    [(X86rep_movs i8)]>, REP, AdSize64,
3940b57cec5SDimitry Andric                   Requires<[IsLP64]>;
3950b57cec5SDimitry Andricdef REP_MOVSW_64 : I<0xA5, RawFrm, (outs), (ins),
3960b57cec5SDimitry Andric                    "{rep;movsw (%rsi), %es:(%rdi)|rep movsw es:[rdi], [rsi]}",
3970b57cec5SDimitry Andric                    [(X86rep_movs i16)]>, REP, AdSize64, OpSize16,
3980b57cec5SDimitry Andric                   Requires<[IsLP64]>;
3990b57cec5SDimitry Andricdef REP_MOVSD_64 : I<0xA5, RawFrm, (outs), (ins),
4000b57cec5SDimitry Andric                    "{rep;movsl (%rsi), %es:(%rdi)|rep movsdi es:[rdi], [rsi]}",
4010b57cec5SDimitry Andric                    [(X86rep_movs i32)]>, REP, AdSize64, OpSize32,
4020b57cec5SDimitry Andric                   Requires<[IsLP64]>;
4030b57cec5SDimitry Andricdef REP_MOVSQ_64 : RI<0xA5, RawFrm, (outs), (ins),
4040b57cec5SDimitry Andric                    "{rep;movsq (%rsi), %es:(%rdi)|rep movsq es:[rdi], [rsi]}",
4050b57cec5SDimitry Andric                    [(X86rep_movs i64)]>, REP, AdSize64,
4060b57cec5SDimitry Andric                   Requires<[IsLP64]>;
4070b57cec5SDimitry Andric}
4080b57cec5SDimitry Andric
4090b57cec5SDimitry Andric// FIXME: Should use "(X86rep_stos AL)" as the pattern.
4100b57cec5SDimitry Andriclet Defs = [ECX,EDI], isCodeGenOnly = 1 in {
4110b57cec5SDimitry Andric  let Uses = [AL,ECX,EDI] in
4120b57cec5SDimitry Andric  def REP_STOSB_32 : I<0xAA, RawFrm, (outs), (ins),
4130b57cec5SDimitry Andric                       "{rep;stosb %al, %es:(%edi)|rep stosb es:[edi], al}",
4140b57cec5SDimitry Andric                      [(X86rep_stos i8)]>, REP, AdSize32,
4150b57cec5SDimitry Andric                     Requires<[NotLP64]>;
4160b57cec5SDimitry Andric  let Uses = [AX,ECX,EDI] in
4170b57cec5SDimitry Andric  def REP_STOSW_32 : I<0xAB, RawFrm, (outs), (ins),
4180b57cec5SDimitry Andric                      "{rep;stosw %ax, %es:(%edi)|rep stosw es:[edi], ax}",
4190b57cec5SDimitry Andric                      [(X86rep_stos i16)]>, REP, AdSize32, OpSize16,
4200b57cec5SDimitry Andric                     Requires<[NotLP64]>;
4210b57cec5SDimitry Andric  let Uses = [EAX,ECX,EDI] in
4220b57cec5SDimitry Andric  def REP_STOSD_32 : I<0xAB, RawFrm, (outs), (ins),
4230b57cec5SDimitry Andric                      "{rep;stosl %eax, %es:(%edi)|rep stosd es:[edi], eax}",
4240b57cec5SDimitry Andric                      [(X86rep_stos i32)]>, REP, AdSize32, OpSize32,
4250b57cec5SDimitry Andric                     Requires<[NotLP64]>;
4260b57cec5SDimitry Andric  let Uses = [RAX,RCX,RDI] in
4270b57cec5SDimitry Andric  def REP_STOSQ_32 : RI<0xAB, RawFrm, (outs), (ins),
4280b57cec5SDimitry Andric                        "{rep;stosq %rax, %es:(%edi)|rep stosq es:[edi], rax}",
4290b57cec5SDimitry Andric                        [(X86rep_stos i64)]>, REP, AdSize32,
4300b57cec5SDimitry Andric                        Requires<[NotLP64, In64BitMode]>;
4310b57cec5SDimitry Andric}
4320b57cec5SDimitry Andric
4330b57cec5SDimitry Andriclet Defs = [RCX,RDI], isCodeGenOnly = 1 in {
4340b57cec5SDimitry Andric  let Uses = [AL,RCX,RDI] in
4350b57cec5SDimitry Andric  def REP_STOSB_64 : I<0xAA, RawFrm, (outs), (ins),
4360b57cec5SDimitry Andric                       "{rep;stosb %al, %es:(%rdi)|rep stosb es:[rdi], al}",
4370b57cec5SDimitry Andric                       [(X86rep_stos i8)]>, REP, AdSize64,
4380b57cec5SDimitry Andric                       Requires<[IsLP64]>;
4390b57cec5SDimitry Andric  let Uses = [AX,RCX,RDI] in
4400b57cec5SDimitry Andric  def REP_STOSW_64 : I<0xAB, RawFrm, (outs), (ins),
4410b57cec5SDimitry Andric                       "{rep;stosw %ax, %es:(%rdi)|rep stosw es:[rdi], ax}",
4420b57cec5SDimitry Andric                       [(X86rep_stos i16)]>, REP, AdSize64, OpSize16,
4430b57cec5SDimitry Andric                       Requires<[IsLP64]>;
4440b57cec5SDimitry Andric  let Uses = [RAX,RCX,RDI] in
4450b57cec5SDimitry Andric  def REP_STOSD_64 : I<0xAB, RawFrm, (outs), (ins),
4460b57cec5SDimitry Andric                      "{rep;stosl %eax, %es:(%rdi)|rep stosd es:[rdi], eax}",
4470b57cec5SDimitry Andric                       [(X86rep_stos i32)]>, REP, AdSize64, OpSize32,
4480b57cec5SDimitry Andric                       Requires<[IsLP64]>;
4490b57cec5SDimitry Andric
4500b57cec5SDimitry Andric  let Uses = [RAX,RCX,RDI] in
4510b57cec5SDimitry Andric  def REP_STOSQ_64 : RI<0xAB, RawFrm, (outs), (ins),
4520b57cec5SDimitry Andric                        "{rep;stosq %rax, %es:(%rdi)|rep stosq es:[rdi], rax}",
4530b57cec5SDimitry Andric                        [(X86rep_stos i64)]>, REP, AdSize64,
4540b57cec5SDimitry Andric                        Requires<[IsLP64]>;
4550b57cec5SDimitry Andric}
4560b57cec5SDimitry Andric} // SchedRW
4570b57cec5SDimitry Andric
4580b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
4590b57cec5SDimitry Andric// Thread Local Storage Instructions
4600b57cec5SDimitry Andric//
4610b57cec5SDimitry Andriclet SchedRW = [WriteSystem] in {
4620b57cec5SDimitry Andric
4630b57cec5SDimitry Andric// ELF TLS Support
4640b57cec5SDimitry Andric// All calls clobber the non-callee saved registers. ESP is marked as
4650b57cec5SDimitry Andric// a use to prevent stack-pointer assignments that appear immediately
4660b57cec5SDimitry Andric// before calls from potentially appearing dead.
4670b57cec5SDimitry Andriclet Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7,
4680b57cec5SDimitry Andric            ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7,
4690b57cec5SDimitry Andric            MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
4700b57cec5SDimitry Andric            XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
4710b57cec5SDimitry Andric            XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS, DF],
4720b57cec5SDimitry Andric    usesCustomInserter = 1, Uses = [ESP, SSP] in {
4730b57cec5SDimitry Andricdef TLS_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
4740b57cec5SDimitry Andric                  "# TLS_addr32",
4750b57cec5SDimitry Andric                  [(X86tlsaddr tls32addr:$sym)]>,
4760b57cec5SDimitry Andric                  Requires<[Not64BitMode]>;
4770b57cec5SDimitry Andricdef TLS_base_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
4780b57cec5SDimitry Andric                  "# TLS_base_addr32",
4790b57cec5SDimitry Andric                  [(X86tlsbaseaddr tls32baseaddr:$sym)]>,
4800b57cec5SDimitry Andric                  Requires<[Not64BitMode]>;
4810b57cec5SDimitry Andric}
4820b57cec5SDimitry Andric
4830b57cec5SDimitry Andric// All calls clobber the non-callee saved registers. RSP is marked as
4840b57cec5SDimitry Andric// a use to prevent stack-pointer assignments that appear immediately
4850b57cec5SDimitry Andric// before calls from potentially appearing dead.
4860b57cec5SDimitry Andriclet Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11,
4870b57cec5SDimitry Andric            FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7,
4880b57cec5SDimitry Andric            ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7,
4890b57cec5SDimitry Andric            MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
4900b57cec5SDimitry Andric            XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
4910b57cec5SDimitry Andric            XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS, DF],
4920b57cec5SDimitry Andric    usesCustomInserter = 1, Uses = [RSP, SSP] in {
4930b57cec5SDimitry Andricdef TLS_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
4940b57cec5SDimitry Andric                   "# TLS_addr64",
4950b57cec5SDimitry Andric                  [(X86tlsaddr tls64addr:$sym)]>,
496e8d8bef9SDimitry Andric                  Requires<[In64BitMode, IsLP64]>;
4970b57cec5SDimitry Andricdef TLS_base_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
4980b57cec5SDimitry Andric                   "# TLS_base_addr64",
4990b57cec5SDimitry Andric                  [(X86tlsbaseaddr tls64baseaddr:$sym)]>,
500e8d8bef9SDimitry Andric                  Requires<[In64BitMode, IsLP64]>;
501e8d8bef9SDimitry Andricdef TLS_addrX32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
502e8d8bef9SDimitry Andric                   "# TLS_addrX32",
503e8d8bef9SDimitry Andric                  [(X86tlsaddr tls32addr:$sym)]>,
504e8d8bef9SDimitry Andric                  Requires<[In64BitMode, NotLP64]>;
505e8d8bef9SDimitry Andricdef TLS_base_addrX32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
506e8d8bef9SDimitry Andric                   "# TLS_base_addrX32",
507e8d8bef9SDimitry Andric                  [(X86tlsbaseaddr tls32baseaddr:$sym)]>,
508e8d8bef9SDimitry Andric                  Requires<[In64BitMode, NotLP64]>;
5090b57cec5SDimitry Andric}
5100b57cec5SDimitry Andric
5110fca6ea1SDimitry Andric// TLSDESC only clobbers EAX and EFLAGS. ESP is marked as a use to prevent
5120fca6ea1SDimitry Andric// stack-pointer assignments that appear immediately before calls from
5130fca6ea1SDimitry Andric// potentially appearing dead.
5140fca6ea1SDimitry Andriclet Defs = [EAX, EFLAGS], usesCustomInserter = 1, Uses = [RSP, SSP] in {
5150fca6ea1SDimitry Andric  def TLS_desc32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
5160fca6ea1SDimitry Andric                     "# TLS_desc32", [(X86tlsdesc tls32addr:$sym)]>;
5170fca6ea1SDimitry Andric  def TLS_desc64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
5180fca6ea1SDimitry Andric                     "# TLS_desc64", [(X86tlsdesc tls64addr:$sym)]>;
5190fca6ea1SDimitry Andric}
5200fca6ea1SDimitry Andric
5210b57cec5SDimitry Andric// Darwin TLS Support
5220b57cec5SDimitry Andric// For i386, the address of the thunk is passed on the stack, on return the
5230b57cec5SDimitry Andric// address of the variable is in %eax.  %ecx is trashed during the function
5240b57cec5SDimitry Andric// call.  All other registers are preserved.
5250b57cec5SDimitry Andriclet Defs = [EAX, ECX, EFLAGS, DF],
5260b57cec5SDimitry Andric    Uses = [ESP, SSP],
5270b57cec5SDimitry Andric    usesCustomInserter = 1 in
5280b57cec5SDimitry Andricdef TLSCall_32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
5290b57cec5SDimitry Andric                "# TLSCall_32",
5300b57cec5SDimitry Andric                [(X86TLSCall addr:$sym)]>,
5310b57cec5SDimitry Andric                Requires<[Not64BitMode]>;
5320b57cec5SDimitry Andric
5330b57cec5SDimitry Andric// For x86_64, the address of the thunk is passed in %rdi, but the
5340b57cec5SDimitry Andric// pseudo directly use the symbol, so do not add an implicit use of
5350b57cec5SDimitry Andric// %rdi. The lowering will do the right thing with RDI.
5360b57cec5SDimitry Andric// On return the address of the variable is in %rax.  All other
5370b57cec5SDimitry Andric// registers are preserved.
5380b57cec5SDimitry Andriclet Defs = [RAX, EFLAGS, DF],
5390b57cec5SDimitry Andric    Uses = [RSP, SSP],
5400b57cec5SDimitry Andric    usesCustomInserter = 1 in
5410b57cec5SDimitry Andricdef TLSCall_64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
5420b57cec5SDimitry Andric                  "# TLSCall_64",
5430b57cec5SDimitry Andric                  [(X86TLSCall addr:$sym)]>,
5440b57cec5SDimitry Andric                  Requires<[In64BitMode]>;
5450b57cec5SDimitry Andric} // SchedRW
5460b57cec5SDimitry Andric
5470b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
5480b57cec5SDimitry Andric// Conditional Move Pseudo Instructions
5490b57cec5SDimitry Andric
5500b57cec5SDimitry Andric// CMOV* - Used to implement the SELECT DAG operation.  Expanded after
5510b57cec5SDimitry Andric// instruction selection into a branch sequence.
5520b57cec5SDimitry Andricmulticlass CMOVrr_PSEUDO<RegisterClass RC, ValueType VT> {
5530b57cec5SDimitry Andric  def CMOV#NAME  : I<0, Pseudo,
5540b57cec5SDimitry Andric                    (outs RC:$dst), (ins RC:$t, RC:$f, i8imm:$cond),
5550b57cec5SDimitry Andric                    "#CMOV_"#NAME#" PSEUDO!",
5568bcb0991SDimitry Andric                    [(set RC:$dst, (VT (X86cmov RC:$t, RC:$f, timm:$cond,
5570b57cec5SDimitry Andric                                                EFLAGS)))]>;
5580b57cec5SDimitry Andric}
5590b57cec5SDimitry Andric
5600b57cec5SDimitry Andriclet usesCustomInserter = 1, hasNoSchedulingInfo = 1, Uses = [EFLAGS] in {
5610b57cec5SDimitry Andric  // X86 doesn't have 8-bit conditional moves. Use a customInserter to
5620b57cec5SDimitry Andric  // emit control flow. An alternative to this is to mark i8 SELECT as Promote,
5630b57cec5SDimitry Andric  // however that requires promoting the operands, and can induce additional
5640b57cec5SDimitry Andric  // i8 register pressure.
5650b57cec5SDimitry Andric  defm _GR8 : CMOVrr_PSEUDO<GR8, i8>;
5660b57cec5SDimitry Andric
56781ad6265SDimitry Andric  let Predicates = [NoCMOV] in {
5680b57cec5SDimitry Andric    defm _GR32 : CMOVrr_PSEUDO<GR32, i32>;
5690b57cec5SDimitry Andric    defm _GR16 : CMOVrr_PSEUDO<GR16, i16>;
57081ad6265SDimitry Andric  } // Predicates = [NoCMOV]
5710b57cec5SDimitry Andric
5720b57cec5SDimitry Andric  // fcmov doesn't handle all possible EFLAGS, provide a fallback if there is no
5730b57cec5SDimitry Andric  // SSE1/SSE2.
5740b57cec5SDimitry Andric  let Predicates = [FPStackf32] in
5750b57cec5SDimitry Andric    defm _RFP32 : CMOVrr_PSEUDO<RFP32, f32>;
5760b57cec5SDimitry Andric
5770b57cec5SDimitry Andric  let Predicates = [FPStackf64] in
5780b57cec5SDimitry Andric    defm _RFP64 : CMOVrr_PSEUDO<RFP64, f64>;
5790b57cec5SDimitry Andric
5800b57cec5SDimitry Andric  defm _RFP80 : CMOVrr_PSEUDO<RFP80, f80>;
5810b57cec5SDimitry Andric
5825ffd83dbSDimitry Andric  let Predicates = [HasMMX] in
5835ffd83dbSDimitry Andric    defm _VR64   : CMOVrr_PSEUDO<VR64, x86mmx>;
5845ffd83dbSDimitry Andric
5855ffd83dbSDimitry Andric  let Predicates = [HasSSE1,NoAVX512] in
5860b57cec5SDimitry Andric    defm _FR32   : CMOVrr_PSEUDO<FR32, f32>;
58781ad6265SDimitry Andric  let Predicates = [HasSSE2,NoAVX512] in {
58881ad6265SDimitry Andric    defm _FR16   : CMOVrr_PSEUDO<FR16, f16>;
5890b57cec5SDimitry Andric    defm _FR64   : CMOVrr_PSEUDO<FR64, f64>;
59081ad6265SDimitry Andric  }
5910b57cec5SDimitry Andric  let Predicates = [HasAVX512] in {
59281ad6265SDimitry Andric    defm _FR16X  : CMOVrr_PSEUDO<FR16X, f16>;
5930b57cec5SDimitry Andric    defm _FR32X  : CMOVrr_PSEUDO<FR32X, f32>;
5940b57cec5SDimitry Andric    defm _FR64X  : CMOVrr_PSEUDO<FR64X, f64>;
5950b57cec5SDimitry Andric  }
5960b57cec5SDimitry Andric  let Predicates = [NoVLX] in {
5970b57cec5SDimitry Andric    defm _VR128  : CMOVrr_PSEUDO<VR128, v2i64>;
5980b57cec5SDimitry Andric    defm _VR256  : CMOVrr_PSEUDO<VR256, v4i64>;
5990b57cec5SDimitry Andric  }
6000b57cec5SDimitry Andric  let Predicates = [HasVLX] in {
6010b57cec5SDimitry Andric    defm _VR128X : CMOVrr_PSEUDO<VR128X, v2i64>;
6020b57cec5SDimitry Andric    defm _VR256X : CMOVrr_PSEUDO<VR256X, v4i64>;
6030b57cec5SDimitry Andric  }
6040b57cec5SDimitry Andric  defm _VR512  : CMOVrr_PSEUDO<VR512, v8i64>;
6055ffd83dbSDimitry Andric  defm _VK1    : CMOVrr_PSEUDO<VK1,  v1i1>;
6060b57cec5SDimitry Andric  defm _VK2    : CMOVrr_PSEUDO<VK2,  v2i1>;
6070b57cec5SDimitry Andric  defm _VK4    : CMOVrr_PSEUDO<VK4,  v4i1>;
6080b57cec5SDimitry Andric  defm _VK8    : CMOVrr_PSEUDO<VK8,  v8i1>;
6090b57cec5SDimitry Andric  defm _VK16   : CMOVrr_PSEUDO<VK16, v16i1>;
6100b57cec5SDimitry Andric  defm _VK32   : CMOVrr_PSEUDO<VK32, v32i1>;
6110b57cec5SDimitry Andric  defm _VK64   : CMOVrr_PSEUDO<VK64, v64i1>;
6120b57cec5SDimitry Andric} // usesCustomInserter = 1, hasNoSchedulingInfo = 1, Uses = [EFLAGS]
6130b57cec5SDimitry Andric
6148bcb0991SDimitry Andricdef : Pat<(f128 (X86cmov VR128:$t, VR128:$f, timm:$cond, EFLAGS)),
6158bcb0991SDimitry Andric          (CMOV_VR128 VR128:$t, VR128:$f, timm:$cond)>;
6160b57cec5SDimitry Andric
6170b57cec5SDimitry Andriclet Predicates = [NoVLX] in {
6188bcb0991SDimitry Andric  def : Pat<(v16i8 (X86cmov VR128:$t, VR128:$f, timm:$cond, EFLAGS)),
6198bcb0991SDimitry Andric            (CMOV_VR128 VR128:$t, VR128:$f, timm:$cond)>;
6208bcb0991SDimitry Andric  def : Pat<(v8i16 (X86cmov VR128:$t, VR128:$f, timm:$cond, EFLAGS)),
6218bcb0991SDimitry Andric            (CMOV_VR128 VR128:$t, VR128:$f, timm:$cond)>;
6228bcb0991SDimitry Andric  def : Pat<(v4i32 (X86cmov VR128:$t, VR128:$f, timm:$cond, EFLAGS)),
6238bcb0991SDimitry Andric            (CMOV_VR128 VR128:$t, VR128:$f, timm:$cond)>;
6248bcb0991SDimitry Andric  def : Pat<(v4f32 (X86cmov VR128:$t, VR128:$f, timm:$cond, EFLAGS)),
6258bcb0991SDimitry Andric            (CMOV_VR128 VR128:$t, VR128:$f, timm:$cond)>;
6268bcb0991SDimitry Andric  def : Pat<(v2f64 (X86cmov VR128:$t, VR128:$f, timm:$cond, EFLAGS)),
6278bcb0991SDimitry Andric            (CMOV_VR128 VR128:$t, VR128:$f, timm:$cond)>;
6280b57cec5SDimitry Andric
6298bcb0991SDimitry Andric  def : Pat<(v32i8 (X86cmov VR256:$t, VR256:$f, timm:$cond, EFLAGS)),
6308bcb0991SDimitry Andric            (CMOV_VR256 VR256:$t, VR256:$f, timm:$cond)>;
6318bcb0991SDimitry Andric  def : Pat<(v16i16 (X86cmov VR256:$t, VR256:$f, timm:$cond, EFLAGS)),
6328bcb0991SDimitry Andric            (CMOV_VR256 VR256:$t, VR256:$f, timm:$cond)>;
6338bcb0991SDimitry Andric  def : Pat<(v8i32 (X86cmov VR256:$t, VR256:$f, timm:$cond, EFLAGS)),
6348bcb0991SDimitry Andric            (CMOV_VR256 VR256:$t, VR256:$f, timm:$cond)>;
6358bcb0991SDimitry Andric  def : Pat<(v8f32 (X86cmov VR256:$t, VR256:$f, timm:$cond, EFLAGS)),
6368bcb0991SDimitry Andric            (CMOV_VR256 VR256:$t, VR256:$f, timm:$cond)>;
6378bcb0991SDimitry Andric  def : Pat<(v4f64 (X86cmov VR256:$t, VR256:$f, timm:$cond, EFLAGS)),
6388bcb0991SDimitry Andric            (CMOV_VR256 VR256:$t, VR256:$f, timm:$cond)>;
6390b57cec5SDimitry Andric}
6400b57cec5SDimitry Andriclet Predicates = [HasVLX] in {
6418bcb0991SDimitry Andric  def : Pat<(v16i8 (X86cmov VR128X:$t, VR128X:$f, timm:$cond, EFLAGS)),
6428bcb0991SDimitry Andric            (CMOV_VR128X VR128X:$t, VR128X:$f, timm:$cond)>;
6438bcb0991SDimitry Andric  def : Pat<(v8i16 (X86cmov VR128X:$t, VR128X:$f, timm:$cond, EFLAGS)),
6448bcb0991SDimitry Andric            (CMOV_VR128X VR128X:$t, VR128X:$f, timm:$cond)>;
645349cc55cSDimitry Andric  def : Pat<(v8f16 (X86cmov VR128X:$t, VR128X:$f, timm:$cond, EFLAGS)),
646349cc55cSDimitry Andric            (CMOV_VR128X VR128X:$t, VR128X:$f, timm:$cond)>;
6478bcb0991SDimitry Andric  def : Pat<(v4i32 (X86cmov VR128X:$t, VR128X:$f, timm:$cond, EFLAGS)),
6488bcb0991SDimitry Andric            (CMOV_VR128X VR128X:$t, VR128X:$f, timm:$cond)>;
6498bcb0991SDimitry Andric  def : Pat<(v4f32 (X86cmov VR128X:$t, VR128X:$f, timm:$cond, EFLAGS)),
6508bcb0991SDimitry Andric            (CMOV_VR128X VR128X:$t, VR128X:$f, timm:$cond)>;
6518bcb0991SDimitry Andric  def : Pat<(v2f64 (X86cmov VR128X:$t, VR128X:$f, timm:$cond, EFLAGS)),
6528bcb0991SDimitry Andric            (CMOV_VR128X VR128X:$t, VR128X:$f, timm:$cond)>;
6530b57cec5SDimitry Andric
6548bcb0991SDimitry Andric  def : Pat<(v32i8 (X86cmov VR256X:$t, VR256X:$f, timm:$cond, EFLAGS)),
6558bcb0991SDimitry Andric            (CMOV_VR256X VR256X:$t, VR256X:$f, timm:$cond)>;
6568bcb0991SDimitry Andric  def : Pat<(v16i16 (X86cmov VR256X:$t, VR256X:$f, timm:$cond, EFLAGS)),
6578bcb0991SDimitry Andric            (CMOV_VR256X VR256X:$t, VR256X:$f, timm:$cond)>;
658349cc55cSDimitry Andric  def : Pat<(v16f16 (X86cmov VR256X:$t, VR256X:$f, timm:$cond, EFLAGS)),
659349cc55cSDimitry Andric            (CMOV_VR256X VR256X:$t, VR256X:$f, timm:$cond)>;
6608bcb0991SDimitry Andric  def : Pat<(v8i32 (X86cmov VR256X:$t, VR256X:$f, timm:$cond, EFLAGS)),
6618bcb0991SDimitry Andric            (CMOV_VR256X VR256X:$t, VR256X:$f, timm:$cond)>;
6628bcb0991SDimitry Andric  def : Pat<(v8f32 (X86cmov VR256X:$t, VR256X:$f, timm:$cond, EFLAGS)),
6638bcb0991SDimitry Andric            (CMOV_VR256X VR256X:$t, VR256X:$f, timm:$cond)>;
6648bcb0991SDimitry Andric  def : Pat<(v4f64 (X86cmov VR256X:$t, VR256X:$f, timm:$cond, EFLAGS)),
6658bcb0991SDimitry Andric            (CMOV_VR256X VR256X:$t, VR256X:$f, timm:$cond)>;
6660b57cec5SDimitry Andric}
6670b57cec5SDimitry Andric
6688bcb0991SDimitry Andricdef : Pat<(v64i8 (X86cmov VR512:$t, VR512:$f, timm:$cond, EFLAGS)),
6698bcb0991SDimitry Andric          (CMOV_VR512 VR512:$t, VR512:$f, timm:$cond)>;
6708bcb0991SDimitry Andricdef : Pat<(v32i16 (X86cmov VR512:$t, VR512:$f, timm:$cond, EFLAGS)),
6718bcb0991SDimitry Andric          (CMOV_VR512 VR512:$t, VR512:$f, timm:$cond)>;
672349cc55cSDimitry Andricdef : Pat<(v32f16 (X86cmov VR512:$t, VR512:$f, timm:$cond, EFLAGS)),
673349cc55cSDimitry Andric          (CMOV_VR512 VR512:$t, VR512:$f, timm:$cond)>;
6748bcb0991SDimitry Andricdef : Pat<(v16i32 (X86cmov VR512:$t, VR512:$f, timm:$cond, EFLAGS)),
6758bcb0991SDimitry Andric          (CMOV_VR512 VR512:$t, VR512:$f, timm:$cond)>;
6768bcb0991SDimitry Andricdef : Pat<(v16f32 (X86cmov VR512:$t, VR512:$f, timm:$cond, EFLAGS)),
6778bcb0991SDimitry Andric          (CMOV_VR512 VR512:$t, VR512:$f, timm:$cond)>;
6788bcb0991SDimitry Andricdef : Pat<(v8f64 (X86cmov VR512:$t, VR512:$f, timm:$cond, EFLAGS)),
6798bcb0991SDimitry Andric          (CMOV_VR512 VR512:$t, VR512:$f, timm:$cond)>;
6800b57cec5SDimitry Andric
6810b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
6820b57cec5SDimitry Andric// Normal-Instructions-With-Lock-Prefix Pseudo Instructions
6830b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
6840b57cec5SDimitry Andric
6850b57cec5SDimitry Andric// FIXME: Use normal instructions and add lock prefix dynamically.
6860b57cec5SDimitry Andric
6870b57cec5SDimitry Andric// Memory barriers
6880b57cec5SDimitry Andric
6890b57cec5SDimitry Andriclet isCodeGenOnly = 1, Defs = [EFLAGS] in
6900b57cec5SDimitry Andricdef OR32mi8Locked  : Ii8<0x83, MRM1m, (outs), (ins i32mem:$dst, i32i8imm:$zero),
6910b57cec5SDimitry Andric                         "or{l}\t{$zero, $dst|$dst, $zero}", []>,
6920b57cec5SDimitry Andric                         Requires<[Not64BitMode]>, OpSize32, LOCK,
6930b57cec5SDimitry Andric                         Sched<[WriteALURMW]>;
6940b57cec5SDimitry Andric
6950b57cec5SDimitry Andric// RegOpc corresponds to the mr version of the instruction
6960b57cec5SDimitry Andric// ImmOpc corresponds to the mi version of the instruction
6970b57cec5SDimitry Andric// ImmOpc8 corresponds to the mi8 version of the instruction
6980b57cec5SDimitry Andric// ImmMod corresponds to the instruction format of the mi and mi8 versions
6990b57cec5SDimitry Andricmulticlass LOCK_ArithBinOp<bits<8> RegOpc, bits<8> ImmOpc, bits<8> ImmOpc8,
7000b57cec5SDimitry Andric                           Format ImmMod, SDNode Op, string mnemonic> {
7010b57cec5SDimitry Andriclet Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1,
7020b57cec5SDimitry Andric    SchedRW = [WriteALURMW] in {
7030b57cec5SDimitry Andric
7040b57cec5SDimitry Andricdef NAME#8mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4},
7050b57cec5SDimitry Andric                  RegOpc{3}, RegOpc{2}, RegOpc{1}, 0 },
7060b57cec5SDimitry Andric                  MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src2),
7070b57cec5SDimitry Andric                  !strconcat(mnemonic, "{b}\t",
7080b57cec5SDimitry Andric                             "{$src2, $dst|$dst, $src2}"),
7090b57cec5SDimitry Andric                  [(set EFLAGS, (Op addr:$dst, GR8:$src2))]>, LOCK;
7100b57cec5SDimitry Andric
7110b57cec5SDimitry Andricdef NAME#16mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4},
7120b57cec5SDimitry Andric                   RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 },
7130b57cec5SDimitry Andric                   MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2),
7140b57cec5SDimitry Andric                   !strconcat(mnemonic, "{w}\t",
7150b57cec5SDimitry Andric                              "{$src2, $dst|$dst, $src2}"),
7160b57cec5SDimitry Andric                   [(set EFLAGS, (Op addr:$dst, GR16:$src2))]>,
7170b57cec5SDimitry Andric                   OpSize16, LOCK;
7180b57cec5SDimitry Andric
7190b57cec5SDimitry Andricdef NAME#32mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4},
7200b57cec5SDimitry Andric                   RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 },
7210b57cec5SDimitry Andric                   MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2),
7220b57cec5SDimitry Andric                   !strconcat(mnemonic, "{l}\t",
7230b57cec5SDimitry Andric                              "{$src2, $dst|$dst, $src2}"),
7240b57cec5SDimitry Andric                   [(set EFLAGS, (Op addr:$dst, GR32:$src2))]>,
7250b57cec5SDimitry Andric                   OpSize32, LOCK;
7260b57cec5SDimitry Andric
7270b57cec5SDimitry Andricdef NAME#64mr : RI<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4},
7280b57cec5SDimitry Andric                    RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 },
7290b57cec5SDimitry Andric                    MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2),
7300b57cec5SDimitry Andric                    !strconcat(mnemonic, "{q}\t",
7310b57cec5SDimitry Andric                               "{$src2, $dst|$dst, $src2}"),
7320b57cec5SDimitry Andric                    [(set EFLAGS, (Op addr:$dst, GR64:$src2))]>, LOCK;
7330b57cec5SDimitry Andric
7340b57cec5SDimitry Andric// NOTE: These are order specific, we want the mi8 forms to be listed
7350b57cec5SDimitry Andric// first so that they are slightly preferred to the mi forms.
7360b57cec5SDimitry Andricdef NAME#16mi8 : Ii8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4},
7370b57cec5SDimitry Andric                      ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 },
7380b57cec5SDimitry Andric                      ImmMod, (outs), (ins i16mem :$dst, i16i8imm :$src2),
7390b57cec5SDimitry Andric                      !strconcat(mnemonic, "{w}\t",
7400b57cec5SDimitry Andric                                 "{$src2, $dst|$dst, $src2}"),
7410b57cec5SDimitry Andric                      [(set EFLAGS, (Op addr:$dst, i16immSExt8:$src2))]>,
7420b57cec5SDimitry Andric                      OpSize16, LOCK;
7430b57cec5SDimitry Andric
7440b57cec5SDimitry Andricdef NAME#32mi8 : Ii8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4},
7450b57cec5SDimitry Andric                      ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 },
7460b57cec5SDimitry Andric                      ImmMod, (outs), (ins i32mem :$dst, i32i8imm :$src2),
7470b57cec5SDimitry Andric                      !strconcat(mnemonic, "{l}\t",
7480b57cec5SDimitry Andric                                 "{$src2, $dst|$dst, $src2}"),
7490b57cec5SDimitry Andric                      [(set EFLAGS, (Op addr:$dst, i32immSExt8:$src2))]>,
7500b57cec5SDimitry Andric                      OpSize32, LOCK;
7510b57cec5SDimitry Andric
7520b57cec5SDimitry Andricdef NAME#64mi8 : RIi8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4},
7530b57cec5SDimitry Andric                       ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 },
7540b57cec5SDimitry Andric                       ImmMod, (outs), (ins i64mem :$dst, i64i8imm :$src2),
7550b57cec5SDimitry Andric                       !strconcat(mnemonic, "{q}\t",
7560b57cec5SDimitry Andric                                  "{$src2, $dst|$dst, $src2}"),
7570b57cec5SDimitry Andric                       [(set EFLAGS, (Op addr:$dst, i64immSExt8:$src2))]>,
7580b57cec5SDimitry Andric                       LOCK;
7590b57cec5SDimitry Andric
7600b57cec5SDimitry Andricdef NAME#8mi : Ii8<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4},
7610b57cec5SDimitry Andric                    ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 0 },
7620b57cec5SDimitry Andric                    ImmMod, (outs), (ins i8mem :$dst, i8imm :$src2),
7630b57cec5SDimitry Andric                    !strconcat(mnemonic, "{b}\t",
7640b57cec5SDimitry Andric                               "{$src2, $dst|$dst, $src2}"),
7650b57cec5SDimitry Andric                    [(set EFLAGS, (Op addr:$dst, (i8 imm:$src2)))]>, LOCK;
7660b57cec5SDimitry Andric
7670b57cec5SDimitry Andricdef NAME#16mi : Ii16<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4},
7680b57cec5SDimitry Andric                      ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 },
7690b57cec5SDimitry Andric                      ImmMod, (outs), (ins i16mem :$dst, i16imm :$src2),
7700b57cec5SDimitry Andric                      !strconcat(mnemonic, "{w}\t",
7710b57cec5SDimitry Andric                                 "{$src2, $dst|$dst, $src2}"),
7720b57cec5SDimitry Andric                      [(set EFLAGS, (Op addr:$dst, (i16 imm:$src2)))]>,
7730b57cec5SDimitry Andric                      OpSize16, LOCK;
7740b57cec5SDimitry Andric
7750b57cec5SDimitry Andricdef NAME#32mi : Ii32<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4},
7760b57cec5SDimitry Andric                      ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 },
7770b57cec5SDimitry Andric                      ImmMod, (outs), (ins i32mem :$dst, i32imm :$src2),
7780b57cec5SDimitry Andric                      !strconcat(mnemonic, "{l}\t",
7790b57cec5SDimitry Andric                                 "{$src2, $dst|$dst, $src2}"),
7800b57cec5SDimitry Andric                      [(set EFLAGS, (Op addr:$dst, (i32 imm:$src2)))]>,
7810b57cec5SDimitry Andric                      OpSize32, LOCK;
7820b57cec5SDimitry Andric
7830b57cec5SDimitry Andricdef NAME#64mi32 : RIi32S<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4},
7840b57cec5SDimitry Andric                          ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 },
7850b57cec5SDimitry Andric                          ImmMod, (outs), (ins i64mem :$dst, i64i32imm :$src2),
7860b57cec5SDimitry Andric                          !strconcat(mnemonic, "{q}\t",
7870b57cec5SDimitry Andric                                     "{$src2, $dst|$dst, $src2}"),
7880b57cec5SDimitry Andric                          [(set EFLAGS, (Op addr:$dst, i64immSExt32:$src2))]>,
7890b57cec5SDimitry Andric                          LOCK;
7900b57cec5SDimitry Andric}
7910b57cec5SDimitry Andric
7920b57cec5SDimitry Andric}
7930b57cec5SDimitry Andric
7940b57cec5SDimitry Andricdefm LOCK_ADD : LOCK_ArithBinOp<0x00, 0x80, 0x83, MRM0m, X86lock_add, "add">;
7950b57cec5SDimitry Andricdefm LOCK_SUB : LOCK_ArithBinOp<0x28, 0x80, 0x83, MRM5m, X86lock_sub, "sub">;
7960b57cec5SDimitry Andricdefm LOCK_OR  : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM1m, X86lock_or , "or">;
7970b57cec5SDimitry Andricdefm LOCK_AND : LOCK_ArithBinOp<0x20, 0x80, 0x83, MRM4m, X86lock_and, "and">;
7980b57cec5SDimitry Andricdefm LOCK_XOR : LOCK_ArithBinOp<0x30, 0x80, 0x83, MRM6m, X86lock_xor, "xor">;
7990b57cec5SDimitry Andric
8000b57cec5SDimitry Andriclet Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1,
8010b57cec5SDimitry Andric    SchedRW = [WriteALURMW]  in {
802bdd1243dSDimitry Andric  let Predicates = [UseIncDec] in {
8030b57cec5SDimitry Andric    def LOCK_INC8m  : I<0xFE, MRM0m, (outs), (ins i8mem :$dst),
8040b57cec5SDimitry Andric                        "inc{b}\t$dst",
8050b57cec5SDimitry Andric                        [(set EFLAGS, (X86lock_add_nocf addr:$dst, (i8 1)))]>,
8060b57cec5SDimitry Andric                        LOCK;
8070b57cec5SDimitry Andric    def LOCK_INC16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst),
8080b57cec5SDimitry Andric                        "inc{w}\t$dst",
8090b57cec5SDimitry Andric                        [(set EFLAGS, (X86lock_add_nocf addr:$dst, (i16 1)))]>,
8100b57cec5SDimitry Andric                        OpSize16, LOCK;
8110b57cec5SDimitry Andric    def LOCK_INC32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst),
8120b57cec5SDimitry Andric                        "inc{l}\t$dst",
8130b57cec5SDimitry Andric                        [(set EFLAGS, (X86lock_add_nocf addr:$dst, (i32 1)))]>,
8140b57cec5SDimitry Andric                        OpSize32, LOCK;
8150b57cec5SDimitry Andric
8160b57cec5SDimitry Andric    def LOCK_DEC8m  : I<0xFE, MRM1m, (outs), (ins i8mem :$dst),
8170b57cec5SDimitry Andric                        "dec{b}\t$dst",
8180b57cec5SDimitry Andric                        [(set EFLAGS, (X86lock_sub_nocf addr:$dst, (i8 1)))]>,
8190b57cec5SDimitry Andric                        LOCK;
8200b57cec5SDimitry Andric    def LOCK_DEC16m : I<0xFF, MRM1m, (outs), (ins i16mem:$dst),
8210b57cec5SDimitry Andric                        "dec{w}\t$dst",
8220b57cec5SDimitry Andric                        [(set EFLAGS, (X86lock_sub_nocf addr:$dst, (i16 1)))]>,
8230b57cec5SDimitry Andric                        OpSize16, LOCK;
8240b57cec5SDimitry Andric    def LOCK_DEC32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst),
8250b57cec5SDimitry Andric                        "dec{l}\t$dst",
8260b57cec5SDimitry Andric                        [(set EFLAGS, (X86lock_sub_nocf addr:$dst, (i32 1)))]>,
8270b57cec5SDimitry Andric                        OpSize32, LOCK;
828bdd1243dSDimitry Andric  }
829bdd1243dSDimitry Andric
830bdd1243dSDimitry Andric  let Predicates = [UseIncDec, In64BitMode] in {
831bdd1243dSDimitry Andric    def LOCK_INC64m : RI<0xFF, MRM0m, (outs), (ins i64mem:$dst),
832bdd1243dSDimitry Andric                         "inc{q}\t$dst",
833bdd1243dSDimitry Andric                         [(set EFLAGS, (X86lock_add_nocf addr:$dst, (i64 1)))]>,
834bdd1243dSDimitry Andric                         LOCK;
8350b57cec5SDimitry Andric    def LOCK_DEC64m : RI<0xFF, MRM1m, (outs), (ins i64mem:$dst),
8360b57cec5SDimitry Andric                         "dec{q}\t$dst",
8370b57cec5SDimitry Andric                         [(set EFLAGS, (X86lock_sub_nocf addr:$dst, (i64 1)))]>,
8380b57cec5SDimitry Andric                         LOCK;
8390b57cec5SDimitry Andric  }
840bdd1243dSDimitry Andric}
8410b57cec5SDimitry Andric
842bdd1243dSDimitry Andriclet Predicates = [UseIncDec] in {
8430b57cec5SDimitry Andric  // Additional patterns for -1 constant.
8440b57cec5SDimitry Andric  def : Pat<(X86lock_add addr:$dst, (i8  -1)), (LOCK_DEC8m  addr:$dst)>;
8450b57cec5SDimitry Andric  def : Pat<(X86lock_add addr:$dst, (i16 -1)), (LOCK_DEC16m addr:$dst)>;
8460b57cec5SDimitry Andric  def : Pat<(X86lock_add addr:$dst, (i32 -1)), (LOCK_DEC32m addr:$dst)>;
8470b57cec5SDimitry Andric  def : Pat<(X86lock_sub addr:$dst, (i8  -1)), (LOCK_INC8m  addr:$dst)>;
8480b57cec5SDimitry Andric  def : Pat<(X86lock_sub addr:$dst, (i16 -1)), (LOCK_INC16m addr:$dst)>;
8490b57cec5SDimitry Andric  def : Pat<(X86lock_sub addr:$dst, (i32 -1)), (LOCK_INC32m addr:$dst)>;
850bdd1243dSDimitry Andric}
851bdd1243dSDimitry Andric
852bdd1243dSDimitry Andriclet Predicates = [UseIncDec, In64BitMode] in {
853bdd1243dSDimitry Andric  // Additional patterns for -1 constant.
854bdd1243dSDimitry Andric  def : Pat<(X86lock_add addr:$dst, (i64 -1)), (LOCK_DEC64m addr:$dst)>;
8550b57cec5SDimitry Andric  def : Pat<(X86lock_sub addr:$dst, (i64 -1)), (LOCK_INC64m addr:$dst)>;
8560b57cec5SDimitry Andric}
8570b57cec5SDimitry Andric
85881ad6265SDimitry Andric// Atomic bit test.
85981ad6265SDimitry Andricdef X86LBTest : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisPtrTy<1>,
86081ad6265SDimitry Andric                                     SDTCisVT<2, i8>, SDTCisVT<3, i32>]>;
86181ad6265SDimitry Andricdef x86bts : SDNode<"X86ISD::LBTS", X86LBTest,
86281ad6265SDimitry Andric                    [SDNPHasChain, SDNPMayLoad, SDNPMayStore, SDNPMemOperand]>;
86381ad6265SDimitry Andricdef x86btc : SDNode<"X86ISD::LBTC", X86LBTest,
86481ad6265SDimitry Andric                    [SDNPHasChain, SDNPMayLoad, SDNPMayStore, SDNPMemOperand]>;
86581ad6265SDimitry Andricdef x86btr : SDNode<"X86ISD::LBTR", X86LBTest,
86681ad6265SDimitry Andric                    [SDNPHasChain, SDNPMayLoad, SDNPMayStore, SDNPMemOperand]>;
86781ad6265SDimitry Andric
868bdd1243dSDimitry Andricdef X86LBTestRM : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisPtrTy<1>,
869bdd1243dSDimitry Andric                                       SDTCisInt<2>]>;
870bdd1243dSDimitry Andric
871bdd1243dSDimitry Andricdef x86_rm_bts : SDNode<"X86ISD::LBTS_RM", X86LBTestRM,
872bdd1243dSDimitry Andric                        [SDNPHasChain, SDNPMayLoad, SDNPMayStore, SDNPMemOperand]>;
873bdd1243dSDimitry Andricdef x86_rm_btc : SDNode<"X86ISD::LBTC_RM", X86LBTestRM,
874bdd1243dSDimitry Andric                        [SDNPHasChain, SDNPMayLoad, SDNPMayStore, SDNPMemOperand]>;
875bdd1243dSDimitry Andricdef x86_rm_btr : SDNode<"X86ISD::LBTR_RM", X86LBTestRM,
876bdd1243dSDimitry Andric                        [SDNPHasChain, SDNPMayLoad, SDNPMayStore, SDNPMemOperand]>;
877bdd1243dSDimitry Andric
878bdd1243dSDimitry Andric
87981ad6265SDimitry Andricmulticlass ATOMIC_LOGIC_OP<Format Form, string s> {
88081ad6265SDimitry Andric  let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1,
88181ad6265SDimitry Andric      SchedRW = [WriteBitTestSetRegRMW]  in {
88281ad6265SDimitry Andric    def 16m : Ii8<0xBA, Form, (outs), (ins i16mem:$src1, i8imm:$src2),
88381ad6265SDimitry Andric                  !strconcat(s, "{w}\t{$src2, $src1|$src1, $src2}"),
88481ad6265SDimitry Andric                  [(set EFLAGS, (!cast<SDNode>("x86" # s) addr:$src1, timm:$src2, (i32 16)))]>,
88581ad6265SDimitry Andric              OpSize16, TB, LOCK;
88681ad6265SDimitry Andric    def 32m : Ii8<0xBA, Form, (outs), (ins i32mem:$src1, i8imm:$src2),
88781ad6265SDimitry Andric                  !strconcat(s, "{l}\t{$src2, $src1|$src1, $src2}"),
88881ad6265SDimitry Andric                  [(set EFLAGS, (!cast<SDNode>("x86" # s) addr:$src1, timm:$src2, (i32 32)))]>,
88981ad6265SDimitry Andric              OpSize32, TB, LOCK;
89081ad6265SDimitry Andric    def 64m : RIi8<0xBA, Form, (outs), (ins i64mem:$src1, i8imm:$src2),
89181ad6265SDimitry Andric                   !strconcat(s, "{q}\t{$src2, $src1|$src1, $src2}"),
89281ad6265SDimitry Andric                   [(set EFLAGS, (!cast<SDNode>("x86" # s) addr:$src1, timm:$src2, (i32 64)))]>,
89381ad6265SDimitry Andric              TB, LOCK;
89481ad6265SDimitry Andric  }
89581ad6265SDimitry Andric}
89681ad6265SDimitry Andric
897bdd1243dSDimitry Andricmulticlass ATOMIC_LOGIC_OP_RM<bits<8> Opc8, string s> {
898bdd1243dSDimitry Andric  let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1,
899bdd1243dSDimitry Andric      SchedRW = [WriteBitTestSetRegRMW]  in {
9001ac55f4cSDimitry Andric    def 16rm : I<Opc8, MRMDestMem, (outs), (ins i16mem:$src1, GR16:$src2),
901bdd1243dSDimitry Andric                  !strconcat(s, "{w}\t{$src2, $src1|$src1, $src2}"),
902bdd1243dSDimitry Andric                  [(set EFLAGS, (!cast<SDNode>("x86_rm_" # s) addr:$src1, GR16:$src2))]>,
903bdd1243dSDimitry Andric               OpSize16, TB, LOCK;
9041ac55f4cSDimitry Andric    def 32rm : I<Opc8, MRMDestMem, (outs), (ins i32mem:$src1, GR32:$src2),
905bdd1243dSDimitry Andric                  !strconcat(s, "{l}\t{$src2, $src1|$src1, $src2}"),
906bdd1243dSDimitry Andric                  [(set EFLAGS, (!cast<SDNode>("x86_rm_" # s) addr:$src1, GR32:$src2))]>,
907bdd1243dSDimitry Andric               OpSize32, TB, LOCK;
9081ac55f4cSDimitry Andric    def 64rm : RI<Opc8, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2),
909bdd1243dSDimitry Andric                   !strconcat(s, "{q}\t{$src2, $src1|$src1, $src2}"),
910bdd1243dSDimitry Andric                   [(set EFLAGS, (!cast<SDNode>("x86_rm_" # s) addr:$src1, GR64:$src2))]>,
911bdd1243dSDimitry Andric               TB, LOCK;
912bdd1243dSDimitry Andric  }
913bdd1243dSDimitry Andric}
914bdd1243dSDimitry Andric
915bdd1243dSDimitry Andric
91681ad6265SDimitry Andricdefm LOCK_BTS : ATOMIC_LOGIC_OP<MRM5m, "bts">;
91781ad6265SDimitry Andricdefm LOCK_BTC : ATOMIC_LOGIC_OP<MRM7m, "btc">;
91881ad6265SDimitry Andricdefm LOCK_BTR : ATOMIC_LOGIC_OP<MRM6m, "btr">;
91981ad6265SDimitry Andric
920bdd1243dSDimitry Andricdefm LOCK_BTS_RM : ATOMIC_LOGIC_OP_RM<0xAB, "bts">;
921bdd1243dSDimitry Andricdefm LOCK_BTC_RM : ATOMIC_LOGIC_OP_RM<0xBB, "btc">;
922bdd1243dSDimitry Andricdefm LOCK_BTR_RM : ATOMIC_LOGIC_OP_RM<0xB3, "btr">;
923bdd1243dSDimitry Andric
9240b57cec5SDimitry Andric// Atomic compare and swap.
9250b57cec5SDimitry Andricmulticlass LCMPXCHG_BinOp<bits<8> Opc8, bits<8> Opc, Format Form,
9260b57cec5SDimitry Andric                          string mnemonic, SDPatternOperator frag> {
9270b57cec5SDimitry Andriclet isCodeGenOnly = 1, SchedRW = [WriteCMPXCHGRMW] in {
9280b57cec5SDimitry Andric  let Defs = [AL, EFLAGS], Uses = [AL] in
9290b57cec5SDimitry Andric  def NAME#8  : I<Opc8, Form, (outs), (ins i8mem:$ptr, GR8:$swap),
9300b57cec5SDimitry Andric                  !strconcat(mnemonic, "{b}\t{$swap, $ptr|$ptr, $swap}"),
9310b57cec5SDimitry Andric                  [(frag addr:$ptr, GR8:$swap, 1)]>, TB, LOCK;
9320b57cec5SDimitry Andric  let Defs = [AX, EFLAGS], Uses = [AX] in
9330b57cec5SDimitry Andric  def NAME#16 : I<Opc, Form, (outs), (ins i16mem:$ptr, GR16:$swap),
9340b57cec5SDimitry Andric                  !strconcat(mnemonic, "{w}\t{$swap, $ptr|$ptr, $swap}"),
9350b57cec5SDimitry Andric                  [(frag addr:$ptr, GR16:$swap, 2)]>, TB, OpSize16, LOCK;
9360b57cec5SDimitry Andric  let Defs = [EAX, EFLAGS], Uses = [EAX] in
9370b57cec5SDimitry Andric  def NAME#32 : I<Opc, Form, (outs), (ins i32mem:$ptr, GR32:$swap),
9380b57cec5SDimitry Andric                  !strconcat(mnemonic, "{l}\t{$swap, $ptr|$ptr, $swap}"),
9390b57cec5SDimitry Andric                  [(frag addr:$ptr, GR32:$swap, 4)]>, TB, OpSize32, LOCK;
9400b57cec5SDimitry Andric  let Defs = [RAX, EFLAGS], Uses = [RAX] in
9410b57cec5SDimitry Andric  def NAME#64 : RI<Opc, Form, (outs), (ins i64mem:$ptr, GR64:$swap),
9420b57cec5SDimitry Andric                   !strconcat(mnemonic, "{q}\t{$swap, $ptr|$ptr, $swap}"),
9430b57cec5SDimitry Andric                   [(frag addr:$ptr, GR64:$swap, 8)]>, TB, LOCK;
9440b57cec5SDimitry Andric}
9450b57cec5SDimitry Andric}
9460b57cec5SDimitry Andric
9470b57cec5SDimitry Andriclet Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EBX, ECX, EDX],
94881ad6265SDimitry Andric    Predicates = [HasCX8], SchedRW = [WriteCMPXCHGRMW],
949e8d8bef9SDimitry Andric    isCodeGenOnly = 1, usesCustomInserter = 1 in {
950e8d8bef9SDimitry Andricdef LCMPXCHG8B : I<0xC7, MRM1m, (outs), (ins i64mem:$ptr),
951e8d8bef9SDimitry Andric                   "cmpxchg8b\t$ptr",
952e8d8bef9SDimitry Andric                   [(X86cas8 addr:$ptr)]>, TB, LOCK;
953e8d8bef9SDimitry Andric}
954e8d8bef9SDimitry Andric
955e8d8bef9SDimitry Andriclet Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RBX, RCX, RDX],
95681ad6265SDimitry Andric    Predicates = [HasCX16,In64BitMode], SchedRW = [WriteCMPXCHGRMW],
957e8d8bef9SDimitry Andric    isCodeGenOnly = 1, mayLoad = 1, mayStore = 1, hasSideEffects = 0 in {
958e8d8bef9SDimitry Andricdef LCMPXCHG16B : RI<0xC7, MRM1m, (outs), (ins i128mem:$ptr),
959e8d8bef9SDimitry Andric                     "cmpxchg16b\t$ptr",
960e8d8bef9SDimitry Andric                     []>, TB, LOCK;
9610b57cec5SDimitry Andric}
9620b57cec5SDimitry Andric
9630b57cec5SDimitry Andric// This pseudo must be used when the frame uses RBX as
9640b57cec5SDimitry Andric// the base pointer. Indeed, in such situation RBX is a reserved
9650b57cec5SDimitry Andric// register and the register allocator will ignore any use/def of
9660b57cec5SDimitry Andric// it. In other words, the register will not fix the clobbering of
9670b57cec5SDimitry Andric// RBX that will happen when setting the arguments for the instrucion.
9680b57cec5SDimitry Andric//
9695ffd83dbSDimitry Andric// Unlike the actual related instruction, we mark that this one
970e8d8bef9SDimitry Andric// defines RBX (instead of using RBX).
9710b57cec5SDimitry Andric// The rationale is that we will define RBX during the expansion of
972e8d8bef9SDimitry Andric// the pseudo. The argument feeding RBX is rbx_input.
9730b57cec5SDimitry Andric//
974e8d8bef9SDimitry Andric// The additional argument, $rbx_save, is a temporary register used to
9750b57cec5SDimitry Andric// save the value of RBX across the actual instruction.
9760b57cec5SDimitry Andric//
977e8d8bef9SDimitry Andric// To make sure the register assigned to $rbx_save does not interfere with
9780b57cec5SDimitry Andric// the definition of the actual instruction, we use a definition $dst which
9790b57cec5SDimitry Andric// is tied to $rbx_save. That way, the live-range of $rbx_save spans across
9800b57cec5SDimitry Andric// the instruction and we are sure we will have a valid register to restore
9810b57cec5SDimitry Andric// the value of RBX.
9820b57cec5SDimitry Andriclet Defs = [RAX, RDX, RBX, EFLAGS], Uses = [RAX, RCX, RDX],
98381ad6265SDimitry Andric    Predicates = [HasCX16,In64BitMode], SchedRW = [WriteCMPXCHGRMW],
984e8d8bef9SDimitry Andric    isCodeGenOnly = 1, isPseudo = 1,
985e8d8bef9SDimitry Andric    mayLoad = 1, mayStore = 1, hasSideEffects = 0,
986e8d8bef9SDimitry Andric    Constraints = "$rbx_save = $dst" in {
9870b57cec5SDimitry Andricdef LCMPXCHG16B_SAVE_RBX :
9880b57cec5SDimitry Andric    I<0, Pseudo, (outs GR64:$dst),
989e8d8bef9SDimitry Andric      (ins i128mem:$ptr, GR64:$rbx_input, GR64:$rbx_save), "", []>;
9900b57cec5SDimitry Andric}
9910b57cec5SDimitry Andric
992e8d8bef9SDimitry Andric// Pseudo instruction that doesn't read/write RBX. Will be turned into either
993e8d8bef9SDimitry Andric// LCMPXCHG16B_SAVE_RBX or LCMPXCHG16B via a custom inserter.
994e8d8bef9SDimitry Andriclet Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RCX, RDX],
99581ad6265SDimitry Andric    Predicates = [HasCX16,In64BitMode], SchedRW = [WriteCMPXCHGRMW],
996e8d8bef9SDimitry Andric    isCodeGenOnly = 1, isPseudo = 1,
997e8d8bef9SDimitry Andric    mayLoad = 1, mayStore = 1, hasSideEffects = 0,
998e8d8bef9SDimitry Andric    usesCustomInserter = 1 in {
999e8d8bef9SDimitry Andricdef LCMPXCHG16B_NO_RBX :
1000e8d8bef9SDimitry Andric    I<0, Pseudo, (outs), (ins i128mem:$ptr, GR64:$rbx_input), "",
1001e8d8bef9SDimitry Andric      [(X86cas16 addr:$ptr, GR64:$rbx_input)]>;
1002e8d8bef9SDimitry Andric}
1003e8d8bef9SDimitry Andric
1004e8d8bef9SDimitry Andric// This pseudo must be used when the frame uses RBX/EBX as
1005e8d8bef9SDimitry Andric// the base pointer.
1006e8d8bef9SDimitry Andric// cf comment for LCMPXCHG16B_SAVE_RBX.
1007e8d8bef9SDimitry Andriclet Defs = [EBX], Uses = [ECX, EAX],
1008e8d8bef9SDimitry Andric    Predicates = [HasMWAITX], SchedRW = [WriteSystem],
1009e8d8bef9SDimitry Andric    isCodeGenOnly = 1, isPseudo = 1, Constraints = "$rbx_save = $dst" in {
1010e8d8bef9SDimitry Andricdef MWAITX_SAVE_RBX :
1011e8d8bef9SDimitry Andric    I<0, Pseudo, (outs GR64:$dst),
1012e8d8bef9SDimitry Andric      (ins GR32:$ebx_input, GR64:$rbx_save),
1013e8d8bef9SDimitry Andric      "mwaitx",
1014e8d8bef9SDimitry Andric      []>;
1015e8d8bef9SDimitry Andric}
1016e8d8bef9SDimitry Andric
1017e8d8bef9SDimitry Andric// Pseudo mwaitx instruction to use for custom insertion.
1018e8d8bef9SDimitry Andriclet Predicates = [HasMWAITX], SchedRW = [WriteSystem],
1019e8d8bef9SDimitry Andric    isCodeGenOnly = 1, isPseudo = 1,
1020e8d8bef9SDimitry Andric    usesCustomInserter = 1 in {
1021e8d8bef9SDimitry Andricdef MWAITX :
1022e8d8bef9SDimitry Andric    I<0, Pseudo, (outs), (ins GR32:$ecx, GR32:$eax, GR32:$ebx),
1023e8d8bef9SDimitry Andric      "mwaitx",
1024e8d8bef9SDimitry Andric      [(int_x86_mwaitx GR32:$ecx, GR32:$eax, GR32:$ebx)]>;
1025e8d8bef9SDimitry Andric}
1026e8d8bef9SDimitry Andric
1027e8d8bef9SDimitry Andric
10280b57cec5SDimitry Andricdefm LCMPXCHG : LCMPXCHG_BinOp<0xB0, 0xB1, MRMDestMem, "cmpxchg", X86cas>;
10290b57cec5SDimitry Andric
10300b57cec5SDimitry Andric// Atomic exchange and add
1031fe6060f1SDimitry Andricmulticlass ATOMIC_RMW_BINOP<bits<8> opc8, bits<8> opc, string mnemonic,
10320b57cec5SDimitry Andric                            string frag> {
1033fe6060f1SDimitry Andric  let Constraints = "$val = $dst", Defs = [EFLAGS], mayLoad = 1, mayStore = 1,
1034fe6060f1SDimitry Andric      isCodeGenOnly = 1, SchedRW = [WriteALURMW] in {
10350b57cec5SDimitry Andric    def NAME#8  : I<opc8, MRMSrcMem, (outs GR8:$dst),
10360b57cec5SDimitry Andric                    (ins GR8:$val, i8mem:$ptr),
10370b57cec5SDimitry Andric                    !strconcat(mnemonic, "{b}\t{$val, $ptr|$ptr, $val}"),
10380b57cec5SDimitry Andric                    [(set GR8:$dst,
10390fca6ea1SDimitry Andric                          (!cast<PatFrag>(frag # "_i8") addr:$ptr, GR8:$val))]>;
10400b57cec5SDimitry Andric    def NAME#16 : I<opc, MRMSrcMem, (outs GR16:$dst),
10410b57cec5SDimitry Andric                    (ins GR16:$val, i16mem:$ptr),
10420b57cec5SDimitry Andric                    !strconcat(mnemonic, "{w}\t{$val, $ptr|$ptr, $val}"),
10430b57cec5SDimitry Andric                    [(set
10440b57cec5SDimitry Andric                       GR16:$dst,
10450fca6ea1SDimitry Andric                       (!cast<PatFrag>(frag # "_i16") addr:$ptr, GR16:$val))]>,
10460b57cec5SDimitry Andric                    OpSize16;
10470b57cec5SDimitry Andric    def NAME#32 : I<opc, MRMSrcMem, (outs GR32:$dst),
10480b57cec5SDimitry Andric                    (ins GR32:$val, i32mem:$ptr),
10490b57cec5SDimitry Andric                    !strconcat(mnemonic, "{l}\t{$val, $ptr|$ptr, $val}"),
10500b57cec5SDimitry Andric                    [(set
10510b57cec5SDimitry Andric                       GR32:$dst,
10520fca6ea1SDimitry Andric                       (!cast<PatFrag>(frag # "_i32") addr:$ptr, GR32:$val))]>,
10530b57cec5SDimitry Andric                    OpSize32;
10540b57cec5SDimitry Andric    def NAME#64 : RI<opc, MRMSrcMem, (outs GR64:$dst),
10550b57cec5SDimitry Andric                     (ins GR64:$val, i64mem:$ptr),
10560b57cec5SDimitry Andric                     !strconcat(mnemonic, "{q}\t{$val, $ptr|$ptr, $val}"),
10570b57cec5SDimitry Andric                     [(set
10580b57cec5SDimitry Andric                        GR64:$dst,
10590fca6ea1SDimitry Andric                        (!cast<PatFrag>(frag # "_i64") addr:$ptr, GR64:$val))]>;
10600b57cec5SDimitry Andric  }
10610b57cec5SDimitry Andric}
10620b57cec5SDimitry Andric
1063fe6060f1SDimitry Andricdefm LXADD : ATOMIC_RMW_BINOP<0xc0, 0xc1, "xadd", "atomic_load_add">, TB, LOCK;
10640b57cec5SDimitry Andric
10650b57cec5SDimitry Andric/* The following multiclass tries to make sure that in code like
10660b57cec5SDimitry Andric *    x.store (immediate op x.load(acquire), release)
10670b57cec5SDimitry Andric * and
10680b57cec5SDimitry Andric *    x.store (register op x.load(acquire), release)
10690b57cec5SDimitry Andric * an operation directly on memory is generated instead of wasting a register.
10700b57cec5SDimitry Andric * It is not automatic as atomic_store/load are only lowered to MOV instructions
10710b57cec5SDimitry Andric * extremely late to prevent them from being accidentally reordered in the backend
10720b57cec5SDimitry Andric * (see below the RELEASE_MOV* / ACQUIRE_MOV* pseudo-instructions)
10730b57cec5SDimitry Andric */
10740b57cec5SDimitry Andricmulticlass RELEASE_BINOP_MI<string Name, SDNode op> {
10755f757f3fSDimitry Andric  def : Pat<(atomic_store_8 (op (atomic_load_8 addr:$dst), (i8 imm:$src)),
10765f757f3fSDimitry Andric                            addr:$dst),
10770b57cec5SDimitry Andric            (!cast<Instruction>(Name#"8mi") addr:$dst, imm:$src)>;
10785f757f3fSDimitry Andric  def : Pat<(atomic_store_16 (op (atomic_load_16 addr:$dst), (i16 imm:$src)),
10795f757f3fSDimitry Andric                             addr:$dst),
10800b57cec5SDimitry Andric            (!cast<Instruction>(Name#"16mi") addr:$dst, imm:$src)>;
10815f757f3fSDimitry Andric  def : Pat<(atomic_store_32 (op (atomic_load_32 addr:$dst), (i32 imm:$src)),
10825f757f3fSDimitry Andric                             addr:$dst),
10830b57cec5SDimitry Andric            (!cast<Instruction>(Name#"32mi") addr:$dst, imm:$src)>;
10845f757f3fSDimitry Andric  def : Pat<(atomic_store_64 (op (atomic_load_64 addr:$dst), (i64immSExt32:$src)),
10855f757f3fSDimitry Andric                             addr:$dst),
10860b57cec5SDimitry Andric            (!cast<Instruction>(Name#"64mi32") addr:$dst, (i64immSExt32:$src))>;
10875f757f3fSDimitry Andric  def : Pat<(atomic_store_8 (op (atomic_load_8 addr:$dst), (i8 GR8:$src)), addr:$dst),
10880b57cec5SDimitry Andric            (!cast<Instruction>(Name#"8mr") addr:$dst, GR8:$src)>;
10895f757f3fSDimitry Andric  def : Pat<(atomic_store_16 (op (atomic_load_16 addr:$dst), (i16 GR16:$src)),
10905f757f3fSDimitry Andric                             addr:$dst),
10910b57cec5SDimitry Andric            (!cast<Instruction>(Name#"16mr") addr:$dst, GR16:$src)>;
10925f757f3fSDimitry Andric  def : Pat<(atomic_store_32 (op (atomic_load_32 addr:$dst), (i32 GR32:$src)),
10935f757f3fSDimitry Andric                             addr:$dst),
10940b57cec5SDimitry Andric            (!cast<Instruction>(Name#"32mr") addr:$dst, GR32:$src)>;
10955f757f3fSDimitry Andric  def : Pat<(atomic_store_64 (op (atomic_load_64 addr:$dst), (i64 GR64:$src)),
10965f757f3fSDimitry Andric                             addr:$dst),
10970b57cec5SDimitry Andric            (!cast<Instruction>(Name#"64mr") addr:$dst, GR64:$src)>;
10980b57cec5SDimitry Andric}
10990b57cec5SDimitry Andricdefm : RELEASE_BINOP_MI<"ADD", add>;
11000b57cec5SDimitry Andricdefm : RELEASE_BINOP_MI<"AND", and>;
11010b57cec5SDimitry Andricdefm : RELEASE_BINOP_MI<"OR",  or>;
11020b57cec5SDimitry Andricdefm : RELEASE_BINOP_MI<"XOR", xor>;
11030b57cec5SDimitry Andricdefm : RELEASE_BINOP_MI<"SUB", sub>;
11040b57cec5SDimitry Andric
11050b57cec5SDimitry Andric// Atomic load + floating point patterns.
11060b57cec5SDimitry Andric// FIXME: This could also handle SIMD operations with *ps and *pd instructions.
11070b57cec5SDimitry Andricmulticlass ATOMIC_LOAD_FP_BINOP_MI<string Name, SDNode op> {
11080b57cec5SDimitry Andric  def : Pat<(op FR32:$src1, (bitconvert (i32 (atomic_load_32 addr:$src2)))),
11090b57cec5SDimitry Andric            (!cast<Instruction>(Name#"SSrm") FR32:$src1, addr:$src2)>,
11100b57cec5SDimitry Andric            Requires<[UseSSE1]>;
11110b57cec5SDimitry Andric  def : Pat<(op FR32:$src1, (bitconvert (i32 (atomic_load_32 addr:$src2)))),
11120b57cec5SDimitry Andric            (!cast<Instruction>("V"#Name#"SSrm") FR32:$src1, addr:$src2)>,
11130b57cec5SDimitry Andric            Requires<[UseAVX]>;
11140b57cec5SDimitry Andric  def : Pat<(op FR32X:$src1, (bitconvert (i32 (atomic_load_32 addr:$src2)))),
11150b57cec5SDimitry Andric            (!cast<Instruction>("V"#Name#"SSZrm") FR32X:$src1, addr:$src2)>,
11160b57cec5SDimitry Andric            Requires<[HasAVX512]>;
11170b57cec5SDimitry Andric
11180b57cec5SDimitry Andric  def : Pat<(op FR64:$src1, (bitconvert (i64 (atomic_load_64 addr:$src2)))),
11190b57cec5SDimitry Andric            (!cast<Instruction>(Name#"SDrm") FR64:$src1, addr:$src2)>,
11200b57cec5SDimitry Andric            Requires<[UseSSE1]>;
11210b57cec5SDimitry Andric  def : Pat<(op FR64:$src1, (bitconvert (i64 (atomic_load_64 addr:$src2)))),
11220b57cec5SDimitry Andric            (!cast<Instruction>("V"#Name#"SDrm") FR64:$src1, addr:$src2)>,
11230b57cec5SDimitry Andric            Requires<[UseAVX]>;
11240b57cec5SDimitry Andric  def : Pat<(op FR64X:$src1, (bitconvert (i64 (atomic_load_64 addr:$src2)))),
11250b57cec5SDimitry Andric            (!cast<Instruction>("V"#Name#"SDZrm") FR64X:$src1, addr:$src2)>,
11260b57cec5SDimitry Andric            Requires<[HasAVX512]>;
11270b57cec5SDimitry Andric}
11280b57cec5SDimitry Andricdefm : ATOMIC_LOAD_FP_BINOP_MI<"ADD", fadd>;
11290fca6ea1SDimitry Andricdefm : ATOMIC_LOAD_FP_BINOP_MI<"SUB", fsub>;
11300fca6ea1SDimitry Andricdefm : ATOMIC_LOAD_FP_BINOP_MI<"MUL", fmul>;
11310fca6ea1SDimitry Andricdefm : ATOMIC_LOAD_FP_BINOP_MI<"DIV", fdiv>;
11320b57cec5SDimitry Andric
11330b57cec5SDimitry Andricmulticlass RELEASE_UNOP<string Name, dag dag8, dag dag16, dag dag32,
11340b57cec5SDimitry Andric                        dag dag64> {
11355f757f3fSDimitry Andric  def : Pat<(atomic_store_8 dag8, addr:$dst),
11360b57cec5SDimitry Andric            (!cast<Instruction>(Name#8m) addr:$dst)>;
11375f757f3fSDimitry Andric  def : Pat<(atomic_store_16 dag16, addr:$dst),
11380b57cec5SDimitry Andric            (!cast<Instruction>(Name#16m) addr:$dst)>;
11395f757f3fSDimitry Andric  def : Pat<(atomic_store_32 dag32, addr:$dst),
11400b57cec5SDimitry Andric            (!cast<Instruction>(Name#32m) addr:$dst)>;
11415f757f3fSDimitry Andric  def : Pat<(atomic_store_64 dag64, addr:$dst),
11420b57cec5SDimitry Andric            (!cast<Instruction>(Name#64m) addr:$dst)>;
11430b57cec5SDimitry Andric}
11440b57cec5SDimitry Andric
11450b57cec5SDimitry Andriclet Predicates = [UseIncDec] in {
11460b57cec5SDimitry Andric  defm : RELEASE_UNOP<"INC",
11470b57cec5SDimitry Andric      (add (atomic_load_8  addr:$dst), (i8 1)),
11480b57cec5SDimitry Andric      (add (atomic_load_16 addr:$dst), (i16 1)),
11490b57cec5SDimitry Andric      (add (atomic_load_32 addr:$dst), (i32 1)),
11500b57cec5SDimitry Andric      (add (atomic_load_64 addr:$dst), (i64 1))>;
11510b57cec5SDimitry Andric  defm : RELEASE_UNOP<"DEC",
11520b57cec5SDimitry Andric      (add (atomic_load_8  addr:$dst), (i8 -1)),
11530b57cec5SDimitry Andric      (add (atomic_load_16 addr:$dst), (i16 -1)),
11540b57cec5SDimitry Andric      (add (atomic_load_32 addr:$dst), (i32 -1)),
11550b57cec5SDimitry Andric      (add (atomic_load_64 addr:$dst), (i64 -1))>;
11560b57cec5SDimitry Andric}
11570b57cec5SDimitry Andric
11580b57cec5SDimitry Andricdefm : RELEASE_UNOP<"NEG",
11590b57cec5SDimitry Andric    (ineg (i8 (atomic_load_8  addr:$dst))),
11600b57cec5SDimitry Andric    (ineg (i16 (atomic_load_16 addr:$dst))),
11610b57cec5SDimitry Andric    (ineg (i32 (atomic_load_32 addr:$dst))),
11620b57cec5SDimitry Andric    (ineg (i64 (atomic_load_64 addr:$dst)))>;
11630b57cec5SDimitry Andricdefm : RELEASE_UNOP<"NOT",
11640b57cec5SDimitry Andric    (not (i8 (atomic_load_8  addr:$dst))),
11650b57cec5SDimitry Andric    (not (i16 (atomic_load_16 addr:$dst))),
11660b57cec5SDimitry Andric    (not (i32 (atomic_load_32 addr:$dst))),
11670b57cec5SDimitry Andric    (not (i64 (atomic_load_64 addr:$dst)))>;
11680b57cec5SDimitry Andric
11695f757f3fSDimitry Andricdef : Pat<(atomic_store_8 (i8 imm:$src), addr:$dst),
11700b57cec5SDimitry Andric          (MOV8mi addr:$dst, imm:$src)>;
11715f757f3fSDimitry Andricdef : Pat<(atomic_store_16 (i16 imm:$src), addr:$dst),
11720b57cec5SDimitry Andric          (MOV16mi addr:$dst, imm:$src)>;
11735f757f3fSDimitry Andricdef : Pat<(atomic_store_32 (i32 imm:$src), addr:$dst),
11740b57cec5SDimitry Andric          (MOV32mi addr:$dst, imm:$src)>;
11755f757f3fSDimitry Andricdef : Pat<(atomic_store_64 (i64immSExt32:$src), addr:$dst),
11760b57cec5SDimitry Andric          (MOV64mi32 addr:$dst, i64immSExt32:$src)>;
11770b57cec5SDimitry Andric
11785f757f3fSDimitry Andricdef : Pat<(atomic_store_8 GR8:$src, addr:$dst),
11790b57cec5SDimitry Andric          (MOV8mr addr:$dst, GR8:$src)>;
11805f757f3fSDimitry Andricdef : Pat<(atomic_store_16 GR16:$src, addr:$dst),
11810b57cec5SDimitry Andric          (MOV16mr addr:$dst, GR16:$src)>;
11825f757f3fSDimitry Andricdef : Pat<(atomic_store_32 GR32:$src, addr:$dst),
11830b57cec5SDimitry Andric          (MOV32mr addr:$dst, GR32:$src)>;
11845f757f3fSDimitry Andricdef : Pat<(atomic_store_64 GR64:$src, addr:$dst),
11850b57cec5SDimitry Andric          (MOV64mr addr:$dst, GR64:$src)>;
11860b57cec5SDimitry Andric
11870b57cec5SDimitry Andricdef : Pat<(i8  (atomic_load_8 addr:$src)),  (MOV8rm addr:$src)>;
11880b57cec5SDimitry Andricdef : Pat<(i16 (atomic_load_16 addr:$src)), (MOV16rm addr:$src)>;
11890b57cec5SDimitry Andricdef : Pat<(i32 (atomic_load_32 addr:$src)), (MOV32rm addr:$src)>;
11900b57cec5SDimitry Andricdef : Pat<(i64 (atomic_load_64 addr:$src)), (MOV64rm addr:$src)>;
11910b57cec5SDimitry Andric
11920b57cec5SDimitry Andric// Floating point loads/stores.
11935f757f3fSDimitry Andricdef : Pat<(atomic_store_32 (i32 (bitconvert (f32 FR32:$src))), addr:$dst),
11940b57cec5SDimitry Andric          (MOVSSmr addr:$dst, FR32:$src)>, Requires<[UseSSE1]>;
11955f757f3fSDimitry Andricdef : Pat<(atomic_store_32 (i32 (bitconvert (f32 FR32:$src))), addr:$dst),
11960b57cec5SDimitry Andric          (VMOVSSmr addr:$dst, FR32:$src)>, Requires<[UseAVX]>;
11975f757f3fSDimitry Andricdef : Pat<(atomic_store_32 (i32 (bitconvert (f32 FR32:$src))), addr:$dst),
11980b57cec5SDimitry Andric          (VMOVSSZmr addr:$dst, FR32:$src)>, Requires<[HasAVX512]>;
11990b57cec5SDimitry Andric
12005f757f3fSDimitry Andricdef : Pat<(atomic_store_64 (i64 (bitconvert (f64 FR64:$src))), addr:$dst),
12010b57cec5SDimitry Andric          (MOVSDmr addr:$dst, FR64:$src)>, Requires<[UseSSE2]>;
12025f757f3fSDimitry Andricdef : Pat<(atomic_store_64 (i64 (bitconvert (f64 FR64:$src))), addr:$dst),
12030b57cec5SDimitry Andric          (VMOVSDmr addr:$dst, FR64:$src)>, Requires<[UseAVX]>;
12045f757f3fSDimitry Andricdef : Pat<(atomic_store_64 (i64 (bitconvert (f64 FR64:$src))), addr:$dst),
12050b57cec5SDimitry Andric          (VMOVSDmr addr:$dst, FR64:$src)>, Requires<[HasAVX512]>;
12060b57cec5SDimitry Andric
12070b57cec5SDimitry Andricdef : Pat<(f32 (bitconvert (i32 (atomic_load_32 addr:$src)))),
12080b57cec5SDimitry Andric          (MOVSSrm_alt addr:$src)>, Requires<[UseSSE1]>;
12090b57cec5SDimitry Andricdef : Pat<(f32 (bitconvert (i32 (atomic_load_32 addr:$src)))),
12100b57cec5SDimitry Andric          (VMOVSSrm_alt addr:$src)>, Requires<[UseAVX]>;
12110b57cec5SDimitry Andricdef : Pat<(f32 (bitconvert (i32 (atomic_load_32 addr:$src)))),
12120b57cec5SDimitry Andric          (VMOVSSZrm_alt addr:$src)>, Requires<[HasAVX512]>;
12130b57cec5SDimitry Andric
12140b57cec5SDimitry Andricdef : Pat<(f64 (bitconvert (i64 (atomic_load_64 addr:$src)))),
12150b57cec5SDimitry Andric          (MOVSDrm_alt addr:$src)>, Requires<[UseSSE2]>;
12160b57cec5SDimitry Andricdef : Pat<(f64 (bitconvert (i64 (atomic_load_64 addr:$src)))),
12170b57cec5SDimitry Andric          (VMOVSDrm_alt addr:$src)>, Requires<[UseAVX]>;
12180b57cec5SDimitry Andricdef : Pat<(f64 (bitconvert (i64 (atomic_load_64 addr:$src)))),
12190b57cec5SDimitry Andric          (VMOVSDZrm_alt addr:$src)>, Requires<[HasAVX512]>;
12200b57cec5SDimitry Andric
12210b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
12220b57cec5SDimitry Andric// DAG Pattern Matching Rules
12230b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
12240b57cec5SDimitry Andric
12250b57cec5SDimitry Andric// Use AND/OR to store 0/-1 in memory when optimizing for minsize. This saves
12260b57cec5SDimitry Andric// binary size compared to a regular MOV, but it introduces an unnecessary
12270b57cec5SDimitry Andric// load, so is not suitable for regular or optsize functions.
12280b57cec5SDimitry Andriclet Predicates = [OptForMinSize] in {
122906c3fb27SDimitry Andricdef : Pat<(simple_store (i16 0), addr:$dst), (AND16mi addr:$dst, 0)>;
123006c3fb27SDimitry Andricdef : Pat<(simple_store (i32 0), addr:$dst), (AND32mi addr:$dst, 0)>;
123106c3fb27SDimitry Andricdef : Pat<(simple_store (i64 0), addr:$dst), (AND64mi32 addr:$dst, 0)>;
123206c3fb27SDimitry Andricdef : Pat<(simple_store (i16 -1), addr:$dst), (OR16mi addr:$dst, -1)>;
123306c3fb27SDimitry Andricdef : Pat<(simple_store (i32 -1), addr:$dst), (OR32mi addr:$dst, -1)>;
123406c3fb27SDimitry Andricdef : Pat<(simple_store (i64 -1), addr:$dst), (OR64mi32 addr:$dst, -1)>;
12350b57cec5SDimitry Andric}
12360b57cec5SDimitry Andric
12370b57cec5SDimitry Andric// In kernel code model, we can get the address of a label
12380b57cec5SDimitry Andric// into a register with 'movq'.  FIXME: This is a hack, the 'imm' predicate of
12390b57cec5SDimitry Andric// the MOV64ri32 should accept these.
12400b57cec5SDimitry Andricdef : Pat<(i64 (X86Wrapper tconstpool  :$dst)),
12410b57cec5SDimitry Andric          (MOV64ri32 tconstpool  :$dst)>, Requires<[KernelCode]>;
12420b57cec5SDimitry Andricdef : Pat<(i64 (X86Wrapper tjumptable  :$dst)),
12430b57cec5SDimitry Andric          (MOV64ri32 tjumptable  :$dst)>, Requires<[KernelCode]>;
12440b57cec5SDimitry Andricdef : Pat<(i64 (X86Wrapper tglobaladdr :$dst)),
12450b57cec5SDimitry Andric          (MOV64ri32 tglobaladdr :$dst)>, Requires<[KernelCode]>;
12460b57cec5SDimitry Andricdef : Pat<(i64 (X86Wrapper texternalsym:$dst)),
12470b57cec5SDimitry Andric          (MOV64ri32 texternalsym:$dst)>, Requires<[KernelCode]>;
12480b57cec5SDimitry Andricdef : Pat<(i64 (X86Wrapper mcsym:$dst)),
12490b57cec5SDimitry Andric          (MOV64ri32 mcsym:$dst)>, Requires<[KernelCode]>;
12500b57cec5SDimitry Andricdef : Pat<(i64 (X86Wrapper tblockaddress:$dst)),
12510b57cec5SDimitry Andric          (MOV64ri32 tblockaddress:$dst)>, Requires<[KernelCode]>;
12520b57cec5SDimitry Andric
12530b57cec5SDimitry Andric// If we have small model and -static mode, it is safe to store global addresses
12540b57cec5SDimitry Andric// directly as immediates.  FIXME: This is really a hack, the 'imm' predicate
12550b57cec5SDimitry Andric// for MOV64mi32 should handle this sort of thing.
12560b57cec5SDimitry Andricdef : Pat<(store (i64 (X86Wrapper tconstpool:$src)), addr:$dst),
12570b57cec5SDimitry Andric          (MOV64mi32 addr:$dst, tconstpool:$src)>,
12580b57cec5SDimitry Andric          Requires<[NearData, IsNotPIC]>;
12590b57cec5SDimitry Andricdef : Pat<(store (i64 (X86Wrapper tjumptable:$src)), addr:$dst),
12600b57cec5SDimitry Andric          (MOV64mi32 addr:$dst, tjumptable:$src)>,
12610b57cec5SDimitry Andric          Requires<[NearData, IsNotPIC]>;
12620b57cec5SDimitry Andricdef : Pat<(store (i64 (X86Wrapper tglobaladdr:$src)), addr:$dst),
12630b57cec5SDimitry Andric          (MOV64mi32 addr:$dst, tglobaladdr:$src)>,
12640b57cec5SDimitry Andric          Requires<[NearData, IsNotPIC]>;
12650b57cec5SDimitry Andricdef : Pat<(store (i64 (X86Wrapper texternalsym:$src)), addr:$dst),
12660b57cec5SDimitry Andric          (MOV64mi32 addr:$dst, texternalsym:$src)>,
12670b57cec5SDimitry Andric          Requires<[NearData, IsNotPIC]>;
12680b57cec5SDimitry Andricdef : Pat<(store (i64 (X86Wrapper mcsym:$src)), addr:$dst),
12690b57cec5SDimitry Andric          (MOV64mi32 addr:$dst, mcsym:$src)>,
12700b57cec5SDimitry Andric          Requires<[NearData, IsNotPIC]>;
12710b57cec5SDimitry Andricdef : Pat<(store (i64 (X86Wrapper tblockaddress:$src)), addr:$dst),
12720b57cec5SDimitry Andric          (MOV64mi32 addr:$dst, tblockaddress:$src)>,
12730b57cec5SDimitry Andric          Requires<[NearData, IsNotPIC]>;
12740b57cec5SDimitry Andric
12750b57cec5SDimitry Andricdef : Pat<(i32 (X86RecoverFrameAlloc mcsym:$dst)), (MOV32ri mcsym:$dst)>;
12760b57cec5SDimitry Andricdef : Pat<(i64 (X86RecoverFrameAlloc mcsym:$dst)), (MOV64ri mcsym:$dst)>;
12770b57cec5SDimitry Andric
12780b57cec5SDimitry Andric// Calls
12790b57cec5SDimitry Andric
12800b57cec5SDimitry Andric// tls has some funny stuff here...
12810b57cec5SDimitry Andric// This corresponds to movabs $foo@tpoff, %rax
12820b57cec5SDimitry Andricdef : Pat<(i64 (X86Wrapper tglobaltlsaddr :$dst)),
12830b57cec5SDimitry Andric          (MOV64ri32 tglobaltlsaddr :$dst)>;
12840b57cec5SDimitry Andric// This corresponds to add $foo@tpoff, %rax
12850b57cec5SDimitry Andricdef : Pat<(add GR64:$src1, (X86Wrapper tglobaltlsaddr :$dst)),
12860b57cec5SDimitry Andric          (ADD64ri32 GR64:$src1, tglobaltlsaddr :$dst)>;
12870b57cec5SDimitry Andric
12880b57cec5SDimitry Andric
12890b57cec5SDimitry Andric// Direct PC relative function call for small code model. 32-bit displacement
12900b57cec5SDimitry Andric// sign extended to 64-bit.
12910b57cec5SDimitry Andricdef : Pat<(X86call (i64 tglobaladdr:$dst)),
12920b57cec5SDimitry Andric          (CALL64pcrel32 tglobaladdr:$dst)>;
12930b57cec5SDimitry Andricdef : Pat<(X86call (i64 texternalsym:$dst)),
12940b57cec5SDimitry Andric          (CALL64pcrel32 texternalsym:$dst)>;
12950b57cec5SDimitry Andric
1296349cc55cSDimitry Andricdef : Pat<(X86call_rvmarker (i64 tglobaladdr:$rvfunc), (i64 texternalsym:$dst)),
1297349cc55cSDimitry Andric          (CALL64pcrel32_RVMARKER tglobaladdr:$rvfunc, texternalsym:$dst)>;
1298349cc55cSDimitry Andricdef : Pat<(X86call_rvmarker (i64 tglobaladdr:$rvfunc), (i64 tglobaladdr:$dst)),
1299349cc55cSDimitry Andric          (CALL64pcrel32_RVMARKER tglobaladdr:$rvfunc, tglobaladdr:$dst)>;
1300fe6060f1SDimitry Andric
1301fe6060f1SDimitry Andric
13020b57cec5SDimitry Andric// Tailcall stuff. The TCRETURN instructions execute after the epilog, so they
13030b57cec5SDimitry Andric// can never use callee-saved registers. That is the purpose of the GR64_TC
13040b57cec5SDimitry Andric// register classes.
13050b57cec5SDimitry Andric//
13060b57cec5SDimitry Andric// The only volatile register that is never used by the calling convention is
13070b57cec5SDimitry Andric// %r11. This happens when calling a vararg function with 6 arguments.
13080b57cec5SDimitry Andric//
13090b57cec5SDimitry Andric// Match an X86tcret that uses less than 7 volatile registers.
1310e8d8bef9SDimitry Andricdef : Pat<(X86tcret ptr_rc_tailcall:$dst, timm:$off),
1311e8d8bef9SDimitry Andric          (TCRETURNri ptr_rc_tailcall:$dst, timm:$off)>,
13120946e70aSDimitry Andric          Requires<[Not64BitMode, NotUseIndirectThunkCalls]>;
13130b57cec5SDimitry Andric
13140b57cec5SDimitry Andric// FIXME: This is disabled for 32-bit PIC mode because the global base
13150b57cec5SDimitry Andric// register which is part of the address mode may be assigned a
13160b57cec5SDimitry Andric// callee-saved register.
131781ad6265SDimitry Andric// Similar to X86tcret_6regs, here we only have 1 register left
131881ad6265SDimitry Andricdef : Pat<(X86tcret_1reg (load addr:$dst), timm:$off),
1319e8d8bef9SDimitry Andric          (TCRETURNmi addr:$dst, timm:$off)>,
13200946e70aSDimitry Andric          Requires<[Not64BitMode, IsNotPIC, NotUseIndirectThunkCalls]>;
13210b57cec5SDimitry Andric
1322e8d8bef9SDimitry Andricdef : Pat<(X86tcret (i32 tglobaladdr:$dst), timm:$off),
1323e8d8bef9SDimitry Andric          (TCRETURNdi tglobaladdr:$dst, timm:$off)>,
13240b57cec5SDimitry Andric          Requires<[NotLP64]>;
13250b57cec5SDimitry Andric
1326e8d8bef9SDimitry Andricdef : Pat<(X86tcret (i32 texternalsym:$dst), timm:$off),
1327e8d8bef9SDimitry Andric          (TCRETURNdi texternalsym:$dst, timm:$off)>,
13280b57cec5SDimitry Andric          Requires<[NotLP64]>;
13290b57cec5SDimitry Andric
1330e8d8bef9SDimitry Andricdef : Pat<(X86tcret ptr_rc_tailcall:$dst, timm:$off),
1331e8d8bef9SDimitry Andric          (TCRETURNri64 ptr_rc_tailcall:$dst, timm:$off)>,
13320946e70aSDimitry Andric          Requires<[In64BitMode, NotUseIndirectThunkCalls]>;
13330b57cec5SDimitry Andric
13340b57cec5SDimitry Andric// Don't fold loads into X86tcret requiring more than 6 regs.
13350b57cec5SDimitry Andric// There wouldn't be enough scratch registers for base+index.
1336e8d8bef9SDimitry Andricdef : Pat<(X86tcret_6regs (load addr:$dst), timm:$off),
1337e8d8bef9SDimitry Andric          (TCRETURNmi64 addr:$dst, timm:$off)>,
13380946e70aSDimitry Andric          Requires<[In64BitMode, NotUseIndirectThunkCalls]>;
13390b57cec5SDimitry Andric
1340e8d8bef9SDimitry Andricdef : Pat<(X86tcret ptr_rc_tailcall:$dst, timm:$off),
1341e8d8bef9SDimitry Andric          (INDIRECT_THUNK_TCRETURN64 ptr_rc_tailcall:$dst, timm:$off)>,
13420946e70aSDimitry Andric          Requires<[In64BitMode, UseIndirectThunkCalls]>;
13430b57cec5SDimitry Andric
1344e8d8bef9SDimitry Andricdef : Pat<(X86tcret ptr_rc_tailcall:$dst, timm:$off),
1345e8d8bef9SDimitry Andric          (INDIRECT_THUNK_TCRETURN32 ptr_rc_tailcall:$dst, timm:$off)>,
13460946e70aSDimitry Andric          Requires<[Not64BitMode, UseIndirectThunkCalls]>;
13470b57cec5SDimitry Andric
1348e8d8bef9SDimitry Andricdef : Pat<(X86tcret (i64 tglobaladdr:$dst), timm:$off),
1349e8d8bef9SDimitry Andric          (TCRETURNdi64 tglobaladdr:$dst, timm:$off)>,
13500b57cec5SDimitry Andric          Requires<[IsLP64]>;
13510b57cec5SDimitry Andric
1352e8d8bef9SDimitry Andricdef : Pat<(X86tcret (i64 texternalsym:$dst), timm:$off),
1353e8d8bef9SDimitry Andric          (TCRETURNdi64 texternalsym:$dst, timm:$off)>,
13540b57cec5SDimitry Andric          Requires<[IsLP64]>;
13550b57cec5SDimitry Andric
13560b57cec5SDimitry Andric// Normal calls, with various flavors of addresses.
13570b57cec5SDimitry Andricdef : Pat<(X86call (i32 tglobaladdr:$dst)),
13580b57cec5SDimitry Andric          (CALLpcrel32 tglobaladdr:$dst)>;
13590b57cec5SDimitry Andricdef : Pat<(X86call (i32 texternalsym:$dst)),
13600b57cec5SDimitry Andric          (CALLpcrel32 texternalsym:$dst)>;
13610b57cec5SDimitry Andricdef : Pat<(X86call (i32 imm:$dst)),
13620b57cec5SDimitry Andric          (CALLpcrel32 imm:$dst)>, Requires<[CallImmAddr]>;
13630b57cec5SDimitry Andric
13640b57cec5SDimitry Andric// Comparisons.
13650b57cec5SDimitry Andric
13660b57cec5SDimitry Andric// TEST R,R is smaller than CMP R,0
13670b57cec5SDimitry Andricdef : Pat<(X86cmp GR8:$src1, 0),
13680b57cec5SDimitry Andric          (TEST8rr GR8:$src1, GR8:$src1)>;
13690b57cec5SDimitry Andricdef : Pat<(X86cmp GR16:$src1, 0),
13700b57cec5SDimitry Andric          (TEST16rr GR16:$src1, GR16:$src1)>;
13710b57cec5SDimitry Andricdef : Pat<(X86cmp GR32:$src1, 0),
13720b57cec5SDimitry Andric          (TEST32rr GR32:$src1, GR32:$src1)>;
13730b57cec5SDimitry Andricdef : Pat<(X86cmp GR64:$src1, 0),
13740b57cec5SDimitry Andric          (TEST64rr GR64:$src1, GR64:$src1)>;
13750b57cec5SDimitry Andric
13760b57cec5SDimitry Andric// zextload bool -> zextload byte
13770b57cec5SDimitry Andric// i1 stored in one byte in zero-extended form.
13780b57cec5SDimitry Andric// Upper bits cleanup should be executed before Store.
13790b57cec5SDimitry Andricdef : Pat<(zextloadi8i1  addr:$src), (MOV8rm addr:$src)>;
13800b57cec5SDimitry Andricdef : Pat<(zextloadi16i1 addr:$src),
13810b57cec5SDimitry Andric          (EXTRACT_SUBREG (MOVZX32rm8 addr:$src), sub_16bit)>;
13820b57cec5SDimitry Andricdef : Pat<(zextloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>;
13830b57cec5SDimitry Andricdef : Pat<(zextloadi64i1 addr:$src),
13840b57cec5SDimitry Andric          (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>;
13850b57cec5SDimitry Andric
13860b57cec5SDimitry Andric// extload bool -> extload byte
13870b57cec5SDimitry Andric// When extloading from 16-bit and smaller memory locations into 64-bit
13880b57cec5SDimitry Andric// registers, use zero-extending loads so that the entire 64-bit register is
13890b57cec5SDimitry Andric// defined, avoiding partial-register updates.
13900b57cec5SDimitry Andric
13910b57cec5SDimitry Andricdef : Pat<(extloadi8i1 addr:$src),   (MOV8rm      addr:$src)>;
13920b57cec5SDimitry Andricdef : Pat<(extloadi16i1 addr:$src),
13930b57cec5SDimitry Andric          (EXTRACT_SUBREG (MOVZX32rm8 addr:$src), sub_16bit)>;
13940b57cec5SDimitry Andricdef : Pat<(extloadi32i1 addr:$src),  (MOVZX32rm8  addr:$src)>;
13950b57cec5SDimitry Andricdef : Pat<(extloadi16i8 addr:$src),
13960b57cec5SDimitry Andric          (EXTRACT_SUBREG (MOVZX32rm8 addr:$src), sub_16bit)>;
13970b57cec5SDimitry Andricdef : Pat<(extloadi32i8 addr:$src),  (MOVZX32rm8  addr:$src)>;
13980b57cec5SDimitry Andricdef : Pat<(extloadi32i16 addr:$src), (MOVZX32rm16 addr:$src)>;
13990b57cec5SDimitry Andric
14000b57cec5SDimitry Andric// For other extloads, use subregs, since the high contents of the register are
14010b57cec5SDimitry Andric// defined after an extload.
14020b57cec5SDimitry Andric// NOTE: The extloadi64i32 pattern needs to be first as it will try to form
14030b57cec5SDimitry Andric// 32-bit loads for 4 byte aligned i8/i16 loads.
14040b57cec5SDimitry Andricdef : Pat<(extloadi64i32 addr:$src),
14050b57cec5SDimitry Andric          (SUBREG_TO_REG (i64 0), (MOV32rm addr:$src), sub_32bit)>;
14060b57cec5SDimitry Andricdef : Pat<(extloadi64i1 addr:$src),
14070b57cec5SDimitry Andric          (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>;
14080b57cec5SDimitry Andricdef : Pat<(extloadi64i8 addr:$src),
14090b57cec5SDimitry Andric          (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>;
14100b57cec5SDimitry Andricdef : Pat<(extloadi64i16 addr:$src),
14110b57cec5SDimitry Andric          (SUBREG_TO_REG (i64 0), (MOVZX32rm16 addr:$src), sub_32bit)>;
14120b57cec5SDimitry Andric
14130b57cec5SDimitry Andric// anyext. Define these to do an explicit zero-extend to
14140b57cec5SDimitry Andric// avoid partial-register updates.
14150b57cec5SDimitry Andricdef : Pat<(i16 (anyext GR8 :$src)), (EXTRACT_SUBREG
14160b57cec5SDimitry Andric                                     (MOVZX32rr8 GR8 :$src), sub_16bit)>;
14170b57cec5SDimitry Andricdef : Pat<(i32 (anyext GR8 :$src)), (MOVZX32rr8  GR8 :$src)>;
14180b57cec5SDimitry Andric
14190b57cec5SDimitry Andric// Except for i16 -> i32 since isel expect i16 ops to be promoted to i32.
14200b57cec5SDimitry Andricdef : Pat<(i32 (anyext GR16:$src)),
14210b57cec5SDimitry Andric          (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR16:$src, sub_16bit)>;
14220b57cec5SDimitry Andric
14230b57cec5SDimitry Andricdef : Pat<(i64 (anyext GR8 :$src)),
14240b57cec5SDimitry Andric          (SUBREG_TO_REG (i64 0), (MOVZX32rr8  GR8  :$src), sub_32bit)>;
14250b57cec5SDimitry Andricdef : Pat<(i64 (anyext GR16:$src)),
14260b57cec5SDimitry Andric          (SUBREG_TO_REG (i64 0), (MOVZX32rr16 GR16 :$src), sub_32bit)>;
14270b57cec5SDimitry Andricdef : Pat<(i64 (anyext GR32:$src)),
14280b57cec5SDimitry Andric          (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src, sub_32bit)>;
14290b57cec5SDimitry Andric
14300b57cec5SDimitry Andricdef : Pat<(i32 (anyext_sdiv GR8:$src)), (MOVSX32rr8 GR8:$src)>;
14310b57cec5SDimitry Andric
14320b57cec5SDimitry Andric// In the case of a 32-bit def that is known to implicitly zero-extend,
14330b57cec5SDimitry Andric// we can use a SUBREG_TO_REG.
14340b57cec5SDimitry Andricdef : Pat<(i64 (zext def32:$src)),
14350b57cec5SDimitry Andric          (SUBREG_TO_REG (i64 0), GR32:$src, sub_32bit)>;
14360b57cec5SDimitry Andricdef : Pat<(i64 (and (anyext def32:$src), 0x00000000FFFFFFFF)),
14370b57cec5SDimitry Andric          (SUBREG_TO_REG (i64 0), GR32:$src, sub_32bit)>;
14380b57cec5SDimitry Andric
14390b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
14400b57cec5SDimitry Andric// Pattern match OR as ADD
14410b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
14420b57cec5SDimitry Andric
14430b57cec5SDimitry Andric// If safe, we prefer to pattern match OR as ADD at isel time. ADD can be
14440b57cec5SDimitry Andric// 3-addressified into an LEA instruction to avoid copies.  However, we also
14450b57cec5SDimitry Andric// want to finally emit these instructions as an or at the end of the code
14460b57cec5SDimitry Andric// generator to make the generated code easier to read.  To do this, we select
14470b57cec5SDimitry Andric// into "disjoint bits" pseudo ops.
14480b57cec5SDimitry Andric
14490b57cec5SDimitry Andric// (or x1, x2) -> (add x1, x2) if two operands are known not to share bits.
14500b57cec5SDimitry Andric// Try this before the selecting to OR.
14510b57cec5SDimitry Andriclet SchedRW = [WriteALU] in {
14520b57cec5SDimitry Andric
14530b57cec5SDimitry Andriclet isConvertibleToThreeAddress = 1, isPseudo = 1,
14540b57cec5SDimitry Andric    Constraints = "$src1 = $dst", Defs = [EFLAGS] in {
14550b57cec5SDimitry Andriclet isCommutable = 1 in {
14560b57cec5SDimitry Andricdef ADD8rr_DB   : I<0, Pseudo, (outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
14570b57cec5SDimitry Andric                    "", // orb/addb REG, REG
14580b57cec5SDimitry Andric                    [(set GR8:$dst, (or_is_add GR8:$src1, GR8:$src2))]>;
14590b57cec5SDimitry Andricdef ADD16rr_DB  : I<0, Pseudo, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
14600b57cec5SDimitry Andric                    "", // orw/addw REG, REG
14610b57cec5SDimitry Andric                    [(set GR16:$dst, (or_is_add GR16:$src1, GR16:$src2))]>;
14620b57cec5SDimitry Andricdef ADD32rr_DB  : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
14630b57cec5SDimitry Andric                    "", // orl/addl REG, REG
14640b57cec5SDimitry Andric                    [(set GR32:$dst, (or_is_add GR32:$src1, GR32:$src2))]>;
14650b57cec5SDimitry Andricdef ADD64rr_DB  : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
14660b57cec5SDimitry Andric                    "", // orq/addq REG, REG
14670b57cec5SDimitry Andric                    [(set GR64:$dst, (or_is_add GR64:$src1, GR64:$src2))]>;
14680b57cec5SDimitry Andric} // isCommutable
14690b57cec5SDimitry Andric
14700b57cec5SDimitry Andricdef ADD8ri_DB :   I<0, Pseudo,
14710b57cec5SDimitry Andric                    (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2),
14720b57cec5SDimitry Andric                    "", // orb/addb REG, imm8
14730b57cec5SDimitry Andric                    [(set GR8:$dst, (or_is_add GR8:$src1, imm:$src2))]>;
14740b57cec5SDimitry Andricdef ADD16ri_DB  : I<0, Pseudo, (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
14750b57cec5SDimitry Andric                    "", // orw/addw REG, imm
14760b57cec5SDimitry Andric                    [(set GR16:$dst, (or_is_add GR16:$src1, imm:$src2))]>;
14770b57cec5SDimitry Andricdef ADD32ri_DB  : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
14780b57cec5SDimitry Andric                    "", // orl/addl REG, imm
14790b57cec5SDimitry Andric                    [(set GR32:$dst, (or_is_add GR32:$src1, imm:$src2))]>;
14800b57cec5SDimitry Andricdef ADD64ri32_DB : I<0, Pseudo,
14810b57cec5SDimitry Andric                     (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2),
14820b57cec5SDimitry Andric                     "", // orq/addq REG, imm
14830b57cec5SDimitry Andric                     [(set GR64:$dst, (or_is_add GR64:$src1,
14840b57cec5SDimitry Andric                                                 i64immSExt32:$src2))]>;
14850b57cec5SDimitry Andric}
14860b57cec5SDimitry Andric} // AddedComplexity, SchedRW
14870b57cec5SDimitry Andric
14880b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
148981ad6265SDimitry Andric// Pattern match XOR as ADD
149081ad6265SDimitry Andric//===----------------------------------------------------------------------===//
149181ad6265SDimitry Andric
149281ad6265SDimitry Andric// Prefer to pattern match XOR with min_signed_value as ADD at isel time.
149381ad6265SDimitry Andric// ADD can be 3-addressified into an LEA instruction to avoid copies.
149481ad6265SDimitry Andriclet AddedComplexity = 5 in {
149581ad6265SDimitry Andricdef : Pat<(xor GR8:$src1, -128),
149681ad6265SDimitry Andric          (ADD8ri GR8:$src1, -128)>;
149781ad6265SDimitry Andricdef : Pat<(xor GR16:$src1, -32768),
149881ad6265SDimitry Andric          (ADD16ri GR16:$src1, -32768)>;
149981ad6265SDimitry Andricdef : Pat<(xor GR32:$src1, -2147483648),
150081ad6265SDimitry Andric          (ADD32ri GR32:$src1, -2147483648)>;
150181ad6265SDimitry Andric}
150281ad6265SDimitry Andric
150381ad6265SDimitry Andric//===----------------------------------------------------------------------===//
15040b57cec5SDimitry Andric// Some peepholes
15050b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
15060b57cec5SDimitry Andric
15070b57cec5SDimitry Andric// Odd encoding trick: -128 fits into an 8-bit immediate field while
15080b57cec5SDimitry Andric// +128 doesn't, so in this special case use a sub instead of an add.
15090fca6ea1SDimitry Andriclet Predicates = [NoNDD] in {
15100b57cec5SDimitry Andric  def : Pat<(add GR16:$src1, 128),
151106c3fb27SDimitry Andric            (SUB16ri GR16:$src1, -128)>;
15120b57cec5SDimitry Andric  def : Pat<(add GR32:$src1, 128),
151306c3fb27SDimitry Andric            (SUB32ri GR32:$src1, -128)>;
15140b57cec5SDimitry Andric  def : Pat<(add GR64:$src1, 128),
151506c3fb27SDimitry Andric            (SUB64ri32 GR64:$src1, -128)>;
15160b57cec5SDimitry Andric
15170b57cec5SDimitry Andric  def : Pat<(X86add_flag_nocf GR16:$src1, 128),
151806c3fb27SDimitry Andric            (SUB16ri GR16:$src1, -128)>;
15190b57cec5SDimitry Andric  def : Pat<(X86add_flag_nocf GR32:$src1, 128),
152006c3fb27SDimitry Andric            (SUB32ri GR32:$src1, -128)>;
15210b57cec5SDimitry Andric  def : Pat<(X86add_flag_nocf GR64:$src1, 128),
152206c3fb27SDimitry Andric            (SUB64ri32 GR64:$src1, -128)>;
15230fca6ea1SDimitry Andric}
15240fca6ea1SDimitry Andriclet Predicates = [HasNDD] in {
15250fca6ea1SDimitry Andric  def : Pat<(add GR16:$src1, 128),
15260fca6ea1SDimitry Andric            (SUB16ri_ND GR16:$src1, -128)>;
15270fca6ea1SDimitry Andric  def : Pat<(add GR32:$src1, 128),
15280fca6ea1SDimitry Andric            (SUB32ri_ND GR32:$src1, -128)>;
15290fca6ea1SDimitry Andric  def : Pat<(add GR64:$src1, 128),
15300fca6ea1SDimitry Andric            (SUB64ri32_ND GR64:$src1, -128)>;
15310fca6ea1SDimitry Andric
15320fca6ea1SDimitry Andric  def : Pat<(X86add_flag_nocf GR16:$src1, 128),
15330fca6ea1SDimitry Andric            (SUB16ri_ND GR16:$src1, -128)>;
15340fca6ea1SDimitry Andric  def : Pat<(X86add_flag_nocf GR32:$src1, 128),
15350fca6ea1SDimitry Andric            (SUB32ri_ND GR32:$src1, -128)>;
15360fca6ea1SDimitry Andric  def : Pat<(X86add_flag_nocf GR64:$src1, 128),
15370fca6ea1SDimitry Andric            (SUB64ri32_ND GR64:$src1, -128)>;
15380fca6ea1SDimitry Andric}
15390fca6ea1SDimitry Andricdef : Pat<(store (add (loadi16 addr:$dst), 128), addr:$dst),
15400fca6ea1SDimitry Andric          (SUB16mi addr:$dst, -128)>;
15410fca6ea1SDimitry Andricdef : Pat<(store (add (loadi32 addr:$dst), 128), addr:$dst),
15420fca6ea1SDimitry Andric          (SUB32mi addr:$dst, -128)>;
15430fca6ea1SDimitry Andricdef : Pat<(store (add (loadi64 addr:$dst), 128), addr:$dst),
15440fca6ea1SDimitry Andric          (SUB64mi32 addr:$dst, -128)>;
15450fca6ea1SDimitry Andriclet Predicates = [HasNDD] in {
15460fca6ea1SDimitry Andric  def : Pat<(add (loadi16 addr:$src), 128),
15470fca6ea1SDimitry Andric            (SUB16mi_ND addr:$src, -128)>;
15480fca6ea1SDimitry Andric  def : Pat<(add (loadi32 addr:$src), 128),
15490fca6ea1SDimitry Andric            (SUB32mi_ND addr:$src, -128)>;
15500fca6ea1SDimitry Andric  def : Pat<(add (loadi64 addr:$src), 128),
15510fca6ea1SDimitry Andric            (SUB64mi32_ND addr:$src, -128)>;
15520fca6ea1SDimitry Andric}
15530fca6ea1SDimitry Andric
15540fca6ea1SDimitry Andric// The same trick applies for 32-bit immediate fields in 64-bit
15550fca6ea1SDimitry Andric// instructions.
15560fca6ea1SDimitry Andriclet Predicates = [NoNDD] in {
15570fca6ea1SDimitry Andric  def : Pat<(add GR64:$src1, 0x0000000080000000),
15580fca6ea1SDimitry Andric            (SUB64ri32 GR64:$src1, 0xffffffff80000000)>;
15590fca6ea1SDimitry Andric  def : Pat<(X86add_flag_nocf GR64:$src1, 0x0000000080000000),
15600fca6ea1SDimitry Andric            (SUB64ri32 GR64:$src1, 0xffffffff80000000)>;
15610fca6ea1SDimitry Andric}
15620fca6ea1SDimitry Andriclet Predicates = [HasNDD] in {
15630fca6ea1SDimitry Andric  def : Pat<(add GR64:$src1, 0x0000000080000000),
15640fca6ea1SDimitry Andric            (SUB64ri32_ND GR64:$src1, 0xffffffff80000000)>;
15650fca6ea1SDimitry Andric  def : Pat<(X86add_flag_nocf GR64:$src1, 0x0000000080000000),
15660fca6ea1SDimitry Andric            (SUB64ri32_ND GR64:$src1, 0xffffffff80000000)>;
15670fca6ea1SDimitry Andric}
15680fca6ea1SDimitry Andricdef : Pat<(store (add (loadi64 addr:$dst), 0x0000000080000000), addr:$dst),
15690fca6ea1SDimitry Andric          (SUB64mi32 addr:$dst, 0xffffffff80000000)>;
15700fca6ea1SDimitry Andriclet Predicates = [HasNDD] in {
15710fca6ea1SDimitry Andric  def : Pat<(add(loadi64 addr:$src), 0x0000000080000000),
15720fca6ea1SDimitry Andric            (SUB64mi32_ND addr:$src, 0xffffffff80000000)>;
15730fca6ea1SDimitry Andric}
15740b57cec5SDimitry Andric
1575cb14a3feSDimitry Andric// Depositing value to 8/16 bit subreg:
1576cb14a3feSDimitry Andricdef : Pat<(or (and GR64:$dst, -256),
1577cb14a3feSDimitry Andric              (i64 (zextloadi8 addr:$src))),
1578cb14a3feSDimitry Andric          (INSERT_SUBREG (i64 (COPY $dst)), (MOV8rm  i8mem:$src), sub_8bit)>;
1579cb14a3feSDimitry Andric
1580cb14a3feSDimitry Andricdef : Pat<(or (and GR32:$dst, -256),
1581cb14a3feSDimitry Andric              (i32 (zextloadi8 addr:$src))),
1582cb14a3feSDimitry Andric          (INSERT_SUBREG (i32 (COPY $dst)), (MOV8rm  i8mem:$src), sub_8bit)>;
1583cb14a3feSDimitry Andric
1584cb14a3feSDimitry Andricdef : Pat<(or (and GR64:$dst, -65536),
1585cb14a3feSDimitry Andric              (i64 (zextloadi16 addr:$src))),
1586cb14a3feSDimitry Andric          (INSERT_SUBREG (i64 (COPY $dst)), (MOV16rm  i16mem:$src), sub_16bit)>;
1587cb14a3feSDimitry Andric
1588cb14a3feSDimitry Andricdef : Pat<(or (and GR32:$dst, -65536),
1589cb14a3feSDimitry Andric              (i32 (zextloadi16 addr:$src))),
1590cb14a3feSDimitry Andric          (INSERT_SUBREG (i32 (COPY $dst)), (MOV16rm  i16mem:$src), sub_16bit)>;
1591cb14a3feSDimitry Andric
15920b57cec5SDimitry Andric// To avoid needing to materialize an immediate in a register, use a 32-bit and
15930b57cec5SDimitry Andric// with implicit zero-extension instead of a 64-bit and if the immediate has at
15940b57cec5SDimitry Andric// least 32 bits of leading zeros. If in addition the last 32 bits can be
15950b57cec5SDimitry Andric// represented with a sign extension of a 8 bit constant, use that.
15960b57cec5SDimitry Andric// This can also reduce instruction size by eliminating the need for the REX
15970b57cec5SDimitry Andric// prefix.
15980b57cec5SDimitry Andric
15990b57cec5SDimitry Andric// AddedComplexity is needed to give priority over i64immSExt8 and i64immSExt32.
16000b57cec5SDimitry Andriclet AddedComplexity = 1 in {
1601297eecfbSDimitry Andric  let Predicates = [NoNDD] in {
16020b57cec5SDimitry Andric    def : Pat<(and GR64:$src, i64immZExt32:$imm),
16030b57cec5SDimitry Andric              (SUBREG_TO_REG
16040b57cec5SDimitry Andric                (i64 0),
16050b57cec5SDimitry Andric                (AND32ri
16060b57cec5SDimitry Andric                  (EXTRACT_SUBREG GR64:$src, sub_32bit),
16070b57cec5SDimitry Andric                  (i32 (GetLo32XForm imm:$imm))),
16080b57cec5SDimitry Andric                sub_32bit)>;
1609297eecfbSDimitry Andric  }
1610297eecfbSDimitry Andric  let Predicates = [HasNDD] in {
1611297eecfbSDimitry Andric    def : Pat<(and GR64:$src, i64immZExt32:$imm),
1612297eecfbSDimitry Andric              (SUBREG_TO_REG
1613297eecfbSDimitry Andric                (i64 0),
1614297eecfbSDimitry Andric                (AND32ri_ND
1615297eecfbSDimitry Andric                  (EXTRACT_SUBREG GR64:$src, sub_32bit),
1616297eecfbSDimitry Andric                  (i32 (GetLo32XForm imm:$imm))),
1617297eecfbSDimitry Andric                sub_32bit)>;
1618297eecfbSDimitry Andric  }
16190b57cec5SDimitry Andric} // AddedComplexity = 1
16200b57cec5SDimitry Andric
16210b57cec5SDimitry Andric
16220b57cec5SDimitry Andric// AddedComplexity is needed due to the increased complexity on the
16230b57cec5SDimitry Andric// i64immZExt32SExt8 and i64immZExt32 patterns above. Applying this to all
16240b57cec5SDimitry Andric// the MOVZX patterns keeps thems together in DAGIsel tables.
16250b57cec5SDimitry Andriclet AddedComplexity = 1 in {
16260b57cec5SDimitry Andric// r & (2^16-1) ==> movz
16270b57cec5SDimitry Andricdef : Pat<(and GR32:$src1, 0xffff),
16280b57cec5SDimitry Andric          (MOVZX32rr16 (EXTRACT_SUBREG GR32:$src1, sub_16bit))>;
16290b57cec5SDimitry Andric// r & (2^8-1) ==> movz
16300b57cec5SDimitry Andricdef : Pat<(and GR32:$src1, 0xff),
16310b57cec5SDimitry Andric          (MOVZX32rr8 (EXTRACT_SUBREG GR32:$src1, sub_8bit))>;
16320b57cec5SDimitry Andric// r & (2^8-1) ==> movz
16330b57cec5SDimitry Andricdef : Pat<(and GR16:$src1, 0xff),
16340b57cec5SDimitry Andric           (EXTRACT_SUBREG (MOVZX32rr8 (EXTRACT_SUBREG GR16:$src1, sub_8bit)),
16350b57cec5SDimitry Andric             sub_16bit)>;
16360b57cec5SDimitry Andric
16370b57cec5SDimitry Andric// r & (2^32-1) ==> movz
16380b57cec5SDimitry Andricdef : Pat<(and GR64:$src, 0x00000000FFFFFFFF),
16390b57cec5SDimitry Andric          (SUBREG_TO_REG (i64 0),
16400b57cec5SDimitry Andric                         (MOV32rr (EXTRACT_SUBREG GR64:$src, sub_32bit)),
16410b57cec5SDimitry Andric                         sub_32bit)>;
16420b57cec5SDimitry Andric// r & (2^16-1) ==> movz
16430b57cec5SDimitry Andricdef : Pat<(and GR64:$src, 0xffff),
16440b57cec5SDimitry Andric          (SUBREG_TO_REG (i64 0),
16450b57cec5SDimitry Andric                      (MOVZX32rr16 (i16 (EXTRACT_SUBREG GR64:$src, sub_16bit))),
16460b57cec5SDimitry Andric                      sub_32bit)>;
16470b57cec5SDimitry Andric// r & (2^8-1) ==> movz
16480b57cec5SDimitry Andricdef : Pat<(and GR64:$src, 0xff),
16490b57cec5SDimitry Andric          (SUBREG_TO_REG (i64 0),
16500b57cec5SDimitry Andric                         (MOVZX32rr8 (i8 (EXTRACT_SUBREG GR64:$src, sub_8bit))),
16510b57cec5SDimitry Andric                         sub_32bit)>;
16520b57cec5SDimitry Andric} // AddedComplexity = 1
16530b57cec5SDimitry Andric
16540b57cec5SDimitry Andric
16550b57cec5SDimitry Andric// Try to use BTS/BTR/BTC for single bit operations on the upper 32-bits.
16560b57cec5SDimitry Andric
16570b57cec5SDimitry Andricdef BTRXForm : SDNodeXForm<imm, [{
16580b57cec5SDimitry Andric  // Transformation function: Find the lowest 0.
165906c3fb27SDimitry Andric  return getI64Imm((uint8_t)N->getAPIntValue().countr_one(), SDLoc(N));
16600b57cec5SDimitry Andric}]>;
16610b57cec5SDimitry Andric
16620b57cec5SDimitry Andricdef BTCBTSXForm : SDNodeXForm<imm, [{
16630b57cec5SDimitry Andric  // Transformation function: Find the lowest 1.
166406c3fb27SDimitry Andric  return getI64Imm((uint8_t)N->getAPIntValue().countr_zero(), SDLoc(N));
16650b57cec5SDimitry Andric}]>;
16660b57cec5SDimitry Andric
16670b57cec5SDimitry Andricdef BTRMask64 : ImmLeaf<i64, [{
16680b57cec5SDimitry Andric  return !isUInt<32>(Imm) && !isInt<32>(Imm) && isPowerOf2_64(~Imm);
16690b57cec5SDimitry Andric}]>;
16700b57cec5SDimitry Andric
16710b57cec5SDimitry Andricdef BTCBTSMask64 : ImmLeaf<i64, [{
16720b57cec5SDimitry Andric  return !isInt<32>(Imm) && isPowerOf2_64(Imm);
16730b57cec5SDimitry Andric}]>;
16740b57cec5SDimitry Andric
16750b57cec5SDimitry Andric// For now only do this for optsize.
16760b57cec5SDimitry Andriclet AddedComplexity = 1, Predicates=[OptForSize] in {
16770b57cec5SDimitry Andric  def : Pat<(and GR64:$src1, BTRMask64:$mask),
16780b57cec5SDimitry Andric            (BTR64ri8 GR64:$src1, (BTRXForm imm:$mask))>;
16790b57cec5SDimitry Andric  def : Pat<(or GR64:$src1, BTCBTSMask64:$mask),
16800b57cec5SDimitry Andric            (BTS64ri8 GR64:$src1, (BTCBTSXForm imm:$mask))>;
16810b57cec5SDimitry Andric  def : Pat<(xor GR64:$src1, BTCBTSMask64:$mask),
16820b57cec5SDimitry Andric            (BTC64ri8 GR64:$src1, (BTCBTSXForm imm:$mask))>;
16830b57cec5SDimitry Andric}
16840b57cec5SDimitry Andric
16850b57cec5SDimitry Andric
16860b57cec5SDimitry Andric// sext_inreg patterns
16870b57cec5SDimitry Andricdef : Pat<(sext_inreg GR32:$src, i16),
16880b57cec5SDimitry Andric          (MOVSX32rr16 (EXTRACT_SUBREG GR32:$src, sub_16bit))>;
16890b57cec5SDimitry Andricdef : Pat<(sext_inreg GR32:$src, i8),
16900b57cec5SDimitry Andric          (MOVSX32rr8 (EXTRACT_SUBREG GR32:$src, sub_8bit))>;
16910b57cec5SDimitry Andric
16920b57cec5SDimitry Andricdef : Pat<(sext_inreg GR16:$src, i8),
16930b57cec5SDimitry Andric           (EXTRACT_SUBREG (MOVSX32rr8 (EXTRACT_SUBREG GR16:$src, sub_8bit)),
16940b57cec5SDimitry Andric             sub_16bit)>;
16950b57cec5SDimitry Andric
16960b57cec5SDimitry Andricdef : Pat<(sext_inreg GR64:$src, i32),
16970b57cec5SDimitry Andric          (MOVSX64rr32 (EXTRACT_SUBREG GR64:$src, sub_32bit))>;
16980b57cec5SDimitry Andricdef : Pat<(sext_inreg GR64:$src, i16),
16990b57cec5SDimitry Andric          (MOVSX64rr16 (EXTRACT_SUBREG GR64:$src, sub_16bit))>;
17000b57cec5SDimitry Andricdef : Pat<(sext_inreg GR64:$src, i8),
17010b57cec5SDimitry Andric          (MOVSX64rr8 (EXTRACT_SUBREG GR64:$src, sub_8bit))>;
17020b57cec5SDimitry Andric
17030b57cec5SDimitry Andric// sext, sext_load, zext, zext_load
17040b57cec5SDimitry Andricdef: Pat<(i16 (sext GR8:$src)),
17050b57cec5SDimitry Andric          (EXTRACT_SUBREG (MOVSX32rr8 GR8:$src), sub_16bit)>;
17060b57cec5SDimitry Andricdef: Pat<(sextloadi16i8 addr:$src),
17070b57cec5SDimitry Andric          (EXTRACT_SUBREG (MOVSX32rm8 addr:$src), sub_16bit)>;
17080b57cec5SDimitry Andricdef: Pat<(i16 (zext GR8:$src)),
17090b57cec5SDimitry Andric          (EXTRACT_SUBREG (MOVZX32rr8 GR8:$src), sub_16bit)>;
17100b57cec5SDimitry Andricdef: Pat<(zextloadi16i8 addr:$src),
17110b57cec5SDimitry Andric          (EXTRACT_SUBREG (MOVZX32rm8 addr:$src), sub_16bit)>;
17120b57cec5SDimitry Andric
17130b57cec5SDimitry Andric// trunc patterns
17140b57cec5SDimitry Andricdef : Pat<(i16 (trunc GR32:$src)),
17150b57cec5SDimitry Andric          (EXTRACT_SUBREG GR32:$src, sub_16bit)>;
17160b57cec5SDimitry Andricdef : Pat<(i8 (trunc GR32:$src)),
17170b57cec5SDimitry Andric          (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)),
17180b57cec5SDimitry Andric                          sub_8bit)>,
17190b57cec5SDimitry Andric      Requires<[Not64BitMode]>;
17200b57cec5SDimitry Andricdef : Pat<(i8 (trunc GR16:$src)),
17210b57cec5SDimitry Andric          (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)),
17220b57cec5SDimitry Andric                          sub_8bit)>,
17230b57cec5SDimitry Andric      Requires<[Not64BitMode]>;
17240b57cec5SDimitry Andricdef : Pat<(i32 (trunc GR64:$src)),
17250b57cec5SDimitry Andric          (EXTRACT_SUBREG GR64:$src, sub_32bit)>;
17260b57cec5SDimitry Andricdef : Pat<(i16 (trunc GR64:$src)),
17270b57cec5SDimitry Andric          (EXTRACT_SUBREG GR64:$src, sub_16bit)>;
17280b57cec5SDimitry Andricdef : Pat<(i8 (trunc GR64:$src)),
17290b57cec5SDimitry Andric          (EXTRACT_SUBREG GR64:$src, sub_8bit)>;
17300b57cec5SDimitry Andricdef : Pat<(i8 (trunc GR32:$src)),
17310b57cec5SDimitry Andric          (EXTRACT_SUBREG GR32:$src, sub_8bit)>,
17320b57cec5SDimitry Andric      Requires<[In64BitMode]>;
17330b57cec5SDimitry Andricdef : Pat<(i8 (trunc GR16:$src)),
17340b57cec5SDimitry Andric          (EXTRACT_SUBREG GR16:$src, sub_8bit)>,
17350b57cec5SDimitry Andric      Requires<[In64BitMode]>;
17360b57cec5SDimitry Andric
17370b57cec5SDimitry Andricdef immff00_ffff  : ImmLeaf<i32, [{
17380b57cec5SDimitry Andric  return Imm >= 0xff00 && Imm <= 0xffff;
17390b57cec5SDimitry Andric}]>;
17400b57cec5SDimitry Andric
17410b57cec5SDimitry Andric// h-register tricks
17420b57cec5SDimitry Andricdef : Pat<(i8 (trunc (srl_su GR16:$src, (i8 8)))),
17430b57cec5SDimitry Andric          (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)>,
17440b57cec5SDimitry Andric      Requires<[Not64BitMode]>;
17450b57cec5SDimitry Andricdef : Pat<(i8 (trunc (srl_su (i32 (anyext GR16:$src)), (i8 8)))),
17460b57cec5SDimitry Andric          (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)>,
17470b57cec5SDimitry Andric      Requires<[Not64BitMode]>;
17480b57cec5SDimitry Andricdef : Pat<(i8 (trunc (srl_su GR32:$src, (i8 8)))),
17490b57cec5SDimitry Andric          (EXTRACT_SUBREG GR32:$src, sub_8bit_hi)>,
17500b57cec5SDimitry Andric      Requires<[Not64BitMode]>;
17510b57cec5SDimitry Andricdef : Pat<(srl GR16:$src, (i8 8)),
17520b57cec5SDimitry Andric          (EXTRACT_SUBREG
17530b57cec5SDimitry Andric            (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)),
17540b57cec5SDimitry Andric            sub_16bit)>;
17550b57cec5SDimitry Andricdef : Pat<(i32 (zext (srl_su GR16:$src, (i8 8)))),
17560b57cec5SDimitry Andric          (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>;
17570b57cec5SDimitry Andricdef : Pat<(i32 (anyext (srl_su GR16:$src, (i8 8)))),
17580b57cec5SDimitry Andric          (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>;
17590b57cec5SDimitry Andricdef : Pat<(and (srl_su GR32:$src, (i8 8)), (i32 255)),
17600b57cec5SDimitry Andric          (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>;
17610b57cec5SDimitry Andricdef : Pat<(srl (and_su GR32:$src, immff00_ffff), (i8 8)),
17620b57cec5SDimitry Andric          (MOVZX32rr8_NOREX (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>;
17630b57cec5SDimitry Andric
17640b57cec5SDimitry Andric// h-register tricks.
17650b57cec5SDimitry Andric// For now, be conservative on x86-64 and use an h-register extract only if the
17660b57cec5SDimitry Andric// value is immediately zero-extended or stored, which are somewhat common
17670b57cec5SDimitry Andric// cases. This uses a bunch of code to prevent a register requiring a REX prefix
17680b57cec5SDimitry Andric// from being allocated in the same instruction as the h register, as there's
17690b57cec5SDimitry Andric// currently no way to describe this requirement to the register allocator.
17700b57cec5SDimitry Andric
17710b57cec5SDimitry Andric// h-register extract and zero-extend.
17720b57cec5SDimitry Andricdef : Pat<(and (srl_su GR64:$src, (i8 8)), (i64 255)),
17730b57cec5SDimitry Andric          (SUBREG_TO_REG
17740b57cec5SDimitry Andric            (i64 0),
17750b57cec5SDimitry Andric            (MOVZX32rr8_NOREX
17760b57cec5SDimitry Andric              (EXTRACT_SUBREG GR64:$src, sub_8bit_hi)),
17770b57cec5SDimitry Andric            sub_32bit)>;
17780b57cec5SDimitry Andricdef : Pat<(i64 (zext (srl_su GR16:$src, (i8 8)))),
17790b57cec5SDimitry Andric          (SUBREG_TO_REG
17800b57cec5SDimitry Andric            (i64 0),
17810b57cec5SDimitry Andric            (MOVZX32rr8_NOREX
17820b57cec5SDimitry Andric              (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)),
17830b57cec5SDimitry Andric            sub_32bit)>;
17840b57cec5SDimitry Andricdef : Pat<(i64 (anyext (srl_su GR16:$src, (i8 8)))),
17850b57cec5SDimitry Andric          (SUBREG_TO_REG
17860b57cec5SDimitry Andric            (i64 0),
17870b57cec5SDimitry Andric            (MOVZX32rr8_NOREX
17880b57cec5SDimitry Andric              (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)),
17890b57cec5SDimitry Andric            sub_32bit)>;
17900b57cec5SDimitry Andric
17910b57cec5SDimitry Andric// h-register extract and store.
17920b57cec5SDimitry Andricdef : Pat<(store (i8 (trunc_su (srl_su GR64:$src, (i8 8)))), addr:$dst),
17930b57cec5SDimitry Andric          (MOV8mr_NOREX
17940b57cec5SDimitry Andric            addr:$dst,
17950b57cec5SDimitry Andric            (EXTRACT_SUBREG GR64:$src, sub_8bit_hi))>;
17960b57cec5SDimitry Andricdef : Pat<(store (i8 (trunc_su (srl_su GR32:$src, (i8 8)))), addr:$dst),
17970b57cec5SDimitry Andric          (MOV8mr_NOREX
17980b57cec5SDimitry Andric            addr:$dst,
17990b57cec5SDimitry Andric            (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>,
18000b57cec5SDimitry Andric      Requires<[In64BitMode]>;
18010b57cec5SDimitry Andricdef : Pat<(store (i8 (trunc_su (srl_su GR16:$src, (i8 8)))), addr:$dst),
18020b57cec5SDimitry Andric          (MOV8mr_NOREX
18030b57cec5SDimitry Andric            addr:$dst,
18040b57cec5SDimitry Andric            (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>,
18050b57cec5SDimitry Andric      Requires<[In64BitMode]>;
18060b57cec5SDimitry Andric
1807e8d8bef9SDimitry Andric// Special pattern to catch the last step of __builtin_parity handling. Our
1808e8d8bef9SDimitry Andric// goal is to use an xor of an h-register with the corresponding l-register.
1809e8d8bef9SDimitry Andric// The above patterns would handle this on non 64-bit targets, but for 64-bit
1810e8d8bef9SDimitry Andric// we need to be more careful. We're using a NOREX instruction here in case
1811e8d8bef9SDimitry Andric// register allocation fails to keep the two registers together. So we need to
1812e8d8bef9SDimitry Andric// make sure we can't accidentally mix R8-R15 with an h-register.
1813e8d8bef9SDimitry Andricdef : Pat<(X86xor_flag (i8 (trunc GR32:$src)),
1814e8d8bef9SDimitry Andric                       (i8 (trunc (srl_su GR32:$src, (i8 8))))),
1815e8d8bef9SDimitry Andric          (XOR8rr_NOREX (EXTRACT_SUBREG GR32:$src, sub_8bit),
1816e8d8bef9SDimitry Andric                        (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>;
18170b57cec5SDimitry Andric
18180b57cec5SDimitry Andric// (shl x, 1) ==> (add x, x)
18190b57cec5SDimitry Andric// Note that if x is undef (immediate or otherwise), we could theoretically
18200b57cec5SDimitry Andric// end up with the two uses of x getting different values, producing a result
18210b57cec5SDimitry Andric// where the least significant bit is not 0. However, the probability of this
18220b57cec5SDimitry Andric// happening is considered low enough that this is officially not a
18230b57cec5SDimitry Andric// "real problem".
1824297eecfbSDimitry Andriclet Predicates = [NoNDD] in {
18250b57cec5SDimitry Andric  def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr  GR8 :$src1, GR8 :$src1)>;
18260b57cec5SDimitry Andric  def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>;
18270b57cec5SDimitry Andric  def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>;
18280b57cec5SDimitry Andric  def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>;
1829297eecfbSDimitry Andric}
1830297eecfbSDimitry Andriclet Predicates = [HasNDD] in {
1831297eecfbSDimitry Andric  def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr_ND  GR8 :$src1, GR8 :$src1)>;
1832297eecfbSDimitry Andric  def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr_ND GR16:$src1, GR16:$src1)>;
1833297eecfbSDimitry Andric  def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr_ND GR32:$src1, GR32:$src1)>;
1834297eecfbSDimitry Andric  def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr_ND GR64:$src1, GR64:$src1)>;
1835297eecfbSDimitry Andric}
18360b57cec5SDimitry Andric
18370b57cec5SDimitry Andric// Shift amount is implicitly masked.
18387a6dacacSDimitry Andricmulticlass MaskedShiftAmountPats<SDNode frag> {
18390b57cec5SDimitry Andric  // (shift x (and y, 31)) ==> (shift x, y)
18400b57cec5SDimitry Andric  // (shift x (and y, 63)) ==> (shift x, y)
18417a6dacacSDimitry Andric  let Predicates = [NoNDD] in {
18427a6dacacSDimitry Andric    def : Pat<(frag GR8:$src1, (shiftMask32 CL)),
18437a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "8rCL") GR8:$src1)>;
18447a6dacacSDimitry Andric    def : Pat<(frag GR16:$src1, (shiftMask32 CL)),
18457a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "16rCL") GR16:$src1)>;
18467a6dacacSDimitry Andric    def : Pat<(frag GR32:$src1, (shiftMask32 CL)),
18477a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "32rCL") GR32:$src1)>;
18480b57cec5SDimitry Andric    def : Pat<(frag GR64:$src1, (shiftMask64 CL)),
18497a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "64rCL") GR64:$src1)>;
18507a6dacacSDimitry Andric  }
18517a6dacacSDimitry Andric  let Predicates = [HasNDD] in {
18527a6dacacSDimitry Andric    def : Pat<(frag GR8:$src1, (shiftMask32 CL)),
18537a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "8rCL_ND") GR8:$src1)>;
18547a6dacacSDimitry Andric    def : Pat<(frag GR16:$src1, (shiftMask32 CL)),
18557a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "16rCL_ND") GR16:$src1)>;
18567a6dacacSDimitry Andric    def : Pat<(frag GR32:$src1, (shiftMask32 CL)),
18577a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "32rCL_ND") GR32:$src1)>;
18587a6dacacSDimitry Andric    def : Pat<(frag GR64:$src1, (shiftMask64 CL)),
18597a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "64rCL_ND") GR64:$src1)>;
18600b57cec5SDimitry Andric  }
18610b57cec5SDimitry Andric
18627a6dacacSDimitry Andric  def : Pat<(store (frag (loadi8 addr:$dst), (shiftMask32 CL)), addr:$dst),
18637a6dacacSDimitry Andric            (!cast<Instruction>(NAME # "8mCL") addr:$dst)>;
18647a6dacacSDimitry Andric  def : Pat<(store (frag (loadi16 addr:$dst), (shiftMask32 CL)), addr:$dst),
18657a6dacacSDimitry Andric            (!cast<Instruction>(NAME # "16mCL") addr:$dst)>;
18667a6dacacSDimitry Andric  def : Pat<(store (frag (loadi32 addr:$dst), (shiftMask32 CL)), addr:$dst),
18677a6dacacSDimitry Andric            (!cast<Instruction>(NAME # "32mCL") addr:$dst)>;
18687a6dacacSDimitry Andric  def : Pat<(store (frag (loadi64 addr:$dst), (shiftMask64 CL)), addr:$dst),
18697a6dacacSDimitry Andric            (!cast<Instruction>(NAME # "64mCL") addr:$dst)>;
18707a6dacacSDimitry Andric
18717a6dacacSDimitry Andric  let Predicates = [HasNDD] in {
18727a6dacacSDimitry Andric    def : Pat<(frag (loadi8 addr:$src), (shiftMask32 CL)),
18737a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "8mCL_ND") addr:$src)>;
18747a6dacacSDimitry Andric    def : Pat<(frag (loadi16 addr:$src), (shiftMask32 CL)),
18757a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "16mCL_ND") addr:$src)>;
18767a6dacacSDimitry Andric    def : Pat<(frag (loadi32 addr:$src), (shiftMask32 CL)),
18777a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "32mCL_ND") addr:$src)>;
18787a6dacacSDimitry Andric    def : Pat<(frag (loadi64 addr:$src), (shiftMask64 CL)),
18797a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "64mCL_ND") addr:$src)>;
18807a6dacacSDimitry Andric  }
18817a6dacacSDimitry Andric}
18827a6dacacSDimitry Andric
18837a6dacacSDimitry Andricdefm SHL : MaskedShiftAmountPats<shl>;
18847a6dacacSDimitry Andricdefm SHR : MaskedShiftAmountPats<srl>;
18857a6dacacSDimitry Andricdefm SAR : MaskedShiftAmountPats<sra>;
18860b57cec5SDimitry Andric
18870b57cec5SDimitry Andric// ROL/ROR instructions allow a stronger mask optimization than shift for 8- and
18880b57cec5SDimitry Andric// 16-bit. We can remove a mask of any (bitwidth - 1) on the rotation amount
18890b57cec5SDimitry Andric// because over-rotating produces the same result. This is noted in the Intel
18900b57cec5SDimitry Andric// docs with: "tempCOUNT <- (COUNT & COUNTMASK) MOD SIZE". Masking the rotation
18910b57cec5SDimitry Andric// amount could affect EFLAGS results, but that does not matter because we are
18920b57cec5SDimitry Andric// not tracking flags for these nodes.
18937a6dacacSDimitry Andricmulticlass MaskedRotateAmountPats<SDNode frag> {
18940b57cec5SDimitry Andric  // (rot x (and y, BitWidth - 1)) ==> (rot x, y)
18957a6dacacSDimitry Andric  let Predicates = [NoNDD] in {
18960b57cec5SDimitry Andric    def : Pat<(frag GR8:$src1, (shiftMask8 CL)),
18977a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "8rCL") GR8:$src1)>;
18980b57cec5SDimitry Andric    def : Pat<(frag GR16:$src1, (shiftMask16 CL)),
18997a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "16rCL") GR16:$src1)>;
19000b57cec5SDimitry Andric    def : Pat<(frag GR32:$src1, (shiftMask32 CL)),
19017a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "32rCL") GR32:$src1)>;
19020b57cec5SDimitry Andric    def : Pat<(frag GR64:$src1, (shiftMask64 CL)),
19037a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "64rCL") GR64:$src1)>;
19047a6dacacSDimitry Andric  }
19057a6dacacSDimitry Andric  let Predicates = [HasNDD] in {
19067a6dacacSDimitry Andric    def : Pat<(frag GR8:$src1, (shiftMask8 CL)),
19077a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "8rCL_ND") GR8:$src1)>;
19087a6dacacSDimitry Andric    def : Pat<(frag GR16:$src1, (shiftMask16 CL)),
19097a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "16rCL_ND") GR16:$src1)>;
19107a6dacacSDimitry Andric    def : Pat<(frag GR32:$src1, (shiftMask32 CL)),
19117a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "32rCL_ND") GR32:$src1)>;
19127a6dacacSDimitry Andric    def : Pat<(frag GR64:$src1, (shiftMask64 CL)),
19137a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "64rCL_ND") GR64:$src1)>;
19140b57cec5SDimitry Andric  }
19150b57cec5SDimitry Andric
19167a6dacacSDimitry Andric  def : Pat<(store (frag (loadi8 addr:$dst), (shiftMask8 CL)), addr:$dst),
19177a6dacacSDimitry Andric            (!cast<Instruction>(NAME # "8mCL") addr:$dst)>;
19187a6dacacSDimitry Andric  def : Pat<(store (frag (loadi16 addr:$dst), (shiftMask16 CL)), addr:$dst),
19197a6dacacSDimitry Andric            (!cast<Instruction>(NAME # "16mCL") addr:$dst)>;
19207a6dacacSDimitry Andric  def : Pat<(store (frag (loadi32 addr:$dst), (shiftMask32 CL)), addr:$dst),
19217a6dacacSDimitry Andric            (!cast<Instruction>(NAME # "32mCL") addr:$dst)>;
19227a6dacacSDimitry Andric  def : Pat<(store (frag (loadi64 addr:$dst), (shiftMask64 CL)), addr:$dst),
19237a6dacacSDimitry Andric            (!cast<Instruction>(NAME # "64mCL") addr:$dst)>;
19240b57cec5SDimitry Andric
19257a6dacacSDimitry Andric  let Predicates = [HasNDD] in {
19267a6dacacSDimitry Andric    def : Pat<(frag (loadi8 addr:$src), (shiftMask8 CL)),
19277a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "8mCL_ND") addr:$src)>;
19287a6dacacSDimitry Andric    def : Pat<(frag (loadi16 addr:$src), (shiftMask16 CL)),
19297a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "16mCL_ND") addr:$src)>;
19307a6dacacSDimitry Andric    def : Pat<(frag (loadi32 addr:$src), (shiftMask32 CL)),
19317a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "32mCL_ND") addr:$src)>;
19327a6dacacSDimitry Andric    def : Pat<(frag (loadi64 addr:$src), (shiftMask64 CL)),
19337a6dacacSDimitry Andric              (!cast<Instruction>(NAME # "64mCL_ND") addr:$src)>;
19347a6dacacSDimitry Andric  }
19357a6dacacSDimitry Andric}
19360b57cec5SDimitry Andric
19377a6dacacSDimitry Andricdefm ROL : MaskedRotateAmountPats<rotl>;
19387a6dacacSDimitry Andricdefm ROR : MaskedRotateAmountPats<rotr>;
19397a6dacacSDimitry Andric
19407a6dacacSDimitry Andricmulticlass MaskedShlrdAmountPats<string suffix, Predicate p> {
19417a6dacacSDimitry Andric  let Predicates = [p] in {
19425ffd83dbSDimitry Andric    // Double "funnel" shift amount is implicitly masked.
19435ffd83dbSDimitry Andric    // (fshl/fshr x (and y, 31)) ==> (fshl/fshr x, y) (NOTE: modulo32)
19445ffd83dbSDimitry Andric    def : Pat<(X86fshl GR16:$src1, GR16:$src2, (shiftMask32 CL)),
19457a6dacacSDimitry Andric              (!cast<Instruction>(SHLD16rrCL#suffix) GR16:$src1, GR16:$src2)>;
19465ffd83dbSDimitry Andric    def : Pat<(X86fshr GR16:$src2, GR16:$src1, (shiftMask32 CL)),
19477a6dacacSDimitry Andric              (!cast<Instruction>(SHRD16rrCL#suffix) GR16:$src1, GR16:$src2)>;
19480b57cec5SDimitry Andric
19495ffd83dbSDimitry Andric    // (fshl/fshr x (and y, 31)) ==> (fshl/fshr x, y)
19505ffd83dbSDimitry Andric    def : Pat<(fshl GR32:$src1, GR32:$src2, (shiftMask32 CL)),
19517a6dacacSDimitry Andric              (!cast<Instruction>(SHLD32rrCL#suffix) GR32:$src1, GR32:$src2)>;
19525ffd83dbSDimitry Andric    def : Pat<(fshr GR32:$src2, GR32:$src1, (shiftMask32 CL)),
19537a6dacacSDimitry Andric              (!cast<Instruction>(SHRD32rrCL#suffix) GR32:$src1, GR32:$src2)>;
19540b57cec5SDimitry Andric
19555ffd83dbSDimitry Andric    // (fshl/fshr x (and y, 63)) ==> (fshl/fshr x, y)
19565ffd83dbSDimitry Andric    def : Pat<(fshl GR64:$src1, GR64:$src2, (shiftMask64 CL)),
19577a6dacacSDimitry Andric              (!cast<Instruction>(SHLD64rrCL#suffix) GR64:$src1, GR64:$src2)>;
19585ffd83dbSDimitry Andric    def : Pat<(fshr GR64:$src2, GR64:$src1, (shiftMask64 CL)),
19597a6dacacSDimitry Andric              (!cast<Instruction>(SHRD64rrCL#suffix) GR64:$src1, GR64:$src2)>;
19607a6dacacSDimitry Andric  }
19610b57cec5SDimitry Andric}
19620b57cec5SDimitry Andric
19637a6dacacSDimitry Andricdefm : MaskedShlrdAmountPats<"", NoNDD>;
19647a6dacacSDimitry Andricdefm : MaskedShlrdAmountPats<"_ND", HasNDD>;
19650b57cec5SDimitry Andric
19660b57cec5SDimitry Andric// Use BTR/BTS/BTC for clearing/setting/toggling a bit in a variable location.
19677a6dacacSDimitry Andricmulticlass OneBitPats<RegisterClass rc, ValueType vt, Instruction btr,
19687a6dacacSDimitry Andric                      Instruction bts, Instruction btc, PatFrag mask> {
19697a6dacacSDimitry Andric  def : Pat<(and rc:$src1, (rotl -2, GR8:$src2)),
19707a6dacacSDimitry Andric            (btr rc:$src1,
19717a6dacacSDimitry Andric                 (INSERT_SUBREG (vt (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
19727a6dacacSDimitry Andric  def : Pat<(or rc:$src1, (shl 1, GR8:$src2)),
19737a6dacacSDimitry Andric            (bts rc:$src1,
19747a6dacacSDimitry Andric                 (INSERT_SUBREG (vt (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
19757a6dacacSDimitry Andric  def : Pat<(xor rc:$src1, (shl 1, GR8:$src2)),
19767a6dacacSDimitry Andric            (btc rc:$src1,
19777a6dacacSDimitry Andric                 (INSERT_SUBREG (vt (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
19780b57cec5SDimitry Andric
19790b57cec5SDimitry Andric  // Similar to above, but removing unneeded masking of the shift amount.
19807a6dacacSDimitry Andric  def : Pat<(and rc:$src1, (rotl -2, (mask GR8:$src2))),
19817a6dacacSDimitry Andric            (btr rc:$src1,
19827a6dacacSDimitry Andric                 (INSERT_SUBREG (vt (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
19837a6dacacSDimitry Andric  def : Pat<(or rc:$src1, (shl 1, (mask GR8:$src2))),
19847a6dacacSDimitry Andric            (bts rc:$src1,
19857a6dacacSDimitry Andric                (INSERT_SUBREG (vt (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
19867a6dacacSDimitry Andric  def : Pat<(xor rc:$src1, (shl 1, (mask GR8:$src2))),
19877a6dacacSDimitry Andric            (btc rc:$src1,
19887a6dacacSDimitry Andric                (INSERT_SUBREG (vt (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
19890b57cec5SDimitry Andric}
19900b57cec5SDimitry Andric
19917a6dacacSDimitry Andricdefm : OneBitPats<GR16, i16, BTR16rr, BTS16rr, BTC16rr, shiftMask16>;
19927a6dacacSDimitry Andricdefm : OneBitPats<GR32, i32, BTR32rr, BTS32rr, BTC32rr, shiftMask32>;
19937a6dacacSDimitry Andricdefm : OneBitPats<GR64, i64, BTR64rr, BTS64rr, BTC64rr, shiftMask64>;
19940b57cec5SDimitry Andric
19950b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
19960b57cec5SDimitry Andric// EFLAGS-defining Patterns
19970b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
19980b57cec5SDimitry Andric
1999297eecfbSDimitry Andricmulticlass EFLAGSDefiningPats<string suffix, Predicate p> {
2000297eecfbSDimitry Andric  let Predicates = [p] in {
20010b57cec5SDimitry Andric    // add reg, reg
2002297eecfbSDimitry Andric    def : Pat<(add GR8 :$src1, GR8 :$src2), (!cast<Instruction>(ADD8rr#suffix) GR8 :$src1, GR8 :$src2)>;
2003297eecfbSDimitry Andric    def : Pat<(add GR16:$src1, GR16:$src2), (!cast<Instruction>(ADD16rr#suffix) GR16:$src1, GR16:$src2)>;
2004297eecfbSDimitry Andric    def : Pat<(add GR32:$src1, GR32:$src2), (!cast<Instruction>(ADD32rr#suffix) GR32:$src1, GR32:$src2)>;
2005297eecfbSDimitry Andric    def : Pat<(add GR64:$src1, GR64:$src2), (!cast<Instruction>(ADD64rr#suffix) GR64:$src1, GR64:$src2)>;
20060b57cec5SDimitry Andric
20070b57cec5SDimitry Andric    // add reg, mem
20080b57cec5SDimitry Andric    def : Pat<(add GR8:$src1, (loadi8 addr:$src2)),
2009297eecfbSDimitry Andric              (!cast<Instruction>(ADD8rm#suffix) GR8:$src1, addr:$src2)>;
20100b57cec5SDimitry Andric    def : Pat<(add GR16:$src1, (loadi16 addr:$src2)),
2011297eecfbSDimitry Andric              (!cast<Instruction>(ADD16rm#suffix) GR16:$src1, addr:$src2)>;
20120b57cec5SDimitry Andric    def : Pat<(add GR32:$src1, (loadi32 addr:$src2)),
2013297eecfbSDimitry Andric              (!cast<Instruction>(ADD32rm#suffix) GR32:$src1, addr:$src2)>;
20140b57cec5SDimitry Andric    def : Pat<(add GR64:$src1, (loadi64 addr:$src2)),
2015297eecfbSDimitry Andric              (!cast<Instruction>(ADD64rm#suffix) GR64:$src1, addr:$src2)>;
20160b57cec5SDimitry Andric
20170b57cec5SDimitry Andric    // add reg, imm
2018297eecfbSDimitry Andric    def : Pat<(add GR8 :$src1, imm:$src2), (!cast<Instruction>(ADD8ri#suffix) GR8:$src1 , imm:$src2)>;
2019297eecfbSDimitry Andric    def : Pat<(add GR16:$src1, imm:$src2), (!cast<Instruction>(ADD16ri#suffix) GR16:$src1, imm:$src2)>;
2020297eecfbSDimitry Andric    def : Pat<(add GR32:$src1, imm:$src2), (!cast<Instruction>(ADD32ri#suffix) GR32:$src1, imm:$src2)>;
2021297eecfbSDimitry Andric    def : Pat<(add GR64:$src1, i64immSExt32:$src2), (!cast<Instruction>(ADD64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>;
20220b57cec5SDimitry Andric
20230b57cec5SDimitry Andric    // sub reg, reg
2024297eecfbSDimitry Andric    def : Pat<(sub GR8 :$src1, GR8 :$src2), (!cast<Instruction>(SUB8rr#suffix)  GR8 :$src1, GR8 :$src2)>;
2025297eecfbSDimitry Andric    def : Pat<(sub GR16:$src1, GR16:$src2), (!cast<Instruction>(SUB16rr#suffix) GR16:$src1, GR16:$src2)>;
2026297eecfbSDimitry Andric    def : Pat<(sub GR32:$src1, GR32:$src2), (!cast<Instruction>(SUB32rr#suffix) GR32:$src1, GR32:$src2)>;
2027297eecfbSDimitry Andric    def : Pat<(sub GR64:$src1, GR64:$src2), (!cast<Instruction>(SUB64rr#suffix) GR64:$src1, GR64:$src2)>;
20280b57cec5SDimitry Andric
20290b57cec5SDimitry Andric    // sub reg, mem
20300b57cec5SDimitry Andric    def : Pat<(sub GR8:$src1, (loadi8 addr:$src2)),
2031297eecfbSDimitry Andric              (!cast<Instruction>(SUB8rm#suffix) GR8:$src1, addr:$src2)>;
20320b57cec5SDimitry Andric    def : Pat<(sub GR16:$src1, (loadi16 addr:$src2)),
2033297eecfbSDimitry Andric              (!cast<Instruction>(SUB16rm#suffix) GR16:$src1, addr:$src2)>;
20340b57cec5SDimitry Andric    def : Pat<(sub GR32:$src1, (loadi32 addr:$src2)),
2035297eecfbSDimitry Andric              (!cast<Instruction>(SUB32rm#suffix) GR32:$src1, addr:$src2)>;
20360b57cec5SDimitry Andric    def : Pat<(sub GR64:$src1, (loadi64 addr:$src2)),
2037297eecfbSDimitry Andric              (!cast<Instruction>(SUB64rm#suffix) GR64:$src1, addr:$src2)>;
20380b57cec5SDimitry Andric
20390b57cec5SDimitry Andric    // sub reg, imm
20400b57cec5SDimitry Andric    def : Pat<(sub GR8:$src1, imm:$src2),
2041297eecfbSDimitry Andric              (!cast<Instruction>(SUB8ri#suffix) GR8:$src1, imm:$src2)>;
20420b57cec5SDimitry Andric    def : Pat<(sub GR16:$src1, imm:$src2),
2043297eecfbSDimitry Andric              (!cast<Instruction>(SUB16ri#suffix) GR16:$src1, imm:$src2)>;
20440b57cec5SDimitry Andric    def : Pat<(sub GR32:$src1, imm:$src2),
2045297eecfbSDimitry Andric              (!cast<Instruction>(SUB32ri#suffix) GR32:$src1, imm:$src2)>;
20460b57cec5SDimitry Andric    def : Pat<(sub GR64:$src1, i64immSExt32:$src2),
2047297eecfbSDimitry Andric              (!cast<Instruction>(SUB64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>;
20480b57cec5SDimitry Andric
20490b57cec5SDimitry Andric    // sub 0, reg
2050297eecfbSDimitry Andric    def : Pat<(X86sub_flag 0, GR8 :$src), (!cast<Instruction>(NEG8r#suffix)  GR8 :$src)>;
2051297eecfbSDimitry Andric    def : Pat<(X86sub_flag 0, GR16:$src), (!cast<Instruction>(NEG16r#suffix) GR16:$src)>;
2052297eecfbSDimitry Andric    def : Pat<(X86sub_flag 0, GR32:$src), (!cast<Instruction>(NEG32r#suffix) GR32:$src)>;
2053297eecfbSDimitry Andric    def : Pat<(X86sub_flag 0, GR64:$src), (!cast<Instruction>(NEG64r#suffix) GR64:$src)>;
20540b57cec5SDimitry Andric
20550b57cec5SDimitry Andric    // mul reg, reg
20560b57cec5SDimitry Andric    def : Pat<(mul GR16:$src1, GR16:$src2),
2057297eecfbSDimitry Andric              (!cast<Instruction>(IMUL16rr#suffix) GR16:$src1, GR16:$src2)>;
20580b57cec5SDimitry Andric    def : Pat<(mul GR32:$src1, GR32:$src2),
2059297eecfbSDimitry Andric              (!cast<Instruction>(IMUL32rr#suffix) GR32:$src1, GR32:$src2)>;
20600b57cec5SDimitry Andric    def : Pat<(mul GR64:$src1, GR64:$src2),
2061297eecfbSDimitry Andric              (!cast<Instruction>(IMUL64rr#suffix) GR64:$src1, GR64:$src2)>;
20620b57cec5SDimitry Andric
20630b57cec5SDimitry Andric    // mul reg, mem
20640b57cec5SDimitry Andric    def : Pat<(mul GR16:$src1, (loadi16 addr:$src2)),
2065297eecfbSDimitry Andric              (!cast<Instruction>(IMUL16rm#suffix) GR16:$src1, addr:$src2)>;
20660b57cec5SDimitry Andric    def : Pat<(mul GR32:$src1, (loadi32 addr:$src2)),
2067297eecfbSDimitry Andric              (!cast<Instruction>(IMUL32rm#suffix) GR32:$src1, addr:$src2)>;
20680b57cec5SDimitry Andric    def : Pat<(mul GR64:$src1, (loadi64 addr:$src2)),
2069297eecfbSDimitry Andric              (!cast<Instruction>(IMUL64rm#suffix) GR64:$src1, addr:$src2)>;
2070297eecfbSDimitry Andric
2071297eecfbSDimitry Andric    // or reg/reg.
2072297eecfbSDimitry Andric    def : Pat<(or GR8 :$src1, GR8 :$src2), (!cast<Instruction>(OR8rr#suffix)  GR8 :$src1, GR8 :$src2)>;
2073297eecfbSDimitry Andric    def : Pat<(or GR16:$src1, GR16:$src2), (!cast<Instruction>(OR16rr#suffix) GR16:$src1, GR16:$src2)>;
2074297eecfbSDimitry Andric    def : Pat<(or GR32:$src1, GR32:$src2), (!cast<Instruction>(OR32rr#suffix) GR32:$src1, GR32:$src2)>;
2075297eecfbSDimitry Andric    def : Pat<(or GR64:$src1, GR64:$src2), (!cast<Instruction>(OR64rr#suffix) GR64:$src1, GR64:$src2)>;
2076297eecfbSDimitry Andric
2077297eecfbSDimitry Andric    // or reg/mem
2078297eecfbSDimitry Andric    def : Pat<(or GR8:$src1, (loadi8 addr:$src2)),
2079297eecfbSDimitry Andric              (!cast<Instruction>(OR8rm#suffix) GR8:$src1, addr:$src2)>;
2080297eecfbSDimitry Andric    def : Pat<(or GR16:$src1, (loadi16 addr:$src2)),
2081297eecfbSDimitry Andric              (!cast<Instruction>(OR16rm#suffix) GR16:$src1, addr:$src2)>;
2082297eecfbSDimitry Andric    def : Pat<(or GR32:$src1, (loadi32 addr:$src2)),
2083297eecfbSDimitry Andric              (!cast<Instruction>(OR32rm#suffix) GR32:$src1, addr:$src2)>;
2084297eecfbSDimitry Andric    def : Pat<(or GR64:$src1, (loadi64 addr:$src2)),
2085297eecfbSDimitry Andric              (!cast<Instruction>(OR64rm#suffix) GR64:$src1, addr:$src2)>;
2086297eecfbSDimitry Andric
2087297eecfbSDimitry Andric    // or reg/imm
2088297eecfbSDimitry Andric    def : Pat<(or GR8:$src1 , imm:$src2), (!cast<Instruction>(OR8ri#suffix)  GR8 :$src1, imm:$src2)>;
2089297eecfbSDimitry Andric    def : Pat<(or GR16:$src1, imm:$src2), (!cast<Instruction>(OR16ri#suffix) GR16:$src1, imm:$src2)>;
2090297eecfbSDimitry Andric    def : Pat<(or GR32:$src1, imm:$src2), (!cast<Instruction>(OR32ri#suffix) GR32:$src1, imm:$src2)>;
2091297eecfbSDimitry Andric    def : Pat<(or GR64:$src1, i64immSExt32:$src2),
2092297eecfbSDimitry Andric              (!cast<Instruction>(OR64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>;
2093297eecfbSDimitry Andric
2094297eecfbSDimitry Andric    // xor reg/reg
2095297eecfbSDimitry Andric    def : Pat<(xor GR8 :$src1, GR8 :$src2), (!cast<Instruction>(XOR8rr#suffix)  GR8 :$src1, GR8 :$src2)>;
2096297eecfbSDimitry Andric    def : Pat<(xor GR16:$src1, GR16:$src2), (!cast<Instruction>(XOR16rr#suffix) GR16:$src1, GR16:$src2)>;
2097297eecfbSDimitry Andric    def : Pat<(xor GR32:$src1, GR32:$src2), (!cast<Instruction>(XOR32rr#suffix) GR32:$src1, GR32:$src2)>;
2098297eecfbSDimitry Andric    def : Pat<(xor GR64:$src1, GR64:$src2), (!cast<Instruction>(XOR64rr#suffix) GR64:$src1, GR64:$src2)>;
2099297eecfbSDimitry Andric
2100297eecfbSDimitry Andric    // xor reg/mem
2101297eecfbSDimitry Andric    def : Pat<(xor GR8:$src1, (loadi8 addr:$src2)),
2102297eecfbSDimitry Andric              (!cast<Instruction>(XOR8rm#suffix) GR8:$src1, addr:$src2)>;
2103297eecfbSDimitry Andric    def : Pat<(xor GR16:$src1, (loadi16 addr:$src2)),
2104297eecfbSDimitry Andric              (!cast<Instruction>(XOR16rm#suffix) GR16:$src1, addr:$src2)>;
2105297eecfbSDimitry Andric    def : Pat<(xor GR32:$src1, (loadi32 addr:$src2)),
2106297eecfbSDimitry Andric              (!cast<Instruction>(XOR32rm#suffix) GR32:$src1, addr:$src2)>;
2107297eecfbSDimitry Andric    def : Pat<(xor GR64:$src1, (loadi64 addr:$src2)),
2108297eecfbSDimitry Andric              (!cast<Instruction>(XOR64rm#suffix) GR64:$src1, addr:$src2)>;
2109297eecfbSDimitry Andric
2110297eecfbSDimitry Andric    // xor reg/imm
2111297eecfbSDimitry Andric    def : Pat<(xor GR8:$src1, imm:$src2),
2112297eecfbSDimitry Andric              (!cast<Instruction>(XOR8ri#suffix) GR8:$src1, imm:$src2)>;
2113297eecfbSDimitry Andric    def : Pat<(xor GR16:$src1, imm:$src2),
2114297eecfbSDimitry Andric              (!cast<Instruction>(XOR16ri#suffix) GR16:$src1, imm:$src2)>;
2115297eecfbSDimitry Andric    def : Pat<(xor GR32:$src1, imm:$src2),
2116297eecfbSDimitry Andric              (!cast<Instruction>(XOR32ri#suffix) GR32:$src1, imm:$src2)>;
2117297eecfbSDimitry Andric    def : Pat<(xor GR64:$src1, i64immSExt32:$src2),
2118297eecfbSDimitry Andric              (!cast<Instruction>(XOR64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>;
2119297eecfbSDimitry Andric
2120297eecfbSDimitry Andric    // and reg/reg
2121297eecfbSDimitry Andric    def : Pat<(and GR8 :$src1, GR8 :$src2), (!cast<Instruction>(AND8rr#suffix)  GR8 :$src1, GR8 :$src2)>;
2122297eecfbSDimitry Andric    def : Pat<(and GR16:$src1, GR16:$src2), (!cast<Instruction>(AND16rr#suffix) GR16:$src1, GR16:$src2)>;
2123297eecfbSDimitry Andric    def : Pat<(and GR32:$src1, GR32:$src2), (!cast<Instruction>(AND32rr#suffix) GR32:$src1, GR32:$src2)>;
2124297eecfbSDimitry Andric    def : Pat<(and GR64:$src1, GR64:$src2), (!cast<Instruction>(AND64rr#suffix) GR64:$src1, GR64:$src2)>;
2125297eecfbSDimitry Andric
2126297eecfbSDimitry Andric    // and reg/mem
2127297eecfbSDimitry Andric    def : Pat<(and GR8:$src1, (loadi8 addr:$src2)),
2128297eecfbSDimitry Andric              (!cast<Instruction>(AND8rm#suffix) GR8:$src1, addr:$src2)>;
2129297eecfbSDimitry Andric    def : Pat<(and GR16:$src1, (loadi16 addr:$src2)),
2130297eecfbSDimitry Andric              (!cast<Instruction>(AND16rm#suffix) GR16:$src1, addr:$src2)>;
2131297eecfbSDimitry Andric    def : Pat<(and GR32:$src1, (loadi32 addr:$src2)),
2132297eecfbSDimitry Andric              (!cast<Instruction>(AND32rm#suffix) GR32:$src1, addr:$src2)>;
2133297eecfbSDimitry Andric    def : Pat<(and GR64:$src1, (loadi64 addr:$src2)),
2134297eecfbSDimitry Andric              (!cast<Instruction>(AND64rm#suffix) GR64:$src1, addr:$src2)>;
2135297eecfbSDimitry Andric
2136297eecfbSDimitry Andric    // and reg/imm
2137297eecfbSDimitry Andric    def : Pat<(and GR8:$src1, imm:$src2),
2138297eecfbSDimitry Andric              (!cast<Instruction>(AND8ri#suffix) GR8:$src1, imm:$src2)>;
2139297eecfbSDimitry Andric    def : Pat<(and GR16:$src1, imm:$src2),
2140297eecfbSDimitry Andric              (!cast<Instruction>(AND16ri#suffix) GR16:$src1, imm:$src2)>;
2141297eecfbSDimitry Andric    def : Pat<(and GR32:$src1, imm:$src2),
2142297eecfbSDimitry Andric              (!cast<Instruction>(AND32ri#suffix) GR32:$src1, imm:$src2)>;
2143297eecfbSDimitry Andric    def : Pat<(and GR64:$src1, i64immSExt32:$src2),
2144297eecfbSDimitry Andric              (!cast<Instruction>(AND64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>;
2145297eecfbSDimitry Andric  }
2146297eecfbSDimitry Andric
2147297eecfbSDimitry Andric  // Increment/Decrement reg.
2148297eecfbSDimitry Andric  // Do not make INC/DEC if it is slow
2149297eecfbSDimitry Andric  let Predicates = [UseIncDec, p] in {
2150297eecfbSDimitry Andric    def : Pat<(add GR8:$src, 1),   (!cast<Instruction>(INC8r#suffix) GR8:$src)>;
2151297eecfbSDimitry Andric    def : Pat<(add GR16:$src, 1),  (!cast<Instruction>(INC16r#suffix) GR16:$src)>;
2152297eecfbSDimitry Andric    def : Pat<(add GR32:$src, 1),  (!cast<Instruction>(INC32r#suffix) GR32:$src)>;
2153297eecfbSDimitry Andric    def : Pat<(add GR64:$src, 1),  (!cast<Instruction>(INC64r#suffix) GR64:$src)>;
2154297eecfbSDimitry Andric    def : Pat<(add GR8:$src, -1),  (!cast<Instruction>(DEC8r#suffix) GR8:$src)>;
2155297eecfbSDimitry Andric    def : Pat<(add GR16:$src, -1), (!cast<Instruction>(DEC16r#suffix) GR16:$src)>;
2156297eecfbSDimitry Andric    def : Pat<(add GR32:$src, -1), (!cast<Instruction>(DEC32r#suffix) GR32:$src)>;
2157297eecfbSDimitry Andric    def : Pat<(add GR64:$src, -1), (!cast<Instruction>(DEC64r#suffix) GR64:$src)>;
2158297eecfbSDimitry Andric
2159297eecfbSDimitry Andric    def : Pat<(X86add_flag_nocf GR8:$src, -1),  (!cast<Instruction>(DEC8r#suffix) GR8:$src)>;
2160297eecfbSDimitry Andric    def : Pat<(X86add_flag_nocf GR16:$src, -1), (!cast<Instruction>(DEC16r#suffix) GR16:$src)>;
2161297eecfbSDimitry Andric    def : Pat<(X86add_flag_nocf GR32:$src, -1), (!cast<Instruction>(DEC32r#suffix) GR32:$src)>;
2162297eecfbSDimitry Andric    def : Pat<(X86add_flag_nocf GR64:$src, -1), (!cast<Instruction>(DEC64r#suffix) GR64:$src)>;
2163297eecfbSDimitry Andric    def : Pat<(X86sub_flag_nocf GR8:$src, -1),  (!cast<Instruction>(INC8r#suffix) GR8:$src)>;
2164297eecfbSDimitry Andric    def : Pat<(X86sub_flag_nocf GR16:$src, -1), (!cast<Instruction>(INC16r#suffix) GR16:$src)>;
2165297eecfbSDimitry Andric    def : Pat<(X86sub_flag_nocf GR32:$src, -1), (!cast<Instruction>(INC32r#suffix) GR32:$src)>;
2166297eecfbSDimitry Andric    def : Pat<(X86sub_flag_nocf GR64:$src, -1), (!cast<Instruction>(INC64r#suffix) GR64:$src)>;
21670fca6ea1SDimitry Andric
21680fca6ea1SDimitry Andric    def : Pat<(or_is_add GR8:$src, 1),   (!cast<Instruction>(INC8r#suffix) GR8:$src)>;
21690fca6ea1SDimitry Andric    def : Pat<(or_is_add GR16:$src, 1),  (!cast<Instruction>(INC16r#suffix) GR16:$src)>;
21700fca6ea1SDimitry Andric    def : Pat<(or_is_add GR32:$src, 1),  (!cast<Instruction>(INC32r#suffix) GR32:$src)>;
21710fca6ea1SDimitry Andric    def : Pat<(or_is_add GR64:$src, 1),  (!cast<Instruction>(INC64r#suffix) GR64:$src)>;
2172297eecfbSDimitry Andric  }
2173297eecfbSDimitry Andric}
2174297eecfbSDimitry Andric
2175297eecfbSDimitry Andricdefm : EFLAGSDefiningPats<"", NoNDD>;
2176297eecfbSDimitry Andricdefm : EFLAGSDefiningPats<"_ND", HasNDD>;
21770b57cec5SDimitry Andric
21780b57cec5SDimitry Andric// mul reg, imm
21790b57cec5SDimitry Andricdef : Pat<(mul GR16:$src1, imm:$src2),
21800b57cec5SDimitry Andric          (IMUL16rri GR16:$src1, imm:$src2)>;
21810b57cec5SDimitry Andricdef : Pat<(mul GR32:$src1, imm:$src2),
21820b57cec5SDimitry Andric          (IMUL32rri GR32:$src1, imm:$src2)>;
21830b57cec5SDimitry Andricdef : Pat<(mul GR64:$src1, i64immSExt32:$src2),
21840b57cec5SDimitry Andric          (IMUL64rri32 GR64:$src1, i64immSExt32:$src2)>;
21850b57cec5SDimitry Andric
21860b57cec5SDimitry Andric// reg = mul mem, imm
21870b57cec5SDimitry Andricdef : Pat<(mul (loadi16 addr:$src1), imm:$src2),
21880b57cec5SDimitry Andric          (IMUL16rmi addr:$src1, imm:$src2)>;
21890b57cec5SDimitry Andricdef : Pat<(mul (loadi32 addr:$src1), imm:$src2),
21900b57cec5SDimitry Andric          (IMUL32rmi addr:$src1, imm:$src2)>;
21910b57cec5SDimitry Andricdef : Pat<(mul (loadi64 addr:$src1), i64immSExt32:$src2),
21920b57cec5SDimitry Andric          (IMUL64rmi32 addr:$src1, i64immSExt32:$src2)>;
21930b57cec5SDimitry Andric
21940b57cec5SDimitry Andric// Bit scan instruction patterns to match explicit zero-undef behavior.
21950b57cec5SDimitry Andricdef : Pat<(cttz_zero_undef GR16:$src), (BSF16rr GR16:$src)>;
21960b57cec5SDimitry Andricdef : Pat<(cttz_zero_undef GR32:$src), (BSF32rr GR32:$src)>;
21970b57cec5SDimitry Andricdef : Pat<(cttz_zero_undef GR64:$src), (BSF64rr GR64:$src)>;
21980b57cec5SDimitry Andricdef : Pat<(cttz_zero_undef (loadi16 addr:$src)), (BSF16rm addr:$src)>;
21990b57cec5SDimitry Andricdef : Pat<(cttz_zero_undef (loadi32 addr:$src)), (BSF32rm addr:$src)>;
22000b57cec5SDimitry Andricdef : Pat<(cttz_zero_undef (loadi64 addr:$src)), (BSF64rm addr:$src)>;
22010b57cec5SDimitry Andric
22020b57cec5SDimitry Andric// When HasMOVBE is enabled it is possible to get a non-legalized
22030b57cec5SDimitry Andric// register-register 16 bit bswap. This maps it to a ROL instruction.
22040b57cec5SDimitry Andriclet Predicates = [HasMOVBE] in {
22050b57cec5SDimitry Andric def : Pat<(bswap GR16:$src), (ROL16ri GR16:$src, (i8 8))>;
22060b57cec5SDimitry Andric}
2207