summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-01-10 07:59:24 +0000
committerChris Lattner <sabre@nondot.org>2008-01-10 07:59:24 +0000
commitba7e756c22446a17a72632b8d4ac66cbdaab33f7 (patch)
tree35b58e8e83a49bdd3f3449e138228e57cacb0b77
parent1778a1590125dbef01b8d85128a11b6fb212b26f (diff)
downloadllvm-ba7e756c22446a17a72632b8d4ac66cbdaab33f7.tar.gz
llvm-ba7e756c22446a17a72632b8d4ac66cbdaab33f7.tar.bz2
llvm-ba7e756c22446a17a72632b8d4ac66cbdaab33f7.tar.xz
Start inferring side effect information more aggressively, and fix many bugs in the
x86 backend where instructions were not marked maystore/mayload, and perf issues where instructions were not marked neverHasSideEffects. It would be really nice if we could write patterns for copy instructions. I have audited all the x86 instructions down to MOVDQAmr. The flags on others and on other targets are probably not right in all cases, but no clients currently use this info that are enabled by default. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45829 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Target.td15
-rw-r--r--lib/Target/X86/X86Instr64bit.td45
-rw-r--r--lib/Target/X86/X86InstrFPStack.td48
-rw-r--r--lib/Target/X86/X86InstrInfo.td81
-rw-r--r--lib/Target/X86/X86InstrMMX.td15
-rw-r--r--lib/Target/X86/X86InstrSSE.td20
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp6
-rw-r--r--utils/TableGen/CodeGenInstruction.h3
-rw-r--r--utils/TableGen/CodeGenTarget.cpp6
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp55
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!";
+ if (mayHaveSideEffects + neverHasSideEffects + hasSideEffects > 1)
+ throw R->getName() + ": multiple conflicting side-effect flags set!";
DagInit *DI;
try {
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index f3cdbfec9f..ad076a2074 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -103,8 +103,7 @@ namespace llvm {
bool hasCtrlDep;
bool isNotDuplicable;
bool hasOptionalDef;
- bool mayHaveSideEffects;
- bool neverHasSideEffects;
+ bool hasSideEffects, mayHaveSideEffects, neverHasSideEffects;
/// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar",
/// where $foo is a whole operand and $foo.bar refers to a suboperand.
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index 53dbbf86f1..cf33fe6b1a 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -340,6 +340,12 @@ ComplexPattern::ComplexPattern(Record *R) {
Properties |= 1 << SDNPHasChain;
} else if (PropList[i]->getName() == "SDNPOptInFlag") {
Properties |= 1 << SDNPOptInFlag;
+ } else if (PropList[i]->getName() == "SDNPMayStore") {
+ Properties |= 1 << SDNPMayStore;
+ } else if (PropList[i]->getName() == "SDNPMayLoad") {
+ Properties |= 1 << SDNPMayLoad;
+ } else if (PropList[i]->getName() == "SDNPSideEffect") {
+ Properties |= 1 << SDNPSideEffect;
} else {
cerr << "Unsupported SD Node property '" << PropList[i]->getName()
<< "' on ComplexPattern '" << R->getName() << "'!\n";
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index bcb8be6625..ed48c33004 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -152,22 +152,36 @@ public:
: CDP(cdp), mayStore(maystore), mayLoad(mayload), HasSideEffects(hse){
}
- void Analyze(Record *InstRecord) {
+ /// Analyze - Analyze the specified instruction, returning true if the
+ /// instruction had a pattern.
+ bool Analyze(Record *InstRecord) {
const TreePattern *Pattern = CDP.getInstruction(InstRecord).getPattern();
if (Pattern == 0) {
HasSideEffects = 1;
- return; // No pattern.
+ return false; // No pattern.
}
// FIXME: Assume only the first tree is the pattern. The others are clobber
// nodes.
AnalyzeNode(Pattern->getTree(0));
+ return true;
}
private:
void AnalyzeNode(const TreePatternNode *N) {
- if (N->isLeaf())
+ if (N->isLeaf()) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
+ Record *LeafRec = DI->getDef();
+ // Handle ComplexPattern leaves.
+ if (LeafRec->isSubClassOf("ComplexPattern")) {
+ const ComplexPattern &CP = CDP.getComplexPattern(LeafRec);
+ if (CP.hasProperty(SDNPMayStore)) mayStore = true;
+ if (CP.hasProperty(SDNPMayLoad)) mayLoad = true;
+ if (CP.hasProperty(SDNPSideEffect)) HasSideEffects = true;
+ }
+ }
return;
+ }
// Analyze children.
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
@@ -180,17 +194,10 @@ private:
// Get information about the SDNode for the operator.
const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N->getOperator());
- // If node writes to memory, it obviously stores to memory.
- if (OpInfo.hasProperty(SDNPMayStore))
- mayStore = true;
-
- // If it reads memory, remember this.
- if (OpInfo.hasProperty(SDNPMayLoad))
- mayLoad = true;
-
- // If it reads memory, remember this.
- if (OpInfo.hasProperty(SDNPSideEffect))
- HasSideEffects = true;
+ // Notice properties of the node.
+ if (OpInfo.hasProperty(SDNPMayStore)) mayStore = true;
+ if (OpInfo.hasProperty(SDNPMayLoad)) mayLoad = true;
+ if (OpInfo.hasProperty(SDNPSideEffect)) HasSideEffects = true;
if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) {
// If this is an intrinsic, analyze it.
@@ -213,7 +220,8 @@ void InstrInfoEmitter::InferFromPattern(const CodeGenInstruction &Inst,
bool &HasSideEffects) {
MayStore = MayLoad = HasSideEffects = false;
- InstAnalyzer(CDP, MayStore, MayLoad, HasSideEffects).Analyze(Inst.TheDef);
+ bool HadPattern =
+ InstAnalyzer(CDP, MayStore, MayLoad, HasSideEffects).Analyze(Inst.TheDef);
// InstAnalyzer only correctly analyzes mayStore/mayLoad so far.
if (Inst.mayStore) { // If the .td file explicitly sets mayStore, use it.
@@ -239,15 +247,18 @@ void InstrInfoEmitter::InferFromPattern(const CodeGenInstruction &Inst,
}
if (Inst.neverHasSideEffects) {
- // If we already decided that this instruction has no side effects, then the
- // .td file entry is redundant.
- if (!HasSideEffects)
- fprintf(stderr,
- "Warning: neverHasSideEffects flag explicitly set on instruction"
- " '%s' but flag already inferred from pattern.\n",
- Inst.TheDef->getName().c_str());
+ if (HadPattern)
+ fprintf(stderr, "Warning: neverHasSideEffects set on instruction '%s' "
+ "which already has a pattern\n", Inst.TheDef->getName().c_str());
HasSideEffects = false;
}
+
+ if (Inst.hasSideEffects) {
+ if (HasSideEffects)
+ fprintf(stderr, "Warning: hasSideEffects set on instruction '%s' "
+ "which already inferred this.\n", Inst.TheDef->getName().c_str());
+ HasSideEffects = true;
+ }
}