forked from OSchip/llvm-project
Replace M_REMATERIALIZIBLE and the newly-added isOtherReMaterializableLoad
with a general target hook to identify rematerializable instructions. Some instructions are only rematerializable with specific operands, such as loads from constant pools, while others are always rematerializable. This hook allows both to be identified as being rematerializable with the same mechanism. llvm-svn: 37644
This commit is contained in:
parent
a7ca624028
commit
9e82064924
|
@ -78,10 +78,6 @@ 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;
|
||||
|
@ -264,10 +260,6 @@ public:
|
|||
return get(Opcode).Flags & M_PREDICABLE;
|
||||
}
|
||||
|
||||
bool isReMaterializable(MachineOpCode Opcode) const {
|
||||
return get(Opcode).Flags & M_REMATERIALIZIBLE;
|
||||
}
|
||||
|
||||
bool clobbersPredicate(MachineOpCode Opcode) const {
|
||||
return get(Opcode).Flags & M_CLOBBERS_PRED;
|
||||
}
|
||||
|
@ -309,13 +301,13 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/// isOtherReMaterializableLoad - If the specified machine instruction is a
|
||||
/// direct load that is trivially rematerializable, not counting loads from
|
||||
/// stack slots, return true. If not, return false. This predicate must
|
||||
/// 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 isOtherReMaterializableLoad(MachineInstr *MI) const {
|
||||
virtual bool isTriviallyReMaterializable(MachineInstr *MI) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -336,14 +336,13 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
|
|||
// time we see a vreg.
|
||||
if (interval.empty()) {
|
||||
// Remember if the definition can be rematerialized. All load's from fixed
|
||||
// stack slots are re-materializable. The target may permit other loads to
|
||||
// be re-materialized as well.
|
||||
// stack slots are re-materializable. The target may permit other
|
||||
// instructions to be re-materialized as well.
|
||||
int FrameIdx = 0;
|
||||
if (vi.DefInst &&
|
||||
(tii_->isReMaterializable(vi.DefInst->getOpcode()) ||
|
||||
(tii_->isTriviallyReMaterializable(vi.DefInst) ||
|
||||
(tii_->isLoadFromStackSlot(vi.DefInst, FrameIdx) &&
|
||||
mf_->getFrameInfo()->isFixedObjectIndex(FrameIdx)) ||
|
||||
tii_->isOtherReMaterializableLoad(vi.DefInst)))
|
||||
mf_->getFrameInfo()->isFixedObjectIndex(FrameIdx))))
|
||||
interval.remat = vi.DefInst;
|
||||
|
||||
// Get the Idx of the defining instructions.
|
||||
|
|
|
@ -663,9 +663,8 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM,
|
|||
|
||||
// If this instruction is being rematerialized, just remove it!
|
||||
int FrameIdx;
|
||||
if ((TID->Flags & M_REMATERIALIZIBLE) ||
|
||||
TII->isLoadFromStackSlot(&MI, FrameIdx) ||
|
||||
TII->isOtherReMaterializableLoad(&MI)) {
|
||||
if (TII->isTriviallyReMaterializable(&MI) ||
|
||||
TII->isLoadFromStackSlot(&MI, FrameIdx)) {
|
||||
bool Remove = true;
|
||||
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
|
||||
MachineOperand &MO = MI.getOperand(i);
|
||||
|
|
|
@ -130,6 +130,20 @@ 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;
|
||||
|
|
|
@ -87,6 +87,7 @@ 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,
|
||||
|
|
|
@ -670,7 +670,6 @@ 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", []>;
|
||||
|
||||
|
@ -804,7 +803,6 @@ 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)]>;
|
||||
|
||||
|
@ -912,7 +910,6 @@ 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)]>;
|
||||
|
||||
|
@ -1183,7 +1180,6 @@ 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)]>;
|
||||
|
|
|
@ -267,7 +267,6 @@ 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
|
||||
|
|
|
@ -186,7 +186,6 @@ 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.
|
||||
|
|
|
@ -413,12 +413,10 @@ 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;
|
||||
|
|
|
@ -112,9 +112,20 @@ unsigned X86InstrInfo::isStoreToStackSlot(MachineInstr *MI,
|
|||
}
|
||||
|
||||
|
||||
bool X86InstrInfo::isOtherReMaterializableLoad(MachineInstr *MI) const {
|
||||
bool X86InstrInfo::isTriviallyReMaterializable(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:
|
||||
|
@ -128,6 +139,7 @@ bool X86InstrInfo::isOtherReMaterializableLoad(MachineInstr *MI) const {
|
|||
case X86::MOVAPDrm:
|
||||
case X86::MMX_MOVD64rm:
|
||||
case X86::MMX_MOVQ64rm:
|
||||
// Loads from constant pools are trivially rematerializable.
|
||||
return MI->getOperand(1).isRegister() && MI->getOperand(2).isImmediate() &&
|
||||
MI->getOperand(3).isRegister() && MI->getOperand(4).isConstantPoolIndex() &&
|
||||
MI->getOperand(1).getReg() == 0 &&
|
||||
|
|
|
@ -239,7 +239,7 @@ public:
|
|||
unsigned& destReg) const;
|
||||
unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const;
|
||||
unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const;
|
||||
bool isOtherReMaterializableLoad(MachineInstr *MI) const;
|
||||
bool isTriviallyReMaterializable(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
|
||||
|
|
|
@ -617,7 +617,6 @@ 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)]>;
|
||||
|
@ -627,7 +626,6 @@ 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)]>;
|
||||
|
|
|
@ -503,14 +503,12 @@ 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.
|
||||
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))]>;
|
||||
}
|
||||
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
|
||||
|
|
|
@ -759,7 +759,6 @@ 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))]>;
|
||||
|
@ -1819,10 +1818,9 @@ 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.
|
||||
let isReMaterializable = 1 in
|
||||
def V_SETALLONES : PDI<0x76, MRMInitReg, (ops VR128:$dst),
|
||||
"pcmpeqd $dst, $dst",
|
||||
[(set VR128:$dst, (v2f64 immAllOnesV))]>;
|
||||
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),
|
||||
|
|
|
@ -91,7 +91,6 @@ namespace llvm {
|
|||
bool isConvertibleToThreeAddress;
|
||||
bool isCommutable;
|
||||
bool isTerminator;
|
||||
bool isReMaterializable;
|
||||
bool hasDelaySlot;
|
||||
bool usesCustomDAGSchedInserter;
|
||||
bool hasVariableNumberOfOperands;
|
||||
|
|
|
@ -365,7 +365,6 @@ 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");
|
||||
|
|
|
@ -240,7 +240,6 @@ 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)
|
||||
|
|
Loading…
Reference in New Issue