Mark re-materializable instructions.
[oota-llvm.git] / lib / Target / X86 / X86InstrInfo.td
index e195f0fb15031e99f9b5d35388d079c550623ca9..fd08e477014276574837c90fe71454e7cb796dbf 100644 (file)
@@ -39,7 +39,7 @@ def SDT_X86CallSeqStart : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>;
 def SDT_X86CallSeqEnd   : SDTypeProfile<0, 2, [ SDTCisVT<0, i32>,
                                                 SDTCisVT<1, i32> ]>;
 
-def SDT_X86Call   : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
+def SDT_X86Call   : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
 
 def SDTX86RepStr  : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>;
 
@@ -51,9 +51,7 @@ def X86shld    : SDNode<"X86ISD::SHLD",     SDTIntShiftDOp>;
 def X86shrd    : SDNode<"X86ISD::SHRD",     SDTIntShiftDOp>;
 
 def X86cmp     : SDNode<"X86ISD::CMP" ,     SDTX86CmpTest,
-                        [SDNPOutFlag]>;
-def X86test    : SDNode<"X86ISD::TEST",     SDTX86CmpTest,
-                        [SDNPOutFlag]>;
+                        [SDNPHasChain, SDNPOutFlag]>;
 
 def X86cmov    : SDNode<"X86ISD::CMOV",     SDTX86Cmov,    
                         [SDNPInFlag, SDNPOutFlag]>;
@@ -67,7 +65,7 @@ def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret,
 
 def X86callseq_start :
                  SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart,
-                        [SDNPHasChain]>;
+                        [SDNPHasChain, SDNPOutFlag]>;
 def X86callseq_end :
                  SDNode<"ISD::CALLSEQ_END",   SDT_X86CallSeqEnd,
                         [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
@@ -86,7 +84,8 @@ def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr,
 def X86rdtsc   : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc,
                         [SDNPHasChain, SDNPOutFlag]>;
 
-def X86Wrapper : SDNode<"X86ISD::Wrapper",  SDTX86Wrapper>;
+def X86Wrapper    : SDNode<"X86ISD::Wrapper",     SDTX86Wrapper>;
+def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP",  SDTX86Wrapper>;
 
 //===----------------------------------------------------------------------===//
 // X86 Operand Definitions.
@@ -96,8 +95,7 @@ def X86Wrapper : SDNode<"X86ISD::Wrapper",  SDTX86Wrapper>;
 //
 class X86MemOperand<string printMethod> : Operand<iPTR> {
   let PrintMethod = printMethod;
-  let NumMIOperands = 4;
-  let MIOperandInfo = (ops GR32, i8imm, GR32, i32imm);
+  let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc, i32imm);
 }
 
 def i8mem   : X86MemOperand<"printi8mem">;
@@ -109,6 +107,11 @@ def f32mem  : X86MemOperand<"printf32mem">;
 def f64mem  : X86MemOperand<"printf64mem">;
 def f128mem : X86MemOperand<"printf128mem">;
 
+def lea32mem : Operand<i32> {
+  let PrintMethod = "printi32mem";
+  let MIOperandInfo = (ops GR32, i8imm, GR32, i32imm);
+}
+
 def SSECC : Operand<i8> {
   let PrintMethod = "printSSECC";
 }
@@ -131,9 +134,9 @@ def brtarget : Operand<OtherVT>;
 //
 
 // Define X86 specific addressing mode.
-def addr    : ComplexPattern<iPTR, 4, "SelectAddr", []>;
-def leaaddr : ComplexPattern<iPTR, 4, "SelectLEAAddr",
-                             [add, mul, shl, or, frameindex]>;
+def addr      : ComplexPattern<iPTR, 4, "SelectAddr", [], []>;
+def lea32addr : ComplexPattern<i32, 4, "SelectLEAAddr",
+                               [add, mul, shl, or, frameindex], []>;
 
 //===----------------------------------------------------------------------===//
 // X86 Instruction Format Definitions.
@@ -160,11 +163,16 @@ def MRMInitReg : Format<32>;
 
 //===----------------------------------------------------------------------===//
 // X86 Instruction Predicate Definitions.
-def HasMMX  : Predicate<"Subtarget->hasMMX()">;
-def HasSSE1 : Predicate<"Subtarget->hasSSE1()">;
-def HasSSE2 : Predicate<"Subtarget->hasSSE2()">;
-def HasSSE3 : Predicate<"Subtarget->hasSSE3()">;
-def FPStack : Predicate<"!Subtarget->hasSSE2()">;
+def HasMMX       : Predicate<"Subtarget->hasMMX()">;
+def HasSSE1      : Predicate<"Subtarget->hasSSE1()">;
+def HasSSE2      : Predicate<"Subtarget->hasSSE2()">;
+def HasSSE3      : Predicate<"Subtarget->hasSSE3()">;
+def FPStack      : Predicate<"!Subtarget->hasSSE2()">;
+def In32BitMode  : Predicate<"!Subtarget->is64Bit()">;
+def In64BitMode  : Predicate<"Subtarget->is64Bit()">;
+def SmallCode    : Predicate<"TM.getCodeModel() == CodeModel::Small">;
+def NotSmallCode : Predicate<"TM.getCodeModel() != CodeModel::Small">;
+def IsStatic     : Predicate<"TM.getRelocationModel() == Reloc::Static">;
 
 //===----------------------------------------------------------------------===//
 // X86 specific pattern fragments.
@@ -173,13 +181,14 @@ def FPStack : Predicate<"!Subtarget->hasSSE2()">;
 // ImmType - This specifies the immediate type used by an instruction. This is
 // part of the ad-hoc solution used to emit machine instruction encodings by our
 // machine code emitter.
-class ImmType<bits<2> val> {
-  bits<2> Value = val;
+class ImmType<bits<3> val> {
+  bits<3> Value = val;
 }
 def NoImm  : ImmType<0>;
 def Imm8   : ImmType<1>;
 def Imm16  : ImmType<2>;
 def Imm32  : ImmType<3>;
+def Imm64  : ImmType<4>;
 
 // FPFormat - This specifies what form this FP instruction has.  This is used by
 // the Floating-Point stackifier pass.
@@ -204,7 +213,7 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag ops, string AsmStr>
   Format Form = f;
   bits<6> FormBits = Form.Value;
   ImmType ImmT = i;
-  bits<2> ImmTypeBits = ImmT.Value;
+  bits<3> ImmTypeBits = ImmT.Value;
 
   dag OperandList = ops;
   string AsmString = AsmStr;
@@ -212,22 +221,21 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag ops, string AsmStr>
   //
   // Attributes specific to X86 instructions...
   //
-  bit hasOpSizePrefix = 0; // Does this inst have a 0x66 prefix?
+  bit hasOpSizePrefix = 0;  // Does this inst have a 0x66 prefix?
+  bit hasAdSizePrefix = 0;  // Does this inst have a 0x67 prefix?
 
   bits<4> Prefix = 0;       // Which prefix byte does this inst have?
+  bit hasREX_WPrefix  = 0;  // Does this inst requires the REX.W prefix?
   FPFormat FPForm;          // What flavor of FP instruction is this?
   bits<3> FPFormBits = 0;
 }
 
-class Imp<list<Register> uses, list<Register> defs> {
-  list<Register> Uses = uses;
-  list<Register> Defs = defs;
-}
-
 
 // Prefix byte classes which are used to indicate to the ad-hoc machine code
 // emitter that various prefix bytes are required.
 class OpSize { bit hasOpSizePrefix = 1; }
+class AdSize { bit hasAdSizePrefix = 1; }
+class REX_W  { bit hasREX_WPrefix = 1; }
 class TB     { bits<4> Prefix = 1; }
 class REP    { bits<4> Prefix = 2; }
 class D8     { bits<4> Prefix = 3; }
@@ -277,15 +285,7 @@ def i32immSExt8  : PatLeaf<(i32 imm), [{
   return (int32_t)N->getValue() == (int8_t)N->getValue();
 }]>;
 
-def i16immZExt8  : PatLeaf<(i16 imm), [{
-  // i16immZExt8 predicate - True if the 16-bit immediate fits in a 8-bit zero
-  // extended field.
-  return (uint16_t)N->getValue() == (uint8_t)N->getValue();
-}]>;
-
 // Helper fragments for loads.
-def loadiPTR : PatFrag<(ops node:$ptr), (iPTR (load node:$ptr))>;
-
 def loadi8  : PatFrag<(ops node:$ptr), (i8  (load node:$ptr))>;
 def loadi16 : PatFrag<(ops node:$ptr), (i16 (load node:$ptr))>;
 def loadi32 : PatFrag<(ops node:$ptr), (i32 (load node:$ptr))>;
@@ -294,55 +294,64 @@ def loadi64 : PatFrag<(ops node:$ptr), (i64 (load node:$ptr))>;
 def loadf32 : PatFrag<(ops node:$ptr), (f32 (load node:$ptr))>;
 def loadf64 : PatFrag<(ops node:$ptr), (f64 (load node:$ptr))>;
 
-def sextloadi16i1  : PatFrag<(ops node:$ptr), (i16 (sextload node:$ptr, i1))>;
-def sextloadi32i1  : PatFrag<(ops node:$ptr), (i32 (sextload node:$ptr, i1))>;
-def sextloadi16i8  : PatFrag<(ops node:$ptr), (i16 (sextload node:$ptr, i8))>;
-def sextloadi32i8  : PatFrag<(ops node:$ptr), (i32 (sextload node:$ptr, i8))>;
-def sextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextload node:$ptr, i16))>;
-
-def zextloadi8i1   : PatFrag<(ops node:$ptr), (i8  (zextload node:$ptr, i1))>;
-def zextloadi16i1  : PatFrag<(ops node:$ptr), (i16 (zextload node:$ptr, i1))>;
-def zextloadi32i1  : PatFrag<(ops node:$ptr), (i32 (zextload node:$ptr, i1))>;
-def zextloadi16i8  : PatFrag<(ops node:$ptr), (i16 (zextload node:$ptr, i8))>;
-def zextloadi32i8  : PatFrag<(ops node:$ptr), (i32 (zextload node:$ptr, i8))>;
-def zextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextload node:$ptr, i16))>;
-
-def extloadi8i1    : PatFrag<(ops node:$ptr), (i8  (extload node:$ptr, i1))>;
-def extloadi16i1   : PatFrag<(ops node:$ptr), (i16 (extload node:$ptr, i1))>;
-def extloadi32i1   : PatFrag<(ops node:$ptr), (i32 (extload node:$ptr, i1))>;
-def extloadi16i8   : PatFrag<(ops node:$ptr), (i16 (extload node:$ptr, i8))>;
-def extloadi32i8   : PatFrag<(ops node:$ptr), (i32 (extload node:$ptr, i8))>;
-def extloadi32i16  : PatFrag<(ops node:$ptr), (i32 (extload node:$ptr, i16))>;
+def sextloadi16i1  : PatFrag<(ops node:$ptr), (i16 (sextloadi1 node:$ptr))>;
+def sextloadi32i1  : PatFrag<(ops node:$ptr), (i32 (sextloadi1 node:$ptr))>;
+def sextloadi16i8  : PatFrag<(ops node:$ptr), (i16 (sextloadi8 node:$ptr))>;
+def sextloadi32i8  : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>;
+def sextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextloadi16 node:$ptr))>;
+
+def zextloadi8i1   : PatFrag<(ops node:$ptr), (i8  (zextloadi1 node:$ptr))>;
+def zextloadi16i1  : PatFrag<(ops node:$ptr), (i16 (zextloadi1 node:$ptr))>;
+def zextloadi32i1  : PatFrag<(ops node:$ptr), (i32 (zextloadi1 node:$ptr))>;
+def zextloadi16i8  : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>;
+def zextloadi32i8  : PatFrag<(ops node:$ptr), (i32 (zextloadi8 node:$ptr))>;
+def zextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextloadi16 node:$ptr))>;
+
+def extloadi8i1    : PatFrag<(ops node:$ptr), (i8  (extloadi1 node:$ptr))>;
+def extloadi16i1   : PatFrag<(ops node:$ptr), (i16 (extloadi1 node:$ptr))>;
+def extloadi32i1   : PatFrag<(ops node:$ptr), (i32 (extloadi1 node:$ptr))>;
+def extloadi16i8   : PatFrag<(ops node:$ptr), (i16 (extloadi8 node:$ptr))>;
+def extloadi32i8   : PatFrag<(ops node:$ptr), (i32 (extloadi8 node:$ptr))>;
+def extloadi32i16  : PatFrag<(ops node:$ptr), (i32 (extloadi16 node:$ptr))>;
 
 //===----------------------------------------------------------------------===//
 // Instruction templates...
+//
 
 class I<bits<8> o, Format f, dag ops, string asm, list<dag> pattern>
   : X86Inst<o, f, NoImm, ops, asm> {
   let Pattern = pattern;
+  let CodeSize = 3;
 }
 class Ii8 <bits<8> o, Format f, dag ops, string asm, list<dag> pattern>
   : X86Inst<o, f, Imm8 , ops, asm> {
   let Pattern = pattern;
+  let CodeSize = 3;
 }
 class Ii16<bits<8> o, Format f, dag ops, string asm, list<dag> pattern>
   : X86Inst<o, f, Imm16, ops, asm> {
   let Pattern = pattern;
+  let CodeSize = 3;
 }
 class Ii32<bits<8> o, Format f, dag ops, string asm, list<dag> pattern>
   : X86Inst<o, f, Imm32, ops, asm> {
   let Pattern = pattern;
+  let CodeSize = 3;
 }
 
 //===----------------------------------------------------------------------===//
 // Instruction list...
 //
 
+// ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into
+// a stack adjustment and the codegen must know that they may modify the stack
+// pointer before prolog-epilog rewriting occurs.
 def ADJCALLSTACKDOWN : I<0, Pseudo, (ops i32imm:$amt), "#ADJCALLSTACKDOWN",
-                         [(X86callseq_start imm:$amt)]>;
+                         [(X86callseq_start imm:$amt)]>, Imp<[ESP],[ESP]>;
 def ADJCALLSTACKUP   : I<0, Pseudo, (ops i32imm:$amt1, i32imm:$amt2),
                          "#ADJCALLSTACKUP",
-                         [(X86callseq_end imm:$amt1, imm:$amt2)]>;
+                         [(X86callseq_end imm:$amt1, imm:$amt2)]>,
+                         Imp<[ESP],[ESP]>;
 def IMPLICIT_USE     : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_USE", []>;
 def IMPLICIT_DEF     : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_DEF", []>;
 def IMPLICIT_DEF_GR8  : I<0, Pseudo, (ops GR8:$dst),
@@ -359,13 +368,13 @@ def IMPLICIT_DEF_GR32  : I<0, Pseudo, (ops GR32:$dst),
 def NOOP : I<0x90, RawFrm, (ops), "nop", []>;
 
 // Truncate
-def TRUNC_GR32_GR8  : I<0x88, MRMDestReg, (ops GR8:$dst, GR32_:$src),
-                      "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}", []>;
-def TRUNC_GR16_GR8  : I<0x88, MRMDestReg, (ops GR8:$dst, GR16_:$src),
-                      "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}}", []>;
-def TRUNC_GR32_GR16 : I<0x89, MRMDestReg, (ops GR16:$dst, GR32:$src),
-                      "mov{w} {${src:subreg16}, $dst|$dst, ${src:subreg16}}",
-                      [(set GR16:$dst, (trunc GR32:$src))]>;
+def TRUNC_32_to8 : I<0x88, MRMDestReg, (ops GR8:$dst, GR32_:$src),
+                     "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}", []>;
+def TRUNC_16_to8 : I<0x88, MRMDestReg, (ops GR8:$dst, GR16_:$src),
+                     "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}}", []>;
+def TRUNC_32to16 : I<0x89, MRMDestReg, (ops GR16:$dst, GR32:$src),
+                     "mov{w} {${src:subreg16}, $dst|$dst, ${src:subreg16}}",
+                     [(set GR16:$dst, (trunc GR32:$src))]>;
 
 //===----------------------------------------------------------------------===//
 //  Control Flow Instructions...
@@ -385,14 +394,14 @@ let isBranch = 1, isTerminator = 1, noResults = 1 in
         I<opcode, RawFrm, ops, asm, pattern>;
 
 // Indirect branches
-let isBarrier = 1 in
+let isBranch = 1, isBarrier = 1 in
   def JMP : IBr<0xE9, (ops brtarget:$dst), "jmp $dst", [(br bb:$dst)]>;
 
 let isBranch = 1, isTerminator = 1, noResults = 1, isBarrier = 1 in {
   def JMP32r     : I<0xFF, MRM4r, (ops GR32:$dst), "jmp{l} {*}$dst",
                      [(brind GR32:$dst)]>;
   def JMP32m     : I<0xFF, MRM4m, (ops i32mem:$dst), "jmp{l} {*}$dst",
-                     [(brind (loadiPTR addr:$dst))]>;
+                     [(brind (loadi32 addr:$dst))]>;
 }
 
 // Conditional branches
@@ -448,22 +457,15 @@ let isCall = 1, noResults = 1 in
 
 // Tail call stuff.
 let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, noResults = 1 in
-  def TAILJMPd : IBr<0xE9, (ops i32imm:$dst), "jmp ${dst:call}  # TAIL CALL", []>;
+  def TAILJMPd : IBr<0xE9, (ops i32imm:$dst), "jmp ${dst:call}  # TAIL CALL",
+                 []>;
 let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, noResults = 1 in
-  def TAILJMPr : I<0xFF, MRM4r, (ops GR32:$dst), "jmp {*}$dst  # TAIL CALL", []>;
+  def TAILJMPr : I<0xFF, MRM4r, (ops GR32:$dst), "jmp {*}$dst  # TAIL CALL",
+                 []>;
 let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, noResults = 1 in
   def TAILJMPm : I<0xFF, MRM4m, (ops i32mem:$dst),
                    "jmp {*}$dst  # TAIL CALL", []>;
 
-// ADJSTACKPTRri - This is a standard ADD32ri instruction, identical in every
-// way, except that it is marked as being a terminator.  This causes the epilog
-// inserter to insert reloads of callee saved registers BEFORE this.  We need
-// this until we have a more accurate way of tracking where the stack pointer is
-// within a function.
-let isTerminator = 1, isTwoAddress = 1 in
-  def ADJSTACKPTRri : Ii32<0x81, MRM0r, (ops GR32:$dst, GR32:$src1, i32imm:$src2),
-                           "add{l} {$src2, $dst|$dst, $src2}", []>;
-
 //===----------------------------------------------------------------------===//
 //  Miscellaneous Instructions...
 //
@@ -514,9 +516,9 @@ def LEA16r   : I<0x8D, MRMSrcMem,
                  (ops GR16:$dst, i32mem:$src),
                  "lea{w} {$src|$dst}, {$dst|$src}", []>, OpSize;
 def LEA32r   : I<0x8D, MRMSrcMem,
-                 (ops GR32:$dst, i32mem:$src),
+                 (ops GR32:$dst, lea32mem:$src),
                  "lea{l} {$src|$dst}, {$dst|$src}",
-                 [(set GR32:$dst, leaaddr:$src)]>;
+                 [(set GR32:$dst, lea32addr:$src)]>, Requires<[In32BitMode]>;
 
 def REP_MOVSB : I<0xA4, RawFrm, (ops), "{rep;movsb|rep movsb}",
                   [(X86rep_movs i8)]>,
@@ -538,6 +540,8 @@ def REP_STOSD : I<0xAB, RawFrm, (ops), "{rep;stosl|rep stosd}",
                   [(X86rep_stos i32)]>,
                 Imp<[EAX,ECX,EDI], [ECX,EDI]>, REP;
 
+def RDTSC : I<0x31, RawFrm, (ops), "rdtsc", [(X86rdtsc)]>,
+            TB, Imp<[],[RAX,RDX]>;
 
 //===----------------------------------------------------------------------===//
 //  Input/Output Instructions...
@@ -597,6 +601,7 @@ def MOV16rr : I<0x89, MRMDestReg, (ops GR16:$dst, GR16:$src),
                 "mov{w} {$src, $dst|$dst, $src}", []>, OpSize;
 def MOV32rr : I<0x89, MRMDestReg, (ops GR32:$dst, GR32:$src),
                 "mov{l} {$src, $dst|$dst, $src}", []>;
+let isReMaterializable = 1 in {
 def MOV8ri  : Ii8 <0xB0, AddRegFrm, (ops GR8 :$dst, i8imm :$src),
                    "mov{b} {$src, $dst|$dst, $src}",
                    [(set GR8:$dst, imm:$src)]>;
@@ -606,6 +611,7 @@ def MOV16ri : Ii16<0xB8, AddRegFrm, (ops GR16:$dst, i16imm:$src),
 def MOV32ri : Ii32<0xB8, AddRegFrm, (ops GR32:$dst, i32imm:$src),
                    "mov{l} {$src, $dst|$dst, $src}",
                    [(set GR32:$dst, imm:$src)]>;
+}
 def MOV8mi  : Ii8 <0xC6, MRM0m, (ops i8mem :$dst, i8imm :$src),
                    "mov{b} {$src, $dst|$dst, $src}",
                    [(store (i8 imm:$src), addr:$dst)]>;
@@ -1066,6 +1072,7 @@ def CMOVNP32rm : I<0x4B, MRMSrcMem,       // if !parity, GR32 = [mem32]
 
 
 // unary instructions
+let CodeSize = 2 in {
 def NEG8r  : I<0xF6, MRM3r, (ops GR8 :$dst, GR8 :$src), "neg{b} $dst",
                [(set GR8:$dst, (ineg GR8:$src))]>;
 def NEG16r : I<0xF7, MRM3r, (ops GR16:$dst, GR16:$src), "neg{w} $dst",
@@ -1096,17 +1103,20 @@ let isTwoAddress = 0 in {
   def NOT32m : I<0xF7, MRM2m, (ops i32mem:$dst), "not{l} $dst",
                  [(store (not (loadi32 addr:$dst)), addr:$dst)]>;
 }
+} // CodeSize
 
 // TODO: inc/dec is slow for P4, but fast for Pentium-M.
+let CodeSize = 2 in
 def INC8r  : I<0xFE, MRM0r, (ops GR8 :$dst, GR8 :$src), "inc{b} $dst",
                [(set GR8:$dst, (add GR8:$src, 1))]>;
-let isConvertibleToThreeAddress = 1 in {   // Can transform into LEA.
-def INC16r : I<0xFF, MRM0r, (ops GR16:$dst, GR16:$src), "inc{w} $dst",
-               [(set GR16:$dst, (add GR16:$src, 1))]>, OpSize;
-def INC32r : I<0xFF, MRM0r, (ops GR32:$dst, GR32:$src), "inc{l} $dst",
-               [(set GR32:$dst, (add GR32:$src, 1))]>;
+let isConvertibleToThreeAddress = 1, CodeSize = 1 in {  // Can xform into LEA.
+def INC16r : I<0x40, AddRegFrm, (ops GR16:$dst, GR16:$src), "inc{w} $dst",
+               [(set GR16:$dst, (add GR16:$src, 1))]>,
+             OpSize, Requires<[In32BitMode]>;
+def INC32r : I<0x40, AddRegFrm, (ops GR32:$dst, GR32:$src), "inc{l} $dst",
+               [(set GR32:$dst, (add GR32:$src, 1))]>, Requires<[In32BitMode]>;
 }
-let isTwoAddress = 0 in {
+let isTwoAddress = 0, CodeSize = 2 in {
   def INC8m  : I<0xFE, MRM0m, (ops i8mem :$dst), "inc{b} $dst",
                [(store (add (loadi8 addr:$dst), 1), addr:$dst)]>;
   def INC16m : I<0xFF, MRM0m, (ops i16mem:$dst), "inc{w} $dst",
@@ -1115,16 +1125,18 @@ let isTwoAddress = 0 in {
                [(store (add (loadi32 addr:$dst), 1), addr:$dst)]>;
 }
 
+let CodeSize = 2 in
 def DEC8r  : I<0xFE, MRM1r, (ops GR8 :$dst, GR8 :$src), "dec{b} $dst",
                [(set GR8:$dst, (add GR8:$src, -1))]>;
-let isConvertibleToThreeAddress = 1 in {   // Can transform into LEA.
-def DEC16r : I<0xFF, MRM1r, (ops GR16:$dst, GR16:$src), "dec{w} $dst",
-               [(set GR16:$dst, (add GR16:$src, -1))]>, OpSize;
-def DEC32r : I<0xFF, MRM1r, (ops GR32:$dst, GR32:$src), "dec{l} $dst",
-               [(set GR32:$dst, (add GR32:$src, -1))]>;
+let isConvertibleToThreeAddress = 1, CodeSize = 1 in {   // Can xform into LEA.
+def DEC16r : I<0x48, AddRegFrm, (ops GR16:$dst, GR16:$src), "dec{w} $dst",
+               [(set GR16:$dst, (add GR16:$src, -1))]>,
+             OpSize, Requires<[In32BitMode]>;
+def DEC32r : I<0x48, AddRegFrm, (ops GR32:$dst, GR32:$src), "dec{l} $dst",
+               [(set GR32:$dst, (add GR32:$src, -1))]>, Requires<[In32BitMode]>;
 }
 
-let isTwoAddress = 0 in {
+let isTwoAddress = 0, CodeSize = 2 in {
   def DEC8m  : I<0xFE, MRM1m, (ops i8mem :$dst), "dec{b} $dst",
                [(store (add (loadi8 addr:$dst), -1), addr:$dst)]>;
   def DEC16m : I<0xFF, MRM1m, (ops i16mem:$dst), "dec{w} $dst",
@@ -1400,6 +1412,14 @@ def SHL32ri  : Ii8<0xC1, MRM4r, (ops GR32:$dst, GR32:$src1, i8imm:$src2),
                    [(set GR32:$dst, (shl GR32:$src1, (i8 imm:$src2)))]>;
 }
 
+// Shift left by one. Not used because (add x, x) is slightly cheaper.
+def SHL8r1   : I<0xD0, MRM4r, (ops GR8 :$dst, GR8 :$src1),
+                 "shl{b} $dst", []>;
+def SHL16r1  : I<0xD1, MRM4r, (ops GR16:$dst, GR16:$src1),
+                 "shl{w} $dst", []>, OpSize;
+def SHL32r1  : I<0xD1, MRM4r, (ops GR32:$dst, GR32:$src1),
+                 "shl{l} $dst", []>;
+
 let isTwoAddress = 0 in {
   def SHL8mCL  : I<0xD2, MRM4m, (ops i8mem :$dst),
                    "shl{b} {%cl, $dst|$dst, %CL}",
@@ -1423,6 +1443,18 @@ let isTwoAddress = 0 in {
   def SHL32mi  : Ii8<0xC1, MRM4m, (ops i32mem:$dst, i8imm:$src),
                      "shl{l} {$src, $dst|$dst, $src}",
                  [(store (shl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>;
+
+  // Shift by 1
+  def SHL8m1   : I<0xD0, MRM4m, (ops i8mem :$dst),
+                   "shl{b} $dst",
+                  [(store (shl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>;
+  def SHL16m1  : I<0xD1, MRM4m, (ops i16mem:$dst),
+                   "shl{w} $dst",
+                 [(store (shl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>,
+                     OpSize;
+  def SHL32m1  : I<0xD1, MRM4m, (ops i32mem:$dst),
+                   "shl{l} $dst",
+                 [(store (shl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>;
 }
 
 def SHR8rCL  : I<0xD2, MRM5r, (ops GR8 :$dst, GR8 :$src),
@@ -1445,6 +1477,17 @@ def SHR32ri  : Ii8<0xC1, MRM5r, (ops GR32:$dst, GR32:$src1, i8imm:$src2),
                    "shr{l} {$src2, $dst|$dst, $src2}",
                    [(set GR32:$dst, (srl GR32:$src1, (i8 imm:$src2)))]>;
 
+// Shift by 1
+def SHR8r1   : I<0xD0, MRM5r, (ops GR8:$dst, GR8:$src1),
+                 "shr{b} $dst",
+                 [(set GR8:$dst, (srl GR8:$src1, (i8 1)))]>;
+def SHR16r1  : I<0xD1, MRM5r, (ops GR16:$dst, GR16:$src1),
+                 "shr{w} $dst",
+                 [(set GR16:$dst, (srl GR16:$src1, (i8 1)))]>, OpSize;
+def SHR32r1  : I<0xD1, MRM5r, (ops GR32:$dst, GR32:$src1),
+                 "shr{l} $dst",
+                 [(set GR32:$dst, (srl GR32:$src1, (i8 1)))]>;
+
 let isTwoAddress = 0 in {
   def SHR8mCL  : I<0xD2, MRM5m, (ops i8mem :$dst),
                    "shr{b} {%cl, $dst|$dst, %CL}",
@@ -1468,6 +1511,17 @@ let isTwoAddress = 0 in {
   def SHR32mi  : Ii8<0xC1, MRM5m, (ops i32mem:$dst, i8imm:$src),
                      "shr{l} {$src, $dst|$dst, $src}",
                  [(store (srl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>;
+
+  // Shift by 1
+  def SHR8m1   : I<0xD0, MRM5m, (ops i8mem :$dst),
+                   "shr{b} $dst",
+                  [(store (srl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>;
+  def SHR16m1  : I<0xD1, MRM5m, (ops i16mem:$dst),
+                   "shr{w} $dst",
+                 [(store (srl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>,OpSize;
+  def SHR32m1  : I<0xD1, MRM5m, (ops i32mem:$dst),
+                   "shr{l} $dst",
+                 [(store (srl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>;
 }
 
 def SAR8rCL  : I<0xD2, MRM7r, (ops GR8 :$dst, GR8 :$src),
@@ -1490,6 +1544,18 @@ def SAR16ri  : Ii8<0xC1, MRM7r, (ops GR16:$dst, GR16:$src1, i8imm:$src2),
 def SAR32ri  : Ii8<0xC1, MRM7r, (ops GR32:$dst, GR32:$src1, i8imm:$src2),
                    "sar{l} {$src2, $dst|$dst, $src2}",
                    [(set GR32:$dst, (sra GR32:$src1, (i8 imm:$src2)))]>;
+
+// Shift by 1
+def SAR8r1   : I<0xD0, MRM7r, (ops GR8 :$dst, GR8 :$src1),
+                 "sar{b} $dst",
+                 [(set GR8:$dst, (sra GR8:$src1, (i8 1)))]>;
+def SAR16r1  : I<0xD1, MRM7r, (ops GR16:$dst, GR16:$src1),
+                 "sar{w} $dst",
+                 [(set GR16:$dst, (sra GR16:$src1, (i8 1)))]>, OpSize;
+def SAR32r1  : I<0xD1, MRM7r, (ops GR32:$dst, GR32:$src1),
+                 "sar{l} $dst",
+                 [(set GR32:$dst, (sra GR32:$src1, (i8 1)))]>;
+
 let isTwoAddress = 0 in {
   def SAR8mCL  : I<0xD2, MRM7m, (ops i8mem :$dst),
                    "sar{b} {%cl, $dst|$dst, %CL}",
@@ -1513,6 +1579,18 @@ let isTwoAddress = 0 in {
   def SAR32mi  : Ii8<0xC1, MRM7m, (ops i32mem:$dst, i8imm:$src),
                      "sar{l} {$src, $dst|$dst, $src}",
                  [(store (sra (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>;
+
+  // Shift by 1
+  def SAR8m1   : I<0xD0, MRM7m, (ops i8mem :$dst),
+                   "sar{b} $dst",
+                  [(store (sra (loadi8 addr:$dst), (i8 1)), addr:$dst)]>;
+  def SAR16m1  : I<0xD1, MRM7m, (ops i16mem:$dst),
+                   "sar{w} $dst",
+                 [(store (sra (loadi16 addr:$dst), (i8 1)), addr:$dst)]>,
+                     OpSize;
+  def SAR32m1  : I<0xD1, MRM7m, (ops i32mem:$dst),
+                   "sar{l} $dst",
+                 [(store (sra (loadi32 addr:$dst), (i8 1)), addr:$dst)]>;
 }
 
 // Rotate instructions
@@ -1537,6 +1615,17 @@ def ROL32ri  : Ii8<0xC1, MRM0r, (ops GR32:$dst, GR32:$src1, i8imm:$src2),
                    "rol{l} {$src2, $dst|$dst, $src2}",
                    [(set GR32:$dst, (rotl GR32:$src1, (i8 imm:$src2)))]>;
 
+// Rotate by 1
+def ROL8r1   : I<0xD0, MRM0r, (ops GR8 :$dst, GR8 :$src1),
+                 "rol{b} $dst",
+                 [(set GR8:$dst, (rotl GR8:$src1, (i8 1)))]>;
+def ROL16r1  : I<0xD1, MRM0r, (ops GR16:$dst, GR16:$src1),
+                 "rol{w} $dst",
+                 [(set GR16:$dst, (rotl GR16:$src1, (i8 1)))]>, OpSize;
+def ROL32r1  : I<0xD1, MRM0r, (ops GR32:$dst, GR32:$src1),
+                 "rol{l} $dst",
+                 [(set GR32:$dst, (rotl GR32:$src1, (i8 1)))]>;
+
 let isTwoAddress = 0 in {
   def ROL8mCL  : I<0xD2, MRM0m, (ops i8mem :$dst),
                    "rol{b} {%cl, $dst|$dst, %CL}",
@@ -1560,6 +1649,18 @@ let isTwoAddress = 0 in {
   def ROL32mi  : Ii8<0xC1, MRM0m, (ops i32mem:$dst, i8imm:$src),
                      "rol{l} {$src, $dst|$dst, $src}",
                 [(store (rotl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>;
+
+  // Rotate by 1
+  def ROL8m1   : I<0xD0, MRM0m, (ops i8mem :$dst),
+                   "rol{b} $dst",
+                 [(store (rotl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>;
+  def ROL16m1  : I<0xD1, MRM0m, (ops i16mem:$dst),
+                   "rol{w} $dst",
+                [(store (rotl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>,
+                     OpSize;
+  def ROL32m1  : I<0xD1, MRM0m, (ops i32mem:$dst),
+                   "rol{l} $dst",
+                [(store (rotl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>;
 }
 
 def ROR8rCL  : I<0xD2, MRM1r, (ops GR8 :$dst, GR8 :$src),
@@ -1581,6 +1682,18 @@ def ROR16ri  : Ii8<0xC1, MRM1r, (ops GR16:$dst, GR16:$src1, i8imm:$src2),
 def ROR32ri  : Ii8<0xC1, MRM1r, (ops GR32:$dst, GR32:$src1, i8imm:$src2),
                    "ror{l} {$src2, $dst|$dst, $src2}",
                    [(set GR32:$dst, (rotr GR32:$src1, (i8 imm:$src2)))]>;
+
+// Rotate by 1
+def ROR8r1   : I<0xD0, MRM1r, (ops GR8 :$dst, GR8 :$src1),
+                 "ror{b} $dst",
+                 [(set GR8:$dst, (rotr GR8:$src1, (i8 1)))]>;
+def ROR16r1  : I<0xD1, MRM1r, (ops GR16:$dst, GR16:$src1),
+                 "ror{w} $dst",
+                 [(set GR16:$dst, (rotr GR16:$src1, (i8 1)))]>, OpSize;
+def ROR32r1  : I<0xD1, MRM1r, (ops GR32:$dst, GR32:$src1),
+                 "ror{l} $dst",
+                 [(set GR32:$dst, (rotr GR32:$src1, (i8 1)))]>;
+
 let isTwoAddress = 0 in {
   def ROR8mCL  : I<0xD2, MRM1m, (ops i8mem :$dst),
                    "ror{b} {%cl, $dst|$dst, %CL}",
@@ -1604,6 +1717,18 @@ let isTwoAddress = 0 in {
   def ROR32mi  : Ii8<0xC1, MRM1m, (ops i32mem:$dst, i8imm:$src),
                      "ror{l} {$src, $dst|$dst, $src}",
                 [(store (rotr (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>;
+
+  // Rotate by 1
+  def ROR8m1   : I<0xD0, MRM1m, (ops i8mem :$dst),
+                   "ror{b} $dst",
+                 [(store (rotr (loadi8 addr:$dst), (i8 1)), addr:$dst)]>;
+  def ROR16m1  : I<0xD1, MRM1m, (ops i16mem:$dst),
+                   "ror{w} $dst",
+                [(store (rotr (loadi16 addr:$dst), (i8 1)), addr:$dst)]>,
+                     OpSize;
+  def ROR32m1  : I<0xD1, MRM1m, (ops i32mem:$dst),
+                   "ror{l} $dst",
+                [(store (rotr (loadi32 addr:$dst), (i8 1)), addr:$dst)]>;
 }
 
 
@@ -1958,60 +2083,52 @@ def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem,                       // GR32 = [mem32]*I8
 let isCommutable = 1 in {   // TEST X, Y   --> TEST Y, X
 def TEST8rr  : I<0x84, MRMDestReg, (ops GR8:$src1, GR8:$src2),
                  "test{b} {$src2, $src1|$src1, $src2}",
-                 [(X86test GR8:$src1, GR8:$src2)]>;
+                 [(X86cmp (and GR8:$src1, GR8:$src2), 0)]>;
 def TEST16rr : I<0x85, MRMDestReg, (ops GR16:$src1, GR16:$src2),
                  "test{w} {$src2, $src1|$src1, $src2}",
-                 [(X86test GR16:$src1, GR16:$src2)]>, OpSize;
+                 [(X86cmp (and GR16:$src1, GR16:$src2), 0)]>, OpSize;
 def TEST32rr : I<0x85, MRMDestReg, (ops GR32:$src1, GR32:$src2),
                  "test{l} {$src2, $src1|$src1, $src2}",
-                 [(X86test GR32:$src1, GR32:$src2)]>;
+                 [(X86cmp (and GR32:$src1, GR32:$src2), 0)]>;
 }
-def TEST8mr  : I<0x84, MRMDestMem, (ops i8mem :$src1, GR8 :$src2),
-                 "test{b} {$src2, $src1|$src1, $src2}",
-                 [(X86test (loadi8 addr:$src1), GR8:$src2)]>;
-def TEST16mr : I<0x85, MRMDestMem, (ops i16mem:$src1, GR16:$src2),
-                 "test{w} {$src2, $src1|$src1, $src2}",
-                 [(X86test (loadi16 addr:$src1), GR16:$src2)]>,
-               OpSize;
-def TEST32mr : I<0x85, MRMDestMem, (ops i32mem:$src1, GR32:$src2),
-                 "test{l} {$src2, $src1|$src1, $src2}",
-                 [(X86test (loadi32 addr:$src1), GR32:$src2)]>;
+
 def TEST8rm  : I<0x84, MRMSrcMem, (ops GR8 :$src1, i8mem :$src2),
                  "test{b} {$src2, $src1|$src1, $src2}",
-                 [(X86test GR8:$src1, (loadi8 addr:$src2))]>;
+                 [(X86cmp (and GR8:$src1, (loadi8 addr:$src2)), 0)]>;
 def TEST16rm : I<0x85, MRMSrcMem, (ops GR16:$src1, i16mem:$src2),
                  "test{w} {$src2, $src1|$src1, $src2}",
-                 [(X86test GR16:$src1, (loadi16 addr:$src2))]>,
+                 [(X86cmp (and GR16:$src1, (loadi16 addr:$src2)), 0)]>,
                OpSize;
 def TEST32rm : I<0x85, MRMSrcMem, (ops GR32:$src1, i32mem:$src2),
                  "test{l} {$src2, $src1|$src1, $src2}",
-                 [(X86test GR32:$src1, (loadi32 addr:$src2))]>;
+                 [(X86cmp (and GR32:$src1, (loadi32 addr:$src2)), 0)]>;
 
 def TEST8ri  : Ii8 <0xF6, MRM0r,                     // flags = GR8  & imm8
                     (ops GR8:$src1, i8imm:$src2),
                     "test{b} {$src2, $src1|$src1, $src2}",
-                    [(X86test GR8:$src1, imm:$src2)]>;
+                    [(X86cmp (and GR8:$src1, imm:$src2), 0)]>;
 def TEST16ri : Ii16<0xF7, MRM0r,                     // flags = GR16 & imm16
                     (ops GR16:$src1, i16imm:$src2),
                     "test{w} {$src2, $src1|$src1, $src2}",
-                    [(X86test GR16:$src1, imm:$src2)]>, OpSize;
+                    [(X86cmp (and GR16:$src1, imm:$src2), 0)]>, OpSize;
 def TEST32ri : Ii32<0xF7, MRM0r,                     // flags = GR32 & imm32
                     (ops GR32:$src1, i32imm:$src2),
                     "test{l} {$src2, $src1|$src1, $src2}",
-                    [(X86test GR32:$src1, imm:$src2)]>;
+                    [(X86cmp (and GR32:$src1, imm:$src2), 0)]>;
+
 def TEST8mi  : Ii8 <0xF6, MRM0m,                     // flags = [mem8]  & imm8
                     (ops i8mem:$src1, i8imm:$src2),
                     "test{b} {$src2, $src1|$src1, $src2}",
-                    [(X86test (loadi8 addr:$src1), imm:$src2)]>;
+                    [(X86cmp (and (loadi8 addr:$src1), imm:$src2), 0)]>;
 def TEST16mi : Ii16<0xF7, MRM0m,                     // flags = [mem16] & imm16
                     (ops i16mem:$src1, i16imm:$src2),
                     "test{w} {$src2, $src1|$src1, $src2}",
-                    [(X86test (loadi16 addr:$src1), imm:$src2)]>,
+                    [(X86cmp (and (loadi16 addr:$src1), imm:$src2), 0)]>,
                OpSize;
 def TEST32mi : Ii32<0xF7, MRM0m,                     // flags = [mem32] & imm32
                     (ops i32mem:$src1, i32imm:$src2),
                     "test{l} {$src2, $src1|$src1, $src2}",
-                    [(X86test (loadi32 addr:$src1), imm:$src2)]>;
+                    [(X86cmp (and (loadi32 addr:$src1), imm:$src2), 0)]>;
 
 
 // Condition code ops, incl. set if equal/not equal/...
@@ -2279,21 +2396,15 @@ def MOVZX32rm16: I<0xB7, MRMSrcMem, (ops GR32:$dst, i16mem:$src),
                    [(set GR32:$dst, (zextloadi32i16 addr:$src))]>, TB;
 
 def CBW : I<0x98, RawFrm, (ops),
-            "{cbtw|cbw}", []>, Imp<[AL],[AX]>;   // AX = signext(AL)
+            "{cbtw|cbw}", []>, Imp<[AL],[AX]>, OpSize;   // AX = signext(AL)
 def CWDE : I<0x98, RawFrm, (ops),
             "{cwtl|cwde}", []>, Imp<[AX],[EAX]>;   // EAX = signext(AX)
 
 def CWD : I<0x99, RawFrm, (ops),
-            "{cwtd|cwd}", []>, Imp<[AX],[AX,DX]>;   // DX:AX = signext(AX)
+            "{cwtd|cwd}", []>, Imp<[AX],[AX,DX]>, OpSize; // DX:AX = signext(AX)
 def CDQ : I<0x99, RawFrm, (ops),
             "{cltd|cdq}", []>, Imp<[EAX],[EAX,EDX]>; // EDX:EAX = signext(EAX)
           
-//===----------------------------------------------------------------------===//
-// Miscellaneous Instructions
-//===----------------------------------------------------------------------===//
-
-def RDTSC : I<0x31, RawFrm, (ops), "rdtsc", [(X86rdtsc)]>,
-            TB, Imp<[],[EAX,EDX]>;
 
 //===----------------------------------------------------------------------===//
 // Alias Instructions
@@ -2340,15 +2451,11 @@ def DWARF_LOC   : I<0, Pseudo, (ops i32imm:$line, i32imm:$col, i32imm:$file),
                     [(dwarf_loc (i32 imm:$line), (i32 imm:$col),
                       (i32 imm:$file))]>;
 
-def DWARF_LABEL : I<0, Pseudo, (ops i32imm:$id),
-                   "\nLdebug_loc${id:debug}:",
-                   [(dwarf_label (i32 imm:$id))]>;
-
 //===----------------------------------------------------------------------===//
 // Non-Instruction Patterns
 //===----------------------------------------------------------------------===//
 
-// ConstantPool GlobalAddress, ExternalSymbol
+// ConstantPool GlobalAddress, ExternalSymbol, and JumpTable
 def : Pat<(i32 (X86Wrapper tconstpool  :$dst)), (MOV32ri tconstpool  :$dst)>;
 def : Pat<(i32 (X86Wrapper tjumptable  :$dst)), (MOV32ri tjumptable  :$dst)>;
 def : Pat<(i32 (X86Wrapper tglobaladdr :$dst)), (MOV32ri tglobaladdr :$dst)>;
@@ -2370,18 +2477,16 @@ def : Pat<(store (i32 (X86Wrapper texternalsym:$src)), addr:$dst),
 
 // Calls
 def : Pat<(X86tailcall GR32:$dst),
-      (CALL32r     GR32:$dst)>;
+          (CALL32r     GR32:$dst)>;
 
-def : Pat<(X86tailcall tglobaladdr:$dst),
+def : Pat<(X86tailcall (i32 tglobaladdr:$dst)),
           (CALLpcrel32 tglobaladdr:$dst)>;
-def : Pat<(X86tailcall texternalsym:$dst),
+def : Pat<(X86tailcall (i32 texternalsym:$dst)),
           (CALLpcrel32 texternalsym:$dst)>;
 
-
-
-def : Pat<(X86call tglobaladdr:$dst),
+def : Pat<(X86call (i32 tglobaladdr:$dst)),
           (CALLpcrel32 tglobaladdr:$dst)>;
-def : Pat<(X86call texternalsym:$dst),
+def : Pat<(X86call (i32 texternalsym:$dst)),
           (CALLpcrel32 texternalsym:$dst)>;
 
 // X86 specific add which produces a flag.
@@ -2403,11 +2508,21 @@ def : Pat<(subc GR32:$src1, imm:$src2),
 def : Pat<(subc GR32:$src1, i32immSExt8:$src2),
           (SUB32ri8 GR32:$src1, i32immSExt8:$src2)>;
 
-def : Pat<(truncstore (i8 imm:$src), addr:$dst, i1), 
+def : Pat<(truncstorei1 (i8 imm:$src), addr:$dst), 
           (MOV8mi addr:$dst, imm:$src)>;
-def : Pat<(truncstore GR8:$src, addr:$dst, i1), 
+def : Pat<(truncstorei1 GR8:$src, addr:$dst), 
           (MOV8mr addr:$dst, GR8:$src)>;
 
+// Comparisons.
+
+// TEST R,R is smaller than CMP R,0
+def : Pat<(X86cmp GR8:$src1, 0),
+          (TEST8rr GR8:$src1, GR8:$src1)>;
+def : Pat<(X86cmp GR16:$src1, 0),
+          (TEST16rr GR16:$src1, GR16:$src1)>;
+def : Pat<(X86cmp GR32:$src1, 0),
+          (TEST32rr GR32:$src1, GR32:$src1)>;
+
 // {s|z}extload bool -> {s|z}extload byte
 def : Pat<(sextloadi16i1 addr:$src), (MOVSX16rm8 addr:$src)>;
 def : Pat<(sextloadi32i1 addr:$src), (MOVSX32rm8 addr:$src)>;
@@ -2494,3 +2609,9 @@ include "X86InstrMMX.td"
 //===----------------------------------------------------------------------===//
 
 include "X86InstrSSE.td"
+
+//===----------------------------------------------------------------------===//
+// X86-64 Support
+//===----------------------------------------------------------------------===//
+
+include "X86InstrX86-64.td"