[SDTCisVT<0, i8>,
SDTCisVT<1, i8>, SDTCisVT<2, i32>]>;
-def SDTX86Ret : SDTypeProfile<0, 1, [SDTCisVT<0, i16>]>;
+def SDTX86cas : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisInt<1>,
+ SDTCisVT<2, i8>]>;
+def SDTX86cas8 : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
+
+def SDTX86Ret : SDTypeProfile<0, -1, [SDTCisVT<0, i16>]>;
def SDT_X86CallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>;
def SDT_X86CallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>,
[SDNPHasChain]>;
def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC>;
+def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas,
+ [SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore,
+ SDNPMayLoad]>;
+def X86cas8 : SDNode<"X86ISD::LCMPXCHG8_DAG", SDTX86cas8,
+ [SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore,
+ SDNPMayLoad]>;
+
def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret,
[SDNPHasChain, SDNPOptInFlag]>;
def X86tcret : SDNode<"X86ISD::TC_RETURN", SDT_X86TCRET,
[SDNPHasChain, SDNPOptInFlag]>;
-def SDT_TRAP : SDTypeProfile<0, 0, []>;
-def trap : SDNode<"ISD::TRAP", SDT_TRAP,
- [SDNPHasChain, SDNPOutFlag, SDNPSideEffect]>;
-
//===----------------------------------------------------------------------===//
// X86 Operand Definitions.
//
def HasSSE2 : Predicate<"Subtarget->hasSSE2()">;
def HasSSE3 : Predicate<"Subtarget->hasSSE3()">;
def HasSSSE3 : Predicate<"Subtarget->hasSSSE3()">;
+def HasSSE41 : Predicate<"Subtarget->hasSSE41()">;
+def HasSSE42 : Predicate<"Subtarget->hasSSE42()">;
def FPStackf32 : Predicate<"!Subtarget->hasSSE1()">;
def FPStackf64 : Predicate<"!Subtarget->hasSSE2()">;
def In32BitMode : Predicate<"!Subtarget->is64Bit()">;
def In64BitMode : Predicate<"Subtarget->is64Bit()">;
-def HasLow4G : Predicate<"Subtarget->hasLow4GUserSpaceAddress()">;
def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">;
def NotSmallCode : Predicate<"TM.getCodeModel() != CodeModel::Small">;
def IsStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">;
def loadf64 : PatFrag<(ops node:$ptr), (f64 (load node:$ptr))>;
def loadf80 : PatFrag<(ops node:$ptr), (f80 (load node:$ptr))>;
-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 extloadi32i8 : PatFrag<(ops node:$ptr), (i32 (extloadi8 node:$ptr))>;
def extloadi32i16 : PatFrag<(ops node:$ptr), (i32 (extloadi16 node:$ptr))>;
+
+// An 'and' node with a single use.
+def and_su : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs), [{
+ return N->hasOneUse();
+}]>;
+
//===----------------------------------------------------------------------===//
// 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.
-// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become sub / add
-// which can clobber EFLAGS.
+// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
+// sub / add which can clobber EFLAGS.
let Defs = [ESP, EFLAGS], Uses = [ESP] in {
def ADJCALLSTACKDOWN : I<0, Pseudo, (outs), (ins i32imm:$amt),
"#ADJCALLSTACKDOWN",
"#ADJCALLSTACKUP",
[(X86callseq_end imm:$amt1, imm:$amt2)]>;
}
-let isImplicitDef = 1 in {
-def IMPLICIT_DEF_GR8 : I<0, Pseudo, (outs GR8:$dst), (ins),
- "#IMPLICIT_DEF $dst",
- [(set GR8:$dst, (undef))]>;
-def IMPLICIT_DEF_GR16 : I<0, Pseudo, (outs GR16:$dst), (ins),
- "#IMPLICIT_DEF $dst",
- [(set GR16:$dst, (undef))]>;
-def IMPLICIT_DEF_GR32 : I<0, Pseudo, (outs GR32:$dst), (ins),
- "#IMPLICIT_DEF $dst",
- [(set GR32:$dst, (undef))]>;
-}
// Nop
let neverHasSideEffects = 1 in
// Return instructions.
let isTerminator = 1, isReturn = 1, isBarrier = 1,
- hasCtrlDep = 1 in {
- def RET : I<0xC3, RawFrm, (outs), (ins), "ret", [(X86retflag 0)]>;
- def RETI : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt), "ret\t$amt",
+ hasCtrlDep = 1, FPForm = SpecialFP, FPFormBits = SpecialFP.Value in {
+ def RET : I <0xC3, RawFrm, (outs), (ins variable_ops),
+ "ret",
+ [/*(X86retflag 0)*/ /*FIXME: Disabled: rdar://5791600*/]>;
+ def RETI : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
+ "ret\t$amt",
[(X86retflag imm:$amt)]>;
}
// Tail call stuff.
-def TAILCALL : I<0, Pseudo, (outs), (ins ),
+def TAILCALL : I<0, Pseudo, (outs), (ins),
"#TAILCALL",
[]>;
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
-def TCRETURNdi : I<0, Pseudo, (outs), (ins i32imm:$dst, i32imm:$offset),
+def TCRETURNdi : I<0, Pseudo, (outs), (ins i32imm:$dst, i32imm:$offset, variable_ops),
"#TC_RETURN $dst $offset",
[]>;
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
-def TCRETURNri : I<0, Pseudo, (outs), (ins GR32:$dst, i32imm:$offset),
+def TCRETURNri : I<0, Pseudo, (outs), (ins GR32:$dst, i32imm:$offset, variable_ops),
"#TC_RETURN $dst $offset",
[]>;
def LEA16r : I<0x8D, MRMSrcMem,
(outs GR16:$dst), (ins i32mem:$src),
"lea{w}\t{$src|$dst}, {$dst|$src}", []>, OpSize;
+let isReMaterializable = 1 in
def LEA32r : I<0x8D, MRMSrcMem,
(outs GR32:$dst), (ins lea32mem:$src),
"lea{l}\t{$src|$dst}, {$dst|$src}",
let isCommutable = 1 in { // TEST X, Y --> TEST Y, X
def TEST8rr : I<0x84, MRMDestReg, (outs), (ins GR8:$src1, GR8:$src2),
"test{b}\t{$src2, $src1|$src1, $src2}",
- [(X86cmp (and GR8:$src1, GR8:$src2), 0),
+ [(X86cmp (and_su GR8:$src1, GR8:$src2), 0),
(implicit EFLAGS)]>;
def TEST16rr : I<0x85, MRMDestReg, (outs), (ins GR16:$src1, GR16:$src2),
"test{w}\t{$src2, $src1|$src1, $src2}",
- [(X86cmp (and GR16:$src1, GR16:$src2), 0),
+ [(X86cmp (and_su GR16:$src1, GR16:$src2), 0),
(implicit EFLAGS)]>,
OpSize;
def TEST32rr : I<0x85, MRMDestReg, (outs), (ins GR32:$src1, GR32:$src2),
"test{l}\t{$src2, $src1|$src1, $src2}",
- [(X86cmp (and GR32:$src1, GR32:$src2), 0),
+ [(X86cmp (and_su GR32:$src1, GR32:$src2), 0),
(implicit EFLAGS)]>;
}
def TEST8ri : Ii8 <0xF6, MRM0r, // flags = GR8 & imm8
(outs), (ins GR8:$src1, i8imm:$src2),
"test{b}\t{$src2, $src1|$src1, $src2}",
- [(X86cmp (and GR8:$src1, imm:$src2), 0),
+ [(X86cmp (and_su GR8:$src1, imm:$src2), 0),
(implicit EFLAGS)]>;
def TEST16ri : Ii16<0xF7, MRM0r, // flags = GR16 & imm16
(outs), (ins GR16:$src1, i16imm:$src2),
"test{w}\t{$src2, $src1|$src1, $src2}",
- [(X86cmp (and GR16:$src1, imm:$src2), 0),
+ [(X86cmp (and_su GR16:$src1, imm:$src2), 0),
(implicit EFLAGS)]>, OpSize;
def TEST32ri : Ii32<0xF7, MRM0r, // flags = GR32 & imm32
(outs), (ins GR32:$src1, i32imm:$src2),
"test{l}\t{$src2, $src1|$src1, $src2}",
- [(X86cmp (and GR32:$src1, imm:$src2), 0),
+ [(X86cmp (and_su GR32:$src1, imm:$src2), 0),
(implicit EFLAGS)]>;
def TEST8mi : Ii8 <0xF6, MRM0m, // flags = [mem8] & imm8
}
+//===----------------------------------------------------------------------===//
+// Atomic support
+//
+
+//FIXME: Please check the format Pseudo is certainly wrong, but the opcode and
+// prefixes should be correct
+
+let Defs = [EAX, EFLAGS], Uses = [EAX] in {
+def CMPXCHG32 : I<0xB1, Pseudo, (outs), (ins i32mem:$ptr, GR32:$swap),
+ "cmpxchgl $swap,$ptr", []>, TB;
+def LCMPXCHG32 : I<0xB1, Pseudo, (outs), (ins i32mem:$ptr, GR32:$swap),
+ "lock cmpxchgl $swap,$ptr",
+ [(X86cas addr:$ptr, GR32:$swap, 4)]>, TB, LOCK;
+}
+let Defs = [EAX, EBX, ECX, EDX, EFLAGS], Uses = [EAX, EBX, ECX, EDX] in {
+def CMPXCHG8B : I<0xC7, Pseudo, (outs), (ins i32mem:$ptr),
+ "cmpxchg8b $ptr", []>, TB;
+def LCMPXCHG8B : I<0xC7, Pseudo, (outs), (ins i32mem:$ptr),
+ "lock cmpxchg8b $ptr",
+ [(X86cas8 addr:$ptr)]>, TB, LOCK;
+}
+
+let Defs = [AX, EFLAGS], Uses = [AX] in {
+def CMPXCHG16 : I<0xB1, Pseudo, (outs), (ins i16mem:$ptr, GR16:$swap),
+ "cmpxchgw $swap,($ptr)", []>, TB, OpSize;
+def LCMPXCHG16 : I<0xB1, Pseudo, (outs), (ins i16mem:$ptr, GR16:$swap),
+ "lock cmpxchgw $swap,$ptr",
+ [(X86cas addr:$ptr, GR16:$swap, 2)]>, TB, OpSize, LOCK;
+}
+let Defs = [AL, EFLAGS], Uses = [AL] in {
+def CMPXCHG8 : I<0xB0, Pseudo, (outs), (ins i8mem:$ptr, GR8:$swap),
+ "cmpxchgb $swap,($ptr)", []>, TB;
+def LCMPXCHG8 : I<0xB0, Pseudo, (outs), (ins i8mem:$ptr, GR8:$swap),
+ "lock cmpxchgb $swap,$ptr",
+ [(X86cas addr:$ptr, GR8:$swap, 1)]>, TB, LOCK;
+}
+
+let Constraints = "$val = $dst", Defs = [EFLAGS] in {
+def LXADD32 : I<0xC1, Pseudo, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val),
+ "lock xadd $val, $ptr",
+ [(set GR32:$dst, (atomic_las_32 addr:$ptr, GR32:$val))]>,
+ TB, LOCK;
+def LXADD16 : I<0xC1, Pseudo, (outs GR16:$dst), (ins i16mem:$ptr, GR16:$val),
+ "lock xadd $val, $ptr",
+ [(set GR16:$dst, (atomic_las_16 addr:$ptr, GR16:$val))]>,
+ TB, OpSize, LOCK;
+def LXADD8 : I<0xC0, Pseudo, (outs GR8:$dst), (ins i8mem:$ptr, GR8:$val),
+ "lock xadd $val, $ptr",
+ [(set GR8:$dst, (atomic_las_8 addr:$ptr, GR8:$val))]>,
+ TB, LOCK;
+def XADD32 : I<0xC1, Pseudo, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val),
+ "xadd $val, $ptr", []>, TB;
+def XADD16 : I<0xC1, Pseudo, (outs GR16:$dst), (ins i16mem:$ptr, GR16:$val),
+ "xadd $val, $ptr", []>, TB, OpSize;
+def XADD8 : I<0xC0, Pseudo, (outs GR8:$dst), (ins i8mem:$ptr, GR8:$val),
+ "xadd $val, $ptr", []>, TB;
+
+def LXCHG32 : I<0x87, Pseudo, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val),
+ "lock xchg $val, $ptr",
+ [(set GR32:$dst, (atomic_swap_32 addr:$ptr, GR32:$val))]>, LOCK;
+def LXCHG16 : I<0x87, Pseudo, (outs GR16:$dst), (ins i16mem:$ptr, GR16:$val),
+ "lock xchg $val, $ptr",
+ [(set GR16:$dst, (atomic_swap_16 addr:$ptr, GR16:$val))]>,
+ OpSize, LOCK;
+def LXCHG8 : I<0x86, Pseudo, (outs GR8:$dst), (ins i8mem:$ptr, GR8:$val),
+ "lock xchg $val, $ptr",
+ [(set GR8:$dst, (atomic_swap_8 addr:$ptr, GR8:$val))]>, LOCK;
+def XCHG32 : I<0x87, Pseudo, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val),
+ "xchg $val, $ptr", []>;
+def XCHG16 : I<0x87, Pseudo, (outs GR16:$dst), (ins i16mem:$ptr, GR16:$val),
+ "xchg $val, $ptr", []>, OpSize;
+def XCHG8 : I<0x86, Pseudo, (outs GR8:$dst), (ins i8mem:$ptr, GR8:$val),
+ "xchg $val, $ptr", []>;
+}
+
//===----------------------------------------------------------------------===//
// Non-Instruction Patterns
//===----------------------------------------------------------------------===//
// 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 tglobaltlsaddr:$dst)), (MOV32ri tglobaltlsaddr:$dst)>;
+def : Pat<(i32 (X86Wrapper tglobaltlsaddr:$dst)),(MOV32ri tglobaltlsaddr:$dst)>;
def : Pat<(i32 (X86Wrapper tglobaladdr :$dst)), (MOV32ri tglobaladdr :$dst)>;
def : Pat<(i32 (X86Wrapper texternalsym:$dst)), (MOV32ri texternalsym:$dst)>;
def : Pat<(subc GR32:$src1, i32immSExt8:$src2),
(SUB32ri8 GR32:$src1, i32immSExt8:$src2)>;
-def : Pat<(truncstorei1 (i8 imm:$src), addr:$dst),
- (MOV8mi addr:$dst, imm:$src)>;
-def : Pat<(truncstorei1 GR8:$src, addr:$dst),
- (MOV8mr addr:$dst, GR8:$src)>;
-
// Comparisons.
// TEST R,R is smaller than CMP R,0
def : Pat<(parallel (X86cmp GR32:$src1, 0), (implicit EFLAGS)),
(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)>;
+// zextload bool -> zextload byte
def : Pat<(zextloadi8i1 addr:$src), (MOV8rm addr:$src)>;
def : Pat<(zextloadi16i1 addr:$src), (MOVZX16rm8 addr:$src)>;
def : Pat<(zextloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>;
(srl GR16:$src2, (sub 16, CL:$amt))), addr:$dst),
(SHLD16mrCL addr:$dst, GR16:$src2)>;
-
//===----------------------------------------------------------------------===//
// Floating Point Stack Support
//===----------------------------------------------------------------------===//