Instead of adding copyfromreg's to handle physical definitions. Now isel can

simply specify them as results and let scheduledag handle them. That
is, instead of
SDOperand Flag = DAG.getTargetNode(Opc, MVT::i32, MVT::Flag, ...)
SDOperand Result = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, Flag)

Just write:
SDOperand Result = DAG.getTargetNode(Opc, MVT::i32, MVT::i32, ...)

And let scheduledag emit the move from X86::EAX to a virtual register.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40710 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng
2007-08-02 00:28:15 +00:00
parent b5910820ce
commit 8409747efa
2 changed files with 87 additions and 68 deletions

View File

@@ -246,6 +246,15 @@ namespace llvm {
/// ///
void EmitNoop(); void EmitNoop();
/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
/// implicit physical register output.
void EmitCopyFromReg(SDNode *Node, unsigned ResNo, unsigned SrcReg,
DenseMap<SDOperand, unsigned> &VRBaseMap);
void CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
const TargetInstrDescriptor &II,
DenseMap<SDOperand, unsigned> &VRBaseMap);
void EmitSchedule(); void EmitSchedule();
void dumpSchedule() const; void dumpSchedule() const;

View File

@@ -254,15 +254,69 @@ static const TargetRegisterClass *getInstrOperandRegClass(
? TII->getPointerRegClass() : MRI->getRegClass(toi.RegClass); ? TII->getPointerRegClass() : MRI->getRegClass(toi.RegClass);
} }
static void CreateVirtualRegisters(SDNode *Node, // Returns the Register Class of a physical register
unsigned NumResults, static const TargetRegisterClass *getPhysicalRegisterRegClass(
const MRegisterInfo *MRI, const MRegisterInfo *MRI,
MVT::ValueType VT,
unsigned reg) {
assert(MRegisterInfo::isPhysicalRegister(reg) &&
"reg must be a physical register");
// Pick the register class of the right type that contains this physreg.
for (MRegisterInfo::regclass_iterator I = MRI->regclass_begin(),
E = MRI->regclass_end(); I != E; ++I)
if ((*I)->hasType(VT) && (*I)->contains(reg))
return *I;
assert(false && "Couldn't find the register class");
return 0;
}
void ScheduleDAG::EmitCopyFromReg(SDNode *Node, unsigned ResNo, unsigned SrcReg,
DenseMap<SDOperand, unsigned> &VRBaseMap) {
unsigned VRBase = 0;
if (MRegisterInfo::isVirtualRegister(SrcReg)) {
// Just use the input register directly!
bool isNew = VRBaseMap.insert(std::make_pair(SDOperand(Node,ResNo),SrcReg));
assert(isNew && "Node emitted out of order - early");
return;
}
// If the node is only used by a CopyToReg and the dest reg is a vreg, use
// the CopyToReg'd destination register instead of creating a new vreg.
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
UI != E; ++UI) {
SDNode *Use = *UI;
if (Use->getOpcode() == ISD::CopyToReg &&
Use->getOperand(2).Val == Node &&
Use->getOperand(2).ResNo == ResNo) {
unsigned DestReg = cast<RegisterSDNode>(Use->getOperand(1))->getReg();
if (MRegisterInfo::isVirtualRegister(DestReg)) {
VRBase = DestReg;
break;
}
}
}
// Figure out the register class to create for the destreg.
const TargetRegisterClass *TRC = 0;
if (VRBase) {
TRC = RegMap->getRegClass(VRBase);
} else {
TRC = getPhysicalRegisterRegClass(MRI, Node->getValueType(ResNo), SrcReg);
// Create the reg, emit the copy.
VRBase = RegMap->createVirtualRegister(TRC);
}
MRI->copyRegToReg(*BB, BB->end(), VRBase, SrcReg, TRC);
bool isNew = VRBaseMap.insert(std::make_pair(SDOperand(Node,ResNo), VRBase));
assert(isNew && "Node emitted out of order - early");
}
void ScheduleDAG::CreateVirtualRegisters(SDNode *Node,
MachineInstr *MI, MachineInstr *MI,
SSARegMap *RegMap,
const TargetInstrInfo *TII,
const TargetInstrDescriptor &II, const TargetInstrDescriptor &II,
DenseMap<SDOperand, unsigned> &VRBaseMap) { DenseMap<SDOperand, unsigned> &VRBaseMap) {
for (unsigned i = 0; i < NumResults; ++i) { for (unsigned i = 0; i < II.numDefs; ++i) {
// If the specific node value is only used by a CopyToReg and the dest reg // If the specific node value is only used by a CopyToReg and the dest reg
// is a vreg, use the CopyToReg'd destination register instead of creating // is a vreg, use the CopyToReg'd destination register instead of creating
// a new vreg. // a new vreg.
@@ -282,9 +336,9 @@ static void CreateVirtualRegisters(SDNode *Node,
} }
} }
if (VRBase == 0) {
// Create the result registers for this node and add the result regs to // Create the result registers for this node and add the result regs to
// the machine instruction. // the machine instruction.
if (VRBase == 0) {
const TargetRegisterClass *RC = getInstrOperandRegClass(MRI, TII, &II, i); const TargetRegisterClass *RC = getInstrOperandRegClass(MRI, TII, &II, i);
assert(RC && "Isn't a register operand!"); assert(RC && "Isn't a register operand!");
VRBase = RegMap->createVirtualRegister(RC); VRBase = RegMap->createVirtualRegister(RC);
@@ -413,22 +467,6 @@ void ScheduleDAG::AddOperand(MachineInstr *MI, SDOperand Op,
} }
// Returns the Register Class of a physical register
static const TargetRegisterClass *getPhysicalRegisterRegClass(
const MRegisterInfo *MRI,
MVT::ValueType VT,
unsigned reg) {
assert(MRegisterInfo::isPhysicalRegister(reg) &&
"reg must be a physical register");
// Pick the register class of the right type that contains this physreg.
for (MRegisterInfo::regclass_iterator I = MRI->regclass_begin(),
E = MRI->regclass_end(); I != E; ++I)
if ((*I)->hasType(VT) && (*I)->contains(reg))
return *I;
assert(false && "Couldn't find the register class");
return 0;
}
// Returns the Register Class of a subregister // Returns the Register Class of a subregister
static const TargetRegisterClass *getSubRegisterRegClass( static const TargetRegisterClass *getSubRegisterRegClass(
const TargetRegisterClass *TRC, const TargetRegisterClass *TRC,
@@ -591,9 +629,10 @@ void ScheduleDAG::EmitNode(SDNode *Node,
unsigned NumResults = CountResults(Node); unsigned NumResults = CountResults(Node);
unsigned NodeOperands = CountOperands(Node); unsigned NodeOperands = CountOperands(Node);
unsigned NumMIOperands = NodeOperands + NumResults; unsigned NumMIOperands = NodeOperands + NumResults;
bool HasPhysRegOuts = (NumResults > II.numDefs) && II.ImplicitDefs;
#ifndef NDEBUG #ifndef NDEBUG
assert((unsigned(II.numOperands) == NumMIOperands || assert((unsigned(II.numOperands) == NumMIOperands ||
(II.Flags & M_VARIABLE_OPS)) && HasPhysRegOuts || (II.Flags & M_VARIABLE_OPS)) &&
"#operands for dag node doesn't match .td file!"); "#operands for dag node doesn't match .td file!");
#endif #endif
@@ -603,13 +642,12 @@ void ScheduleDAG::EmitNode(SDNode *Node,
// Add result register values for things that are defined by this // Add result register values for things that are defined by this
// instruction. // instruction.
if (NumResults) if (NumResults)
CreateVirtualRegisters(Node, NumResults, MRI, MI, RegMap, CreateVirtualRegisters(Node, MI, II, VRBaseMap);
TII, II, VRBaseMap);
// Emit all of the actual operands of this instruction, adding them to the // Emit all of the actual operands of this instruction, adding them to the
// instruction as appropriate. // instruction as appropriate.
for (unsigned i = 0; i != NodeOperands; ++i) for (unsigned i = 0; i != NodeOperands; ++i)
AddOperand(MI, Node->getOperand(i), i+NumResults, &II, VRBaseMap); AddOperand(MI, Node->getOperand(i), i+II.numDefs, &II, VRBaseMap);
// Commute node if it has been determined to be profitable. // Commute node if it has been determined to be profitable.
if (CommuteSet.count(Node)) { if (CommuteSet.count(Node)) {
@@ -633,6 +671,14 @@ void ScheduleDAG::EmitNode(SDNode *Node,
// taking some custom action. // taking some custom action.
BB = DAG.getTargetLoweringInfo().InsertAtEndOfBasicBlock(MI, BB); BB = DAG.getTargetLoweringInfo().InsertAtEndOfBasicBlock(MI, BB);
} }
// Additional results must be an physical register def.
if (HasPhysRegOuts) {
for (unsigned i = II.numDefs; i < NumResults; ++i) {
unsigned Reg = II.ImplicitDefs[i - II.numDefs];
EmitCopyFromReg(Node, i, Reg, VRBaseMap);
}
}
} else { } else {
switch (Node->getOpcode()) { switch (Node->getOpcode()) {
default: default:
@@ -665,44 +711,8 @@ void ScheduleDAG::EmitNode(SDNode *Node,
break; break;
} }
case ISD::CopyFromReg: { case ISD::CopyFromReg: {
unsigned VRBase = 0;
unsigned SrcReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg(); unsigned SrcReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg();
if (MRegisterInfo::isVirtualRegister(SrcReg)) { EmitCopyFromReg(Node, 0, SrcReg, VRBaseMap);
// Just use the input register directly!
bool isNew = VRBaseMap.insert(std::make_pair(SDOperand(Node,0),SrcReg));
assert(isNew && "Node emitted out of order - early");
break;
}
// If the node is only used by a CopyToReg and the dest reg is a vreg, use
// the CopyToReg'd destination register instead of creating a new vreg.
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
UI != E; ++UI) {
SDNode *Use = *UI;
if (Use->getOpcode() == ISD::CopyToReg &&
Use->getOperand(2).Val == Node) {
unsigned DestReg = cast<RegisterSDNode>(Use->getOperand(1))->getReg();
if (MRegisterInfo::isVirtualRegister(DestReg)) {
VRBase = DestReg;
break;
}
}
}
// Figure out the register class to create for the destreg.
const TargetRegisterClass *TRC = 0;
if (VRBase) {
TRC = RegMap->getRegClass(VRBase);
} else {
TRC = getPhysicalRegisterRegClass(MRI, Node->getValueType(0), SrcReg);
// Create the reg, emit the copy.
VRBase = RegMap->createVirtualRegister(TRC);
}
MRI->copyRegToReg(*BB, BB->end(), VRBase, SrcReg, TRC);
bool isNew = VRBaseMap.insert(std::make_pair(SDOperand(Node,0), VRBase));
assert(isNew && "Node emitted out of order - early");
break; break;
} }
case ISD::INLINEASM: { case ISD::INLINEASM: {