diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 339b39171fd..8fa73a78d9b 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -78,6 +78,10 @@ const unsigned M_VARIABLE_OPS = 1 << 11; // controls execution. It may be set to 'always'. const unsigned M_PREDICABLE = 1 << 12; +// M_REMATERIALIZIBLE - Set if this instruction can be trivally re-materialized +// at any time, e.g. constant generation, load from constant pool. +const unsigned M_REMATERIALIZIBLE = 1 << 13; + // M_CLOBBERS_PRED - Set if this instruction may clobbers the condition code // register and / or registers that are used to predicate instructions. const unsigned M_CLOBBERS_PRED = 1 << 14; @@ -268,6 +272,28 @@ public: return get(Opcode).Flags & M_NOT_DUPLICABLE; } + /// isTriviallyReMaterializable - Return true if the instruction is trivially + /// rematerializable, meaning it has no side effects and requires no operands + /// that aren't always available. + bool isTriviallyReMaterializable(MachineInstr *MI) const { + return (MI->getInstrDescriptor()->Flags & M_REMATERIALIZIBLE) && + isReallyTriviallyReMaterializable(MI); + } + +protected: + /// isReallyTriviallyReMaterializable - For instructions with opcodes for + /// which the M_REMATERIALIZABLE flag is set, this function tests whether the + /// instruction itself is actually trivially rematerializable, considering + /// its operands. This is used for targets that have instructions that are + /// only trivially rematerializable for specific uses. This predicate must + /// return false if the instruction has any side effects other than + /// producing a value, or if it requres any address registers that are not + /// always available. + virtual bool isReallyTriviallyReMaterializable(MachineInstr *MI) const { + return true; + } + +public: /// getOperandConstraint - Returns the value of the specific constraint if /// it is set. Returns -1 if it is not set. int getOperandConstraint(MachineOpCode Opcode, unsigned OpNum, @@ -301,16 +327,6 @@ public: return 0; } - /// isTriviallyReMaterializable - If the specified machine instruction can - /// be trivally re-materialized at any time, e.g. constant generation or - /// loads from constant pools. If not, return false. This predicate must - /// return false if the instruction has any side effects other than - /// producing the value from the load, or if it requres any address - /// registers that are not always available. - virtual bool isTriviallyReMaterializable(MachineInstr *MI) const { - return false; - } - /// 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 one or moretrue diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp index a1e02581cd0..1370faba4d7 100644 --- a/lib/Target/ARM/ARMInstrInfo.cpp +++ b/lib/Target/ARM/ARMInstrInfo.cpp @@ -130,20 +130,6 @@ unsigned ARMInstrInfo::isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) con return 0; } -bool ARMInstrInfo::isTriviallyReMaterializable(MachineInstr *MI) const { - switch (MI->getOpcode()) { - default: break; - case ARM::LDRcp: - case ARM::MOVi: - case ARM::MVNi: - case ARM::MOVi2pieces: - case ARM::tLDRcp: - // These instructions are always trivially rematerializable. - return true; - } - return false; -} - static unsigned getUnindexedOpcode(unsigned Opc) { switch (Opc) { default: break; diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h index 8e6a2fd5ad7..5b406cb8168 100644 --- a/lib/Target/ARM/ARMInstrInfo.h +++ b/lib/Target/ARM/ARMInstrInfo.h @@ -87,7 +87,6 @@ public: unsigned &SrcReg, unsigned &DstReg) const; virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const; virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const; - virtual bool isTriviallyReMaterializable(MachineInstr *MI) const; virtual MachineInstr *convertToThreeAddress(MachineFunction::iterator &MFI, MachineBasicBlock::iterator &MBBI, diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index deeb236cb3b..db6814c54db 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -677,6 +677,7 @@ def LDR : AI2<(ops GPR:$dst, addrmode2:$addr), [(set GPR:$dst, (load addrmode2:$addr))]>; // Special LDR for loads from non-pc-relative constpools. +let isReMaterializable = 1 in def LDRcp : AI2<(ops GPR:$dst, addrmode2:$addr), "ldr", " $dst, $addr", []>; @@ -810,6 +811,7 @@ def MOVr : AI1<(ops GPR:$dst, GPR:$src), def MOVs : AI1<(ops GPR:$dst, so_reg:$src), "mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>; +let isReMaterializable = 1 in def MOVi : AI1<(ops GPR:$dst, so_imm:$src), "mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>; @@ -917,6 +919,7 @@ def MVNr : AI<(ops GPR:$dst, GPR:$src), "mvn", " $dst, $src", [(set GPR:$dst, (not GPR:$src))]>; def MVNs : AI<(ops GPR:$dst, so_reg:$src), "mvn", " $dst, $src", [(set GPR:$dst, (not so_reg:$src))]>; +let isReMaterializable = 1 in def MVNi : AI<(ops GPR:$dst, so_imm:$imm), "mvn", " $dst, $imm", [(set GPR:$dst, so_imm_not:$imm)]>; @@ -1187,6 +1190,7 @@ def : ARMPat<(ARMWrapperJT tjumptable:$dst, imm:$id), // Large immediate handling. // Two piece so_imms. +let isReMaterializable = 1 in def MOVi2pieces : AI1x2<(ops GPR:$dst, so_imm2part:$src), "mov", " $dst, $src", [(set GPR:$dst, so_imm2part:$src)]>; diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index de71410e0af..996b635338e 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -267,6 +267,7 @@ def tLDRpci : TIs<(ops GPR:$dst, i32imm:$addr), [(set GPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>; // Special LDR for loads from non-pc-relative constpools. +let isReMaterializable = 1 in def tLDRcp : TIs<(ops GPR:$dst, i32imm:$addr), "ldr $dst, $addr", []>; } // isLoad diff --git a/lib/Target/Target.td b/lib/Target/Target.td index 2258199ddf0..43e3af8667a 100644 --- a/lib/Target/Target.td +++ b/lib/Target/Target.td @@ -186,6 +186,7 @@ class Instruction { bit isConvertibleToThreeAddress = 0; // Can this 2-addr instruction promote? bit isCommutable = 0; // Is this 3 operand instruction commutable? bit isTerminator = 0; // Is this part of the terminator for a basic block? + bit isReMaterializable = 0; // Is this instruction re-materializable? bit isPredicable = 0; // Is this instruction predicable? bit hasDelaySlot = 0; // Does this instruction have an delay slot? bit usesCustomDAGSchedInserter = 0; // Pseudo instr needing special help. diff --git a/lib/Target/X86/X86InstrFPStack.td b/lib/Target/X86/X86InstrFPStack.td index 48b216a199c..848d370db4d 100644 --- a/lib/Target/X86/X86InstrFPStack.td +++ b/lib/Target/X86/X86InstrFPStack.td @@ -413,10 +413,12 @@ def FSTPrr : FPI<0xD8, AddRegFrm, (ops RST:$op), "fstp $op">, DD; def FXCH : FPI<0xC8, AddRegFrm, (ops RST:$op), "fxch $op">, D9; // Floating point constant loads. +let isReMaterializable = 1 in { def FpLD0 : FpI<(ops RFP:$dst), ZeroArgFP, [(set RFP:$dst, fp64imm0)]>; def FpLD1 : FpI<(ops RFP:$dst), ZeroArgFP, [(set RFP:$dst, fp64imm1)]>; +} def FLD0 : FPI<0xEE, RawFrm, (ops), "fldz">, D9; def FLD1 : FPI<0xE8, RawFrm, (ops), "fld1">, D9; diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 0e02ef0be84..99594906a68 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -112,20 +112,9 @@ unsigned X86InstrInfo::isStoreToStackSlot(MachineInstr *MI, } -bool X86InstrInfo::isTriviallyReMaterializable(MachineInstr *MI) const { +bool X86InstrInfo::isReallyTriviallyReMaterializable(MachineInstr *MI) const { switch (MI->getOpcode()) { default: break; - case X86::FpLD0: - case X86::FpLD1: - case X86::MOV8ri: - case X86::MOV16ri: - case X86::MOV32ri: - case X86::MMX_V_SET0: - case X86::MMX_V_SETALLONES: - case X86::V_SET0: - case X86::V_SETALLONES: - // These instructions are always trivially rematerializable. - return true; case X86::MOV8rm: case X86::MOV16rm: case X86::MOV16_rm: @@ -146,7 +135,9 @@ bool X86InstrInfo::isTriviallyReMaterializable(MachineInstr *MI) const { MI->getOperand(2).getImmedValue() == 1 && MI->getOperand(3).getReg() == 0; } - return false; + // All other instructions marked M_REMATERIALIZABLE are always trivially + // rematerializable. + return true; } /// convertToThreeAddress - This method must be implemented by targets that diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index f3d571a43dd..ec30cc7c8c9 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -239,7 +239,7 @@ public: unsigned& destReg) const; unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const; unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const; - bool isTriviallyReMaterializable(MachineInstr *MI) const; + bool isReallyTriviallyReMaterializable(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 diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index a221c42a1bd..f8eac7e7049 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -617,6 +617,7 @@ def MOV16rr : I<0x89, MRMDestReg, (ops GR16:$dst, GR16:$src), "mov{w} {$src, $dst|$dst, $src}", []>, OpSize; def MOV32rr : I<0x89, MRMDestReg, (ops GR32:$dst, GR32:$src), "mov{l} {$src, $dst|$dst, $src}", []>; +let isReMaterializable = 1 in { def MOV8ri : Ii8 <0xB0, AddRegFrm, (ops GR8 :$dst, i8imm :$src), "mov{b} {$src, $dst|$dst, $src}", [(set GR8:$dst, imm:$src)]>; @@ -626,6 +627,7 @@ def MOV16ri : Ii16<0xB8, AddRegFrm, (ops GR16:$dst, i16imm:$src), def MOV32ri : Ii32<0xB8, AddRegFrm, (ops GR32:$dst, i32imm:$src), "mov{l} {$src, $dst|$dst, $src}", [(set GR32:$dst, imm:$src)]>; +} def MOV8mi : Ii8 <0xC6, MRM0m, (ops i8mem :$dst, i8imm :$src), "mov{b} {$src, $dst|$dst, $src}", [(store (i8 imm:$src), addr:$dst)]>; diff --git a/lib/Target/X86/X86InstrMMX.td b/lib/Target/X86/X86InstrMMX.td index cc22f4fb585..897d8f2aab2 100644 --- a/lib/Target/X86/X86InstrMMX.td +++ b/lib/Target/X86/X86InstrMMX.td @@ -503,12 +503,14 @@ def MMX_MASKMOVQ : MMXI<0xF7, MRMDestMem, (ops VR64:$src, VR64:$mask), // Alias instructions that map zero vector to pxor. // FIXME: remove when we can teach regalloc that xor reg, reg is ok. -def MMX_V_SET0 : MMXI<0xEF, MRMInitReg, (ops VR64:$dst), - "pxor $dst, $dst", - [(set VR64:$dst, (v1i64 immAllZerosV))]>; -def MMX_V_SETALLONES : MMXI<0x76, MRMInitReg, (ops VR64:$dst), - "pcmpeqd $dst, $dst", - [(set VR64:$dst, (v1i64 immAllOnesV))]>; +let isReMaterializable = 1 in { + def MMX_V_SET0 : MMXI<0xEF, MRMInitReg, (ops VR64:$dst), + "pxor $dst, $dst", + [(set VR64:$dst, (v1i64 immAllZerosV))]>; + def MMX_V_SETALLONES : MMXI<0x76, MRMInitReg, (ops VR64:$dst), + "pcmpeqd $dst, $dst", + [(set VR64:$dst, (v1i64 immAllOnesV))]>; +} //===----------------------------------------------------------------------===// // Non-Instruction Patterns diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index 78574eee6c0..d604091aefe 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -762,6 +762,7 @@ def STMXCSR : PSI<0xAE, MRM3m, (ops i32mem:$dst), // Alias instructions that map zero vector to pxor / xorp* for sse. // FIXME: remove when we can teach regalloc that xor reg, reg is ok. +let isReMaterializable = 1 in def V_SET0 : PSI<0x57, MRMInitReg, (ops VR128:$dst), "xorps $dst, $dst", [(set VR128:$dst, (v4f32 immAllZerosV))]>; @@ -1821,9 +1822,10 @@ def MFENCE : I<0xAE, MRM6m, (ops), // Alias instructions that map zero vector to pxor / xorp* for sse. // FIXME: remove when we can teach regalloc that xor reg, reg is ok. -def V_SETALLONES : PDI<0x76, MRMInitReg, (ops VR128:$dst), - "pcmpeqd $dst, $dst", - [(set VR128:$dst, (v2f64 immAllOnesV))]>; +let isReMaterializable = 1 in + def V_SETALLONES : PDI<0x76, MRMInitReg, (ops VR128:$dst), + "pcmpeqd $dst, $dst", + [(set VR128:$dst, (v2f64 immAllOnesV))]>; // FR64 to 128-bit vector conversion. def MOVSD2PDrr : SDI<0x10, MRMSrcReg, (ops VR128:$dst, FR64:$src), diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 4f76de8f35c..54d9b3fea7b 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -91,6 +91,7 @@ namespace llvm { bool isConvertibleToThreeAddress; bool isCommutable; bool isTerminator; + bool isReMaterializable; bool hasDelaySlot; bool usesCustomDAGSchedInserter; bool hasVariableNumberOfOperands; diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index b02c423ad74..c54ecd02e48 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -365,6 +365,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); isCommutable = R->getValueAsBit("isCommutable"); isTerminator = R->getValueAsBit("isTerminator"); + isReMaterializable = R->getValueAsBit("isReMaterializable"); hasDelaySlot = R->getValueAsBit("hasDelaySlot"); usesCustomDAGSchedInserter = R->getValueAsBit("usesCustomDAGSchedInserter"); hasCtrlDep = R->getValueAsBit("hasCtrlDep"); diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index bf027dd29a4..af01e4cd75a 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -240,6 +240,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isConvertibleToThreeAddress) OS << "|M_CONVERTIBLE_TO_3_ADDR"; if (Inst.isCommutable) OS << "|M_COMMUTABLE"; if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG"; + if (Inst.isReMaterializable) OS << "|M_REMATERIALIZIBLE"; if (Inst.clobbersPred) OS << "|M_CLOBBERS_PRED"; if (Inst.isNotDuplicable) OS << "|M_NOT_DUPLICABLE"; if (Inst.usesCustomDAGSchedInserter)