diff options
-rw-r--r-- | lib/Target/Target.td | 15 | ||||
-rw-r--r-- | lib/Target/X86/X86Instr64bit.td | 45 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrFPStack.td | 48 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.td | 81 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrMMX.td | 15 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrSSE.td | 20 | ||||
-rw-r--r-- | utils/TableGen/CodeGenInstruction.cpp | 6 | ||||
-rw-r--r-- | utils/TableGen/CodeGenInstruction.h | 3 | ||||
-rw-r--r-- | utils/TableGen/CodeGenTarget.cpp | 6 | ||||
-rw-r--r-- | utils/TableGen/InstrInfoEmitter.cpp | 55 |
10 files changed, 192 insertions, 102 deletions
diff --git a/lib/Target/Target.td b/lib/Target/Target.td index 766966f550..d155e713c0 100644 --- a/lib/Target/Target.td +++ b/lib/Target/Target.td @@ -204,19 +204,20 @@ class Instruction { bit hasCtrlDep = 0; // Does this instruction r/w ctrl-flow chains? bit isNotDuplicable = 0; // Is it unsafe to duplicate this instruction? - // Side effect flags - If neither of these flags is set, then the instruction - // *always* has side effects. When set, the flags have these meanings: + // Side effect flags - When set, the flags have these meanings: // - // neverHasSideEffects - The instruction has no side effects that are not - // captured by any operands of the instruction or other flags, and when - // *all* instances of the instruction of that opcode have no side effects. + // hasSideEffects - The instruction has side effects that are not + // captured by any operands of the instruction or other flags. // mayHaveSideEffects - Some instances of the instruction can have side // effects. The virtual method "isReallySideEffectFree" is called to // determine this. Load instructions are an example of where this is // useful. In general, loads always have side effects. However, loads from // constant pools don't. Individual back ends make this determination. - bit neverHasSideEffects = 0; + // neverHasSideEffects - Set on an instruction with no pattern if it has no + // side effects. + bit hasSideEffects = 0; bit mayHaveSideEffects = 0; + bit neverHasSideEffects = 0; InstrItinClass Itinerary = NoItinerary;// Execution steps used for scheduling. @@ -343,12 +344,14 @@ def EXTRACT_SUBREG : Instruction { let InOperandList = (ops variable_ops); let AsmString = ""; let Namespace = "TargetInstrInfo"; + let neverHasSideEffects = 1; } def INSERT_SUBREG : Instruction { let OutOperandList = (ops variable_ops); let InOperandList = (ops variable_ops); let AsmString = ""; let Namespace = "TargetInstrInfo"; + let neverHasSideEffects = 1; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index d677c671f9..bd7b4f28f7 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -131,19 +131,21 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { //===----------------------------------------------------------------------===// // Miscellaneous Instructions... // -let Defs = [RBP,RSP], Uses = [RBP,RSP] in +let Defs = [RBP,RSP], Uses = [RBP,RSP], mayLoad = 1, neverHasSideEffects = 1 in def LEAVE64 : I<0xC9, RawFrm, (outs), (ins), "leave", []>; -let Defs = [RSP], Uses = [RSP] in { +let Defs = [RSP], Uses = [RSP], neverHasSideEffects=1 in { +let mayLoad = 1 in def POP64r : I<0x58, AddRegFrm, (outs GR64:$reg), (ins), "pop{q}\t$reg", []>; +let mayStore = 1 in def PUSH64r : I<0x50, AddRegFrm, (outs), (ins GR64:$reg), "push{q}\t$reg", []>; } -let Defs = [RSP, EFLAGS], Uses = [RSP] in +let Defs = [RSP, EFLAGS], Uses = [RSP], mayLoad = 1 in def POPFQ : I<0x9D, RawFrm, (outs), (ins), "popf", []>, REX_W; -let Defs = [RSP], Uses = [RSP, EFLAGS] in +let Defs = [RSP], Uses = [RSP, EFLAGS], mayStore = 1 in def PUSHFQ : I<0x9C, RawFrm, (outs), (ins), "pushf", []>; def LEA64_32r : I<0x8D, MRMSrcMem, @@ -160,12 +162,16 @@ def BSWAP64r : RI<0xC8, AddRegFrm, (outs GR64:$dst), (ins GR64:$src), "bswap{q}\t$dst", [(set GR64:$dst, (bswap GR64:$src))]>, TB; // Exchange +let neverHasSideEffects = 1 in { def XCHG64rr : RI<0x87, MRMDestReg, (outs), (ins GR64:$src1, GR64:$src2), "xchg{q}\t{$src2|$src1}, {$src1|$src2}", []>; +let mayLoad = 1, mayStore = 1 in { def XCHG64mr : RI<0x87, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2), "xchg{q}\t{$src2|$src1}, {$src1|$src2}", []>; def XCHG64rm : RI<0x87, MRMSrcMem, (outs), (ins GR64:$src1, i64mem:$src2), "xchg{q}\t{$src2|$src1}, {$src1|$src2}", []>; +} +} // Bit scan instructions. let Defs = [EFLAGS] in { @@ -198,6 +204,7 @@ def REP_STOSQ : RI<0xAB, RawFrm, (outs), (ins), "{rep;stosq|rep stosq}", // Move Instructions... // +let neverHasSideEffects = 1 in def MOV64rr : RI<0x89, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), "mov{q}\t{$src, $dst|$dst, $src}", []>; @@ -256,13 +263,15 @@ def MOVZX64rm16: RI<0xB7, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src), "movz{wq|x}\t{$src, $dst|$dst, $src}", [(set GR64:$dst, (zextloadi64i16 addr:$src))]>, TB; -let Defs = [RAX], Uses = [EAX] in -def CDQE : RI<0x98, RawFrm, (outs), (ins), - "{cltq|cdqe}", []>; // RAX = signext(EAX) +let neverHasSideEffects = 1 in { + let Defs = [RAX], Uses = [EAX] in + def CDQE : RI<0x98, RawFrm, (outs), (ins), + "{cltq|cdqe}", []>; // RAX = signext(EAX) -let Defs = [RAX,RDX], Uses = [RAX] in -def CQO : RI<0x99, RawFrm, (outs), (ins), - "{cqto|cqo}", []>; // RDX:RAX = signext(RAX) + let Defs = [RAX,RDX], Uses = [RAX] in + def CQO : RI<0x99, RawFrm, (outs), (ins), + "{cqto|cqo}", []>; // RDX:RAX = signext(RAX) +} //===----------------------------------------------------------------------===// // Arithmetic Instructions... @@ -387,15 +396,17 @@ def SBB64mi8 : RIi8<0x83, MRM3m, (outs), (ins i64mem:$dst, i64i8imm :$src2), } // Defs = [EFLAGS] // Unsigned multiplication -let Defs = [RAX,RDX,EFLAGS], Uses = [RAX] in { +let Defs = [RAX,RDX,EFLAGS], Uses = [RAX], neverHasSideEffects = 1 in { def MUL64r : RI<0xF7, MRM4r, (outs), (ins GR64:$src), "mul{q}\t$src", []>; // RAX,RDX = RAX*GR64 +let mayLoad = 1 in def MUL64m : RI<0xF7, MRM4m, (outs), (ins i64mem:$src), "mul{q}\t$src", []>; // RAX,RDX = RAX*[mem64] // Signed multiplication def IMUL64r : RI<0xF7, MRM5r, (outs), (ins GR64:$src), "imul{q}\t$src", []>; // RAX,RDX = RAX*GR64 +let mayLoad = 1 in def IMUL64m : RI<0xF7, MRM5m, (outs), (ins i64mem:$src), "imul{q}\t$src", []>; // RAX,RDX = RAX*[mem64] } @@ -432,18 +443,21 @@ def IMUL64rmi8 : RIi8<0x6B, MRMSrcMem, // GR64 = [mem64]*I8 } // Defs = [EFLAGS] // Unsigned division / remainder +let neverHasSideEffects = 1 in { let Defs = [RAX,RDX,EFLAGS], Uses = [RAX,RDX] in { def DIV64r : RI<0xF7, MRM6r, (outs), (ins GR64:$src), // RDX:RAX/r64 = RAX,RDX "div{q}\t$src", []>; -def DIV64m : RI<0xF7, MRM6m, (outs), (ins i64mem:$src), // RDX:RAX/[mem64] = RAX,RDX - "div{q}\t$src", []>; - // Signed division / remainder def IDIV64r: RI<0xF7, MRM7r, (outs), (ins GR64:$src), // RDX:RAX/r64 = RAX,RDX "idiv{q}\t$src", []>; +let mayLoad = 1 in { +def DIV64m : RI<0xF7, MRM6m, (outs), (ins i64mem:$src), // RDX:RAX/[mem64] = RAX,RDX + "div{q}\t$src", []>; def IDIV64m: RI<0xF7, MRM7m, (outs), (ins i64mem:$src), // RDX:RAX/[mem64] = RAX,RDX "idiv{q}\t$src", []>; } +} +} // Unary instructions let Defs = [EFLAGS], CodeSize = 2 in { @@ -1035,11 +1049,12 @@ def CVTSI2SS64rr: RSSI<0x2A, MRMSrcReg, (outs FR32:$dst), (ins GR64:$src), def CVTSI2SS64rm: RSSI<0x2A, MRMSrcMem, (outs FR32:$dst), (ins i64mem:$src), "cvtsi2ss{q}\t{$src, $dst|$dst, $src}", [(set FR32:$dst, (sint_to_fp (loadi64 addr:$src)))]>; -let isTwoAddress = 1 in { +let isTwoAddress = 1, neverHasSideEffects = 1 in { def Int_CVTSI2SS64rr: RSSI<0x2A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, GR64:$src2), "cvtsi2ss{q}\t{$src2, $dst|$dst, $src2}", []>; // TODO: add intrinsic +let mayLoad = 1 in def Int_CVTSI2SS64rm: RSSI<0x2A, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i64mem:$src2), "cvtsi2ss{q}\t{$src2, $dst|$dst, $src2}", diff --git a/lib/Target/X86/X86InstrFPStack.td b/lib/Target/X86/X86InstrFPStack.td index d27e72de4b..e3eb4abcaf 100644 --- a/lib/Target/X86/X86InstrFPStack.td +++ b/lib/Target/X86/X86InstrFPStack.td @@ -32,25 +32,25 @@ def SDTX86FpToIMem : SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisPtrTy<1>]>; def SDTX86CwdStore : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; def X86fpget : SDNode<"X86ISD::FP_GET_RESULT", SDTX86FpGet, - [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>; + [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>; def X86fpset : SDNode<"X86ISD::FP_SET_RESULT", SDTX86FpSet, - [SDNPHasChain, SDNPOutFlag]>; -def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, - [SDNPHasChain, SDNPMayLoad]>; -def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, - [SDNPHasChain, SDNPInFlag, SDNPMayStore]>; -def X86fild : SDNode<"X86ISD::FILD", SDTX86Fild, - [SDNPHasChain, SDNPMayLoad]>; -def X86fildflag : SDNode<"X86ISD::FILD_FLAG",SDTX86Fild, - [SDNPHasChain, SDNPOutFlag, SDNPMayLoad]>; + [SDNPHasChain, SDNPOutFlag]>; +def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, + [SDNPHasChain, SDNPMayLoad]>; +def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, + [SDNPHasChain, SDNPInFlag, SDNPMayStore]>; +def X86fild : SDNode<"X86ISD::FILD", SDTX86Fild, + [SDNPHasChain, SDNPMayLoad]>; +def X86fildflag : SDNode<"X86ISD::FILD_FLAG", SDTX86Fild, + [SDNPHasChain, SDNPOutFlag, SDNPMayLoad]>; def X86fp_to_i16mem : SDNode<"X86ISD::FP_TO_INT16_IN_MEM", SDTX86FpToIMem, - [SDNPHasChain]>; + [SDNPHasChain, SDNPMayStore]>; def X86fp_to_i32mem : SDNode<"X86ISD::FP_TO_INT32_IN_MEM", SDTX86FpToIMem, - [SDNPHasChain]>; + [SDNPHasChain, SDNPMayStore]>; def X86fp_to_i64mem : SDNode<"X86ISD::FP_TO_INT64_IN_MEM", SDTX86FpToIMem, - [SDNPHasChain]>; + [SDNPHasChain, SDNPMayStore]>; def X86fp_cwd_get16 : SDNode<"X86ISD::FNSTCW16m", SDTX86CwdStore, - [SDNPHasChain]>; + [SDNPHasChain, SDNPMayStore, SDNPSideEffect]>; //===----------------------------------------------------------------------===// // FPStack pattern fragments @@ -208,9 +208,9 @@ def _Fp80m64: FpI_<(outs RFP80:$dst), (ins RFP80:$src1, f64mem:$src2), OneArgFPR [(set RFP80:$dst, (OpNode RFP80:$src1, (f80 (extloadf64 addr:$src2))))]>; def _F32m : FPI<0xD8, fp, (outs), (ins f32mem:$src), - !strconcat("f", !strconcat(asmstring, "{s}\t$src"))>; + !strconcat("f", !strconcat(asmstring, "{s}\t$src"))> { let mayLoad = 1; } def _F64m : FPI<0xDC, fp, (outs), (ins f64mem:$src), - !strconcat("f", !strconcat(asmstring, "{l}\t$src"))>; + !strconcat("f", !strconcat(asmstring, "{l}\t$src"))> { let mayLoad = 1; } // ST(0) = ST(0) + [memint] def _FpI16m32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, i16mem:$src2), OneArgFPRW, [(set RFP32:$dst, (OpNode RFP32:$src1, @@ -231,9 +231,9 @@ def _FpI32m80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, i32mem:$src2), OneArgF [(set RFP80:$dst, (OpNode RFP80:$src1, (X86fild addr:$src2, i32)))]>; def _FI16m : FPI<0xDE, fp, (outs), (ins i16mem:$src), - !strconcat("fi", !strconcat(asmstring, "{s}\t$src"))>; + !strconcat("fi", !strconcat(asmstring, "{s}\t$src"))> { let mayLoad = 1; } def _FI32m : FPI<0xDA, fp, (outs), (ins i32mem:$src), - !strconcat("fi", !strconcat(asmstring, "{l}\t$src"))>; + !strconcat("fi", !strconcat(asmstring, "{l}\t$src"))> { let mayLoad = 1; } } defm ADD : FPBinary_rr<fadd>; @@ -392,13 +392,16 @@ def ST_Fp80m64 : FpI_<(outs), (ins f64mem:$op, RFP80:$src), OneArgFP, [(truncstoref64 RFP80:$src, addr:$op)]>; // FST does not support 80-bit memory target; FSTP must be used. +let mayStore = 1 in { def ST_FpP32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, []>; def ST_FpP64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, []>; def ST_FpP64m : FpIf64<(outs), (ins f64mem:$op, RFP64:$src), OneArgFP, []>; def ST_FpP80m32 : FpI_<(outs), (ins f32mem:$op, RFP80:$src), OneArgFP, []>; def ST_FpP80m64 : FpI_<(outs), (ins f64mem:$op, RFP80:$src), OneArgFP, []>; +} def ST_FpP80m : FpI_<(outs), (ins f80mem:$op, RFP80:$src), OneArgFP, [(store RFP80:$src, addr:$op)]>; +let mayStore = 1 in { def IST_Fp16m32 : FpIf32<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, []>; def IST_Fp32m32 : FpIf32<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, []>; def IST_Fp64m32 : FpIf32<(outs), (ins i64mem:$op, RFP32:$src), OneArgFP, []>; @@ -408,13 +411,17 @@ def IST_Fp64m64 : FpIf64<(outs), (ins i64mem:$op, RFP64:$src), OneArgFP, []>; def IST_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, []>; def IST_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, []>; def IST_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, []>; +} +let mayLoad = 1 in { def LD_F32m : FPI<0xD9, MRM0m, (outs), (ins f32mem:$src), "fld{s}\t$src">; def LD_F64m : FPI<0xDD, MRM0m, (outs), (ins f64mem:$src), "fld{l}\t$src">; def LD_F80m : FPI<0xDB, MRM5m, (outs), (ins f80mem:$src), "fld{t}\t$src">; def ILD_F16m : FPI<0xDF, MRM0m, (outs), (ins i16mem:$src), "fild{s}\t$src">; def ILD_F32m : FPI<0xDB, MRM0m, (outs), (ins i32mem:$src), "fild{l}\t$src">; def ILD_F64m : FPI<0xDF, MRM5m, (outs), (ins i64mem:$src), "fild{ll}\t$src">; +} +let mayStore = 1 in { def ST_F32m : FPI<0xD9, MRM2m, (outs), (ins f32mem:$dst), "fst{s}\t$dst">; def ST_F64m : FPI<0xDD, MRM2m, (outs), (ins f64mem:$dst), "fst{l}\t$dst">; def ST_FP32m : FPI<0xD9, MRM3m, (outs), (ins f32mem:$dst), "fstp{s}\t$dst">; @@ -425,6 +432,7 @@ def IST_F32m : FPI<0xDB, MRM2m, (outs), (ins i32mem:$dst), "fist{l}\t$dst">; def IST_FP16m : FPI<0xDF, MRM3m, (outs), (ins i16mem:$dst), "fistp{s}\t$dst">; def IST_FP32m : FPI<0xDB, MRM3m, (outs), (ins i32mem:$dst), "fistp{l}\t$dst">; def IST_FP64m : FPI<0xDF, MRM7m, (outs), (ins i64mem:$dst), "fistp{ll}\t$dst">; +} // FISTTP requires SSE3 even though it's a FPStack op. def ISTT_Fp16m32 : FpI_<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, @@ -455,9 +463,11 @@ def ISTT_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, [(X86fp_to_i64mem RFP80:$src, addr:$op)]>, Requires<[HasSSE3]>; +let mayStore = 1 in { def ISTT_FP16m : FPI<0xDF, MRM1m, (outs), (ins i16mem:$dst), "fisttp{s}\t$dst">; def ISTT_FP32m : FPI<0xDB, MRM1m, (outs), (ins i32mem:$dst), "fisttp{l}\t$dst">; def ISTT_FP64m : FPI<0xDD, MRM1m, (outs), (ins i64mem:$dst), "fisttp{ll}\t$dst">; +} // FP Stack manipulation instructions. def LD_Frr : FPI<0xC0, AddRegFrm, (outs), (ins RST:$op), "fld\t$op">, D9; @@ -531,6 +541,8 @@ def FNSTSW8r : I<0xE0, RawFrm, // AX = fp flags def FNSTCW16m : I<0xD9, MRM7m, // [mem16] = X87 control world (outs), (ins i16mem:$dst), "fnstcw\t$dst", [(X86fp_cwd_get16 addr:$dst)]>; + +let mayLoad = 1 in def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] (outs), (ins i16mem:$dst), "fldcw\t$dst", []>; diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index d7d81f6f3a..b9426c7112 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -92,7 +92,7 @@ def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr, SDNPMayLoad]>; def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc, - [SDNPHasChain, SDNPOutFlag]>; + [SDNPHasChain, SDNPOutFlag, SDNPSideEffect]>; def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", SDTX86Wrapper>; @@ -266,6 +266,7 @@ def ADJCALLSTACKUP : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), def IMPLICIT_USE : I<0, Pseudo, (outs), (ins variable_ops), "#IMPLICIT_USE", []>; let isImplicitDef = 1 in { +let neverHasSideEffects = 1 in def IMPLICIT_DEF : I<0, Pseudo, (outs variable_ops), (ins), "#IMPLICIT_DEF", []>; def IMPLICIT_DEF_GR8 : I<0, Pseudo, (outs GR8:$dst), (ins), @@ -280,13 +281,13 @@ def IMPLICIT_DEF_GR32 : I<0, Pseudo, (outs GR32:$dst), (ins), } // Nop -def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>; +let neverHasSideEffects = 1 in + def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>; // PIC base -let neverHasSideEffects = 1, isNotDuplicable = 1 in { -def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins piclabel:$label), - "call\t$label\n\tpop{l}\t$reg", []>; -} +let neverHasSideEffects = 1, isNotDuplicable = 1 in + def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins piclabel:$label), + "call\t$label\n\tpop{l}\t$reg", []>; //===----------------------------------------------------------------------===// // Control Flow Instructions... @@ -399,19 +400,21 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in //===----------------------------------------------------------------------===// // Miscellaneous Instructions... // -let Defs = [EBP, ESP], Uses = [EBP, ESP] in +let Defs = [EBP, ESP], Uses = [EBP, ESP], mayLoad = 1, neverHasSideEffects=1 in def LEAVE : I<0xC9, RawFrm, (outs), (ins), "leave", []>; -let Defs = [ESP], Uses = [ESP] in { +let Defs = [ESP], Uses = [ESP], neverHasSideEffects=1 in { +let mayLoad = 1 in def POP32r : I<0x58, AddRegFrm, (outs GR32:$reg), (ins), "pop{l}\t$reg", []>; +let mayStore = 1 in def PUSH32r : I<0x50, AddRegFrm, (outs), (ins GR32:$reg), "push{l}\t$reg",[]>; } -let Defs = [ESP, EFLAGS], Uses = [ESP] in +let Defs = [ESP, EFLAGS], Uses = [ESP], mayLoad = 1, neverHasSideEffects=1 in def POPFD : I<0x9D, RawFrm, (outs), (ins), "popf", []>; -let Defs = [ESP], Uses = [ESP, EFLAGS] in +let Defs = [ESP], Uses = [ESP, EFLAGS], mayStore = 1, neverHasSideEffects=1 in def PUSHFD : I<0x9C, RawFrm, (outs), (ins), "pushf", []>; let isTwoAddress = 1 in // GR32 = bswap GR32 @@ -483,6 +486,7 @@ def BSR32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), (implicit EFLAGS)]>, TB; } // Defs = [EFLAGS] +let neverHasSideEffects = 1 in def LEA16r : I<0x8D, MRMSrcMem, (outs GR16:$dst), (ins i32mem:$src), "lea{w}\t{$src|$dst}, {$dst|$src}", []>, OpSize; @@ -560,12 +564,14 @@ def OUT32ir : Ii8<0xE7, RawFrm, (outs), (ins i16i8imm:$port), //===----------------------------------------------------------------------===// // Move Instructions... // +let neverHasSideEffects = 1 in { def MOV8rr : I<0x88, MRMDestReg, (outs GR8 :$dst), (ins GR8 :$src), "mov{b}\t{$src, $dst|$dst, $src}", []>; def MOV16rr : I<0x89, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize; def MOV32rr : I<0x89, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), "mov{l}\t{$src, $dst|$dst, $src}", []>; +} let isReMaterializable = 1 in { def MOV8ri : Ii8 <0xB0, AddRegFrm, (outs GR8 :$dst), (ins i8imm :$src), "mov{b}\t{$src, $dst|$dst, $src}", @@ -633,13 +639,16 @@ def MUL8m : I<0xF6, MRM4m, (outs), (ins i8mem :$src), // This probably ought to be moved to a def : Pat<> if the // syntax can be accepted. [(set AL, (mul AL, (loadi8 addr:$src)))]>; // AL,AH = AL*[mem8] +let mayLoad = 1, neverHasSideEffects = 1 in { let Defs = [AX,DX,EFLAGS], Uses = [AX] in def MUL16m : I<0xF7, MRM4m, (outs), (ins i16mem:$src), "mul{w}\t$src", []>, OpSize; // AX,DX = AX*[mem16] let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in def MUL32m : I<0xF7, MRM4m, (outs), (ins i32mem:$src), "mul{l}\t$src", []>; // EAX,EDX = EAX*[mem32] +} +let neverHasSideEffects = 1 in { let Defs = [AL,AH,EFLAGS], Uses = [AL] in def IMUL8r : I<0xF6, MRM5r, (outs), (ins GR8:$src), "imul{b}\t$src", []>; // AL,AH = AL*GR8 @@ -649,6 +658,7 @@ def IMUL16r : I<0xF7, MRM5r, (outs), (ins GR16:$src), "imul{w}\t$src", []>, let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in def IMUL32r : I<0xF7, MRM5r, (outs), (ins GR32:$src), "imul{l}\t$src", []>; // EAX,EDX = EAX*GR32 +let mayLoad = 1 in { let Defs = [AL,AH,EFLAGS], Uses = [AL] in def IMUL8m : I<0xF6, MRM5m, (outs), (ins i8mem :$src), "imul{b}\t$src", []>; // AL,AH = AL*[mem8] @@ -658,6 +668,7 @@ def IMUL16m : I<0xF7, MRM5m, (outs), (ins i16mem:$src), let Defs = [EAX,EDX], Uses = [EAX] in def IMUL32m : I<0xF7, MRM5m, (outs), (ins i32mem:$src), "imul{l}\t$src", []>; // EAX,EDX = EAX*[mem32] +} // unsigned division/remainder let Defs = [AX,EFLAGS], Uses = [AL,AH] in @@ -669,6 +680,7 @@ def DIV16r : I<0xF7, MRM6r, (outs), (ins GR16:$src), // DX:AX/r16 = AX, let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in def DIV32r : I<0xF7, MRM6r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX "div{l}\t$src", []>; +let mayLoad = 1 in { let Defs = [AX,EFLAGS], Uses = [AL,AH] in def DIV8m : I<0xF6, MRM6m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH "div{b}\t$src", []>; @@ -678,6 +690,7 @@ def DIV16m : I<0xF7, MRM6m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = A let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in def DIV32m : I<0xF7, MRM6m, (outs), (ins i32mem:$src), // EDX:EAX/[mem32] = EAX,EDX "div{l}\t$src", []>; +} // Signed division/remainder. let Defs = [AX,EFLAGS], Uses = [AL,AH] in @@ -689,6 +702,7 @@ def IDIV16r: I<0xF7, MRM7r, (outs), (ins GR16:$src), // DX:AX/r16 = AX, let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in def IDIV32r: I<0xF7, MRM7r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX "idiv{l}\t$src", []>; +let mayLoad = 1, mayLoad = 1 in { let Defs = [AX,EFLAGS], Uses = [AL,AH] in def IDIV8m : I<0xF6, MRM7m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH "idiv{b}\t$src", []>; @@ -698,10 +712,11 @@ def IDIV16m: I<0xF7, MRM7m, (outs), (ins i16mem:$src), // DX:AX/[mem16] = AX let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in def IDIV32m: I<0xF7, MRM7m, (outs), (ins i32mem:$src), // EDX:EAX/[mem32] = EAX,EDX "idiv{l}\t$src", []>; - +} +} // neverHasSideEffects //===----------------------------------------------------------------------===// -// Two address Instructions... +// Two address Instructions. // let isTwoAddress = 1 in { @@ -2161,9 +2176,9 @@ def TEST32mi : Ii32<0xF7, MRM0m, // flags = [mem32] & imm32 // Condition code ops, incl. set if equal/not equal/... -let Defs = [EFLAGS], Uses = [AH] in +let Defs = [EFLAGS], Uses = [AH], neverHasSideEffects = 1 in def SAHF : I<0x9E, RawFrm, (outs), (ins), "sahf", []>; // flags = AH -let Defs = [AH], Uses = [EFLAGS] in +let Defs = [AH], Uses = [EFLAGS], neverHasSideEffects = 1 in def LAHF : I<0x9F, RawFrm, (outs), (ins), "lahf", []>; // AH = flags let Uses = [EFLAGS] in { @@ -2445,20 +2460,21 @@ def MOVZX32rm16: I<0xB7, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src), "movz{wl|x}\t{$src, $dst|$dst, $src}", [(set GR32:$dst, (zextloadi32i16 addr:$src))]>, TB; -let Defs = [AX], Uses = [AL] in -def CBW : I<0x98, RawFrm, (outs), (ins), - "{cbtw|cbw}", []>, OpSize; // AX = signext(AL) -let Defs = [EAX], Uses = [AX] in -def CWDE : I<0x98, RawFrm, (outs), (ins), - "{cwtl|cwde}", []>; // EAX = signext(AX) - -let Defs = [AX,DX], Uses = [AX] in -def CWD : I<0x99, RawFrm, (outs), (ins), - "{cwtd|cwd}", []>, OpSize; // DX:AX = signext(AX) -let Defs = [EAX,EDX], Uses = [EAX] in -def CDQ : I<0x99, RawFrm, (outs), (ins), - "{cltd|cdq}", []>; // EDX:EAX = signext(EAX) - +let neverHasSideEffects = 1 in { + let Defs = [AX], Uses = [AL] in + def CBW : I<0x98, RawFrm, (outs), (ins), + "{cbtw|cbw}", []>, OpSize; // AX = signext(AL) + let Defs = [EAX], Uses = [AX] in + def CWDE : I<0x98, RawFrm, (outs), (ins), + "{cwtl|cwde}", []>; // EAX = signext(AX) + + let Defs = [AX,DX], Uses = [AX] in + def CWD : I<0x99, RawFrm, (outs), (ins), + "{cwtd|cwd}", []>, OpSize; // DX:AX = signext(AX) + let Defs = [EAX,EDX], Uses = [EAX] in + def CDQ : I<0x99, RawFrm, (outs), (ins), + "{cltd|cdq}", []>; // EDX:EAX = signext(EAX) +} //===----------------------------------------------------------------------===// // Alias Instructions @@ -2480,25 +2496,30 @@ def MOV32r0 : I<0x31, MRMInitReg, (outs GR32:$dst), (ins), // Basic operations on GR16 / GR32 subclasses GR16_ and GR32_ which contains only // those registers that have GR8 sub-registers (i.e. AX - DX, EAX - EDX). +let neverHasSideEffects = 1 in { def MOV16to16_ : I<0x89, MRMDestReg, (outs GR16_:$dst), (ins GR16:$src), "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize; def MOV32to32_ : I<0x89, MRMDestReg, (outs GR32_:$dst), (ins GR32:$src), "mov{l}\t{$src, $dst|$dst, $src}", []>; - + def MOV16_rr : I<0x89, MRMDestReg, (outs GR16_:$dst), (ins GR16_:$src), "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize; def MOV32_rr : I<0x89, MRMDestReg, (outs GR32_:$dst), (ins GR32_:$src), "mov{l}\t{$src, $dst|$dst, $src}", []>; -let isSimpleLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { +} // neverHasSideEffects + +let isSimpleLoad = 1, mayLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { def MOV16_rm : I<0x8B, MRMSrcMem, (outs GR16_:$dst), (ins i16mem:$src), "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize; def MOV32_rm : I<0x8B, MRMSrcMem, (outs GR32_:$dst), (ins i32mem:$src), "mov{l}\t{$src, $dst|$dst, $src}", []>; } +let mayStore = 1, neverHasSideEffects = 1 in { def MOV16_mr : I<0x89, MRMDestMem, (outs), (ins i16mem:$dst, GR16_:$src), "mov{w}\t{$src, $dst|$dst, $src}", []>, OpSize; def MOV32_mr : I<0x89, MRMDestMem, (outs), (ins i32mem:$dst, GR32_:$src), "mov{l}\t{$src, $dst|$dst, $src}", []>; +} //===----------------------------------------------------------------------===// // Thread Local Storage Instructions diff --git a/lib/Target/X86/X86InstrMMX.td b/lib/Target/X86/X86InstrMMX.td index 3362289326..3f2f1debbf 100644 --- a/lib/Target/X86/X86InstrMMX.td +++ b/lib/Target/X86/X86InstrMMX.td @@ -156,17 +156,21 @@ def MMX_FEMMS : MMXI<0x0E, RawFrm, (outs), (ins), "femms", [(int_x86_mmx_femms)] //===----------------------------------------------------------------------===// // Data Transfer Instructions +let neverHasSideEffects = 1 in def MMX_MOVD64rr : MMXI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR32:$src), "movd\t{$src, $dst|$dst, $src}", []>; -let isSimpleLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let isSimpleLoad = 1, mayLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in def MMX_MOVD64rm : MMXI<0x6E, MRMSrcMem, (outs VR64:$dst), (ins i32mem:$src), "movd\t{$src, $dst|$dst, $src}", []>; +let mayStore = 1 in def MMX_MOVD64mr : MMXI<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, VR64:$src), "movd\t{$src, $dst|$dst, $src}", []>; +let neverHasSideEffects = 1 in def MMX_MOVD64to64rr : MMXRI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR64:$src), "movd\t{$src, $dst|$dst, $src}", []>; +let neverHasSideEffects = 1 in def MMX_MOVQ64rr : MMXI<0x6F, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src), "movq\t{$src, $dst|$dst, $src}", []>; let isSimpleLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in @@ -417,35 +421,44 @@ def MMX_PSHUFWmi : MMXIi8<0x70, MRMSrcMem, MMX_PSHUFW_shuffle_mask:$src2)))]>; // -- Conversion Instructions +let neverHasSideEffects = 1 in { def MMX_CVTPD2PIrr : MMX2I<0x2D, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), "cvtpd2pi\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in def MMX_CVTPD2PIrm : MMX2I<0x2D, MRMSrcMem, (outs VR64:$dst), (ins f128mem:$src), "cvtpd2pi\t{$src, $dst|$dst, $src}", []>; def MMX_CVTPI2PDrr : MMX2I<0x2A, MRMSrcReg, (outs VR128:$dst), (ins VR64:$src), "cvtpi2pd\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in def MMX_CVTPI2PDrm : MMX2I<0x2A, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), "cvtpi2pd\t{$src, $dst|$dst, $src}", []>; def MMX_CVTPI2PSrr : MMXI<0x2A, MRMSrcReg, (outs VR128:$dst), (ins VR64:$src), "cvtpi2ps\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in def MMX_CVTPI2PSrm : MMXI<0x2A, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), "cvtpi2ps\t{$src, $dst|$dst, $src}", []>; def MMX_CVTPS2PIrr : MMXI<0x2D, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), "cvtps2pi\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in def MMX_CVTPS2PIrm : MMXI<0x2D, MRMSrcMem, (outs VR64:$dst), (ins f64mem:$src), "cvtps2pi\t{$src, $dst|$dst, $src}", []>; def MMX_CVTTPD2PIrr : MMX2I<0x2C, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), "cvttpd2pi\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in def MMX_CVTTPD2PIrm : MMX2I<0x2C, MRMSrcMem, (outs VR64:$dst), (ins f128mem:$src), "cvttpd2pi\t{$src, $dst|$dst, $src}", []>; def MMX_CVTTPS2PIrr : MMXI<0x2C, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src), "cvttps2pi\t{$src, $dst|$dst, $src}", []>; +let mayLoad = 1 in def MMX_CVTTPS2PIrm : MMXI<0x2C, MRMSrcMem, (outs VR64:$dst), (ins f64mem:$src), "cvttps2pi\t{$src, $dst|$dst, $src}", []>; +} // end neverHasSideEffects + // Extract / Insert def MMX_X86pextrw : SDNode<"X86ISD::PEXTRW", SDTypeProfile<1, 2, []>, []>; diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index 703300379f..c38594c3bd 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -42,7 +42,7 @@ def X86pinsrw : SDNode<"X86ISD::PINSRW", SDTypeProfile<1, 3, []>, []>; // SSE 'Special' Instructions //===----------------------------------------------------------------------===// -let isImplicitDef = 1 in +let isImplicitDef = 1 in { def IMPLICIT_DEF_VR128 : I<0, Pseudo, (outs VR128:$dst), (ins), "#IMPLICIT_DEF $dst", [(set VR128:$dst, (v4f32 (undef)))]>, @@ -53,6 +53,7 @@ def IMPLICIT_DEF_FR32 : I<0, Pseudo, (outs FR32:$dst), (ins), def IMPLICIT_DEF_FR64 : I<0, Pseudo, (outs FR64:$dst), (ins), "#IMPLICIT_DEF $dst", [(set FR64:$dst, (undef))]>, Requires<[HasSSE2]>; +} //===----------------------------------------------------------------------===// // SSE Complex Patterns @@ -62,9 +63,9 @@ def IMPLICIT_DEF_FR64 : I<0, Pseudo, (outs FR64:$dst), (ins), // the top elements. These are used for the SSE 'ss' and 'sd' instruction // forms. def sse_load_f32 : ComplexPattern<v4f32, 4, "SelectScalarSSELoad", [], - [SDNPHasChain]>; + [SDNPHasChain, SDNPMayLoad]>; def sse_load_f64 : ComplexPattern<v2f64, 4, "SelectScalarSSELoad", [], - [SDNPHasChain]>; + [SDNPHasChain, SDNPMayLoad]>; def ssmem : Operand<v4f32> { let PrintMethod = "printf32mem"; @@ -452,6 +453,7 @@ def FsFLD0SS : I<0xEF, MRMInitReg, (outs FR32:$dst), (ins), // Alias instruction to do FR32 reg-to-reg copy using movaps. Upper bits are // disregarded. +let neverHasSideEffects = 1 in def FsMOVAPSrr : PSI<0x28, MRMSrcReg, (outs FR32:$dst), (ins FR32:$src), "movaps\t{$src, $dst|$dst, $src}", []>; @@ -488,14 +490,17 @@ def FsXORPSrm : PSI<0x57, MRMSrcMem, (outs FR32:$dst), (ins FR32:$src1, f128mem: "xorps\t{$src2, $dst|$dst, $src2}", [(set FR32:$dst, (X86fxor FR32:$src1, (memopfsf32 addr:$src2)))]>; - +let neverHasSideEffects = 1 in { def FsANDNPSrr : PSI<0x55, MRMSrcReg, (outs FR32:$dst), (ins FR32:$src1, FR32:$src2), "andnps\t{$src2, $dst|$dst, $src2}", []>; + +let mayLoad = 1 in def FsANDNPSrm : PSI<0x55, MRMSrcMem, (outs FR32:$dst), (ins FR32:$src1, f128mem:$src2), "andnps\t{$src2, $dst|$dst, $src2}", []>; } +} /// basic_sse1_fp_binop_rm - SSE1 binops come in both scalar and vector forms. /// @@ -632,6 +637,7 @@ defm MIN : sse1_fp_binop_rm<0x5D, "min", X86fmin, // SSE packed FP Instructions // Move Instructions +let neverHasSideEffects = 1 in def MOVAPSrr : PSI<0x28, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movaps\t{$src, $dst|$dst, $src}", []>; let isSimpleLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in @@ -1148,6 +1154,7 @@ def FsFLD0SD : I<0xEF, MRMInitReg, (outs FR64:$dst), (ins), // Alias instruction to do FR64 reg-to-reg copy using movapd. Upper bits are // disregarded. +let neverHasSideEffects = 1 in def FsMOVAPDrr : PDI<0x28, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src), "movapd\t{$src, $dst|$dst, $src}", []>; @@ -1185,13 +1192,16 @@ def FsXORPDrm : PDI<0x57, MRMSrcMem, (outs FR64:$dst), (ins FR64:$src1, f128mem: [(set FR64:$dst, (X86fxor FR64:$src1, (memopfsf64 addr:$src2)))]>; +let neverHasSideEffects = 1 in { def FsANDNPDrr : PDI<0x55, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src1, FR64:$src2), "andnpd\t{$src2, $dst|$dst, $src2}", []>; +let mayLoad = 1 in def FsANDNPDrm : PDI<0x55, MRMSrcMem, (outs FR64:$dst), (ins FR64:$src1, f128mem:$src2), "andnpd\t{$src2, $dst|$dst, $src2}", []>; } +} /// basic_sse2_fp_binop_rm - SSE2 binops come in both scalar and vector forms. /// @@ -1328,6 +1338,7 @@ defm MIN : sse2_fp_binop_rm<0x5D, "min", X86fmin, // SSE packed FP Instructions // Move Instructions +let neverHasSideEffects = 1 in def MOVAPDrr : PDI<0x28, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movapd\t{$src, $dst|$dst, $src}", []>; let isSimpleLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in @@ -2117,7 +2128,6 @@ def LFENCE : I<0xAE, MRM5m, (outs), (ins), def MFENCE : I<0xAE, MRM6m, (outs), (ins), "mfence", [(int_x86_sse2_mfence)]>, TB, Requires<[HasSSE2]>; - // Alias instructions that map zero vector to pxor / xorp* for sse. let isReMaterializable = 1 in def V_SETALLONES : PDI<0x76, MRMInitReg, (outs VR128:$dst), (ins), diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 9778db3ccf..0ee6b41d90 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -97,14 +97,14 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) usesCustomDAGSchedInserter = R->getValueAsBit("usesCustomDAGSchedInserter"); hasCtrlDep = R->getValueAsBit("hasCtrlDep"); isNotDuplicable = R->getValueAsBit("isNotDuplicable"); + hasSideEffects = R->getValueAsBit("hasSideEffects"); mayHaveSideEffects = R->getValueAsBit("mayHaveSideEffects"); neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); hasOptionalDef = false; isVariadic = false; - if (mayHaveSideEffects && neverHasSideEffects) - throw R->getName() + - ": cannot have both 'mayHaveSideEffects' and 'neverHasSideEffects' set!"; |