diff --git a/lib/Target/X86/X86InstrFPStack.td b/lib/Target/X86/X86InstrFPStack.td index 13b5d229d17..3c6790fc27d 100644 --- a/lib/Target/X86/X86InstrFPStack.td +++ b/lib/Target/X86/X86InstrFPStack.td @@ -349,7 +349,7 @@ def CMOVNP_F : FPI<0xD8, AddRegFrm, (outs RST:$op), (ins), let isLoad = 1 in { def LD_Fp32m : FpIf32<(outs RFP32:$dst), (ins f32mem:$src), ZeroArgFP, [(set RFP32:$dst, (loadf32 addr:$src))]>; -let isReMaterializable = 1 in +let isReMaterializable = 1, mayHaveSideEffects = 1 in def LD_Fp64m : FpIf64<(outs RFP64:$dst), (ins f64mem:$src), ZeroArgFP, [(set RFP64:$dst, (loadf64 addr:$src))]>; def LD_Fp80m : FpI_<(outs RFP80:$dst), (ins f80mem:$src), ZeroArgFP, @@ -466,7 +466,7 @@ def ST_FPrr : FPI<0xD8, AddRegFrm, (outs), (ins RST:$op), "fstp\t$op">, DD; def XCH_F : FPI<0xC8, AddRegFrm, (outs), (ins RST:$op), "fxch\t$op">, D9; // Floating point constant loads. -let isReMaterializable = 1 in { +let isReMaterializable = 1, neverHasSideEffects = 1 in { def LD_Fp032 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, [(set RFP32:$dst, fpimm0)]>; def LD_Fp132 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 9d5e6371199..d6d146f2a55 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -144,6 +144,40 @@ bool X86InstrInfo::isReallyTriviallyReMaterializable(MachineInstr *MI) const { return true; } +/// isReallySideEffectFree - If the M_MAY_HAVE_SIDE_EFFECTS flag is set, this +/// method is called to determine if the specific instance of this instruction +/// has side effects. This is useful in cases of instructions, like loads, which +/// generally always have side effects. A load from a constant pool doesn't have +/// side effects, though. So we need to differentiate it from the general case. +bool X86InstrInfo::isReallySideEffectFree(MachineInstr *MI) const { + switch (MI->getOpcode()) { + default: break; + case X86::MOV8rm: + case X86::MOV16rm: + case X86::MOV16_rm: + case X86::MOV32rm: + case X86::MOV32_rm: + case X86::MOV64rm: + case X86::LD_Fp64m: + case X86::MOVSSrm: + case X86::MOVSDrm: + case X86::MOVAPSrm: + case X86::MOVAPDrm: + case X86::MMX_MOVD64rm: + case X86::MMX_MOVQ64rm: + // Loads from constant pools have no side effects + return MI->getOperand(1).isRegister() && MI->getOperand(2).isImmediate() && + MI->getOperand(3).isRegister() && MI->getOperand(4).isConstantPoolIndex() && + MI->getOperand(1).getReg() == 0 && + MI->getOperand(2).getImmedValue() == 1 && + MI->getOperand(3).getReg() == 0; + } + + // All other instances of these instructions are presumed to have side + // effects. + return false; +} + /// hasLiveCondCodeDef - True if MI has a condition code def, e.g. EFLAGS, that /// is not marked dead. static bool hasLiveCondCodeDef(MachineInstr *MI) { diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index 2694481caab..02d25c73c77 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -240,7 +240,8 @@ public: unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const; unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const; bool isReallyTriviallyReMaterializable(MachineInstr *MI) const; - + bool isReallySideEffectFree(MachineInstr *MI) const; + /// convertToThreeAddress - This method must be implemented by targets that /// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target /// may be able to convert a two-address instruction into a true diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index e41ef7a6041..f3b51dc127d 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -563,7 +563,7 @@ 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 { +let isReMaterializable = 1, neverHasSideEffects = 1 in { def MOV8ri : Ii8 <0xB0, AddRegFrm, (outs GR8 :$dst), (ins i8imm :$src), "mov{b}\t{$src, $dst|$dst, $src}", [(set GR8:$dst, imm:$src)]>; @@ -584,7 +584,7 @@ def MOV32mi : Ii32<0xC7, MRM0m, (outs), (ins i32mem:$dst, i32imm:$src), "mov{l}\t{$src, $dst|$dst, $src}", [(store (i32 imm:$src), addr:$dst)]>; -let isLoad = 1 in { +let isLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { def MOV8rm : I<0x8A, MRMSrcMem, (outs GR8 :$dst), (ins i8mem :$src), "mov{b}\t{$src, $dst|$dst, $src}", [(set GR8:$dst, (load addr:$src))]>; @@ -2463,7 +2463,7 @@ def CDQ : I<0x99, RawFrm, (outs), (ins), // Alias instructions that map movr0 to xor. // FIXME: remove when we can teach regalloc that xor reg, reg is ok. -let Defs = [EFLAGS], isReMaterializable = 1 in { +let Defs = [EFLAGS], isReMaterializable = 1, neverHasSideEffects = 1 in { def MOV8r0 : I<0x30, MRMInitReg, (outs GR8 :$dst), (ins), "xor{b}\t$dst, $dst", [(set GR8:$dst, 0)]>; @@ -2486,7 +2486,7 @@ 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 isLoad = 1 in { +let isLoad = 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), diff --git a/lib/Target/X86/X86InstrMMX.td b/lib/Target/X86/X86InstrMMX.td index 08fa0dfe984..09ba4c9c0a5 100644 --- a/lib/Target/X86/X86InstrMMX.td +++ b/lib/Target/X86/X86InstrMMX.td @@ -158,7 +158,7 @@ def MMX_FEMMS : MMXI<0x0E, RawFrm, (outs), (ins), "femms", [(int_x86_mmx_femms)] // Data Transfer Instructions def MMX_MOVD64rr : MMXI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR32:$src), "movd\t{$src, $dst|$dst, $src}", []>; -let isLoad = 1, isReMaterializable = 1 in +let isLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in def MMX_MOVD64rm : MMXI<0x6E, MRMSrcMem, (outs VR64:$dst), (ins i32mem:$src), "movd\t{$src, $dst|$dst, $src}", []>; def MMX_MOVD64mr : MMXI<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, VR64:$src), @@ -169,7 +169,7 @@ def MMX_MOVD64to64rr : MMXRI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR64:$src), def MMX_MOVQ64rr : MMXI<0x6F, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src), "movq\t{$src, $dst|$dst, $src}", []>; -let isLoad = 1, isReMaterializable = 1 in +let isLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in def MMX_MOVQ64rm : MMXI<0x6F, MRMSrcMem, (outs VR64:$dst), (ins i64mem:$src), "movq\t{$src, $dst|$dst, $src}", [(set VR64:$dst, (load_mmx addr:$src))]>; @@ -487,7 +487,7 @@ def MMX_MASKMOVQ : MMXI<0xF7, MRMDestMem, (outs), (ins VR64:$src, VR64:$mask), //===----------------------------------------------------------------------===// // Alias instructions that map zero vector to pxor. -let isReMaterializable = 1 in { +let isReMaterializable = 1, neverHasSideEffects = 1 in { def MMX_V_SET0 : MMXI<0xEF, MRMInitReg, (outs VR64:$dst), (ins), "pxor\t$dst, $dst", [(set VR64:$dst, (v2i32 immAllZerosV))]>; diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index a4e76b3ce1e..d6a77a2e3bf 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -301,7 +301,7 @@ let Uses = [EFLAGS], usesCustomDAGSchedInserter = 1 in { // Move Instructions def MOVSSrr : SSI<0x10, MRMSrcReg, (outs FR32:$dst), (ins FR32:$src), "movss\t{$src, $dst|$dst, $src}", []>; -let isLoad = 1, isReMaterializable = 1 in +let isLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in def MOVSSrm : SSI<0x10, MRMSrcMem, (outs FR32:$dst), (ins f32mem:$src), "movss\t{$src, $dst|$dst, $src}", [(set FR32:$dst, (loadf32 addr:$src))]>; @@ -445,7 +445,7 @@ def Int_COMISSrm: PSI<0x2F, MRMSrcMem, (outs), // start with 'Fs'. // Alias instructions that map fld0 to pxor for sse. -let isReMaterializable = 1 in +let isReMaterializable = 1, neverHasSideEffects = 1 in def FsFLD0SS : I<0xEF, MRMInitReg, (outs FR32:$dst), (ins), "pxor\t$dst, $dst", [(set FR32:$dst, fp32imm0)]>, Requires<[HasSSE1]>, TB, OpSize; @@ -634,7 +634,7 @@ defm MIN : sse1_fp_binop_rm<0x5D, "min", X86fmin, // Move Instructions def MOVAPSrr : PSI<0x28, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movaps\t{$src, $dst|$dst, $src}", []>; -let isLoad = 1, isReMaterializable = 1 in +let isLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in def MOVAPSrm : PSI<0x28, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "movaps\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (alignedloadv4f32 addr:$src))]>; @@ -940,7 +940,7 @@ def STMXCSR : PSI<0xAE, MRM3m, (outs), (ins i32mem:$dst), "stmxcsr\t$dst", [(int_x86_sse_stmxcsr addr:$dst)]>; // Alias instructions that map zero vector to pxor / xorp* for sse. -let isReMaterializable = 1 in +let isReMaterializable = 1, neverHasSideEffects = 1 in def V_SET0 : PSI<0x57, MRMInitReg, (outs VR128:$dst), (ins), "xorps\t$dst, $dst", [(set VR128:$dst, (v4i32 immAllZerosV))]>; @@ -1003,7 +1003,7 @@ def MOVZSS2PSrm : SSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f32mem:$src), // Move Instructions def MOVSDrr : SDI<0x10, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src), "movsd\t{$src, $dst|$dst, $src}", []>; -let isLoad = 1, isReMaterializable = 1 in +let isLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in def MOVSDrm : SDI<0x10, MRMSrcMem, (outs FR64:$dst), (ins f64mem:$src), "movsd\t{$src, $dst|$dst, $src}", [(set FR64:$dst, (loadf64 addr:$src))]>; @@ -1141,7 +1141,7 @@ def Int_COMISDrm: PDI<0x2F, MRMSrcMem, (outs), (ins VR128:$src1, f128mem:$src2), // start with 'Fs'. // Alias instructions that map fld0 to pxor for sse. -let isReMaterializable = 1 in +let isReMaterializable = 1, neverHasSideEffects = 1 in def FsFLD0SD : I<0xEF, MRMInitReg, (outs FR64:$dst), (ins), "pxor\t$dst, $dst", [(set FR64:$dst, fpimm0)]>, Requires<[HasSSE2]>, TB, OpSize; @@ -1330,7 +1330,7 @@ defm MIN : sse2_fp_binop_rm<0x5D, "min", X86fmin, // Move Instructions def MOVAPDrr : PDI<0x28, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movapd\t{$src, $dst|$dst, $src}", []>; -let isLoad = 1, isReMaterializable = 1 in +let isLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in def MOVAPDrm : PDI<0x28, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "movapd\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (alignedloadv2f64 addr:$src))]>; @@ -2119,7 +2119,7 @@ def MFENCE : I<0xAE, MRM6m, (outs), (ins), // Alias instructions that map zero vector to pxor / xorp* for sse. -let isReMaterializable = 1 in +let isReMaterializable = 1, neverHasSideEffects = 1 in def V_SETALLONES : PDI<0x76, MRMInitReg, (outs VR128:$dst), (ins), "pcmpeqd\t$dst, $dst", [(set VR128:$dst, (v4i32 immAllOnesV))]>; diff --git a/lib/Target/X86/X86InstrX86-64.td b/lib/Target/X86/X86InstrX86-64.td index 91df425242c..ecdbf9eb817 100644 --- a/lib/Target/X86/X86InstrX86-64.td +++ b/lib/Target/X86/X86InstrX86-64.td @@ -201,7 +201,7 @@ def REP_STOSQ : RI<0xAB, RawFrm, (outs), (ins), "{rep;stosq|rep stosq}", def MOV64rr : RI<0x89, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), "mov{q}\t{$src, $dst|$dst, $src}", []>; -let isReMaterializable = 1 in { +let isReMaterializable = 1, neverHasSideEffects = 1 in { def MOV64ri : RIi64<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64imm:$src), "movabs{q}\t{$src, $dst|$dst, $src}", [(set GR64:$dst, imm:$src)]>; @@ -1105,13 +1105,14 @@ def PsMOVZX64rm32: I<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i32mem:$src), // FIXME: remove when we can teach regalloc that xor reg, reg is ok. // FIXME: AddedComplexity gives MOV64r0 a higher priority than MOV64ri32. Remove // when we have a better way to specify isel priority. -let Defs = [EFLAGS], AddedComplexity = 1, isReMaterializable = 1 in +let Defs = [EFLAGS], AddedComplexity = 1, isReMaterializable = 1, + neverHasSideEffects = 1 in def MOV64r0 : RI<0x31, MRMInitReg, (outs GR64:$dst), (ins), "xor{l}\t${dst:subreg32}, ${dst:subreg32}", [(set GR64:$dst, 0)]>; // Materialize i64 constant where top 32-bits are zero. -let AddedComplexity = 1, isReMaterializable = 1 in +let AddedComplexity = 1, isReMaterializable = 1, neverHasSideEffects = 1 in def MOV64ri64i32 : Ii32<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64i32imm:$src), "mov{l}\t{$src, ${dst:subreg32}|${dst:subreg32}, $src}", [(set GR64:$dst, i64immZExt32:$src)]>;