aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2007-08-02 00:28:15 +0000
committerEvan Cheng <evan.cheng@apple.com>2007-08-02 00:28:15 +0000
commit8409747efadda025aa3cce626b1a2c33429fd5e5 (patch)
tree4dcfb93fa84aad0a5e1328b72d7682ef5020fb53
parentb5910820ce8608b75cb88e6c4efd2d1a5858159a (diff)
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
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h9
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAG.cpp146
2 files changed, 87 insertions, 68 deletions
diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h
index fd72aebdb1..d52936abab 100644
--- a/include/llvm/CodeGen/ScheduleDAG.h
+++ b/include/llvm/CodeGen/ScheduleDAG.h
@@ -245,7 +245,16 @@ namespace llvm {
/// EmitNoop - Emit a noop instruction.
///
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 dumpSchedule() const;
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
index cd4e9619fe..3738702dc8 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
@@ -254,15 +254,69 @@ static const TargetRegisterClass *getInstrOperandRegClass(
? TII->getPointerRegClass() : MRI->getRegClass(toi.RegClass);
}
-static void CreateVirtualRegisters(SDNode *Node,
- unsigned NumResults,
- const MRegisterInfo *MRI,
- MachineInstr *MI,
- SSARegMap *RegMap,
- const TargetInstrInfo *TII,
- const TargetInstrDescriptor &II,
- DenseMap<SDOperand, unsigned> &VRBaseMap) {
- for (unsigned i = 0; i < NumResults; ++i) {
+// 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;
+}
+
+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,
+ const TargetInstrDescriptor &II,
+ DenseMap<SDOperand, unsigned> &VRBaseMap) {
+ for (unsigned i = 0; i < II.numDefs; ++i) {
// 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
// a new vreg.
@@ -282,9 +336,9 @@ static void CreateVirtualRegisters(SDNode *Node,
}
}
+ // Create the result registers for this node and add the result regs to
+ // the machine instruction.
if (VRBase == 0) {
- // Create the result registers for this node and add the result regs to
- // the machine instruction.
const TargetRegisterClass *RC = getInstrOperandRegClass(MRI, TII, &II, i);
assert(RC && "Isn't a register operand!");
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
static const TargetRegisterClass *getSubRegisterRegClass(
const TargetRegisterClass *TRC,
@@ -591,9 +629,10 @@ void ScheduleDAG::EmitNode(SDNode *Node,
unsigned NumResults = CountResults(Node);
unsigned NodeOperands = CountOperands(Node);
unsigned NumMIOperands = NodeOperands + NumResults;
+ bool HasPhysRegOuts = (NumResults > II.numDefs) && II.ImplicitDefs;
#ifndef NDEBUG
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!");
#endif
@@ -603,13 +642,12 @@ void ScheduleDAG::EmitNode(SDNode *Node,
// Add result register values for things that are defined by this
// instruction.
if (NumResults)
- CreateVirtualRegisters(Node, NumResults, MRI, MI, RegMap,
- TII, II, VRBaseMap);
+ CreateVirtualRegisters(Node, MI, II, VRBaseMap);
// Emit all of the actual operands of this instruction, adding them to the
// instruction as appropriate.
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.
if (CommuteSet.count(Node)) {
@@ -633,6 +671,14 @@ void ScheduleDAG::EmitNode(SDNode *Node,
// taking some custom action.
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 {
switch (Node->getOpcode()) {
default:
@@ -665,44 +711,8 @@ void ScheduleDAG::EmitNode(SDNode *Node,
break;
}
case ISD::CopyFromReg: {
- unsigned VRBase = 0;
unsigned SrcReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg();
- if (MRegisterInfo::isVirtualRegister(SrcReg)) {
- // 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");
+ EmitCopyFromReg(Node, 0, SrcReg, VRBaseMap);
break;
}
case ISD::INLINEASM: {