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