diff options
-rw-r--r-- | include/llvm/Target/Target.td | 8 | ||||
-rw-r--r-- | include/llvm/Target/TargetInstrInfo.h | 9 | ||||
-rw-r--r-- | include/llvm/Target/TargetRegisterInfo.h | 47 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h | 13 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp | 232 | ||||
-rw-r--r-- | utils/TableGen/CodeEmitterGen.cpp | 13 | ||||
-rw-r--r-- | utils/TableGen/CodeGenDAGPatterns.cpp | 6 | ||||
-rw-r--r-- | utils/TableGen/CodeGenTarget.cpp | 11 | ||||
-rw-r--r-- | utils/TableGen/DAGISelEmitter.cpp | 9 | ||||
-rw-r--r-- | utils/TableGen/InstrInfoEmitter.cpp | 3 | ||||
-rw-r--r-- | utils/TableGen/RegisterInfoEmitter.cpp | 79 |
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 << ", " |