aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Target/Target.td8
-rw-r--r--include/llvm/Target/TargetInstrInfo.h9
-rw-r--r--include/llvm/Target/TargetRegisterInfo.h47
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h13
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp232
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp13
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp6
-rw-r--r--utils/TableGen/CodeGenTarget.cpp11
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp9
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp3
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp79
11 files changed, 337 insertions, 93 deletions
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index 99b314c29b..3ce360bce7 100644
--- a/include/llvm/Target/Target.td
+++ b/include/llvm/Target/Target.td
@@ -400,6 +400,14 @@ def SUBREG_TO_REG : Instruction {
let Namespace = "TargetInstrInfo";
let neverHasSideEffects = 1;
}
+def COPY_TO_SUBCLASS : Instruction {
+ let OutOperandList = (ops unknown:$dst);
+ let InOperandList = (ops unknown:$src, i32imm:$regclass);
+ let AsmString = "";
+ let Namespace = "TargetInstrInfo";
+ let neverHasSideEffects = 1;
+ let isAsCheapAsAMove = 1;
+}
//===----------------------------------------------------------------------===//
// AsmWriter - This class can be implemented by targets that need to customize
diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h
index 6637424bf5..fb41e4d3e5 100644
--- a/include/llvm/Target/TargetInstrInfo.h
+++ b/include/llvm/Target/TargetInstrInfo.h
@@ -73,7 +73,14 @@ public:
/// is often zero, as is commonly used to implement zext operations on
/// target architectures which support it, such as with x86-64 (with
/// zext from i32 to i64 via implicit zero-extension).
- SUBREG_TO_REG = 9
+ SUBREG_TO_REG = 9,
+
+ /// COPY_TO_SUBCLASS - This instruction is a placeholder for a plain
+ /// register-to-register copy into a specific register class. This is only
+ /// used between instruction selection and MachineInstr creation, before
+ /// virtual registers have been created for all the instructions. As with
+ /// normal copies, these may be optimized away by the coalescer.
+ COPY_TO_SUBCLASS = 10
};
unsigned getNumOpcodes() const { return NumOpcodes; }
diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h
index 69011477ca..92f709fbb8 100644
--- a/include/llvm/Target/TargetRegisterInfo.h
+++ b/include/llvm/Target/TargetRegisterInfo.h
@@ -62,6 +62,8 @@ private:
const vt_iterator VTs;
const sc_iterator SubClasses;
const sc_iterator SuperClasses;
+ const sc_iterator SubRegClasses;
+ const sc_iterator SuperRegClasses;
const unsigned RegSize, Alignment; // Size & Alignment of register in bytes
const int CopyCost;
const iterator RegsBegin, RegsEnd;
@@ -72,9 +74,12 @@ public:
const MVT *vts,
const TargetRegisterClass * const *subcs,
const TargetRegisterClass * const *supcs,
+ const TargetRegisterClass * const *subregcs,
+ const TargetRegisterClass * const *superregcs,
unsigned RS, unsigned Al, int CC,
iterator RB, iterator RE)
: ID(id), Name(name), VTs(vts), SubClasses(subcs), SuperClasses(supcs),
+ SubRegClasses(subregcs), SuperRegClasses(superregcs),
RegSize(RS), Alignment(Al), CopyCost(CC), RegsBegin(RB), RegsEnd(RE) {
for (iterator I = RegsBegin, E = RegsEnd; I != E; ++I)
RegSet.insert(*I);
@@ -132,8 +137,32 @@ public:
return I;
}
- /// hasSubClass - return true if the specified TargetRegisterClass is a
- /// sub-register class of this TargetRegisterClass.
+ /// subregclasses_begin / subregclasses_end - Loop over all of
+ /// the subreg register classes of this register class.
+ sc_iterator subregclasses_begin() const {
+ return SubRegClasses;
+ }
+
+ sc_iterator subregclasses_end() const {
+ sc_iterator I = SubRegClasses;
+ while (*I != NULL) ++I;
+ return I;
+ }
+
+ /// superregclasses_begin / superregclasses_end - Loop over all of
+ /// the superreg register classes of this register class.
+ sc_iterator superregclasses_begin() const {
+ return SuperRegClasses;
+ }
+
+ sc_iterator superregclasses_end() const {
+ sc_iterator I = SuperRegClasses;
+ while (*I != NULL) ++I;
+ return I;
+ }
+
+ /// hasSubClass - return true if the the specified TargetRegisterClass
+ /// is a proper subset of this TargetRegisterClass.
bool hasSubClass(const TargetRegisterClass *cs) const {
for (int i = 0; SubClasses[i] != NULL; ++i)
if (SubClasses[i] == cs)
@@ -141,8 +170,8 @@ public:
return false;
}
- /// subclasses_begin / subclasses_end - Loop over all of the sub-classes of
- /// this register class.
+ /// subclasses_begin / subclasses_end - Loop over all of the classes
+ /// that are proper subsets of this register class.
sc_iterator subclasses_begin() const {
return SubClasses;
}
@@ -154,7 +183,7 @@ public:
}
/// hasSuperClass - return true if the specified TargetRegisterClass is a
- /// super-register class of this TargetRegisterClass.
+ /// proper superset of this TargetRegisterClass.
bool hasSuperClass(const TargetRegisterClass *cs) const {
for (int i = 0; SuperClasses[i] != NULL; ++i)
if (SuperClasses[i] == cs)
@@ -162,8 +191,8 @@ public:
return false;
}
- /// superclasses_begin / superclasses_end - Loop over all of the super-classes
- /// of this register class.
+ /// superclasses_begin / superclasses_end - Loop over all of the classes
+ /// that are proper supersets of this register class.
sc_iterator superclasses_begin() const {
return SuperClasses;
}
@@ -174,8 +203,8 @@ public:
return I;
}
- /// isASubClass - return true if this TargetRegisterClass is a sub-class of at
- /// least one other TargetRegisterClass.
+ /// isASubClass - return true if this TargetRegisterClass is a subset
+ /// class of at least one other TargetRegisterClass.
bool isASubClass() const {
return SuperClasses[0] != 0;
}
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
index af3adaafa5..cd969dc733 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
@@ -134,6 +134,12 @@ namespace llvm {
void EmitSubregNode(SDNode *Node,
DenseMap<SDValue, unsigned> &VRBaseMap);
+ /// EmitCopyToSubclassNode - Generate machine code for COPY_TO_SUBCLASS
+ /// nodes.
+ ///
+ void EmitCopyToSubclassNode(SDNode *Node,
+ DenseMap<SDValue, unsigned> &VRBaseMap);
+
/// getVR - Return the virtual register corresponding to the specified result
/// of the specified node.
unsigned getVR(SDValue Op, DenseMap<SDValue, unsigned> &VRBaseMap);
@@ -146,6 +152,13 @@ namespace llvm {
const TargetInstrDesc *II,
DenseMap<SDValue, unsigned> &VRBaseMap);
+ /// AddRegisterOperand - Add the specified register as an operand to the
+ /// specified machine instr. Insert register copies if the register is
+ /// not in the required register class.
+ void AddRegisterOperand(MachineInstr *MI, SDValue Op,
+ unsigned IIOpNum, const TargetInstrDesc *II,
+ DenseMap<SDValue, unsigned> &VRBaseMap);
+
/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
/// implicit physical register output.
void EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone,
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
index abeb7f4dbf..084ecb7555 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
@@ -93,9 +93,13 @@ void ScheduleDAGSDNodes::EmitCopyFromReg(SDNode *Node, unsigned ResNo,
getInstrOperandRegClass(TRI, II, i+II.getNumDefs());
if (!UseRC)
UseRC = RC;
- else if (RC)
- assert(UseRC == RC &&
- "Multiple uses expecting different register classes!");
+ else if (RC) {
+ if (UseRC->hasSuperClass(RC))
+ UseRC = RC;
+ else
+ assert((UseRC == RC || RC->hasSuperClass(UseRC)) &&
+ "Multiple uses expecting different register classes!");
+ }
}
}
}
@@ -127,10 +131,14 @@ void ScheduleDAGSDNodes::EmitCopyFromReg(SDNode *Node, unsigned ResNo,
VRBase = MRI.createVirtualRegister(DstRC);
bool Emitted = TII->copyRegToReg(*BB, InsertPos, VRBase, SrcReg,
DstRC, SrcRC);
- if (!Emitted) {
- cerr << "Unable to issue a copy instruction!\n";
- abort();
- }
+ // If the target didn't handle the copy with different register
+ // classes and the destination is a subset of the source,
+ // try a normal same-RC copy.
+ if (!Emitted && DstRC->hasSuperClass(SrcRC))
+ Emitted = TII->copyRegToReg(*BB, InsertPos, VRBase, SrcReg,
+ SrcRC, SrcRC);
+
+ assert(Emitted && "Unable to issue a copy instruction!\n");
}
SDValue Op(Node, ResNo);
@@ -168,9 +176,10 @@ void ScheduleDAGSDNodes::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
for (unsigned i = 0; i < II.getNumDefs(); ++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.
+ // is a vreg in the same register class, use the CopyToReg'd destination
+ // register instead of creating a new vreg.
unsigned VRBase = 0;
+ const TargetRegisterClass *RC = getInstrOperandRegClass(TRI, II, i);
if (!IsClone && !IsCloned)
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
@@ -181,9 +190,12 @@ void ScheduleDAGSDNodes::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
User->getOperand(2).getResNo() == i) {
unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
- VRBase = Reg;
- MI->addOperand(MachineOperand::CreateReg(Reg, true));
- break;
+ const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
+ if (RegRC == RC) {
+ VRBase = Reg;
+ MI->addOperand(MachineOperand::CreateReg(Reg, true));
+ break;
+ }
}
}
}
@@ -191,7 +203,6 @@ void ScheduleDAGSDNodes::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
// Create the result registers for this node and add the result regs to
// the machine instruction.
if (VRBase == 0) {
- const TargetRegisterClass *RC = getInstrOperandRegClass(TRI, II, i);
assert(RC && "Isn't a register operand!");
VRBase = MRI.createVirtualRegister(RC);
MI->addOperand(MachineOperand::CreateReg(VRBase, true));
@@ -230,6 +241,52 @@ unsigned ScheduleDAGSDNodes::getVR(SDValue Op,
}
+/// AddRegisterOperand - Add the specified register as an operand to the
+/// specified machine instr. Insert register copies if the register is
+/// not in the required register class.
+void
+ScheduleDAGSDNodes::AddRegisterOperand(MachineInstr *MI, SDValue Op,
+ unsigned IIOpNum,
+ const TargetInstrDesc *II,
+ DenseMap<SDValue, unsigned> &VRBaseMap) {
+ assert(Op.getValueType() != MVT::Other &&
+ Op.getValueType() != MVT::Flag &&
+ "Chain and flag operands should occur at end of operand list!");
+ // Get/emit the operand.
+ unsigned VReg = getVR(Op, VRBaseMap);
+ assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?");
+
+ const TargetInstrDesc &TID = MI->getDesc();
+ bool isOptDef = IIOpNum < TID.getNumOperands() &&
+ TID.OpInfo[IIOpNum].isOptionalDef();
+
+ // If the instruction requires a register in a different class, create
+ // a new virtual register and copy the value into it.
+ if (II) {
+ const TargetRegisterClass *SrcRC =
+ MRI.getRegClass(VReg);
+ const TargetRegisterClass *DstRC =
+ getInstrOperandRegClass(TRI, *II, IIOpNum);
+ assert((DstRC || (TID.isVariadic() && IIOpNum >= TID.getNumOperands())) &&
+ "Don't have operand info for this instruction!");
+ if (DstRC && SrcRC != DstRC && !SrcRC->hasSuperClass(DstRC)) {
+ unsigned NewVReg = MRI.createVirtualRegister(DstRC);
+ bool Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg,
+ DstRC, SrcRC);
+ // If the target didn't handle the copy with different register
+ // classes and the destination is a subset of the source,
+ // try a normal same-RC copy.
+ if (!Emitted && DstRC->hasSuperClass(SrcRC))
+ Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg,
+ SrcRC, SrcRC);
+ assert(Emitted && "Unable to issue a copy instruction!\n");
+ VReg = NewVReg;
+ }
+ }
+
+ MI->addOperand(MachineOperand::CreateReg(VReg, isOptDef));
+}
+
/// AddOperand - Add the specified operand to the specified machine instr. II
/// specifies the instruction information for the node, and IIOpNum is the
/// operand number (in the II) that we are adding. IIOpNum and II are used for
@@ -239,46 +296,7 @@ void ScheduleDAGSDNodes::AddOperand(MachineInstr *MI, SDValue Op,
const TargetInstrDesc *II,
DenseMap<SDValue, unsigned> &VRBaseMap) {
if (Op.isMachineOpcode()) {
- // Note that this case is redundant with the final else block, but we
- // include it because it is the most common and it makes the logic
- // simpler here.
- assert(Op.getValueType() != MVT::Other &&
- Op.getValueType() != MVT::Flag &&
- "Chain and flag operands should occur at end of operand list!");
- // Get/emit the operand.
- unsigned VReg = getVR(Op, VRBaseMap);
- const TargetInstrDesc &TID = MI->getDesc();
- bool isOptDef = IIOpNum < TID.getNumOperands() &&
- TID.OpInfo[IIOpNum].isOptionalDef();
- MI->addOperand(MachineOperand::CreateReg(VReg, isOptDef));
-
- // Verify that it is right.
- assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?");
-#ifndef NDEBUG
- if (II) {
- // There may be no register class for this operand if it is a variadic
- // argument (RC will be NULL in this case). In this case, we just assume
- // the regclass is ok.
- const TargetRegisterClass *RC= getInstrOperandRegClass(TRI, *II, IIOpNum);
- assert((RC || II->isVariadic()) && "Expected reg class info!");
- const TargetRegisterClass *VRC = MRI.getRegClass(VReg);
- if (RC && VRC != RC) {
- cerr << "Register class of operand and regclass of use don't agree!\n";
- cerr << "Operand = " << IIOpNum << "\n";
- cerr << "Op->Val = "; Op.getNode()->dump(DAG); cerr << "\n";
- cerr << "MI = "; MI->print(cerr);
- cerr << "VReg = " << VReg << "\n";
- cerr << "VReg RegClass " << VRC->getName()
- << " size = " << VRC->getSize()
- << ", align = " << VRC->getAlignment() << "\n";
- cerr << "Expected RegClass " << RC->getName()
- << " size = " << RC->getSize()
- << ", align = " << RC->getAlignment() << "\n";
- cerr << "Fatal error, aborting.\n";
- abort();
- }
- }
-#endif
+ AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap);
} else if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateImm(C->getZExtValue()));
} else if (ConstantFPSDNode *F = dyn_cast<ConstantFPSDNode>(Op)) {
@@ -288,8 +306,8 @@ void ScheduleDAGSDNodes::AddOperand(MachineInstr *MI, SDValue Op,
MI->addOperand(MachineOperand::CreateReg(R->getReg(), false));
} else if (GlobalAddressSDNode *TGA = dyn_cast<GlobalAddressSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateGA(TGA->getGlobal(),TGA->getOffset()));
- } else if (BasicBlockSDNode *BB = dyn_cast<BasicBlockSDNode>(Op)) {
- MI->addOperand(MachineOperand::CreateMBB(BB->getBasicBlock()));
+ } else if (BasicBlockSDNode *BBNode = dyn_cast<BasicBlockSDNode>(Op)) {
+ MI->addOperand(MachineOperand::CreateMBB(BBNode->getBasicBlock()));
} else if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateFI(FI->getIndex()));
} else if (JumpTableSDNode *JT = dyn_cast<JumpTableSDNode>(Op)) {
@@ -319,19 +337,35 @@ void ScheduleDAGSDNodes::AddOperand(MachineInstr *MI, SDValue Op,
assert(Op.getValueType() != MVT::Other &&
Op.getValueType() != MVT::Flag &&
"Chain and flag operands should occur at end of operand list!");
- unsigned VReg = getVR(Op, VRBaseMap);
- MI->addOperand(MachineOperand::CreateReg(VReg, false));
-
- // Verify that it is right. Note that the reg class of the physreg and the
- // vreg don't necessarily need to match, but the target copy insertion has
- // to be able to handle it. This handles things like copies from ST(0) to
- // an FP vreg on x86.
- assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?");
- if (II && !II->isVariadic()) {
- assert(getInstrOperandRegClass(TRI, *II, IIOpNum) &&
- "Don't have operand info for this instruction!");
- }
- }
+ AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap);
+ }
+}
+
+/// getSubRegisterRegClass - Returns the register class of specified register
+/// class' "SubIdx"'th sub-register class.
+static const TargetRegisterClass*
+getSubRegisterRegClass(const TargetRegisterClass *TRC, unsigned SubIdx) {
+ // Pick the register class of the subregister
+ TargetRegisterInfo::regclass_iterator I =
+ TRC->subregclasses_begin() + SubIdx-1;
+ assert(I < TRC->subregclasses_end() &&
+ "Invalid subregister index for register class");
+ return *I;
+}
+
+/// getSuperRegisterRegClass - Returns the register class of a superreg A whose
+/// "SubIdx"'th sub-register class is the specified register class and whose
+/// type matches the specified type.
+static const TargetRegisterClass*
+getSuperRegisterRegClass(const TargetRegisterClass *TRC,
+ unsigned SubIdx, MVT VT) {
+ // Pick the register class of the superegister for this type
+ for (TargetRegisterInfo::regclass_iterator I = TRC->superregclasses_begin(),
+ E = TRC->superregclasses_end(); I != E; ++I)
+ if ((*I)->hasType(VT) && getSubRegisterRegClass(*I, SubIdx) == TRC)
+ return *I;
+ assert(false && "Couldn't find the register class");
+ return 0;
}
/// EmitSubregNode - Generate machine code for subreg nodes.
@@ -364,13 +398,15 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
TII->get(TargetInstrInfo::EXTRACT_SUBREG));
// Figure out the register class to create for the destreg.
- const TargetRegisterClass *SRC = TLI->getRegClassFor(Node->getValueType(0));
+ unsigned VReg = getVR(Node->getOperand(0), VRBaseMap);
+ const TargetRegisterClass *TRC = MRI.getRegClass(VReg);
+ const TargetRegisterClass *SRC = getSubRegisterRegClass(TRC, SubIdx);
if (VRBase) {
// Grab the destination register
#ifndef NDEBUG
const TargetRegisterClass *DRC = MRI.getRegClass(VRBase);
- assert(SRC && DRC && SRC == DRC &&
+ assert(SRC && DRC && (SRC == DRC || DRC->hasSubClass(SRC)) &&
"Source subregister and destination must have the same class");
#endif
} else {
@@ -389,6 +425,7 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
SDValue N0 = Node->getOperand(0);
SDValue N1 = Node->getOperand(1);
SDValue N2 = Node->getOperand(2);
+ unsigned SubReg = getVR(N1, VRBaseMap);
unsigned SubIdx = cast<ConstantSDNode>(N2)->getZExtValue();
@@ -397,7 +434,8 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
if (VRBase) {
TRC = MRI.getRegClass(VRBase);
} else {
- TRC = TLI->getRegClassFor(Node->getValueType(0));
+ TRC = getSuperRegisterRegClass(MRI.getRegClass(SubReg), SubIdx,
+ Node->getValueType(0));
assert(TRC && "Couldn't determine register class for insert_subreg");
VRBase = MRI.createVirtualRegister(TRC); // Create the reg
}
@@ -426,6 +464,39 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
assert(isNew && "Node emitted out of order - early");
}
+/// EmitCopyToSubclassNode - Generate machine code for COPY_TO_SUBCLASS nodes.
+/// COPY_TO_SUBCLASS is just a normal copy, except that the destination
+/// register is constrained to be in a particular register class.
+///
+void
+ScheduleDAGSDNodes::EmitCopyToSubclassNode(SDNode *Node,
+ DenseMap<SDValue, unsigned> &VRBaseMap) {
+ unsigned VReg = getVR(Node->getOperand(0), VRBaseMap);
+ const TargetRegisterClass *SrcRC = MRI.getRegClass(VReg);
+
+ unsigned DstRCIdx = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
+ const TargetRegisterClass *DstRC = TRI->getRegClass(DstRCIdx);
+
+ assert(SrcRC->hasSubClass(DstRC) &&
+ "COPY_TO_SUBCLASS destination class is not a proper subclass!");
+
+ // Create the new VReg in the destination class and emit a copy.
+ unsigned NewVReg = MRI.createVirtualRegister(DstRC);
+ bool Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg,
+ DstRC, SrcRC);
+ // If the target didn't handle that, emit a plain copy.
+ if (!Emitted)
+ Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg,
+ SrcRC, SrcRC);
+ assert(Emitted &&
+ "Unable to issue a copy instruction for a COPY_TO_SUBCLASS node!\n");
+
+ SDValue Op(Node, 0);
+ bool isNew = VRBaseMap.insert(std::make_pair(Op, NewVReg)).second;
+ isNew = isNew; // Silence compiler warning.
+ assert(isNew && "Node emitted out of order - early");
+}
+
/// EmitNode - Generate machine code for an node and needed dependencies.
///
void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
@@ -442,6 +513,12 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
return;
}
+ // Handle COPY_TO_SUBCLASS specially.
+ if (Opc == TargetInstrInfo::COPY_TO_SUBCLASS) {
+ EmitCopyToSubclassNode(Node, VRBaseMap);
+ return;
+ }
+
if (Opc == TargetInstrInfo::IMPLICIT_DEF)
// We want a unique VR for each IMPLICIT_DEF use.
return;
@@ -532,12 +609,17 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
else
DstTRC = TRI->getPhysicalRegisterRegClass(DestReg,
Node->getOperand(1).getValueType());
+
bool Emitted = TII->copyRegToReg(*BB, InsertPos, DestReg, SrcReg,
DstTRC, SrcTRC);
- if (!Emitted) {
- cerr << "Unable to issue a copy instruction!\n";
- abort();
- }
+ // If the target didn't handle the copy with different register
+ // classes and the destination is a subset of the source,
+ // try a normal same-RC copy.
+ if (!Emitted && DstTRC->hasSubClass(SrcTRC))
+ Emitted = TII->copyRegToReg(*BB, InsertPos, DestReg, SrcReg,
+ DstTRC, DstTRC);
+
+ assert(Emitted && "Unable to issue a copy instruction!\n");
break;
}
case ISD::CopyFromReg: {
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index ae4a6aa445..912617bc01 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/utils/TableGen/CodeEmitterGen.cpp
@@ -33,8 +33,9 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
R->getName() == "EXTRACT_SUBREG" ||
R->getName() == "INSERT_SUBREG" ||
R->getName() == "IMPLICIT_DEF" ||
- R->getName() == "SUBREG_TO_REG") continue;
-
+ R->getName() == "SUBREG_TO_REG" ||
+ R->getName() == "COPY_TO_SUBCLASS") continue;
+
BitsInit *BI = R->getValueAsBitsInit("Inst");
unsigned numBits = BI->getNumBits();
@@ -109,7 +110,8 @@ void CodeEmitterGen::run(std::ostream &o) {
R->getName() == "EXTRACT_SUBREG" ||
R->getName() == "INSERT_SUBREG" ||
R->getName() == "IMPLICIT_DEF" ||
- R->getName() == "SUBREG_TO_REG") {
+ R->getName() == "SUBREG_TO_REG" ||
+ R->getName() == "COPY_TO_SUBCLASS") {
o << " 0U,\n";
continue;
}
@@ -146,8 +148,9 @@ void CodeEmitterGen::run(std::ostream &o) {
InstName == "EXTRACT_SUBREG" ||
InstName == "INSERT_SUBREG" ||
InstName == "IMPLICIT_DEF" ||
- InstName == "SUBREG_TO_REG") continue;
-
+ InstName == "SUBREG_TO_REG" ||
+ InstName == "COPY_TO_SUBCLASS") continue;
+
BitsInit *BI = R->getValueAsBitsInit("Inst");
const std::vector<RecordVal> &Vals = R->getValues();
CodeGenInstruction &CGI = Target.getInstruction(InstName);
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 5bb4ddb223..eb0b099048 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -884,6 +884,12 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
return MadeChange;
+ } else if (getOperator()->getName() == "COPY_TO_SUBCLASS") {
+ bool MadeChange = false;
+ MadeChange |= getChild(0)->ApplyTypeConstraints(TP, NotRegisters);
+ MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters);
+ MadeChange |= UpdateNodeType(getChild(1)->getTypeNum(0), TP);
+ return MadeChange;
} else if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {
bool MadeChange = false;
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index 9ef64d66b5..c5d4c494c0 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -344,7 +344,12 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
if (I == Instructions.end())
throw "Could not find 'SUBREG_TO_REG' instruction!";
const CodeGenInstruction *SUBREG_TO_REG = &I->second;
-
+
+ I = getInstructions().find("COPY_TO_SUBCLASS");
+ if (I == Instructions.end())
+ throw "Could not find 'COPY_TO_SUBCLASS' instruction!";
+ const CodeGenInstruction *COPY_TO_SUBCLASS = &I->second;
+
// Print out the rest of the instructions now.
NumberedInstructions.push_back(PHI);
NumberedInstructions.push_back(INLINEASM);
@@ -356,6 +361,7 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
NumberedInstructions.push_back(INSERT_SUBREG);
NumberedInstructions.push_back(IMPLICIT_DEF);
NumberedInstructions.push_back(SUBREG_TO_REG);
+ NumberedInstructions.push_back(COPY_TO_SUBCLASS);
for (inst_iterator II = inst_begin(), E = inst_end(); II != E; ++II)
if (&II->second != PHI &&
&II->second != INLINEASM &&
@@ -366,7 +372,8 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
&II->second != EXTRACT_SUBREG &&
&II->second != INSERT_SUBREG &&
&II->second != IMPLICIT_DEF &&
- &II->second != SUBREG_TO_REG)
+ &II->second != SUBREG_TO_REG &&
+ &II->second != COPY_TO_SUBCLASS)
NumberedInstructions.push_back(&II->second);
}
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 63912a1e4e..3335d00f72 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -918,6 +918,15 @@ public:
getEnumName(N->getTypeNum(0)) + ");");
NodeOps.push_back("Tmp" + utostr(ResNo));
return NodeOps;
+ } else if (DI->getDef()->isSubClassOf("RegisterClass")) {
+ // Handle a reference to a register class. This is used
+ // in COPY_TO_SUBREG instructions.
+ emitCode("SDValue Tmp" + utostr(ResNo) +
+ " = CurDAG->getTargetConstant(" +
+ getQualifiedName(DI->getDef()) + "RegClassID, " +
+ "MVT::i32);");
+ NodeOps.push_back("Tmp" + utostr(ResNo));
+ return NodeOps;
}
} else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
unsigned ResNo = TmpNo++;
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index 6201690b10..1a32828e7d 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -340,7 +340,8 @@ void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
R->getName() != "EXTRACT_SUBREG" &&
R->getName() != "INSERT_SUBREG" &&
R->getName() != "IMPLICIT_DEF" &&
- R->getName() != "SUBREG_TO_REG")
+ R->getName() != "SUBREG_TO_REG" &&
+ R->getName() != "COPY_TO_SUBCLASS")
throw R->getName() + " doesn't have a field named '" +
Val->getValue() + "'!";
return;
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index d45f565e25..3c3b2e8ff4 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -240,8 +240,85 @@ void RegisterInfoEmitter::run(std::ostream &OS) {
<< RegisterClasses[i].getName() << "RegClass;\n";
std::map<unsigned, std::set<unsigned> > SuperClassMap;
+ std::map<unsigned, std::set<unsigned> > SuperRegClassMap;
OS << "\n";
+ // Emit the sub-register classes for each RegisterClass
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = RegisterClasses[rc];
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.TheDef->getName();
+
+ OS << " // " << Name
+ << " Sub-register Classes...\n"
+ << " static const TargetRegisterClass* const "
+ << Name << "SubRegClasses [] = {\n ";
+
+ bool Empty = true;
+
+ for (unsigned subrc = 0, subrcMax = RC.SubRegClasses.size();
+ subrc != subrcMax; ++subrc) {
+ unsigned rc2 = 0, e2 = RegisterClasses.size();
+ for (; rc2 != e2; ++rc2) {
+ const CodeGenRegisterClass &RC2 = RegisterClasses[rc2];
+ if (RC.SubRegClasses[subrc]->getName() == RC2.getName()) {
+ if (!Empty)
+ OS << ", ";
+ OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
+ Empty = false;
+
+ std::map<unsigned, std::set<unsigned> >::iterator SCMI =
+ SuperRegClassMap.find(rc2);
+ if (SCMI == SuperRegClassMap.end()) {
+ SuperRegClassMap.insert(std::make_pair(rc2,
+ std::set<unsigned>()));
+ SCMI = SuperRegClassMap.find(rc2);
+ }
+ SCMI->second.insert(rc);
+ break;
+ }
+ }
+ if (rc2 == e2)
+ throw "Register Class member '" +
+ RC.SubRegClasses[subrc]->getName() +
+ "' is not a valid RegisterClass!";
+ }
+
+ OS << (!Empty ? ", " : "") << "NULL";
+ OS << "\n };\n\n";
+ }
+
+ // Emit the super-register classes for each RegisterClass
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = RegisterClasses[rc];
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.TheDef->getName();
+
+ OS << " // " << Name
+ << " Super-register Classes...\n"
+ << " static const TargetRegisterClass* const "
+ << Name << "SuperRegClasses [] = {\n ";
+
+ bool Empty = true;
+ std::map<unsigned, std::set<unsigned> >::iterator I =
+ SuperRegClassMap.find(rc);
+ if (I != SuperRegClassMap.end()) {
+ for (std::set<unsigned>::iterator II = I->second.begin(),
+ EE = I->second.end(); II != EE; ++II) {
+ const CodeGenRegisterClass &RC2 = RegisterClasses[*II];
+ if (!Empty)
+ OS << ", ";
+ OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
+ Empty = false;
+ }
+ }
+
+ OS << (!Empty ? ", " : "") << "NULL";
+ OS << "\n };\n\n";
+ }
+
// Emit the sub-classes array for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
const CodeGenRegisterClass &RC = RegisterClasses[rc];
@@ -323,6 +400,8 @@ void RegisterInfoEmitter::run(std::ostream &OS) {
<< RC.getName() + "VTs" << ", "
<< RC.getName() + "Subclasses" << ", "
<< RC.getName() + "Superclasses" << ", "
+ << RC.getName() + "SubRegClasses" << ", "
+ << RC.getName() + "SuperRegClasses" << ", "
<< RC.SpillSize/8 << ", "
<< RC.SpillAlignment/8 << ", "
<< RC.CopyCost << ", "