mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-10-05 11:17:53 +00:00
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:
@@ -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;
|
||||||
|
@@ -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: {
|
||||||
|
Reference in New Issue
Block a user