| Chris Lattner | ae33f5d | 2010-10-05 06:04:14 +0000 | [diff] [blame] | 1 | //===- X86InstrCompiler.td - Compiler Pseudos and Patterns -*- tablegen -*-===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This file describes the various pseudo instructions used by the compiler, | 
|  | 11 | // as well as Pat patterns used during instruction selection. | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
| Chris Lattner | 44a5a2b | 2010-10-05 06:37:31 +0000 | [diff] [blame] | 15 | //===----------------------------------------------------------------------===// | 
|  | 16 | // Pattern Matching Support | 
|  | 17 |  | 
|  | 18 | def GetLo32XForm : SDNodeXForm<imm, [{ | 
|  | 19 | // Transformation function: get the low 32 bits. | 
|  | 20 | return getI32Imm((unsigned)N->getZExtValue()); | 
|  | 21 | }]>; | 
|  | 22 |  | 
|  | 23 |  | 
|  | 24 | //===----------------------------------------------------------------------===// | 
|  | 25 | // Random Pseudo Instructions. | 
|  | 26 |  | 
| Chris Lattner | c793f8b | 2010-10-05 06:10:16 +0000 | [diff] [blame] | 27 | // PIC base construction.  This expands to code that looks like this: | 
|  | 28 | //     call  $next_inst | 
|  | 29 | //     popl %destreg" | 
|  | 30 | let neverHasSideEffects = 1, isNotDuplicable = 1, Uses = [ESP] in | 
|  | 31 | def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins i32imm:$label), | 
|  | 32 | "", []>; | 
|  | 33 |  | 
|  | 34 |  | 
|  | 35 | // ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into | 
|  | 36 | // a stack adjustment and the codegen must know that they may modify the stack | 
|  | 37 | // pointer before prolog-epilog rewriting occurs. | 
|  | 38 | // Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become | 
|  | 39 | // sub / add which can clobber EFLAGS. | 
|  | 40 | let Defs = [ESP, EFLAGS], Uses = [ESP] in { | 
|  | 41 | def ADJCALLSTACKDOWN32 : I<0, Pseudo, (outs), (ins i32imm:$amt), | 
|  | 42 | "#ADJCALLSTACKDOWN", | 
|  | 43 | [(X86callseq_start timm:$amt)]>, | 
|  | 44 | Requires<[In32BitMode]>; | 
|  | 45 | def ADJCALLSTACKUP32   : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), | 
|  | 46 | "#ADJCALLSTACKUP", | 
|  | 47 | [(X86callseq_end timm:$amt1, timm:$amt2)]>, | 
|  | 48 | Requires<[In32BitMode]>; | 
|  | 49 | } | 
|  | 50 |  | 
|  | 51 | // ADJCALLSTACKDOWN/UP implicitly use/def RSP because they may be expanded into | 
|  | 52 | // a stack adjustment and the codegen must know that they may modify the stack | 
|  | 53 | // pointer before prolog-epilog rewriting occurs. | 
|  | 54 | // Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become | 
|  | 55 | // sub / add which can clobber EFLAGS. | 
|  | 56 | let Defs = [RSP, EFLAGS], Uses = [RSP] in { | 
|  | 57 | def ADJCALLSTACKDOWN64 : I<0, Pseudo, (outs), (ins i32imm:$amt), | 
|  | 58 | "#ADJCALLSTACKDOWN", | 
|  | 59 | [(X86callseq_start timm:$amt)]>, | 
|  | 60 | Requires<[In64BitMode]>; | 
|  | 61 | def ADJCALLSTACKUP64   : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), | 
|  | 62 | "#ADJCALLSTACKUP", | 
|  | 63 | [(X86callseq_end timm:$amt1, timm:$amt2)]>, | 
|  | 64 | Requires<[In64BitMode]>; | 
|  | 65 | } | 
|  | 66 |  | 
|  | 67 |  | 
|  | 68 |  | 
|  | 69 | // x86-64 va_start lowering magic. | 
|  | 70 | let usesCustomInserter = 1 in { | 
|  | 71 | def VASTART_SAVE_XMM_REGS : I<0, Pseudo, | 
|  | 72 | (outs), | 
|  | 73 | (ins GR8:$al, | 
|  | 74 | i64imm:$regsavefi, i64imm:$offset, | 
|  | 75 | variable_ops), | 
|  | 76 | "#VASTART_SAVE_XMM_REGS $al, $regsavefi, $offset", | 
|  | 77 | [(X86vastart_save_xmm_regs GR8:$al, | 
|  | 78 | imm:$regsavefi, | 
|  | 79 | imm:$offset)]>; | 
|  | 80 |  | 
|  | 81 | // Dynamic stack allocation yields _alloca call for Cygwin/Mingw targets.  Calls | 
|  | 82 | // to _alloca is needed to probe the stack when allocating more than 4k bytes in | 
|  | 83 | // one go. Touching the stack at 4K increments is necessary to ensure that the | 
|  | 84 | // guard pages used by the OS virtual memory manager are allocated in correct | 
|  | 85 | // sequence. | 
|  | 86 | // The main point of having separate instruction are extra unmodelled effects | 
|  | 87 | // (compared to ordinary calls) like stack pointer change. | 
|  | 88 |  | 
|  | 89 | let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in | 
|  | 90 | def MINGW_ALLOCA : I<0, Pseudo, (outs), (ins), | 
|  | 91 | "# dynamic stack allocation", | 
|  | 92 | [(X86MingwAlloca)]>; | 
|  | 93 | } | 
|  | 94 |  | 
|  | 95 |  | 
| Chris Lattner | ae33f5d | 2010-10-05 06:04:14 +0000 | [diff] [blame] | 96 |  | 
|  | 97 | //===----------------------------------------------------------------------===// | 
|  | 98 | // EH Pseudo Instructions | 
|  | 99 | // | 
|  | 100 | let isTerminator = 1, isReturn = 1, isBarrier = 1, | 
|  | 101 | hasCtrlDep = 1, isCodeGenOnly = 1 in { | 
|  | 102 | def EH_RETURN   : I<0xC3, RawFrm, (outs), (ins GR32:$addr), | 
|  | 103 | "ret\t#eh_return, addr: $addr", | 
|  | 104 | [(X86ehret GR32:$addr)]>; | 
|  | 105 |  | 
|  | 106 | } | 
|  | 107 |  | 
|  | 108 | let isTerminator = 1, isReturn = 1, isBarrier = 1, | 
|  | 109 | hasCtrlDep = 1, isCodeGenOnly = 1 in { | 
|  | 110 | def EH_RETURN64   : I<0xC3, RawFrm, (outs), (ins GR64:$addr), | 
|  | 111 | "ret\t#eh_return, addr: $addr", | 
|  | 112 | [(X86ehret GR64:$addr)]>; | 
|  | 113 |  | 
|  | 114 | } | 
|  | 115 |  | 
| Chris Lattner | c793f8b | 2010-10-05 06:10:16 +0000 | [diff] [blame] | 116 | //===----------------------------------------------------------------------===// | 
|  | 117 | // Alias Instructions | 
|  | 118 | //===----------------------------------------------------------------------===// | 
|  | 119 |  | 
|  | 120 | // Alias instructions that map movr0 to xor. | 
|  | 121 | // FIXME: remove when we can teach regalloc that xor reg, reg is ok. | 
|  | 122 | // FIXME: Set encoding to pseudo. | 
|  | 123 | let Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1, | 
|  | 124 | isCodeGenOnly = 1 in { | 
|  | 125 | def MOV8r0   : I<0x30, MRMInitReg, (outs GR8 :$dst), (ins), "", | 
|  | 126 | [(set GR8:$dst, 0)]>; | 
|  | 127 |  | 
|  | 128 | // We want to rewrite MOV16r0 in terms of MOV32r0, because it's a smaller | 
|  | 129 | // encoding and avoids a partial-register update sometimes, but doing so | 
|  | 130 | // at isel time interferes with rematerialization in the current register | 
|  | 131 | // allocator. For now, this is rewritten when the instruction is lowered | 
|  | 132 | // to an MCInst. | 
|  | 133 | def MOV16r0   : I<0x31, MRMInitReg, (outs GR16:$dst), (ins), | 
|  | 134 | "", | 
|  | 135 | [(set GR16:$dst, 0)]>, OpSize; | 
|  | 136 |  | 
|  | 137 | // FIXME: Set encoding to pseudo. | 
|  | 138 | def MOV32r0  : I<0x31, MRMInitReg, (outs GR32:$dst), (ins), "", | 
|  | 139 | [(set GR32:$dst, 0)]>; | 
|  | 140 | } | 
|  | 141 |  | 
| Chris Lattner | c184a57 | 2010-10-05 06:22:35 +0000 | [diff] [blame] | 142 | // We want to rewrite MOV64r0 in terms of MOV32r0, because it's sometimes a | 
|  | 143 | // smaller encoding, but doing so at isel time interferes with rematerialization | 
|  | 144 | // in the current register allocator. For now, this is rewritten when the | 
|  | 145 | // instruction is lowered to an MCInst. | 
|  | 146 | // FIXME: AddedComplexity gives this a higher priority than MOV64ri32. Remove | 
|  | 147 | // when we have a better way to specify isel priority. | 
|  | 148 | let Defs = [EFLAGS], | 
|  | 149 | AddedComplexity = 1, isReMaterializable = 1, isAsCheapAsAMove = 1 in | 
|  | 150 | def MOV64r0   : I<0x31, MRMInitReg, (outs GR64:$dst), (ins), "", | 
|  | 151 | [(set GR64:$dst, 0)]>; | 
|  | 152 |  | 
|  | 153 | // Materialize i64 constant where top 32-bits are zero. This could theoretically | 
|  | 154 | // use MOV32ri with a SUBREG_TO_REG to represent the zero-extension, however | 
|  | 155 | // that would make it more difficult to rematerialize. | 
|  | 156 | let AddedComplexity = 1, isReMaterializable = 1, isAsCheapAsAMove = 1 in | 
|  | 157 | def MOV64ri64i32 : Ii32<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64i32imm:$src), | 
|  | 158 | "", [(set GR64:$dst, i64immZExt32:$src)]>; | 
|  | 159 |  | 
| Chris Lattner | fa9b058 | 2010-10-05 06:33:16 +0000 | [diff] [blame] | 160 |  | 
| Chris Lattner | 8f4f1d1 | 2010-10-05 21:18:04 +0000 | [diff] [blame] | 161 | // Use sbb to materialize carry bit. | 
|  | 162 | let Uses = [EFLAGS], Defs = [EFLAGS], isCodeGenOnly = 1 in { | 
|  | 163 | // FIXME: These are pseudo ops that should be replaced with Pat<> patterns. | 
| Chris Lattner | fa9b058 | 2010-10-05 06:33:16 +0000 | [diff] [blame] | 164 | // However, Pat<> can't replicate the destination reg into the inputs of the | 
|  | 165 | // result. | 
| Chris Lattner | 8f4f1d1 | 2010-10-05 21:18:04 +0000 | [diff] [blame] | 166 | // FIXME: Change these to have encoding Pseudo when X86MCCodeEmitter replaces | 
| Chris Lattner | fa9b058 | 2010-10-05 06:33:16 +0000 | [diff] [blame] | 167 | // X86CodeEmitter. | 
| Chris Lattner | 8f4f1d1 | 2010-10-05 21:18:04 +0000 | [diff] [blame] | 168 | def SETB_C8r : I<0x18, MRMInitReg, (outs GR8:$dst), (ins), "", | 
|  | 169 | [(set GR8:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; | 
|  | 170 | def SETB_C16r : I<0x19, MRMInitReg, (outs GR16:$dst), (ins), "", | 
|  | 171 | [(set GR16:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>, | 
|  | 172 | OpSize; | 
|  | 173 | def SETB_C32r : I<0x19, MRMInitReg, (outs GR32:$dst), (ins), "", | 
|  | 174 | [(set GR32:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; | 
| Chris Lattner | fa9b058 | 2010-10-05 06:33:16 +0000 | [diff] [blame] | 175 | def SETB_C64r : RI<0x19, MRMInitReg, (outs GR64:$dst), (ins), "", | 
|  | 176 | [(set GR64:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; | 
| Chris Lattner | 8f4f1d1 | 2010-10-05 21:18:04 +0000 | [diff] [blame] | 177 | } // isCodeGenOnly | 
|  | 178 |  | 
| Chris Lattner | fa9b058 | 2010-10-05 06:33:16 +0000 | [diff] [blame] | 179 |  | 
|  | 180 | def : Pat<(i64 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), | 
|  | 181 | (SETB_C64r)>; | 
|  | 182 |  | 
| Chris Lattner | c184a57 | 2010-10-05 06:22:35 +0000 | [diff] [blame] | 183 |  | 
| Chris Lattner | f9594ba | 2010-10-05 06:27:48 +0000 | [diff] [blame] | 184 | //===----------------------------------------------------------------------===// | 
|  | 185 | // String Pseudo Instructions | 
|  | 186 | // | 
|  | 187 | let Defs = [ECX,EDI,ESI], Uses = [ECX,EDI,ESI], isCodeGenOnly = 1 in { | 
|  | 188 | def REP_MOVSB : I<0xA4, RawFrm, (outs), (ins), "{rep;movsb|rep movsb}", | 
|  | 189 | [(X86rep_movs i8)]>, REP; | 
|  | 190 | def REP_MOVSW : I<0xA5, RawFrm, (outs), (ins), "{rep;movsw|rep movsw}", | 
|  | 191 | [(X86rep_movs i16)]>, REP, OpSize; | 
|  | 192 | def REP_MOVSD : I<0xA5, RawFrm, (outs), (ins), "{rep;movsl|rep movsd}", | 
|  | 193 | [(X86rep_movs i32)]>, REP; | 
|  | 194 | } | 
|  | 195 |  | 
|  | 196 | let Defs = [RCX,RDI,RSI], Uses = [RCX,RDI,RSI], isCodeGenOnly = 1 in | 
|  | 197 | def REP_MOVSQ : RI<0xA5, RawFrm, (outs), (ins), "{rep;movsq|rep movsq}", | 
|  | 198 | [(X86rep_movs i64)]>, REP; | 
|  | 199 |  | 
|  | 200 |  | 
|  | 201 | // FIXME: Should use "(X86rep_stos AL)" as the pattern. | 
|  | 202 | let Defs = [ECX,EDI], Uses = [AL,ECX,EDI], isCodeGenOnly = 1 in | 
|  | 203 | def REP_STOSB : I<0xAA, RawFrm, (outs), (ins), "{rep;stosb|rep stosb}", | 
|  | 204 | [(X86rep_stos i8)]>, REP; | 
|  | 205 | let Defs = [ECX,EDI], Uses = [AX,ECX,EDI], isCodeGenOnly = 1 in | 
|  | 206 | def REP_STOSW : I<0xAB, RawFrm, (outs), (ins), "{rep;stosw|rep stosw}", | 
|  | 207 | [(X86rep_stos i16)]>, REP, OpSize; | 
|  | 208 | let Defs = [ECX,EDI], Uses = [EAX,ECX,EDI], isCodeGenOnly = 1 in | 
|  | 209 | def REP_STOSD : I<0xAB, RawFrm, (outs), (ins), "{rep;stosl|rep stosd}", | 
|  | 210 | [(X86rep_stos i32)]>, REP; | 
|  | 211 |  | 
|  | 212 | let Defs = [RCX,RDI], Uses = [RAX,RCX,RDI], isCodeGenOnly = 1 in | 
|  | 213 | def REP_STOSQ : RI<0xAB, RawFrm, (outs), (ins), "{rep;stosq|rep stosq}", | 
|  | 214 | [(X86rep_stos i64)]>, REP; | 
| Chris Lattner | c184a57 | 2010-10-05 06:22:35 +0000 | [diff] [blame] | 215 |  | 
|  | 216 |  | 
| Chris Lattner | c793f8b | 2010-10-05 06:10:16 +0000 | [diff] [blame] | 217 | //===----------------------------------------------------------------------===// | 
|  | 218 | // Thread Local Storage Instructions | 
|  | 219 | // | 
|  | 220 |  | 
|  | 221 | // ELF TLS Support | 
|  | 222 | // All calls clobber the non-callee saved registers. ESP is marked as | 
|  | 223 | // a use to prevent stack-pointer assignments that appear immediately | 
|  | 224 | // before calls from potentially appearing dead. | 
|  | 225 | let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, | 
|  | 226 | MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, | 
|  | 227 | XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, | 
|  | 228 | XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], | 
|  | 229 | Uses = [ESP] in | 
|  | 230 | def TLS_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym), | 
|  | 231 | "leal\t$sym, %eax; " | 
|  | 232 | "call\t___tls_get_addr@PLT", | 
|  | 233 | [(X86tlsaddr tls32addr:$sym)]>, | 
|  | 234 | Requires<[In32BitMode]>; | 
|  | 235 |  | 
|  | 236 | // All calls clobber the non-callee saved registers. RSP is marked as | 
|  | 237 | // a use to prevent stack-pointer assignments that appear immediately | 
|  | 238 | // before calls from potentially appearing dead. | 
|  | 239 | let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, | 
|  | 240 | FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, ST1, | 
|  | 241 | MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, | 
|  | 242 | XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, | 
|  | 243 | XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], | 
|  | 244 | Uses = [RSP] in | 
|  | 245 | def TLS_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym), | 
|  | 246 | ".byte\t0x66; " | 
|  | 247 | "leaq\t$sym(%rip), %rdi; " | 
|  | 248 | ".word\t0x6666; " | 
|  | 249 | "rex64; " | 
|  | 250 | "call\t__tls_get_addr@PLT", | 
|  | 251 | [(X86tlsaddr tls64addr:$sym)]>, | 
|  | 252 | Requires<[In64BitMode]>; | 
|  | 253 |  | 
|  | 254 | // Darwin TLS Support | 
|  | 255 | // For i386, the address of the thunk is passed on the stack, on return the | 
|  | 256 | // address of the variable is in %eax.  %ecx is trashed during the function | 
|  | 257 | // call.  All other registers are preserved. | 
|  | 258 | let Defs = [EAX, ECX], | 
|  | 259 | Uses = [ESP], | 
|  | 260 | usesCustomInserter = 1 in | 
|  | 261 | def TLSCall_32 : I<0, Pseudo, (outs), (ins i32mem:$sym), | 
|  | 262 | "# TLSCall_32", | 
|  | 263 | [(X86TLSCall addr:$sym)]>, | 
|  | 264 | Requires<[In32BitMode]>; | 
|  | 265 |  | 
|  | 266 | // For x86_64, the address of the thunk is passed in %rdi, on return | 
|  | 267 | // the address of the variable is in %rax.  All other registers are preserved. | 
|  | 268 | let Defs = [RAX], | 
|  | 269 | Uses = [RDI], | 
|  | 270 | usesCustomInserter = 1 in | 
|  | 271 | def TLSCall_64 : I<0, Pseudo, (outs), (ins i64mem:$sym), | 
|  | 272 | "# TLSCall_64", | 
|  | 273 | [(X86TLSCall addr:$sym)]>, | 
|  | 274 | Requires<[In64BitMode]>; | 
| Chris Lattner | ae33f5d | 2010-10-05 06:04:14 +0000 | [diff] [blame] | 275 |  | 
| Chris Lattner | cff5b0e | 2010-10-05 23:09:10 +0000 | [diff] [blame^] | 276 |  | 
|  | 277 | //===----------------------------------------------------------------------===// | 
|  | 278 | // Conditional Move Pseudo Instructions | 
|  | 279 |  | 
|  | 280 | let Constraints = "$src1 = $dst" in { | 
|  | 281 |  | 
|  | 282 | // Conditional moves | 
|  | 283 | let Uses = [EFLAGS] in { | 
|  | 284 |  | 
|  | 285 | // X86 doesn't have 8-bit conditional moves. Use a customInserter to | 
|  | 286 | // emit control flow. An alternative to this is to mark i8 SELECT as Promote, | 
|  | 287 | // however that requires promoting the operands, and can induce additional | 
|  | 288 | // i8 register pressure. Note that CMOV_GR8 is conservatively considered to | 
|  | 289 | // clobber EFLAGS, because if one of the operands is zero, the expansion | 
|  | 290 | // could involve an xor. | 
|  | 291 | let usesCustomInserter = 1, Constraints = "", Defs = [EFLAGS] in { | 
|  | 292 | def CMOV_GR8 : I<0, Pseudo, | 
|  | 293 | (outs GR8:$dst), (ins GR8:$src1, GR8:$src2, i8imm:$cond), | 
|  | 294 | "#CMOV_GR8 PSEUDO!", | 
|  | 295 | [(set GR8:$dst, (X86cmov GR8:$src1, GR8:$src2, | 
|  | 296 | imm:$cond, EFLAGS))]>; | 
|  | 297 |  | 
|  | 298 | let Predicates = [NoCMov] in { | 
|  | 299 | def CMOV_GR32 : I<0, Pseudo, | 
|  | 300 | (outs GR32:$dst), (ins GR32:$src1, GR32:$src2, i8imm:$cond), | 
|  | 301 | "#CMOV_GR32* PSEUDO!", | 
|  | 302 | [(set GR32:$dst, | 
|  | 303 | (X86cmov GR32:$src1, GR32:$src2, imm:$cond, EFLAGS))]>; | 
|  | 304 | def CMOV_GR16 : I<0, Pseudo, | 
|  | 305 | (outs GR16:$dst), (ins GR16:$src1, GR16:$src2, i8imm:$cond), | 
|  | 306 | "#CMOV_GR16* PSEUDO!", | 
|  | 307 | [(set GR16:$dst, | 
|  | 308 | (X86cmov GR16:$src1, GR16:$src2, imm:$cond, EFLAGS))]>; | 
|  | 309 | def CMOV_RFP32 : I<0, Pseudo, | 
|  | 310 | (outs RFP32:$dst), | 
|  | 311 | (ins RFP32:$src1, RFP32:$src2, i8imm:$cond), | 
|  | 312 | "#CMOV_RFP32 PSEUDO!", | 
|  | 313 | [(set RFP32:$dst, | 
|  | 314 | (X86cmov RFP32:$src1, RFP32:$src2, imm:$cond, | 
|  | 315 | EFLAGS))]>; | 
|  | 316 | def CMOV_RFP64 : I<0, Pseudo, | 
|  | 317 | (outs RFP64:$dst), | 
|  | 318 | (ins RFP64:$src1, RFP64:$src2, i8imm:$cond), | 
|  | 319 | "#CMOV_RFP64 PSEUDO!", | 
|  | 320 | [(set RFP64:$dst, | 
|  | 321 | (X86cmov RFP64:$src1, RFP64:$src2, imm:$cond, | 
|  | 322 | EFLAGS))]>; | 
|  | 323 | def CMOV_RFP80 : I<0, Pseudo, | 
|  | 324 | (outs RFP80:$dst), | 
|  | 325 | (ins RFP80:$src1, RFP80:$src2, i8imm:$cond), | 
|  | 326 | "#CMOV_RFP80 PSEUDO!", | 
|  | 327 | [(set RFP80:$dst, | 
|  | 328 | (X86cmov RFP80:$src1, RFP80:$src2, imm:$cond, | 
|  | 329 | EFLAGS))]>; | 
|  | 330 | } // Predicates = [NoCMov] | 
|  | 331 | } // UsesCustomInserter = 1, Constraints = "", Defs = [EFLAGS] | 
|  | 332 | } // Uses = [EFLAGS] | 
|  | 333 |  | 
|  | 334 | } // Constraints = "$src1 = $dst" in | 
|  | 335 |  | 
|  | 336 |  | 
| Chris Lattner | ae33f5d | 2010-10-05 06:04:14 +0000 | [diff] [blame] | 337 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | c184a57 | 2010-10-05 06:22:35 +0000 | [diff] [blame] | 338 | // Atomic Instruction Pseudo Instructions | 
|  | 339 | //===----------------------------------------------------------------------===// | 
|  | 340 |  | 
|  | 341 | // Atomic exchange, and, or, xor | 
|  | 342 | let Constraints = "$val = $dst", Defs = [EFLAGS], | 
|  | 343 | usesCustomInserter = 1 in { | 
|  | 344 |  | 
|  | 345 | def ATOMAND8 : I<0, Pseudo, (outs GR8:$dst),(ins i8mem:$ptr, GR8:$val), | 
|  | 346 | "#ATOMAND8 PSEUDO!", | 
|  | 347 | [(set GR8:$dst, (atomic_load_and_8 addr:$ptr, GR8:$val))]>; | 
|  | 348 | def ATOMOR8 : I<0, Pseudo, (outs GR8:$dst),(ins i8mem:$ptr, GR8:$val), | 
|  | 349 | "#ATOMOR8 PSEUDO!", | 
|  | 350 | [(set GR8:$dst, (atomic_load_or_8 addr:$ptr, GR8:$val))]>; | 
|  | 351 | def ATOMXOR8 : I<0, Pseudo,(outs GR8:$dst),(ins i8mem:$ptr, GR8:$val), | 
|  | 352 | "#ATOMXOR8 PSEUDO!", | 
|  | 353 | [(set GR8:$dst, (atomic_load_xor_8 addr:$ptr, GR8:$val))]>; | 
|  | 354 | def ATOMNAND8 : I<0, Pseudo,(outs GR8:$dst),(ins i8mem:$ptr, GR8:$val), | 
|  | 355 | "#ATOMNAND8 PSEUDO!", | 
|  | 356 | [(set GR8:$dst, (atomic_load_nand_8 addr:$ptr, GR8:$val))]>; | 
|  | 357 |  | 
|  | 358 | def ATOMAND16 : I<0, Pseudo, (outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), | 
|  | 359 | "#ATOMAND16 PSEUDO!", | 
|  | 360 | [(set GR16:$dst, (atomic_load_and_16 addr:$ptr, GR16:$val))]>; | 
|  | 361 | def ATOMOR16 : I<0, Pseudo, (outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), | 
|  | 362 | "#ATOMOR16 PSEUDO!", | 
|  | 363 | [(set GR16:$dst, (atomic_load_or_16 addr:$ptr, GR16:$val))]>; | 
|  | 364 | def ATOMXOR16 : I<0, Pseudo,(outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), | 
|  | 365 | "#ATOMXOR16 PSEUDO!", | 
|  | 366 | [(set GR16:$dst, (atomic_load_xor_16 addr:$ptr, GR16:$val))]>; | 
|  | 367 | def ATOMNAND16 : I<0, Pseudo,(outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), | 
|  | 368 | "#ATOMNAND16 PSEUDO!", | 
|  | 369 | [(set GR16:$dst, (atomic_load_nand_16 addr:$ptr, GR16:$val))]>; | 
|  | 370 | def ATOMMIN16: I<0, Pseudo, (outs GR16:$dst), (ins i16mem:$ptr, GR16:$val), | 
|  | 371 | "#ATOMMIN16 PSEUDO!", | 
|  | 372 | [(set GR16:$dst, (atomic_load_min_16 addr:$ptr, GR16:$val))]>; | 
|  | 373 | def ATOMMAX16: I<0, Pseudo, (outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), | 
|  | 374 | "#ATOMMAX16 PSEUDO!", | 
|  | 375 | [(set GR16:$dst, (atomic_load_max_16 addr:$ptr, GR16:$val))]>; | 
|  | 376 | def ATOMUMIN16: I<0, Pseudo, (outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), | 
|  | 377 | "#ATOMUMIN16 PSEUDO!", | 
|  | 378 | [(set GR16:$dst, (atomic_load_umin_16 addr:$ptr, GR16:$val))]>; | 
|  | 379 | def ATOMUMAX16: I<0, Pseudo, (outs GR16:$dst),(ins i16mem:$ptr, GR16:$val), | 
|  | 380 | "#ATOMUMAX16 PSEUDO!", | 
|  | 381 | [(set GR16:$dst, (atomic_load_umax_16 addr:$ptr, GR16:$val))]>; | 
|  | 382 |  | 
|  | 383 |  | 
|  | 384 | def ATOMAND32 : I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), | 
|  | 385 | "#ATOMAND32 PSEUDO!", | 
|  | 386 | [(set GR32:$dst, (atomic_load_and_32 addr:$ptr, GR32:$val))]>; | 
|  | 387 | def ATOMOR32 : I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), | 
|  | 388 | "#ATOMOR32 PSEUDO!", | 
|  | 389 | [(set GR32:$dst, (atomic_load_or_32 addr:$ptr, GR32:$val))]>; | 
|  | 390 | def ATOMXOR32 : I<0, Pseudo,(outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), | 
|  | 391 | "#ATOMXOR32 PSEUDO!", | 
|  | 392 | [(set GR32:$dst, (atomic_load_xor_32 addr:$ptr, GR32:$val))]>; | 
|  | 393 | def ATOMNAND32 : I<0, Pseudo,(outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), | 
|  | 394 | "#ATOMNAND32 PSEUDO!", | 
|  | 395 | [(set GR32:$dst, (atomic_load_nand_32 addr:$ptr, GR32:$val))]>; | 
|  | 396 | def ATOMMIN32: I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val), | 
|  | 397 | "#ATOMMIN32 PSEUDO!", | 
|  | 398 | [(set GR32:$dst, (atomic_load_min_32 addr:$ptr, GR32:$val))]>; | 
|  | 399 | def ATOMMAX32: I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), | 
|  | 400 | "#ATOMMAX32 PSEUDO!", | 
|  | 401 | [(set GR32:$dst, (atomic_load_max_32 addr:$ptr, GR32:$val))]>; | 
|  | 402 | def ATOMUMIN32: I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), | 
|  | 403 | "#ATOMUMIN32 PSEUDO!", | 
|  | 404 | [(set GR32:$dst, (atomic_load_umin_32 addr:$ptr, GR32:$val))]>; | 
|  | 405 | def ATOMUMAX32: I<0, Pseudo, (outs GR32:$dst),(ins i32mem:$ptr, GR32:$val), | 
|  | 406 | "#ATOMUMAX32 PSEUDO!", | 
|  | 407 | [(set GR32:$dst, (atomic_load_umax_32 addr:$ptr, GR32:$val))]>; | 
|  | 408 |  | 
|  | 409 |  | 
|  | 410 |  | 
|  | 411 | def ATOMAND64 : I<0, Pseudo, (outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), | 
|  | 412 | "#ATOMAND64 PSEUDO!", | 
|  | 413 | [(set GR64:$dst, (atomic_load_and_64 addr:$ptr, GR64:$val))]>; | 
|  | 414 | def ATOMOR64 : I<0, Pseudo, (outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), | 
|  | 415 | "#ATOMOR64 PSEUDO!", | 
|  | 416 | [(set GR64:$dst, (atomic_load_or_64 addr:$ptr, GR64:$val))]>; | 
|  | 417 | def ATOMXOR64 : I<0, Pseudo,(outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), | 
|  | 418 | "#ATOMXOR64 PSEUDO!", | 
|  | 419 | [(set GR64:$dst, (atomic_load_xor_64 addr:$ptr, GR64:$val))]>; | 
|  | 420 | def ATOMNAND64 : I<0, Pseudo,(outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), | 
|  | 421 | "#ATOMNAND64 PSEUDO!", | 
|  | 422 | [(set GR64:$dst, (atomic_load_nand_64 addr:$ptr, GR64:$val))]>; | 
|  | 423 | def ATOMMIN64: I<0, Pseudo, (outs GR64:$dst), (ins i64mem:$ptr, GR64:$val), | 
|  | 424 | "#ATOMMIN64 PSEUDO!", | 
|  | 425 | [(set GR64:$dst, (atomic_load_min_64 addr:$ptr, GR64:$val))]>; | 
|  | 426 | def ATOMMAX64: I<0, Pseudo, (outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), | 
|  | 427 | "#ATOMMAX64 PSEUDO!", | 
|  | 428 | [(set GR64:$dst, (atomic_load_max_64 addr:$ptr, GR64:$val))]>; | 
|  | 429 | def ATOMUMIN64: I<0, Pseudo, (outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), | 
|  | 430 | "#ATOMUMIN64 PSEUDO!", | 
|  | 431 | [(set GR64:$dst, (atomic_load_umin_64 addr:$ptr, GR64:$val))]>; | 
|  | 432 | def ATOMUMAX64: I<0, Pseudo, (outs GR64:$dst),(ins i64mem:$ptr, GR64:$val), | 
|  | 433 | "#ATOMUMAX64 PSEUDO!", | 
|  | 434 | [(set GR64:$dst, (atomic_load_umax_64 addr:$ptr, GR64:$val))]>; | 
|  | 435 | } | 
|  | 436 |  | 
|  | 437 | let Constraints = "$val1 = $dst1, $val2 = $dst2", | 
|  | 438 | Defs = [EFLAGS, EAX, EBX, ECX, EDX], | 
|  | 439 | Uses = [EAX, EBX, ECX, EDX], | 
|  | 440 | mayLoad = 1, mayStore = 1, | 
|  | 441 | usesCustomInserter = 1 in { | 
|  | 442 | def ATOMAND6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), | 
|  | 443 | (ins i64mem:$ptr, GR32:$val1, GR32:$val2), | 
|  | 444 | "#ATOMAND6432 PSEUDO!", []>; | 
|  | 445 | def ATOMOR6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), | 
|  | 446 | (ins i64mem:$ptr, GR32:$val1, GR32:$val2), | 
|  | 447 | "#ATOMOR6432 PSEUDO!", []>; | 
|  | 448 | def ATOMXOR6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), | 
|  | 449 | (ins i64mem:$ptr, GR32:$val1, GR32:$val2), | 
|  | 450 | "#ATOMXOR6432 PSEUDO!", []>; | 
|  | 451 | def ATOMNAND6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), | 
|  | 452 | (ins i64mem:$ptr, GR32:$val1, GR32:$val2), | 
|  | 453 | "#ATOMNAND6432 PSEUDO!", []>; | 
|  | 454 | def ATOMADD6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), | 
|  | 455 | (ins i64mem:$ptr, GR32:$val1, GR32:$val2), | 
|  | 456 | "#ATOMADD6432 PSEUDO!", []>; | 
|  | 457 | def ATOMSUB6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), | 
|  | 458 | (ins i64mem:$ptr, GR32:$val1, GR32:$val2), | 
|  | 459 | "#ATOMSUB6432 PSEUDO!", []>; | 
|  | 460 | def ATOMSWAP6432 : I<0, Pseudo, (outs GR32:$dst1, GR32:$dst2), | 
|  | 461 | (ins i64mem:$ptr, GR32:$val1, GR32:$val2), | 
|  | 462 | "#ATOMSWAP6432 PSEUDO!", []>; | 
|  | 463 | } | 
|  | 464 |  | 
|  | 465 | //===----------------------------------------------------------------------===// | 
|  | 466 | // Normal-Instructions-With-Lock-Prefix Pseudo Instructions | 
|  | 467 | //===----------------------------------------------------------------------===// | 
|  | 468 |  | 
|  | 469 | // FIXME: Use normal instructions and add lock prefix dynamically. | 
|  | 470 |  | 
|  | 471 | // Memory barriers | 
|  | 472 |  | 
|  | 473 | // TODO: Get this to fold the constant into the instruction. | 
|  | 474 | def OR32mrLocked  : I<0x09, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$zero), | 
|  | 475 | "lock\n\t" | 
|  | 476 | "or{l}\t{$zero, $dst|$dst, $zero}", | 
|  | 477 | []>, Requires<[In32BitMode]>, LOCK; | 
|  | 478 |  | 
|  | 479 | let hasSideEffects = 1 in | 
|  | 480 | def Int_MemBarrier : I<0, Pseudo, (outs), (ins), | 
|  | 481 | "#MEMBARRIER", | 
|  | 482 | [(X86MemBarrier)]>, Requires<[HasSSE2]>; | 
|  | 483 |  | 
|  | 484 | // TODO: Get this to fold the constant into the instruction. | 
|  | 485 | let hasSideEffects = 1, Defs = [ESP] in | 
|  | 486 | def Int_MemBarrierNoSSE64  : RI<0x09, MRM1r, (outs), (ins GR64:$zero), | 
|  | 487 | "lock\n\t" | 
|  | 488 | "or{q}\t{$zero, (%rsp)|(%rsp), $zero}", | 
|  | 489 | [(X86MemBarrierNoSSE GR64:$zero)]>, | 
|  | 490 | Requires<[In64BitMode]>, LOCK; | 
|  | 491 |  | 
|  | 492 |  | 
|  | 493 | // Optimized codegen when the non-memory output is not used. | 
|  | 494 | let Defs = [EFLAGS], mayLoad = 1, mayStore = 1 in { | 
|  | 495 | def LOCK_ADD8mr  : I<0x00, MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src2), | 
|  | 496 | "lock\n\t" | 
|  | 497 | "add{b}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 498 | def LOCK_ADD16mr  : I<0x01, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), | 
|  | 499 | "lock\n\t" | 
|  | 500 | "add{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize, LOCK; | 
|  | 501 | def LOCK_ADD32mr  : I<0x01, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), | 
|  | 502 | "lock\n\t" | 
|  | 503 | "add{l}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 504 | def LOCK_ADD64mr : RI<0x01, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), | 
|  | 505 | "lock\n\t" | 
|  | 506 | "add{q}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 507 |  | 
|  | 508 | def LOCK_ADD8mi   : Ii8<0x80, MRM0m, (outs), (ins i8mem :$dst, i8imm :$src2), | 
|  | 509 | "lock\n\t" | 
|  | 510 | "add{b}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 511 | def LOCK_ADD16mi  : Ii16<0x81, MRM0m, (outs), (ins i16mem:$dst, i16imm:$src2), | 
|  | 512 | "lock\n\t" | 
|  | 513 | "add{w}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 514 | def LOCK_ADD32mi  : Ii32<0x81, MRM0m, (outs), (ins i32mem:$dst, i32imm:$src2), | 
|  | 515 | "lock\n\t" | 
|  | 516 | "add{l}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 517 | def LOCK_ADD64mi32 : RIi32<0x81, MRM0m, (outs), | 
|  | 518 | (ins i64mem:$dst, i64i32imm :$src2), | 
|  | 519 | "lock\n\t" | 
|  | 520 | "add{q}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 521 |  | 
|  | 522 | def LOCK_ADD16mi8 : Ii8<0x83, MRM0m, (outs), (ins i16mem:$dst, i16i8imm :$src2), | 
|  | 523 | "lock\n\t" | 
|  | 524 | "add{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize, LOCK; | 
|  | 525 | def LOCK_ADD32mi8 : Ii8<0x83, MRM0m, (outs), (ins i32mem:$dst, i32i8imm :$src2), | 
|  | 526 | "lock\n\t" | 
|  | 527 | "add{l}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 528 | def LOCK_ADD64mi8 : RIi8<0x83, MRM0m, (outs), | 
|  | 529 | (ins i64mem:$dst, i64i8imm :$src2), | 
|  | 530 | "lock\n\t" | 
|  | 531 | "add{q}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 532 |  | 
|  | 533 | def LOCK_SUB8mr   : I<0x28, MRMDestMem, (outs), (ins i8mem :$dst, GR8 :$src2), | 
|  | 534 | "lock\n\t" | 
|  | 535 | "sub{b}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 536 | def LOCK_SUB16mr  : I<0x29, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), | 
|  | 537 | "lock\n\t" | 
|  | 538 | "sub{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize, LOCK; | 
|  | 539 | def LOCK_SUB32mr  : I<0x29, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), | 
|  | 540 | "lock\n\t" | 
|  | 541 | "sub{l}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 542 | def LOCK_SUB64mr : RI<0x29, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), | 
|  | 543 | "lock\n\t" | 
|  | 544 | "sub{q}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 545 |  | 
|  | 546 |  | 
|  | 547 | def LOCK_SUB8mi   : Ii8<0x80, MRM5m, (outs), (ins i8mem :$dst, i8imm:$src2), | 
|  | 548 | "lock\n\t" | 
|  | 549 | "sub{b}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 550 | def LOCK_SUB16mi  : Ii16<0x81, MRM5m, (outs), (ins i16mem:$dst, i16imm:$src2), | 
|  | 551 | "lock\n\t" | 
|  | 552 | "sub{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize, LOCK; | 
|  | 553 | def LOCK_SUB32mi  : Ii32<0x81, MRM5m, (outs), (ins i32mem:$dst, i32imm:$src2), | 
|  | 554 | "lock\n\t" | 
|  | 555 | "sub{l}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 556 | def LOCK_SUB64mi32 : RIi32<0x81, MRM5m, (outs), | 
|  | 557 | (ins i64mem:$dst, i64i32imm:$src2), | 
|  | 558 | "lock\n\t" | 
|  | 559 | "sub{q}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 560 |  | 
|  | 561 |  | 
|  | 562 | def LOCK_SUB16mi8 : Ii8<0x83, MRM5m, (outs), (ins i16mem:$dst, i16i8imm :$src2), | 
|  | 563 | "lock\n\t" | 
|  | 564 | "sub{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize, LOCK; | 
|  | 565 | def LOCK_SUB32mi8 : Ii8<0x83, MRM5m, (outs), (ins i32mem:$dst, i32i8imm :$src2), | 
|  | 566 | "lock\n\t" | 
|  | 567 | "sub{l}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 568 | def LOCK_SUB64mi8 : RIi8<0x83, MRM5m, (outs), | 
|  | 569 | (ins i64mem:$dst, i64i8imm :$src2), | 
|  | 570 | "lock\n\t" | 
|  | 571 | "sub{q}\t{$src2, $dst|$dst, $src2}", []>, LOCK; | 
|  | 572 |  | 
|  | 573 | def LOCK_INC8m  : I<0xFE, MRM0m, (outs), (ins i8mem :$dst), | 
|  | 574 | "lock\n\t" | 
|  | 575 | "inc{b}\t$dst", []>, LOCK; | 
|  | 576 | def LOCK_INC16m : I<0xFF, MRM0m, (outs), (ins i16mem:$dst), | 
|  | 577 | "lock\n\t" | 
|  | 578 | "inc{w}\t$dst", []>, OpSize, LOCK; | 
|  | 579 | def LOCK_INC32m : I<0xFF, MRM0m, (outs), (ins i32mem:$dst), | 
|  | 580 | "lock\n\t" | 
|  | 581 | "inc{l}\t$dst", []>, LOCK; | 
|  | 582 | def LOCK_INC64m : RI<0xFF, MRM0m, (outs), (ins i64mem:$dst), | 
|  | 583 | "lock\n\t" | 
|  | 584 | "inc{q}\t$dst", []>, LOCK; | 
|  | 585 |  | 
|  | 586 | def LOCK_DEC8m  : I<0xFE, MRM1m, (outs), (ins i8mem :$dst), | 
|  | 587 | "lock\n\t" | 
|  | 588 | "dec{b}\t$dst", []>, LOCK; | 
|  | 589 | def LOCK_DEC16m : I<0xFF, MRM1m, (outs), (ins i16mem:$dst), | 
|  | 590 | "lock\n\t" | 
|  | 591 | "dec{w}\t$dst", []>, OpSize, LOCK; | 
|  | 592 | def LOCK_DEC32m : I<0xFF, MRM1m, (outs), (ins i32mem:$dst), | 
|  | 593 | "lock\n\t" | 
|  | 594 | "dec{l}\t$dst", []>, LOCK; | 
|  | 595 | def LOCK_DEC64m : RI<0xFF, MRM1m, (outs), (ins i64mem:$dst), | 
|  | 596 | "lock\n\t" | 
|  | 597 | "dec{q}\t$dst", []>, LOCK; | 
|  | 598 | } | 
|  | 599 |  | 
|  | 600 | // Atomic compare and swap. | 
|  | 601 | let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EBX, ECX, EDX] in { | 
|  | 602 | def LCMPXCHG8B : I<0xC7, MRM1m, (outs), (ins i64mem:$ptr), | 
|  | 603 | "lock\n\t" | 
|  | 604 | "cmpxchg8b\t$ptr", | 
|  | 605 | [(X86cas8 addr:$ptr)]>, TB, LOCK; | 
|  | 606 | } | 
|  | 607 | let Defs = [AL, EFLAGS], Uses = [AL] in { | 
|  | 608 | def LCMPXCHG8 : I<0xB0, MRMDestMem, (outs), (ins i8mem:$ptr, GR8:$swap), | 
|  | 609 | "lock\n\t" | 
|  | 610 | "cmpxchg{b}\t{$swap, $ptr|$ptr, $swap}", | 
|  | 611 | [(X86cas addr:$ptr, GR8:$swap, 1)]>, TB, LOCK; | 
|  | 612 | } | 
|  | 613 |  | 
|  | 614 | let Defs = [AX, EFLAGS], Uses = [AX] in { | 
|  | 615 | def LCMPXCHG16 : I<0xB1, MRMDestMem, (outs), (ins i16mem:$ptr, GR16:$swap), | 
|  | 616 | "lock\n\t" | 
|  | 617 | "cmpxchg{w}\t{$swap, $ptr|$ptr, $swap}", | 
|  | 618 | [(X86cas addr:$ptr, GR16:$swap, 2)]>, TB, OpSize, LOCK; | 
|  | 619 | } | 
|  | 620 |  | 
|  | 621 | let Defs = [EAX, EFLAGS], Uses = [EAX] in { | 
|  | 622 | def LCMPXCHG32 : I<0xB1, MRMDestMem, (outs), (ins i32mem:$ptr, GR32:$swap), | 
|  | 623 | "lock\n\t" | 
|  | 624 | "cmpxchg{l}\t{$swap, $ptr|$ptr, $swap}", | 
|  | 625 | [(X86cas addr:$ptr, GR32:$swap, 4)]>, TB, LOCK; | 
|  | 626 | } | 
|  | 627 |  | 
|  | 628 | let Defs = [RAX, EFLAGS], Uses = [RAX] in { | 
|  | 629 | def LCMPXCHG64 : RI<0xB1, MRMDestMem, (outs), (ins i64mem:$ptr, GR64:$swap), | 
|  | 630 | "lock\n\t" | 
|  | 631 | "cmpxchgq\t$swap,$ptr", | 
|  | 632 | [(X86cas addr:$ptr, GR64:$swap, 8)]>, TB, LOCK; | 
|  | 633 | } | 
|  | 634 |  | 
|  | 635 | // Atomic exchange and add | 
|  | 636 | let Constraints = "$val = $dst", Defs = [EFLAGS] in { | 
|  | 637 | def LXADD8  : I<0xC0, MRMSrcMem, (outs GR8:$dst), (ins GR8:$val, i8mem:$ptr), | 
|  | 638 | "lock\n\t" | 
|  | 639 | "xadd{b}\t{$val, $ptr|$ptr, $val}", | 
|  | 640 | [(set GR8:$dst, (atomic_load_add_8 addr:$ptr, GR8:$val))]>, | 
|  | 641 | TB, LOCK; | 
|  | 642 | def LXADD16 : I<0xC1, MRMSrcMem, (outs GR16:$dst), (ins GR16:$val, i16mem:$ptr), | 
|  | 643 | "lock\n\t" | 
|  | 644 | "xadd{w}\t{$val, $ptr|$ptr, $val}", | 
|  | 645 | [(set GR16:$dst, (atomic_load_add_16 addr:$ptr, GR16:$val))]>, | 
|  | 646 | TB, OpSize, LOCK; | 
|  | 647 | def LXADD32 : I<0xC1, MRMSrcMem, (outs GR32:$dst), (ins GR32:$val, i32mem:$ptr), | 
|  | 648 | "lock\n\t" | 
|  | 649 | "xadd{l}\t{$val, $ptr|$ptr, $val}", | 
|  | 650 | [(set GR32:$dst, (atomic_load_add_32 addr:$ptr, GR32:$val))]>, | 
|  | 651 | TB, LOCK; | 
|  | 652 | def LXADD64 : RI<0xC1, MRMSrcMem, (outs GR64:$dst), (ins GR64:$val,i64mem:$ptr), | 
|  | 653 | "lock\n\t" | 
|  | 654 | "xadd\t$val, $ptr", | 
|  | 655 | [(set GR64:$dst, (atomic_load_add_64 addr:$ptr, GR64:$val))]>, | 
|  | 656 | TB, LOCK; | 
|  | 657 | } | 
|  | 658 |  | 
| Chris Lattner | da8c94e | 2010-10-05 06:41:40 +0000 | [diff] [blame] | 659 | //===----------------------------------------------------------------------===// | 
|  | 660 | // Conditional Move Pseudo Instructions. | 
|  | 661 | //===----------------------------------------------------------------------===// | 
|  | 662 |  | 
|  | 663 |  | 
|  | 664 | // CMOV* - Used to implement the SSE SELECT DAG operation.  Expanded after | 
|  | 665 | // instruction selection into a branch sequence. | 
|  | 666 | let Uses = [EFLAGS], usesCustomInserter = 1 in { | 
|  | 667 | def CMOV_FR32 : I<0, Pseudo, | 
|  | 668 | (outs FR32:$dst), (ins FR32:$t, FR32:$f, i8imm:$cond), | 
|  | 669 | "#CMOV_FR32 PSEUDO!", | 
|  | 670 | [(set FR32:$dst, (X86cmov FR32:$t, FR32:$f, imm:$cond, | 
|  | 671 | EFLAGS))]>; | 
|  | 672 | def CMOV_FR64 : I<0, Pseudo, | 
|  | 673 | (outs FR64:$dst), (ins FR64:$t, FR64:$f, i8imm:$cond), | 
|  | 674 | "#CMOV_FR64 PSEUDO!", | 
|  | 675 | [(set FR64:$dst, (X86cmov FR64:$t, FR64:$f, imm:$cond, | 
|  | 676 | EFLAGS))]>; | 
|  | 677 | def CMOV_V4F32 : I<0, Pseudo, | 
|  | 678 | (outs VR128:$dst), (ins VR128:$t, VR128:$f, i8imm:$cond), | 
|  | 679 | "#CMOV_V4F32 PSEUDO!", | 
|  | 680 | [(set VR128:$dst, | 
|  | 681 | (v4f32 (X86cmov VR128:$t, VR128:$f, imm:$cond, | 
|  | 682 | EFLAGS)))]>; | 
|  | 683 | def CMOV_V2F64 : I<0, Pseudo, | 
|  | 684 | (outs VR128:$dst), (ins VR128:$t, VR128:$f, i8imm:$cond), | 
|  | 685 | "#CMOV_V2F64 PSEUDO!", | 
|  | 686 | [(set VR128:$dst, | 
|  | 687 | (v2f64 (X86cmov VR128:$t, VR128:$f, imm:$cond, | 
|  | 688 | EFLAGS)))]>; | 
|  | 689 | def CMOV_V2I64 : I<0, Pseudo, | 
|  | 690 | (outs VR128:$dst), (ins VR128:$t, VR128:$f, i8imm:$cond), | 
|  | 691 | "#CMOV_V2I64 PSEUDO!", | 
|  | 692 | [(set VR128:$dst, | 
|  | 693 | (v2i64 (X86cmov VR128:$t, VR128:$f, imm:$cond, | 
|  | 694 | EFLAGS)))]>; | 
|  | 695 | } | 
|  | 696 |  | 
| Chris Lattner | c184a57 | 2010-10-05 06:22:35 +0000 | [diff] [blame] | 697 |  | 
|  | 698 | //===----------------------------------------------------------------------===// | 
|  | 699 | // DAG Pattern Matching Rules | 
| Chris Lattner | ae33f5d | 2010-10-05 06:04:14 +0000 | [diff] [blame] | 700 | //===----------------------------------------------------------------------===// | 
|  | 701 |  | 
|  | 702 | // ConstantPool GlobalAddress, ExternalSymbol, and JumpTable | 
|  | 703 | def : Pat<(i32 (X86Wrapper tconstpool  :$dst)), (MOV32ri tconstpool  :$dst)>; | 
|  | 704 | def : Pat<(i32 (X86Wrapper tjumptable  :$dst)), (MOV32ri tjumptable  :$dst)>; | 
|  | 705 | def : Pat<(i32 (X86Wrapper tglobaltlsaddr:$dst)),(MOV32ri tglobaltlsaddr:$dst)>; | 
|  | 706 | def : Pat<(i32 (X86Wrapper tglobaladdr :$dst)), (MOV32ri tglobaladdr :$dst)>; | 
|  | 707 | def : Pat<(i32 (X86Wrapper texternalsym:$dst)), (MOV32ri texternalsym:$dst)>; | 
|  | 708 | def : Pat<(i32 (X86Wrapper tblockaddress:$dst)), (MOV32ri tblockaddress:$dst)>; | 
|  | 709 |  | 
|  | 710 | def : Pat<(add GR32:$src1, (X86Wrapper tconstpool:$src2)), | 
|  | 711 | (ADD32ri GR32:$src1, tconstpool:$src2)>; | 
|  | 712 | def : Pat<(add GR32:$src1, (X86Wrapper tjumptable:$src2)), | 
|  | 713 | (ADD32ri GR32:$src1, tjumptable:$src2)>; | 
|  | 714 | def : Pat<(add GR32:$src1, (X86Wrapper tglobaladdr :$src2)), | 
|  | 715 | (ADD32ri GR32:$src1, tglobaladdr:$src2)>; | 
|  | 716 | def : Pat<(add GR32:$src1, (X86Wrapper texternalsym:$src2)), | 
|  | 717 | (ADD32ri GR32:$src1, texternalsym:$src2)>; | 
|  | 718 | def : Pat<(add GR32:$src1, (X86Wrapper tblockaddress:$src2)), | 
|  | 719 | (ADD32ri GR32:$src1, tblockaddress:$src2)>; | 
|  | 720 |  | 
|  | 721 | def : Pat<(store (i32 (X86Wrapper tglobaladdr:$src)), addr:$dst), | 
|  | 722 | (MOV32mi addr:$dst, tglobaladdr:$src)>; | 
|  | 723 | def : Pat<(store (i32 (X86Wrapper texternalsym:$src)), addr:$dst), | 
|  | 724 | (MOV32mi addr:$dst, texternalsym:$src)>; | 
|  | 725 | def : Pat<(store (i32 (X86Wrapper tblockaddress:$src)), addr:$dst), | 
|  | 726 | (MOV32mi addr:$dst, tblockaddress:$src)>; | 
|  | 727 |  | 
|  | 728 |  | 
|  | 729 |  | 
|  | 730 | // ConstantPool GlobalAddress, ExternalSymbol, and JumpTable when not in small | 
|  | 731 | // code model mode, should use 'movabs'.  FIXME: This is really a hack, the | 
|  | 732 | //  'movabs' predicate should handle this sort of thing. | 
|  | 733 | def : Pat<(i64 (X86Wrapper tconstpool  :$dst)), | 
|  | 734 | (MOV64ri tconstpool  :$dst)>, Requires<[FarData]>; | 
|  | 735 | def : Pat<(i64 (X86Wrapper tjumptable  :$dst)), | 
|  | 736 | (MOV64ri tjumptable  :$dst)>, Requires<[FarData]>; | 
|  | 737 | def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)), | 
|  | 738 | (MOV64ri tglobaladdr :$dst)>, Requires<[FarData]>; | 
|  | 739 | def : Pat<(i64 (X86Wrapper texternalsym:$dst)), | 
|  | 740 | (MOV64ri texternalsym:$dst)>, Requires<[FarData]>; | 
|  | 741 | def : Pat<(i64 (X86Wrapper tblockaddress:$dst)), | 
|  | 742 | (MOV64ri tblockaddress:$dst)>, Requires<[FarData]>; | 
|  | 743 |  | 
|  | 744 | // In static codegen with small code model, we can get the address of a label | 
|  | 745 | // into a register with 'movl'.  FIXME: This is a hack, the 'imm' predicate of | 
|  | 746 | // the MOV64ri64i32 should accept these. | 
|  | 747 | def : Pat<(i64 (X86Wrapper tconstpool  :$dst)), | 
|  | 748 | (MOV64ri64i32 tconstpool  :$dst)>, Requires<[SmallCode]>; | 
|  | 749 | def : Pat<(i64 (X86Wrapper tjumptable  :$dst)), | 
|  | 750 | (MOV64ri64i32 tjumptable  :$dst)>, Requires<[SmallCode]>; | 
|  | 751 | def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)), | 
|  | 752 | (MOV64ri64i32 tglobaladdr :$dst)>, Requires<[SmallCode]>; | 
|  | 753 | def : Pat<(i64 (X86Wrapper texternalsym:$dst)), | 
|  | 754 | (MOV64ri64i32 texternalsym:$dst)>, Requires<[SmallCode]>; | 
|  | 755 | def : Pat<(i64 (X86Wrapper tblockaddress:$dst)), | 
|  | 756 | (MOV64ri64i32 tblockaddress:$dst)>, Requires<[SmallCode]>; | 
|  | 757 |  | 
|  | 758 | // In kernel code model, we can get the address of a label | 
|  | 759 | // into a register with 'movq'.  FIXME: This is a hack, the 'imm' predicate of | 
|  | 760 | // the MOV64ri32 should accept these. | 
|  | 761 | def : Pat<(i64 (X86Wrapper tconstpool  :$dst)), | 
|  | 762 | (MOV64ri32 tconstpool  :$dst)>, Requires<[KernelCode]>; | 
|  | 763 | def : Pat<(i64 (X86Wrapper tjumptable  :$dst)), | 
|  | 764 | (MOV64ri32 tjumptable  :$dst)>, Requires<[KernelCode]>; | 
|  | 765 | def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)), | 
|  | 766 | (MOV64ri32 tglobaladdr :$dst)>, Requires<[KernelCode]>; | 
|  | 767 | def : Pat<(i64 (X86Wrapper texternalsym:$dst)), | 
|  | 768 | (MOV64ri32 texternalsym:$dst)>, Requires<[KernelCode]>; | 
|  | 769 | def : Pat<(i64 (X86Wrapper tblockaddress:$dst)), | 
|  | 770 | (MOV64ri32 tblockaddress:$dst)>, Requires<[KernelCode]>; | 
|  | 771 |  | 
|  | 772 | // If we have small model and -static mode, it is safe to store global addresses | 
|  | 773 | // directly as immediates.  FIXME: This is really a hack, the 'imm' predicate | 
|  | 774 | // for MOV64mi32 should handle this sort of thing. | 
|  | 775 | def : Pat<(store (i64 (X86Wrapper tconstpool:$src)), addr:$dst), | 
|  | 776 | (MOV64mi32 addr:$dst, tconstpool:$src)>, | 
|  | 777 | Requires<[NearData, IsStatic]>; | 
|  | 778 | def : Pat<(store (i64 (X86Wrapper tjumptable:$src)), addr:$dst), | 
|  | 779 | (MOV64mi32 addr:$dst, tjumptable:$src)>, | 
|  | 780 | Requires<[NearData, IsStatic]>; | 
|  | 781 | def : Pat<(store (i64 (X86Wrapper tglobaladdr:$src)), addr:$dst), | 
|  | 782 | (MOV64mi32 addr:$dst, tglobaladdr:$src)>, | 
|  | 783 | Requires<[NearData, IsStatic]>; | 
|  | 784 | def : Pat<(store (i64 (X86Wrapper texternalsym:$src)), addr:$dst), | 
|  | 785 | (MOV64mi32 addr:$dst, texternalsym:$src)>, | 
|  | 786 | Requires<[NearData, IsStatic]>; | 
|  | 787 | def : Pat<(store (i64 (X86Wrapper tblockaddress:$src)), addr:$dst), | 
|  | 788 | (MOV64mi32 addr:$dst, tblockaddress:$src)>, | 
|  | 789 | Requires<[NearData, IsStatic]>; | 
|  | 790 |  | 
|  | 791 |  | 
|  | 792 |  | 
|  | 793 | // Calls | 
|  | 794 |  | 
|  | 795 | // tls has some funny stuff here... | 
|  | 796 | // This corresponds to movabs $foo@tpoff, %rax | 
|  | 797 | def : Pat<(i64 (X86Wrapper tglobaltlsaddr :$dst)), | 
|  | 798 | (MOV64ri tglobaltlsaddr :$dst)>; | 
|  | 799 | // This corresponds to add $foo@tpoff, %rax | 
|  | 800 | def : Pat<(add GR64:$src1, (X86Wrapper tglobaltlsaddr :$dst)), | 
|  | 801 | (ADD64ri32 GR64:$src1, tglobaltlsaddr :$dst)>; | 
|  | 802 | // This corresponds to mov foo@tpoff(%rbx), %eax | 
|  | 803 | def : Pat<(load (i64 (X86Wrapper tglobaltlsaddr :$dst))), | 
|  | 804 | (MOV64rm tglobaltlsaddr :$dst)>; | 
|  | 805 |  | 
|  | 806 |  | 
|  | 807 | // Direct PC relative function call for small code model. 32-bit displacement | 
|  | 808 | // sign extended to 64-bit. | 
|  | 809 | def : Pat<(X86call (i64 tglobaladdr:$dst)), | 
|  | 810 | (CALL64pcrel32 tglobaladdr:$dst)>, Requires<[NotWin64]>; | 
|  | 811 | def : Pat<(X86call (i64 texternalsym:$dst)), | 
|  | 812 | (CALL64pcrel32 texternalsym:$dst)>, Requires<[NotWin64]>; | 
|  | 813 |  | 
|  | 814 | def : Pat<(X86call (i64 tglobaladdr:$dst)), | 
|  | 815 | (WINCALL64pcrel32 tglobaladdr:$dst)>, Requires<[IsWin64]>; | 
|  | 816 | def : Pat<(X86call (i64 texternalsym:$dst)), | 
|  | 817 | (WINCALL64pcrel32 texternalsym:$dst)>, Requires<[IsWin64]>; | 
|  | 818 |  | 
|  | 819 | // tailcall stuff | 
|  | 820 | def : Pat<(X86tcret GR32_TC:$dst, imm:$off), | 
|  | 821 | (TCRETURNri GR32_TC:$dst, imm:$off)>, | 
|  | 822 | Requires<[In32BitMode]>; | 
|  | 823 |  | 
|  | 824 | // FIXME: This is disabled for 32-bit PIC mode because the global base | 
|  | 825 | // register which is part of the address mode may be assigned a | 
|  | 826 | // callee-saved register. | 
|  | 827 | def : Pat<(X86tcret (load addr:$dst), imm:$off), | 
|  | 828 | (TCRETURNmi addr:$dst, imm:$off)>, | 
|  | 829 | Requires<[In32BitMode, IsNotPIC]>; | 
|  | 830 |  | 
|  | 831 | def : Pat<(X86tcret (i32 tglobaladdr:$dst), imm:$off), | 
|  | 832 | (TCRETURNdi texternalsym:$dst, imm:$off)>, | 
|  | 833 | Requires<[In32BitMode]>; | 
|  | 834 |  | 
|  | 835 | def : Pat<(X86tcret (i32 texternalsym:$dst), imm:$off), | 
|  | 836 | (TCRETURNdi texternalsym:$dst, imm:$off)>, | 
|  | 837 | Requires<[In32BitMode]>; | 
|  | 838 |  | 
|  | 839 | def : Pat<(X86tcret GR64_TC:$dst, imm:$off), | 
|  | 840 | (TCRETURNri64 GR64_TC:$dst, imm:$off)>, | 
|  | 841 | Requires<[In64BitMode]>; | 
|  | 842 |  | 
|  | 843 | def : Pat<(X86tcret (load addr:$dst), imm:$off), | 
|  | 844 | (TCRETURNmi64 addr:$dst, imm:$off)>, | 
|  | 845 | Requires<[In64BitMode]>; | 
|  | 846 |  | 
|  | 847 | def : Pat<(X86tcret (i64 tglobaladdr:$dst), imm:$off), | 
|  | 848 | (TCRETURNdi64 tglobaladdr:$dst, imm:$off)>, | 
|  | 849 | Requires<[In64BitMode]>; | 
|  | 850 |  | 
|  | 851 | def : Pat<(X86tcret (i64 texternalsym:$dst), imm:$off), | 
|  | 852 | (TCRETURNdi64 texternalsym:$dst, imm:$off)>, | 
|  | 853 | Requires<[In64BitMode]>; | 
|  | 854 |  | 
|  | 855 | // Normal calls, with various flavors of addresses. | 
|  | 856 | def : Pat<(X86call (i32 tglobaladdr:$dst)), | 
|  | 857 | (CALLpcrel32 tglobaladdr:$dst)>; | 
|  | 858 | def : Pat<(X86call (i32 texternalsym:$dst)), | 
|  | 859 | (CALLpcrel32 texternalsym:$dst)>; | 
|  | 860 | def : Pat<(X86call (i32 imm:$dst)), | 
|  | 861 | (CALLpcrel32 imm:$dst)>, Requires<[CallImmAddr]>; | 
|  | 862 |  | 
|  | 863 | // X86 specific add which produces a flag. | 
|  | 864 | def : Pat<(addc GR32:$src1, GR32:$src2), | 
|  | 865 | (ADD32rr GR32:$src1, GR32:$src2)>; | 
|  | 866 | def : Pat<(addc GR32:$src1, (load addr:$src2)), | 
|  | 867 | (ADD32rm GR32:$src1, addr:$src2)>; | 
|  | 868 | def : Pat<(addc GR32:$src1, imm:$src2), | 
|  | 869 | (ADD32ri GR32:$src1, imm:$src2)>; | 
|  | 870 | def : Pat<(addc GR32:$src1, i32immSExt8:$src2), | 
|  | 871 | (ADD32ri8 GR32:$src1, i32immSExt8:$src2)>; | 
|  | 872 |  | 
|  | 873 | def : Pat<(addc GR64:$src1, GR64:$src2), | 
|  | 874 | (ADD64rr GR64:$src1, GR64:$src2)>; | 
|  | 875 | def : Pat<(addc GR64:$src1, (load addr:$src2)), | 
|  | 876 | (ADD64rm GR64:$src1, addr:$src2)>; | 
|  | 877 | def : Pat<(addc GR64:$src1, i64immSExt8:$src2), | 
|  | 878 | (ADD64ri8 GR64:$src1, i64immSExt8:$src2)>; | 
|  | 879 | def : Pat<(addc GR64:$src1, i64immSExt32:$src2), | 
|  | 880 | (ADD64ri32 GR64:$src1, imm:$src2)>; | 
|  | 881 |  | 
|  | 882 | def : Pat<(subc GR32:$src1, GR32:$src2), | 
|  | 883 | (SUB32rr GR32:$src1, GR32:$src2)>; | 
|  | 884 | def : Pat<(subc GR32:$src1, (load addr:$src2)), | 
|  | 885 | (SUB32rm GR32:$src1, addr:$src2)>; | 
|  | 886 | def : Pat<(subc GR32:$src1, imm:$src2), | 
|  | 887 | (SUB32ri GR32:$src1, imm:$src2)>; | 
|  | 888 | def : Pat<(subc GR32:$src1, i32immSExt8:$src2), | 
|  | 889 | (SUB32ri8 GR32:$src1, i32immSExt8:$src2)>; | 
|  | 890 |  | 
|  | 891 | def : Pat<(subc GR64:$src1, GR64:$src2), | 
|  | 892 | (SUB64rr GR64:$src1, GR64:$src2)>; | 
|  | 893 | def : Pat<(subc GR64:$src1, (load addr:$src2)), | 
|  | 894 | (SUB64rm GR64:$src1, addr:$src2)>; | 
|  | 895 | def : Pat<(subc GR64:$src1, i64immSExt8:$src2), | 
|  | 896 | (SUB64ri8 GR64:$src1, i64immSExt8:$src2)>; | 
|  | 897 | def : Pat<(subc GR64:$src1, imm:$src2), | 
|  | 898 | (SUB64ri32 GR64:$src1, i64immSExt32:$src2)>; | 
|  | 899 |  | 
|  | 900 | // Comparisons. | 
|  | 901 |  | 
|  | 902 | // TEST R,R is smaller than CMP R,0 | 
|  | 903 | def : Pat<(X86cmp GR8:$src1, 0), | 
|  | 904 | (TEST8rr GR8:$src1, GR8:$src1)>; | 
|  | 905 | def : Pat<(X86cmp GR16:$src1, 0), | 
|  | 906 | (TEST16rr GR16:$src1, GR16:$src1)>; | 
|  | 907 | def : Pat<(X86cmp GR32:$src1, 0), | 
|  | 908 | (TEST32rr GR32:$src1, GR32:$src1)>; | 
|  | 909 | def : Pat<(X86cmp GR64:$src1, 0), | 
|  | 910 | (TEST64rr GR64:$src1, GR64:$src1)>; | 
|  | 911 |  | 
|  | 912 | // Conditional moves with folded loads with operands swapped and conditions | 
|  | 913 | // inverted. | 
| Chris Lattner | fa25dd9 | 2010-10-05 22:42:54 +0000 | [diff] [blame] | 914 | multiclass CMOVmr<PatLeaf InvertedCond, Instruction Inst16, Instruction Inst32, | 
|  | 915 | Instruction Inst64> { | 
|  | 916 | def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, InvertedCond, EFLAGS), | 
|  | 917 | (Inst16 GR16:$src2, addr:$src1)>; | 
|  | 918 | def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, InvertedCond, EFLAGS), | 
|  | 919 | (Inst32 GR32:$src2, addr:$src1)>; | 
|  | 920 | def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, InvertedCond, EFLAGS), | 
|  | 921 | (Inst64 GR64:$src2, addr:$src1)>; | 
|  | 922 | } | 
| Chris Lattner | ae33f5d | 2010-10-05 06:04:14 +0000 | [diff] [blame] | 923 |  | 
| Chris Lattner | 7538ed8 | 2010-10-05 22:51:56 +0000 | [diff] [blame] | 924 | defm : CMOVmr<X86_COND_B , CMOVAE16rm, CMOVAE32rm, CMOVAE64rm>; | 
|  | 925 | defm : CMOVmr<X86_COND_AE, CMOVB16rm , CMOVB32rm , CMOVB64rm>; | 
|  | 926 | defm : CMOVmr<X86_COND_E , CMOVNE16rm, CMOVNE32rm, CMOVNE64rm>; | 
|  | 927 | defm : CMOVmr<X86_COND_NE, CMOVE16rm , CMOVE32rm , CMOVE64rm>; | 
|  | 928 | defm : CMOVmr<X86_COND_BE, CMOVA16rm , CMOVA32rm , CMOVA64rm>; | 
| Chris Lattner | 1a1c600 | 2010-10-05 23:00:14 +0000 | [diff] [blame] | 929 | defm : CMOVmr<X86_COND_A , CMOVBE16rm, CMOVBE32rm, CMOVBE64rm>; | 
| Chris Lattner | 7538ed8 | 2010-10-05 22:51:56 +0000 | [diff] [blame] | 930 | defm : CMOVmr<X86_COND_L , CMOVGE16rm, CMOVGE32rm, CMOVGE64rm>; | 
|  | 931 | defm : CMOVmr<X86_COND_GE, CMOVL16rm , CMOVL32rm , CMOVL64rm>; | 
|  | 932 | defm : CMOVmr<X86_COND_LE, CMOVG16rm , CMOVG32rm , CMOVG64rm>; | 
|  | 933 | defm : CMOVmr<X86_COND_G , CMOVLE16rm, CMOVLE32rm, CMOVLE64rm>; | 
|  | 934 | defm : CMOVmr<X86_COND_P , CMOVNP16rm, CMOVNP32rm, CMOVNP64rm>; | 
|  | 935 | defm : CMOVmr<X86_COND_NP, CMOVP16rm , CMOVP32rm , CMOVP64rm>; | 
|  | 936 | defm : CMOVmr<X86_COND_S , CMOVNS16rm, CMOVNS32rm, CMOVNS64rm>; | 
|  | 937 | defm : CMOVmr<X86_COND_NS, CMOVS16rm , CMOVS32rm , CMOVS64rm>; | 
|  | 938 | defm : CMOVmr<X86_COND_O , CMOVNO16rm, CMOVNO32rm, CMOVNO64rm>; | 
|  | 939 | defm : CMOVmr<X86_COND_NO, CMOVO16rm , CMOVO32rm , CMOVO64rm>; | 
| Chris Lattner | ae33f5d | 2010-10-05 06:04:14 +0000 | [diff] [blame] | 940 |  | 
|  | 941 | // zextload bool -> zextload byte | 
|  | 942 | def : Pat<(zextloadi8i1  addr:$src), (MOV8rm     addr:$src)>; | 
|  | 943 | def : Pat<(zextloadi16i1 addr:$src), (MOVZX16rm8 addr:$src)>; | 
|  | 944 | def : Pat<(zextloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>; | 
|  | 945 | def : Pat<(zextloadi64i1 addr:$src), (MOVZX64rm8 addr:$src)>; | 
|  | 946 |  | 
|  | 947 | // extload bool -> extload byte | 
|  | 948 | // When extloading from 16-bit and smaller memory locations into 64-bit | 
|  | 949 | // registers, use zero-extending loads so that the entire 64-bit register is | 
|  | 950 | // defined, avoiding partial-register updates. | 
|  | 951 |  | 
|  | 952 | def : Pat<(extloadi8i1 addr:$src),   (MOV8rm      addr:$src)>; | 
|  | 953 | def : Pat<(extloadi16i1 addr:$src),  (MOVZX16rm8  addr:$src)>; | 
|  | 954 | def : Pat<(extloadi32i1 addr:$src),  (MOVZX32rm8  addr:$src)>; | 
|  | 955 | def : Pat<(extloadi16i8 addr:$src),  (MOVZX16rm8  addr:$src)>; | 
|  | 956 | def : Pat<(extloadi32i8 addr:$src),  (MOVZX32rm8  addr:$src)>; | 
|  | 957 | def : Pat<(extloadi32i16 addr:$src), (MOVZX32rm16 addr:$src)>; | 
|  | 958 |  | 
|  | 959 | def : Pat<(extloadi64i1 addr:$src),  (MOVZX64rm8  addr:$src)>; | 
|  | 960 | def : Pat<(extloadi64i8 addr:$src),  (MOVZX64rm8  addr:$src)>; | 
|  | 961 | def : Pat<(extloadi64i16 addr:$src), (MOVZX64rm16 addr:$src)>; | 
|  | 962 | // For other extloads, use subregs, since the high contents of the register are | 
|  | 963 | // defined after an extload. | 
|  | 964 | def : Pat<(extloadi64i32 addr:$src), | 
|  | 965 | (SUBREG_TO_REG (i64 0), (MOV32rm addr:$src), | 
|  | 966 | sub_32bit)>; | 
|  | 967 |  | 
|  | 968 | // anyext. Define these to do an explicit zero-extend to | 
|  | 969 | // avoid partial-register updates. | 
|  | 970 | def : Pat<(i16 (anyext GR8 :$src)), (MOVZX16rr8  GR8 :$src)>; | 
|  | 971 | def : Pat<(i32 (anyext GR8 :$src)), (MOVZX32rr8  GR8 :$src)>; | 
|  | 972 |  | 
|  | 973 | // Except for i16 -> i32 since isel expect i16 ops to be promoted to i32. | 
|  | 974 | def : Pat<(i32 (anyext GR16:$src)), | 
|  | 975 | (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR16:$src, sub_16bit)>; | 
|  | 976 |  | 
|  | 977 | def : Pat<(i64 (anyext GR8 :$src)), (MOVZX64rr8  GR8  :$src)>; | 
|  | 978 | def : Pat<(i64 (anyext GR16:$src)), (MOVZX64rr16 GR16 :$src)>; | 
|  | 979 | def : Pat<(i64 (anyext GR32:$src)), | 
|  | 980 | (SUBREG_TO_REG (i64 0), GR32:$src, sub_32bit)>; | 
|  | 981 |  | 
| Chris Lattner | 84571a1 | 2010-10-05 06:47:35 +0000 | [diff] [blame] | 982 |  | 
|  | 983 | // Any instruction that defines a 32-bit result leaves the high half of the | 
|  | 984 | // register. Truncate can be lowered to EXTRACT_SUBREG. CopyFromReg may | 
|  | 985 | // be copying from a truncate. And x86's cmov doesn't do anything if the | 
|  | 986 | // condition is false. But any other 32-bit operation will zero-extend | 
|  | 987 | // up to 64 bits. | 
|  | 988 | def def32 : PatLeaf<(i32 GR32:$src), [{ | 
|  | 989 | return N->getOpcode() != ISD::TRUNCATE && | 
|  | 990 | N->getOpcode() != TargetOpcode::EXTRACT_SUBREG && | 
|  | 991 | N->getOpcode() != ISD::CopyFromReg && | 
|  | 992 | N->getOpcode() != X86ISD::CMOV; | 
|  | 993 | }]>; | 
|  | 994 |  | 
|  | 995 | // In the case of a 32-bit def that is known to implicitly zero-extend, | 
|  | 996 | // we can use a SUBREG_TO_REG. | 
|  | 997 | def : Pat<(i64 (zext def32:$src)), | 
|  | 998 | (SUBREG_TO_REG (i64 0), GR32:$src, sub_32bit)>; | 
|  | 999 |  | 
| Chris Lattner | ae33f5d | 2010-10-05 06:04:14 +0000 | [diff] [blame] | 1000 | //===----------------------------------------------------------------------===// | 
|  | 1001 | // Some peepholes | 
|  | 1002 | //===----------------------------------------------------------------------===// | 
|  | 1003 |  | 
|  | 1004 | // Odd encoding trick: -128 fits into an 8-bit immediate field while | 
|  | 1005 | // +128 doesn't, so in this special case use a sub instead of an add. | 
|  | 1006 | def : Pat<(add GR16:$src1, 128), | 
|  | 1007 | (SUB16ri8 GR16:$src1, -128)>; | 
|  | 1008 | def : Pat<(store (add (loadi16 addr:$dst), 128), addr:$dst), | 
|  | 1009 | (SUB16mi8 addr:$dst, -128)>; | 
|  | 1010 |  | 
|  | 1011 | def : Pat<(add GR32:$src1, 128), | 
|  | 1012 | (SUB32ri8 GR32:$src1, -128)>; | 
|  | 1013 | def : Pat<(store (add (loadi32 addr:$dst), 128), addr:$dst), | 
|  | 1014 | (SUB32mi8 addr:$dst, -128)>; | 
|  | 1015 |  | 
|  | 1016 | def : Pat<(add GR64:$src1, 128), | 
|  | 1017 | (SUB64ri8 GR64:$src1, -128)>; | 
|  | 1018 | def : Pat<(store (add (loadi64 addr:$dst), 128), addr:$dst), | 
|  | 1019 | (SUB64mi8 addr:$dst, -128)>; | 
|  | 1020 |  | 
|  | 1021 | // The same trick applies for 32-bit immediate fields in 64-bit | 
|  | 1022 | // instructions. | 
|  | 1023 | def : Pat<(add GR64:$src1, 0x0000000080000000), | 
|  | 1024 | (SUB64ri32 GR64:$src1, 0xffffffff80000000)>; | 
|  | 1025 | def : Pat<(store (add (loadi64 addr:$dst), 0x00000000800000000), addr:$dst), | 
|  | 1026 | (SUB64mi32 addr:$dst, 0xffffffff80000000)>; | 
|  | 1027 |  | 
|  | 1028 | // Use a 32-bit and with implicit zero-extension instead of a 64-bit and if it | 
|  | 1029 | // has an immediate with at least 32 bits of leading zeros, to avoid needing to | 
|  | 1030 | // materialize that immediate in a register first. | 
|  | 1031 | def : Pat<(and GR64:$src, i64immZExt32:$imm), | 
|  | 1032 | (SUBREG_TO_REG | 
|  | 1033 | (i64 0), | 
|  | 1034 | (AND32ri | 
|  | 1035 | (EXTRACT_SUBREG GR64:$src, sub_32bit), | 
|  | 1036 | (i32 (GetLo32XForm imm:$imm))), | 
|  | 1037 | sub_32bit)>; | 
|  | 1038 |  | 
|  | 1039 |  | 
|  | 1040 | // r & (2^16-1) ==> movz | 
|  | 1041 | def : Pat<(and GR32:$src1, 0xffff), | 
|  | 1042 | (MOVZX32rr16 (EXTRACT_SUBREG GR32:$src1, sub_16bit))>; | 
|  | 1043 | // r & (2^8-1) ==> movz | 
|  | 1044 | def : Pat<(and GR32:$src1, 0xff), | 
|  | 1045 | (MOVZX32rr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src1, | 
|  | 1046 | GR32_ABCD)), | 
|  | 1047 | sub_8bit))>, | 
|  | 1048 | Requires<[In32BitMode]>; | 
|  | 1049 | // r & (2^8-1) ==> movz | 
|  | 1050 | def : Pat<(and GR16:$src1, 0xff), | 
|  | 1051 | (MOVZX16rr8 (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src1, | 
|  | 1052 | GR16_ABCD)), | 
|  | 1053 | sub_8bit))>, | 
|  | 1054 | Requires<[In32BitMode]>; | 
|  | 1055 |  | 
|  | 1056 | // r & (2^32-1) ==> movz | 
|  | 1057 | def : Pat<(and GR64:$src, 0x00000000FFFFFFFF), | 
|  | 1058 | (MOVZX64rr32 (EXTRACT_SUBREG GR64:$src, sub_32bit))>; | 
|  | 1059 | // r & (2^16-1) ==> movz | 
|  | 1060 | def : Pat<(and GR64:$src, 0xffff), | 
|  | 1061 | (MOVZX64rr16 (i16 (EXTRACT_SUBREG GR64:$src, sub_16bit)))>; | 
|  | 1062 | // r & (2^8-1) ==> movz | 
|  | 1063 | def : Pat<(and GR64:$src, 0xff), | 
|  | 1064 | (MOVZX64rr8 (i8 (EXTRACT_SUBREG GR64:$src, sub_8bit)))>; | 
|  | 1065 | // r & (2^8-1) ==> movz | 
|  | 1066 | def : Pat<(and GR32:$src1, 0xff), | 
|  | 1067 | (MOVZX32rr8 (EXTRACT_SUBREG GR32:$src1, sub_8bit))>, | 
|  | 1068 | Requires<[In64BitMode]>; | 
|  | 1069 | // r & (2^8-1) ==> movz | 
|  | 1070 | def : Pat<(and GR16:$src1, 0xff), | 
|  | 1071 | (MOVZX16rr8 (i8 (EXTRACT_SUBREG GR16:$src1, sub_8bit)))>, | 
|  | 1072 | Requires<[In64BitMode]>; | 
|  | 1073 |  | 
|  | 1074 |  | 
|  | 1075 | // sext_inreg patterns | 
|  | 1076 | def : Pat<(sext_inreg GR32:$src, i16), | 
|  | 1077 | (MOVSX32rr16 (EXTRACT_SUBREG GR32:$src, sub_16bit))>; | 
|  | 1078 | def : Pat<(sext_inreg GR32:$src, i8), | 
|  | 1079 | (MOVSX32rr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, | 
|  | 1080 | GR32_ABCD)), | 
|  | 1081 | sub_8bit))>, | 
|  | 1082 | Requires<[In32BitMode]>; | 
|  | 1083 | def : Pat<(sext_inreg GR16:$src, i8), | 
|  | 1084 | (MOVSX16rr8 (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, | 
|  | 1085 | GR16_ABCD)), | 
|  | 1086 | sub_8bit))>, | 
|  | 1087 | Requires<[In32BitMode]>; | 
|  | 1088 |  | 
|  | 1089 | def : Pat<(sext_inreg GR64:$src, i32), | 
|  | 1090 | (MOVSX64rr32 (EXTRACT_SUBREG GR64:$src, sub_32bit))>; | 
|  | 1091 | def : Pat<(sext_inreg GR64:$src, i16), | 
|  | 1092 | (MOVSX64rr16 (EXTRACT_SUBREG GR64:$src, sub_16bit))>; | 
|  | 1093 | def : Pat<(sext_inreg GR64:$src, i8), | 
|  | 1094 | (MOVSX64rr8 (EXTRACT_SUBREG GR64:$src, sub_8bit))>; | 
|  | 1095 | def : Pat<(sext_inreg GR32:$src, i8), | 
|  | 1096 | (MOVSX32rr8 (EXTRACT_SUBREG GR32:$src, sub_8bit))>, | 
|  | 1097 | Requires<[In64BitMode]>; | 
|  | 1098 | def : Pat<(sext_inreg GR16:$src, i8), | 
|  | 1099 | (MOVSX16rr8 (i8 (EXTRACT_SUBREG GR16:$src, sub_8bit)))>, | 
|  | 1100 | Requires<[In64BitMode]>; | 
|  | 1101 |  | 
|  | 1102 |  | 
|  | 1103 | // trunc patterns | 
|  | 1104 | def : Pat<(i16 (trunc GR32:$src)), | 
|  | 1105 | (EXTRACT_SUBREG GR32:$src, sub_16bit)>; | 
|  | 1106 | def : Pat<(i8 (trunc GR32:$src)), | 
|  | 1107 | (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), | 
|  | 1108 | sub_8bit)>, | 
|  | 1109 | Requires<[In32BitMode]>; | 
|  | 1110 | def : Pat<(i8 (trunc GR16:$src)), | 
|  | 1111 | (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), | 
|  | 1112 | sub_8bit)>, | 
|  | 1113 | Requires<[In32BitMode]>; | 
|  | 1114 | def : Pat<(i32 (trunc GR64:$src)), | 
|  | 1115 | (EXTRACT_SUBREG GR64:$src, sub_32bit)>; | 
|  | 1116 | def : Pat<(i16 (trunc GR64:$src)), | 
|  | 1117 | (EXTRACT_SUBREG GR64:$src, sub_16bit)>; | 
|  | 1118 | def : Pat<(i8 (trunc GR64:$src)), | 
|  | 1119 | (EXTRACT_SUBREG GR64:$src, sub_8bit)>; | 
|  | 1120 | def : Pat<(i8 (trunc GR32:$src)), | 
|  | 1121 | (EXTRACT_SUBREG GR32:$src, sub_8bit)>, | 
|  | 1122 | Requires<[In64BitMode]>; | 
|  | 1123 | def : Pat<(i8 (trunc GR16:$src)), | 
|  | 1124 | (EXTRACT_SUBREG GR16:$src, sub_8bit)>, | 
|  | 1125 | Requires<[In64BitMode]>; | 
|  | 1126 |  | 
|  | 1127 | // h-register tricks | 
|  | 1128 | def : Pat<(i8 (trunc (srl_su GR16:$src, (i8 8)))), | 
|  | 1129 | (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), | 
|  | 1130 | sub_8bit_hi)>, | 
|  | 1131 | Requires<[In32BitMode]>; | 
|  | 1132 | def : Pat<(i8 (trunc (srl_su GR32:$src, (i8 8)))), | 
|  | 1133 | (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), | 
|  | 1134 | sub_8bit_hi)>, | 
|  | 1135 | Requires<[In32BitMode]>; | 
|  | 1136 | def : Pat<(srl GR16:$src, (i8 8)), | 
|  | 1137 | (EXTRACT_SUBREG | 
|  | 1138 | (MOVZX32rr8 | 
|  | 1139 | (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), | 
|  | 1140 | sub_8bit_hi)), | 
|  | 1141 | sub_16bit)>, | 
|  | 1142 | Requires<[In32BitMode]>; | 
|  | 1143 | def : Pat<(i32 (zext (srl_su GR16:$src, (i8 8)))), | 
|  | 1144 | (MOVZX32rr8 (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, | 
|  | 1145 | GR16_ABCD)), | 
|  | 1146 | sub_8bit_hi))>, | 
|  | 1147 | Requires<[In32BitMode]>; | 
|  | 1148 | def : Pat<(i32 (anyext (srl_su GR16:$src, (i8 8)))), | 
|  | 1149 | (MOVZX32rr8 (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, | 
|  | 1150 | GR16_ABCD)), | 
|  | 1151 | sub_8bit_hi))>, | 
|  | 1152 | Requires<[In32BitMode]>; | 
|  | 1153 | def : Pat<(and (srl_su GR32:$src, (i8 8)), (i32 255)), | 
|  | 1154 | (MOVZX32rr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, | 
|  | 1155 | GR32_ABCD)), | 
|  | 1156 | sub_8bit_hi))>, | 
|  | 1157 | Requires<[In32BitMode]>; | 
|  | 1158 | def : Pat<(srl (and_su GR32:$src, 0xff00), (i8 8)), | 
|  | 1159 | (MOVZX32rr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, | 
|  | 1160 | GR32_ABCD)), | 
|  | 1161 | sub_8bit_hi))>, | 
|  | 1162 | Requires<[In32BitMode]>; | 
|  | 1163 |  | 
|  | 1164 | // h-register tricks. | 
|  | 1165 | // For now, be conservative on x86-64 and use an h-register extract only if the | 
|  | 1166 | // value is immediately zero-extended or stored, which are somewhat common | 
|  | 1167 | // cases. This uses a bunch of code to prevent a register requiring a REX prefix | 
|  | 1168 | // from being allocated in the same instruction as the h register, as there's | 
|  | 1169 | // currently no way to describe this requirement to the register allocator. | 
|  | 1170 |  | 
|  | 1171 | // h-register extract and zero-extend. | 
|  | 1172 | def : Pat<(and (srl_su GR64:$src, (i8 8)), (i64 255)), | 
|  | 1173 | (SUBREG_TO_REG | 
|  | 1174 | (i64 0), | 
|  | 1175 | (MOVZX32_NOREXrr8 | 
|  | 1176 | (EXTRACT_SUBREG (i64 (COPY_TO_REGCLASS GR64:$src, GR64_ABCD)), | 
|  | 1177 | sub_8bit_hi)), | 
|  | 1178 | sub_32bit)>; | 
|  | 1179 | def : Pat<(and (srl_su GR32:$src, (i8 8)), (i32 255)), | 
|  | 1180 | (MOVZX32_NOREXrr8 | 
|  | 1181 | (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), | 
|  | 1182 | sub_8bit_hi))>, | 
|  | 1183 | Requires<[In64BitMode]>; | 
|  | 1184 | def : Pat<(srl (and_su GR32:$src, 0xff00), (i8 8)), | 
|  | 1185 | (MOVZX32_NOREXrr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, | 
|  | 1186 | GR32_ABCD)), | 
|  | 1187 | sub_8bit_hi))>, | 
|  | 1188 | Requires<[In64BitMode]>; | 
|  | 1189 | def : Pat<(srl GR16:$src, (i8 8)), | 
|  | 1190 | (EXTRACT_SUBREG | 
|  | 1191 | (MOVZX32_NOREXrr8 | 
|  | 1192 | (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), | 
|  | 1193 | sub_8bit_hi)), | 
|  | 1194 | sub_16bit)>, | 
|  | 1195 | Requires<[In64BitMode]>; | 
|  | 1196 | def : Pat<(i32 (zext (srl_su GR16:$src, (i8 8)))), | 
|  | 1197 | (MOVZX32_NOREXrr8 | 
|  | 1198 | (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), | 
|  | 1199 | sub_8bit_hi))>, | 
|  | 1200 | Requires<[In64BitMode]>; | 
|  | 1201 | def : Pat<(i32 (anyext (srl_su GR16:$src, (i8 8)))), | 
|  | 1202 | (MOVZX32_NOREXrr8 | 
|  | 1203 | (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), | 
|  | 1204 | sub_8bit_hi))>, | 
|  | 1205 | Requires<[In64BitMode]>; | 
|  | 1206 | def : Pat<(i64 (zext (srl_su GR16:$src, (i8 8)))), | 
|  | 1207 | (SUBREG_TO_REG | 
|  | 1208 | (i64 0), | 
|  | 1209 | (MOVZX32_NOREXrr8 | 
|  | 1210 | (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), | 
|  | 1211 | sub_8bit_hi)), | 
|  | 1212 | sub_32bit)>; | 
|  | 1213 | def : Pat<(i64 (anyext (srl_su GR16:$src, (i8 8)))), | 
|  | 1214 | (SUBREG_TO_REG | 
|  | 1215 | (i64 0), | 
|  | 1216 | (MOVZX32_NOREXrr8 | 
|  | 1217 | (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), | 
|  | 1218 | sub_8bit_hi)), | 
|  | 1219 | sub_32bit)>; | 
|  | 1220 |  | 
|  | 1221 | // h-register extract and store. | 
|  | 1222 | def : Pat<(store (i8 (trunc_su (srl_su GR64:$src, (i8 8)))), addr:$dst), | 
|  | 1223 | (MOV8mr_NOREX | 
|  | 1224 | addr:$dst, | 
|  | 1225 | (EXTRACT_SUBREG (i64 (COPY_TO_REGCLASS GR64:$src, GR64_ABCD)), | 
|  | 1226 | sub_8bit_hi))>; | 
|  | 1227 | def : Pat<(store (i8 (trunc_su (srl_su GR32:$src, (i8 8)))), addr:$dst), | 
|  | 1228 | (MOV8mr_NOREX | 
|  | 1229 | addr:$dst, | 
|  | 1230 | (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), | 
|  | 1231 | sub_8bit_hi))>, | 
|  | 1232 | Requires<[In64BitMode]>; | 
|  | 1233 | def : Pat<(store (i8 (trunc_su (srl_su GR16:$src, (i8 8)))), addr:$dst), | 
|  | 1234 | (MOV8mr_NOREX | 
|  | 1235 | addr:$dst, | 
|  | 1236 | (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), | 
|  | 1237 | sub_8bit_hi))>, | 
|  | 1238 | Requires<[In64BitMode]>; | 
|  | 1239 |  | 
|  | 1240 |  | 
|  | 1241 | // (shl x, 1) ==> (add x, x) | 
|  | 1242 | def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr  GR8 :$src1, GR8 :$src1)>; | 
|  | 1243 | def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>; | 
|  | 1244 | def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>; | 
|  | 1245 | def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>; | 
|  | 1246 |  | 
|  | 1247 | // (shl x (and y, 31)) ==> (shl x, y) | 
|  | 1248 | def : Pat<(shl GR8:$src1, (and CL, 31)), | 
|  | 1249 | (SHL8rCL GR8:$src1)>; | 
|  | 1250 | def : Pat<(shl GR16:$src1, (and CL, 31)), | 
|  | 1251 | (SHL16rCL GR16:$src1)>; | 
|  | 1252 | def : Pat<(shl GR32:$src1, (and CL, 31)), | 
|  | 1253 | (SHL32rCL GR32:$src1)>; | 
|  | 1254 | def : Pat<(store (shl (loadi8 addr:$dst), (and CL, 31)), addr:$dst), | 
|  | 1255 | (SHL8mCL addr:$dst)>; | 
|  | 1256 | def : Pat<(store (shl (loadi16 addr:$dst), (and CL, 31)), addr:$dst), | 
|  | 1257 | (SHL16mCL addr:$dst)>; | 
|  | 1258 | def : Pat<(store (shl (loadi32 addr:$dst), (and CL, 31)), addr:$dst), | 
|  | 1259 | (SHL32mCL addr:$dst)>; | 
|  | 1260 |  | 
|  | 1261 | def : Pat<(srl GR8:$src1, (and CL, 31)), | 
|  | 1262 | (SHR8rCL GR8:$src1)>; | 
|  | 1263 | def : Pat<(srl GR16:$src1, (and CL, 31)), | 
|  | 1264 | (SHR16rCL GR16:$src1)>; | 
|  | 1265 | def : Pat<(srl GR32:$src1, (and CL, 31)), | 
|  | 1266 | (SHR32rCL GR32:$src1)>; | 
|  | 1267 | def : Pat<(store (srl (loadi8 addr:$dst), (and CL, 31)), addr:$dst), | 
|  | 1268 | (SHR8mCL addr:$dst)>; | 
|  | 1269 | def : Pat<(store (srl (loadi16 addr:$dst), (and CL, 31)), addr:$dst), | 
|  | 1270 | (SHR16mCL addr:$dst)>; | 
|  | 1271 | def : Pat<(store (srl (loadi32 addr:$dst), (and CL, 31)), addr:$dst), | 
|  | 1272 | (SHR32mCL addr:$dst)>; | 
|  | 1273 |  | 
|  | 1274 | def : Pat<(sra GR8:$src1, (and CL, 31)), | 
|  | 1275 | (SAR8rCL GR8:$src1)>; | 
|  | 1276 | def : Pat<(sra GR16:$src1, (and CL, 31)), | 
|  | 1277 | (SAR16rCL GR16:$src1)>; | 
|  | 1278 | def : Pat<(sra GR32:$src1, (and CL, 31)), | 
|  | 1279 | (SAR32rCL GR32:$src1)>; | 
|  | 1280 | def : Pat<(store (sra (loadi8 addr:$dst), (and CL, 31)), addr:$dst), | 
|  | 1281 | (SAR8mCL addr:$dst)>; | 
|  | 1282 | def : Pat<(store (sra (loadi16 addr:$dst), (and CL, 31)), addr:$dst), | 
|  | 1283 | (SAR16mCL addr:$dst)>; | 
|  | 1284 | def : Pat<(store (sra (loadi32 addr:$dst), (and CL, 31)), addr:$dst), | 
|  | 1285 | (SAR32mCL addr:$dst)>; | 
|  | 1286 |  | 
|  | 1287 | // (shl x (and y, 63)) ==> (shl x, y) | 
|  | 1288 | def : Pat<(shl GR64:$src1, (and CL, 63)), | 
|  | 1289 | (SHL64rCL GR64:$src1)>; | 
|  | 1290 | def : Pat<(store (shl (loadi64 addr:$dst), (and CL, 63)), addr:$dst), | 
|  | 1291 | (SHL64mCL addr:$dst)>; | 
|  | 1292 |  | 
|  | 1293 | def : Pat<(srl GR64:$src1, (and CL, 63)), | 
|  | 1294 | (SHR64rCL GR64:$src1)>; | 
|  | 1295 | def : Pat<(store (srl (loadi64 addr:$dst), (and CL, 63)), addr:$dst), | 
|  | 1296 | (SHR64mCL addr:$dst)>; | 
|  | 1297 |  | 
|  | 1298 | def : Pat<(sra GR64:$src1, (and CL, 63)), | 
|  | 1299 | (SAR64rCL GR64:$src1)>; | 
|  | 1300 | def : Pat<(store (sra (loadi64 addr:$dst), (and CL, 63)), addr:$dst), | 
|  | 1301 | (SAR64mCL addr:$dst)>; | 
|  | 1302 |  | 
|  | 1303 |  | 
|  | 1304 | // (anyext (setcc_carry)) -> (setcc_carry) | 
|  | 1305 | def : Pat<(i16 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), | 
|  | 1306 | (SETB_C16r)>; | 
|  | 1307 | def : Pat<(i32 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), | 
|  | 1308 | (SETB_C32r)>; | 
|  | 1309 | def : Pat<(i32 (anyext (i16 (X86setcc_c X86_COND_B, EFLAGS)))), | 
|  | 1310 | (SETB_C32r)>; | 
|  | 1311 |  | 
|  | 1312 | // (or x1, x2) -> (add x1, x2) if two operands are known not to share bits. | 
|  | 1313 | let AddedComplexity = 5 in { // Try this before the selecting to OR | 
|  | 1314 | def : Pat<(or_is_add GR16:$src1, imm:$src2), | 
|  | 1315 | (ADD16ri GR16:$src1, imm:$src2)>; | 
|  | 1316 | def : Pat<(or_is_add GR32:$src1, imm:$src2), | 
|  | 1317 | (ADD32ri GR32:$src1, imm:$src2)>; | 
|  | 1318 | def : Pat<(or_is_add GR16:$src1, i16immSExt8:$src2), | 
|  | 1319 | (ADD16ri8 GR16:$src1, i16immSExt8:$src2)>; | 
|  | 1320 | def : Pat<(or_is_add GR32:$src1, i32immSExt8:$src2), | 
|  | 1321 | (ADD32ri8 GR32:$src1, i32immSExt8:$src2)>; | 
|  | 1322 | def : Pat<(or_is_add GR16:$src1, GR16:$src2), | 
|  | 1323 | (ADD16rr GR16:$src1, GR16:$src2)>; | 
|  | 1324 | def : Pat<(or_is_add GR32:$src1, GR32:$src2), | 
|  | 1325 | (ADD32rr GR32:$src1, GR32:$src2)>; | 
|  | 1326 | def : Pat<(or_is_add GR64:$src1, i64immSExt8:$src2), | 
|  | 1327 | (ADD64ri8 GR64:$src1, i64immSExt8:$src2)>; | 
|  | 1328 | def : Pat<(or_is_add GR64:$src1, i64immSExt32:$src2), | 
|  | 1329 | (ADD64ri32 GR64:$src1, i64immSExt32:$src2)>; | 
|  | 1330 | def : Pat<(or_is_add GR64:$src1, GR64:$src2), | 
|  | 1331 | (ADD64rr GR64:$src1, GR64:$src2)>; | 
|  | 1332 | } // AddedComplexity | 
|  | 1333 |  | 
|  | 1334 | //===----------------------------------------------------------------------===// | 
|  | 1335 | // EFLAGS-defining Patterns | 
|  | 1336 | //===----------------------------------------------------------------------===// | 
|  | 1337 |  | 
|  | 1338 | // add reg, reg | 
|  | 1339 | def : Pat<(add GR8 :$src1, GR8 :$src2), (ADD8rr  GR8 :$src1, GR8 :$src2)>; | 
|  | 1340 | def : Pat<(add GR16:$src1, GR16:$src2), (ADD16rr GR16:$src1, GR16:$src2)>; | 
|  | 1341 | def : Pat<(add GR32:$src1, GR32:$src2), (ADD32rr GR32:$src1, GR32:$src2)>; | 
|  | 1342 |  | 
|  | 1343 | // add reg, mem | 
|  | 1344 | def : Pat<(add GR8:$src1, (loadi8 addr:$src2)), | 
|  | 1345 | (ADD8rm GR8:$src1, addr:$src2)>; | 
|  | 1346 | def : Pat<(add GR16:$src1, (loadi16 addr:$src2)), | 
|  | 1347 | (ADD16rm GR16:$src1, addr:$src2)>; | 
|  | 1348 | def : Pat<(add GR32:$src1, (loadi32 addr:$src2)), | 
|  | 1349 | (ADD32rm GR32:$src1, addr:$src2)>; | 
|  | 1350 |  | 
|  | 1351 | // add reg, imm | 
|  | 1352 | def : Pat<(add GR8 :$src1, imm:$src2), (ADD8ri  GR8:$src1 , imm:$src2)>; | 
|  | 1353 | def : Pat<(add GR16:$src1, imm:$src2), (ADD16ri GR16:$src1, imm:$src2)>; | 
|  | 1354 | def : Pat<(add GR32:$src1, imm:$src2), (ADD32ri GR32:$src1, imm:$src2)>; | 
|  | 1355 | def : Pat<(add GR16:$src1, i16immSExt8:$src2), | 
|  | 1356 | (ADD16ri8 GR16:$src1, i16immSExt8:$src2)>; | 
|  | 1357 | def : Pat<(add GR32:$src1, i32immSExt8:$src2), | 
|  | 1358 | (ADD32ri8 GR32:$src1, i32immSExt8:$src2)>; | 
|  | 1359 |  | 
|  | 1360 | // sub reg, reg | 
|  | 1361 | def : Pat<(sub GR8 :$src1, GR8 :$src2), (SUB8rr  GR8 :$src1, GR8 :$src2)>; | 
|  | 1362 | def : Pat<(sub GR16:$src1, GR16:$src2), (SUB16rr GR16:$src1, GR16:$src2)>; | 
|  | 1363 | def : Pat<(sub GR32:$src1, GR32:$src2), (SUB32rr GR32:$src1, GR32:$src2)>; | 
|  | 1364 |  | 
|  | 1365 | // sub reg, mem | 
|  | 1366 | def : Pat<(sub GR8:$src1, (loadi8 addr:$src2)), | 
|  | 1367 | (SUB8rm GR8:$src1, addr:$src2)>; | 
|  | 1368 | def : Pat<(sub GR16:$src1, (loadi16 addr:$src2)), | 
|  | 1369 | (SUB16rm GR16:$src1, addr:$src2)>; | 
|  | 1370 | def : Pat<(sub GR32:$src1, (loadi32 addr:$src2)), | 
|  | 1371 | (SUB32rm GR32:$src1, addr:$src2)>; | 
|  | 1372 |  | 
|  | 1373 | // sub reg, imm | 
|  | 1374 | def : Pat<(sub GR8:$src1, imm:$src2), | 
|  | 1375 | (SUB8ri GR8:$src1, imm:$src2)>; | 
|  | 1376 | def : Pat<(sub GR16:$src1, imm:$src2), | 
|  | 1377 | (SUB16ri GR16:$src1, imm:$src2)>; | 
|  | 1378 | def : Pat<(sub GR32:$src1, imm:$src2), | 
|  | 1379 | (SUB32ri GR32:$src1, imm:$src2)>; | 
|  | 1380 | def : Pat<(sub GR16:$src1, i16immSExt8:$src2), | 
|  | 1381 | (SUB16ri8 GR16:$src1, i16immSExt8:$src2)>; | 
|  | 1382 | def : Pat<(sub GR32:$src1, i32immSExt8:$src2), | 
|  | 1383 | (SUB32ri8 GR32:$src1, i32immSExt8:$src2)>; | 
|  | 1384 |  | 
|  | 1385 | // mul reg, reg | 
|  | 1386 | def : Pat<(mul GR16:$src1, GR16:$src2), | 
|  | 1387 | (IMUL16rr GR16:$src1, GR16:$src2)>; | 
|  | 1388 | def : Pat<(mul GR32:$src1, GR32:$src2), | 
|  | 1389 | (IMUL32rr GR32:$src1, GR32:$src2)>; | 
|  | 1390 |  | 
|  | 1391 | // mul reg, mem | 
|  | 1392 | def : Pat<(mul GR16:$src1, (loadi16 addr:$src2)), | 
|  | 1393 | (IMUL16rm GR16:$src1, addr:$src2)>; | 
|  | 1394 | def : Pat<(mul GR32:$src1, (loadi32 addr:$src2)), | 
|  | 1395 | (IMUL32rm GR32:$src1, addr:$src2)>; | 
|  | 1396 |  | 
|  | 1397 | // mul reg, imm | 
|  | 1398 | def : Pat<(mul GR16:$src1, imm:$src2), | 
|  | 1399 | (IMUL16rri GR16:$src1, imm:$src2)>; | 
|  | 1400 | def : Pat<(mul GR32:$src1, imm:$src2), | 
|  | 1401 | (IMUL32rri GR32:$src1, imm:$src2)>; | 
|  | 1402 | def : Pat<(mul GR16:$src1, i16immSExt8:$src2), | 
|  | 1403 | (IMUL16rri8 GR16:$src1, i16immSExt8:$src2)>; | 
|  | 1404 | def : Pat<(mul GR32:$src1, i32immSExt8:$src2), | 
|  | 1405 | (IMUL32rri8 GR32:$src1, i32immSExt8:$src2)>; | 
|  | 1406 |  | 
|  | 1407 | // reg = mul mem, imm | 
|  | 1408 | def : Pat<(mul (loadi16 addr:$src1), imm:$src2), | 
|  | 1409 | (IMUL16rmi addr:$src1, imm:$src2)>; | 
|  | 1410 | def : Pat<(mul (loadi32 addr:$src1), imm:$src2), | 
|  | 1411 | (IMUL32rmi addr:$src1, imm:$src2)>; | 
|  | 1412 | def : Pat<(mul (loadi16 addr:$src1), i16immSExt8:$src2), | 
|  | 1413 | (IMUL16rmi8 addr:$src1, i16immSExt8:$src2)>; | 
|  | 1414 | def : Pat<(mul (loadi32 addr:$src1), i32immSExt8:$src2), | 
|  | 1415 | (IMUL32rmi8 addr:$src1, i32immSExt8:$src2)>; | 
|  | 1416 |  | 
|  | 1417 | // Optimize multiply by 2 with EFLAGS result. | 
|  | 1418 | let AddedComplexity = 2 in { | 
|  | 1419 | def : Pat<(X86smul_flag GR16:$src1, 2), (ADD16rr GR16:$src1, GR16:$src1)>; | 
|  | 1420 | def : Pat<(X86smul_flag GR32:$src1, 2), (ADD32rr GR32:$src1, GR32:$src1)>; | 
|  | 1421 | } | 
|  | 1422 |  | 
|  | 1423 | // Patterns for nodes that do not produce flags, for instructions that do. | 
|  | 1424 |  | 
|  | 1425 | // addition | 
|  | 1426 | def : Pat<(add GR64:$src1, GR64:$src2), | 
|  | 1427 | (ADD64rr GR64:$src1, GR64:$src2)>; | 
|  | 1428 | def : Pat<(add GR64:$src1, i64immSExt8:$src2), | 
|  | 1429 | (ADD64ri8 GR64:$src1, i64immSExt8:$src2)>; | 
|  | 1430 | def : Pat<(add GR64:$src1, i64immSExt32:$src2), | 
|  | 1431 | (ADD64ri32 GR64:$src1, i64immSExt32:$src2)>; | 
|  | 1432 | def : Pat<(add GR64:$src1, (loadi64 addr:$src2)), | 
|  | 1433 | (ADD64rm GR64:$src1, addr:$src2)>; | 
|  | 1434 |  | 
|  | 1435 | // subtraction | 
|  | 1436 | def : Pat<(sub GR64:$src1, GR64:$src2), | 
|  | 1437 | (SUB64rr GR64:$src1, GR64:$src2)>; | 
|  | 1438 | def : Pat<(sub GR64:$src1, (loadi64 addr:$src2)), | 
|  | 1439 | (SUB64rm GR64:$src1, addr:$src2)>; | 
|  | 1440 | def : Pat<(sub GR64:$src1, i64immSExt8:$src2), | 
|  | 1441 | (SUB64ri8 GR64:$src1, i64immSExt8:$src2)>; | 
|  | 1442 | def : Pat<(sub GR64:$src1, i64immSExt32:$src2), | 
|  | 1443 | (SUB64ri32 GR64:$src1, i64immSExt32:$src2)>; | 
|  | 1444 |  | 
|  | 1445 | // Multiply | 
|  | 1446 | def : Pat<(mul GR64:$src1, GR64:$src2), | 
|  | 1447 | (IMUL64rr GR64:$src1, GR64:$src2)>; | 
|  | 1448 | def : Pat<(mul GR64:$src1, (loadi64 addr:$src2)), | 
|  | 1449 | (IMUL64rm GR64:$src1, addr:$src2)>; | 
|  | 1450 | def : Pat<(mul GR64:$src1, i64immSExt8:$src2), | 
|  | 1451 | (IMUL64rri8 GR64:$src1, i64immSExt8:$src2)>; | 
|  | 1452 | def : Pat<(mul GR64:$src1, i64immSExt32:$src2), | 
|  | 1453 | (IMUL64rri32 GR64:$src1, i64immSExt32:$src2)>; | 
|  | 1454 | def : Pat<(mul (loadi64 addr:$src1), i64immSExt8:$src2), | 
|  | 1455 | (IMUL64rmi8 addr:$src1, i64immSExt8:$src2)>; | 
|  | 1456 | def : Pat<(mul (loadi64 addr:$src1), i64immSExt32:$src2), | 
|  | 1457 | (IMUL64rmi32 addr:$src1, i64immSExt32:$src2)>; | 
|  | 1458 |  | 
|  | 1459 | // Increment reg. | 
|  | 1460 | def : Pat<(add GR8 :$src, 1), (INC8r     GR8 :$src)>; | 
|  | 1461 | def : Pat<(add GR16:$src, 1), (INC16r    GR16:$src)>, Requires<[In32BitMode]>; | 
|  | 1462 | def : Pat<(add GR16:$src, 1), (INC64_16r GR16:$src)>, Requires<[In64BitMode]>; | 
|  | 1463 | def : Pat<(add GR32:$src, 1), (INC32r    GR32:$src)>, Requires<[In32BitMode]>; | 
|  | 1464 | def : Pat<(add GR32:$src, 1), (INC64_32r GR32:$src)>, Requires<[In64BitMode]>; | 
|  | 1465 | def : Pat<(add GR64:$src, 1), (INC64r    GR64:$src)>; | 
|  | 1466 |  | 
|  | 1467 | // Decrement reg. | 
|  | 1468 | def : Pat<(add GR8 :$src, -1), (DEC8r     GR8 :$src)>; | 
|  | 1469 | def : Pat<(add GR16:$src, -1), (DEC16r    GR16:$src)>, Requires<[In32BitMode]>; | 
|  | 1470 | def : Pat<(add GR16:$src, -1), (DEC64_16r GR16:$src)>, Requires<[In64BitMode]>; | 
|  | 1471 | def : Pat<(add GR32:$src, -1), (DEC32r    GR32:$src)>, Requires<[In32BitMode]>; | 
|  | 1472 | def : Pat<(add GR32:$src, -1), (DEC64_32r GR32:$src)>, Requires<[In64BitMode]>; | 
|  | 1473 | def : Pat<(add GR64:$src, -1), (DEC64r    GR64:$src)>; | 
|  | 1474 |  | 
|  | 1475 | // or reg/reg. | 
|  | 1476 | def : Pat<(or GR8 :$src1, GR8 :$src2), (OR8rr  GR8 :$src1, GR8 :$src2)>; | 
|  | 1477 | def : Pat<(or GR16:$src1, GR16:$src2), (OR16rr GR16:$src1, GR16:$src2)>; | 
|  | 1478 | def : Pat<(or GR32:$src1, GR32:$src2), (OR32rr GR32:$src1, GR32:$src2)>; | 
|  | 1479 | def : Pat<(or GR64:$src1, GR64:$src2), (OR64rr GR64:$src1, GR64:$src2)>; | 
|  | 1480 |  | 
|  | 1481 | // or reg/mem | 
|  | 1482 | def : Pat<(or GR8:$src1, (loadi8 addr:$src2)), | 
|  | 1483 | (OR8rm GR8:$src1, addr:$src2)>; | 
|  | 1484 | def : Pat<(or GR16:$src1, (loadi16 addr:$src2)), | 
|  | 1485 | (OR16rm GR16:$src1, addr:$src2)>; | 
|  | 1486 | def : Pat<(or GR32:$src1, (loadi32 addr:$src2)), | 
|  | 1487 | (OR32rm GR32:$src1, addr:$src2)>; | 
|  | 1488 | def : Pat<(or GR64:$src1, (loadi64 addr:$src2)), | 
|  | 1489 | (OR64rm GR64:$src1, addr:$src2)>; | 
|  | 1490 |  | 
|  | 1491 | // or reg/imm | 
|  | 1492 | def : Pat<(or GR8:$src1 , imm:$src2), (OR8ri  GR8 :$src1, imm:$src2)>; | 
|  | 1493 | def : Pat<(or GR16:$src1, imm:$src2), (OR16ri GR16:$src1, imm:$src2)>; | 
|  | 1494 | def : Pat<(or GR32:$src1, imm:$src2), (OR32ri GR32:$src1, imm:$src2)>; | 
|  | 1495 | def : Pat<(or GR16:$src1, i16immSExt8:$src2), | 
|  | 1496 | (OR16ri8 GR16:$src1, i16immSExt8:$src2)>; | 
|  | 1497 | def : Pat<(or GR32:$src1, i32immSExt8:$src2), | 
|  | 1498 | (OR32ri8 GR32:$src1, i32immSExt8:$src2)>; | 
|  | 1499 | def : Pat<(or GR64:$src1, i64immSExt8:$src2), | 
|  | 1500 | (OR64ri8 GR64:$src1, i64immSExt8:$src2)>; | 
|  | 1501 | def : Pat<(or GR64:$src1, i64immSExt32:$src2), | 
|  | 1502 | (OR64ri32 GR64:$src1, i64immSExt32:$src2)>; | 
|  | 1503 |  | 
|  | 1504 | // xor reg/reg | 
|  | 1505 | def : Pat<(xor GR8 :$src1, GR8 :$src2), (XOR8rr  GR8 :$src1, GR8 :$src2)>; | 
|  | 1506 | def : Pat<(xor GR16:$src1, GR16:$src2), (XOR16rr GR16:$src1, GR16:$src2)>; | 
|  | 1507 | def : Pat<(xor GR32:$src1, GR32:$src2), (XOR32rr GR32:$src1, GR32:$src2)>; | 
|  | 1508 | def : Pat<(xor GR64:$src1, GR64:$src2), (XOR64rr GR64:$src1, GR64:$src2)>; | 
|  | 1509 |  | 
|  | 1510 | // xor reg/mem | 
|  | 1511 | def : Pat<(xor GR8:$src1, (loadi8 addr:$src2)), | 
|  | 1512 | (XOR8rm GR8:$src1, addr:$src2)>; | 
|  | 1513 | def : Pat<(xor GR16:$src1, (loadi16 addr:$src2)), | 
|  | 1514 | (XOR16rm GR16:$src1, addr:$src2)>; | 
|  | 1515 | def : Pat<(xor GR32:$src1, (loadi32 addr:$src2)), | 
|  | 1516 | (XOR32rm GR32:$src1, addr:$src2)>; | 
|  | 1517 | def : Pat<(xor GR64:$src1, (loadi64 addr:$src2)), | 
|  | 1518 | (XOR64rm GR64:$src1, addr:$src2)>; | 
|  | 1519 |  | 
|  | 1520 | // xor reg/imm | 
|  | 1521 | def : Pat<(xor GR8:$src1, imm:$src2), | 
|  | 1522 | (XOR8ri GR8:$src1, imm:$src2)>; | 
|  | 1523 | def : Pat<(xor GR16:$src1, imm:$src2), | 
|  | 1524 | (XOR16ri GR16:$src1, imm:$src2)>; | 
|  | 1525 | def : Pat<(xor GR32:$src1, imm:$src2), | 
|  | 1526 | (XOR32ri GR32:$src1, imm:$src2)>; | 
|  | 1527 | def : Pat<(xor GR16:$src1, i16immSExt8:$src2), | 
|  | 1528 | (XOR16ri8 GR16:$src1, i16immSExt8:$src2)>; | 
|  | 1529 | def : Pat<(xor GR32:$src1, i32immSExt8:$src2), | 
|  | 1530 | (XOR32ri8 GR32:$src1, i32immSExt8:$src2)>; | 
|  | 1531 | def : Pat<(xor GR64:$src1, i64immSExt8:$src2), | 
|  | 1532 | (XOR64ri8 GR64:$src1, i64immSExt8:$src2)>; | 
|  | 1533 | def : Pat<(xor GR64:$src1, i64immSExt32:$src2), | 
|  | 1534 | (XOR64ri32 GR64:$src1, i64immSExt32:$src2)>; | 
|  | 1535 |  | 
|  | 1536 | // and reg/reg | 
|  | 1537 | def : Pat<(and GR8 :$src1, GR8 :$src2), (AND8rr  GR8 :$src1, GR8 :$src2)>; | 
|  | 1538 | def : Pat<(and GR16:$src1, GR16:$src2), (AND16rr GR16:$src1, GR16:$src2)>; | 
|  | 1539 | def : Pat<(and GR32:$src1, GR32:$src2), (AND32rr GR32:$src1, GR32:$src2)>; | 
|  | 1540 | def : Pat<(and GR64:$src1, GR64:$src2), (AND64rr GR64:$src1, GR64:$src2)>; | 
|  | 1541 |  | 
|  | 1542 | // and reg/mem | 
|  | 1543 | def : Pat<(and GR8:$src1, (loadi8 addr:$src2)), | 
|  | 1544 | (AND8rm GR8:$src1, addr:$src2)>; | 
|  | 1545 | def : Pat<(and GR16:$src1, (loadi16 addr:$src2)), | 
|  | 1546 | (AND16rm GR16:$src1, addr:$src2)>; | 
|  | 1547 | def : Pat<(and GR32:$src1, (loadi32 addr:$src2)), | 
|  | 1548 | (AND32rm GR32:$src1, addr:$src2)>; | 
|  | 1549 | def : Pat<(and GR64:$src1, (loadi64 addr:$src2)), | 
|  | 1550 | (AND64rm GR64:$src1, addr:$src2)>; | 
|  | 1551 |  | 
|  | 1552 | // and reg/imm | 
|  | 1553 | def : Pat<(and GR8:$src1, imm:$src2), | 
|  | 1554 | (AND8ri GR8:$src1, imm:$src2)>; | 
|  | 1555 | def : Pat<(and GR16:$src1, imm:$src2), | 
|  | 1556 | (AND16ri GR16:$src1, imm:$src2)>; | 
|  | 1557 | def : Pat<(and GR32:$src1, imm:$src2), | 
|  | 1558 | (AND32ri GR32:$src1, imm:$src2)>; | 
|  | 1559 | def : Pat<(and GR16:$src1, i16immSExt8:$src2), | 
|  | 1560 | (AND16ri8 GR16:$src1, i16immSExt8:$src2)>; | 
|  | 1561 | def : Pat<(and GR32:$src1, i32immSExt8:$src2), | 
|  | 1562 | (AND32ri8 GR32:$src1, i32immSExt8:$src2)>; | 
|  | 1563 | def : Pat<(and GR64:$src1, i64immSExt8:$src2), | 
|  | 1564 | (AND64ri8 GR64:$src1, i64immSExt8:$src2)>; | 
|  | 1565 | def : Pat<(and GR64:$src1, i64immSExt32:$src2), | 
|  | 1566 | (AND64ri32 GR64:$src1, i64immSExt32:$src2)>; | 
| Chris Lattner | ae33f5d | 2010-10-05 06:04:14 +0000 | [diff] [blame] | 1567 |  |