mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-27 00:21:03 +00:00
Add a new TargetInstrInfo MachineInstr opcode, COPY_TO_SUBCLASS.
This will be used to replace things like X86's MOV32to32_. Enhance ScheduleDAGSDNodesEmit to be more flexible and robust in the presense of subregister superclasses and subclasses. It can now cope with the definition of a virtual register being in a subclass of a use. Re-introduce the code for recording register superreg classes and subreg classes. This is needed because when subreg extracts and inserts get coalesced away, the virtual registers are left in the correct subclass. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@68961 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -400,6 +400,14 @@ def SUBREG_TO_REG : Instruction {
|
|||||||
let Namespace = "TargetInstrInfo";
|
let Namespace = "TargetInstrInfo";
|
||||||
let neverHasSideEffects = 1;
|
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
|
// AsmWriter - This class can be implemented by targets that need to customize
|
||||||
|
@@ -73,7 +73,14 @@ public:
|
|||||||
/// is often zero, as is commonly used to implement zext operations on
|
/// is often zero, as is commonly used to implement zext operations on
|
||||||
/// target architectures which support it, such as with x86-64 (with
|
/// target architectures which support it, such as with x86-64 (with
|
||||||
/// zext from i32 to i64 via implicit zero-extension).
|
/// 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; }
|
unsigned getNumOpcodes() const { return NumOpcodes; }
|
||||||
|
@@ -62,6 +62,8 @@ private:
|
|||||||
const vt_iterator VTs;
|
const vt_iterator VTs;
|
||||||
const sc_iterator SubClasses;
|
const sc_iterator SubClasses;
|
||||||
const sc_iterator SuperClasses;
|
const sc_iterator SuperClasses;
|
||||||
|
const sc_iterator SubRegClasses;
|
||||||
|
const sc_iterator SuperRegClasses;
|
||||||
const unsigned RegSize, Alignment; // Size & Alignment of register in bytes
|
const unsigned RegSize, Alignment; // Size & Alignment of register in bytes
|
||||||
const int CopyCost;
|
const int CopyCost;
|
||||||
const iterator RegsBegin, RegsEnd;
|
const iterator RegsBegin, RegsEnd;
|
||||||
@@ -72,9 +74,12 @@ public:
|
|||||||
const MVT *vts,
|
const MVT *vts,
|
||||||
const TargetRegisterClass * const *subcs,
|
const TargetRegisterClass * const *subcs,
|
||||||
const TargetRegisterClass * const *supcs,
|
const TargetRegisterClass * const *supcs,
|
||||||
|
const TargetRegisterClass * const *subregcs,
|
||||||
|
const TargetRegisterClass * const *superregcs,
|
||||||
unsigned RS, unsigned Al, int CC,
|
unsigned RS, unsigned Al, int CC,
|
||||||
iterator RB, iterator RE)
|
iterator RB, iterator RE)
|
||||||
: ID(id), Name(name), VTs(vts), SubClasses(subcs), SuperClasses(supcs),
|
: ID(id), Name(name), VTs(vts), SubClasses(subcs), SuperClasses(supcs),
|
||||||
|
SubRegClasses(subregcs), SuperRegClasses(superregcs),
|
||||||
RegSize(RS), Alignment(Al), CopyCost(CC), RegsBegin(RB), RegsEnd(RE) {
|
RegSize(RS), Alignment(Al), CopyCost(CC), RegsBegin(RB), RegsEnd(RE) {
|
||||||
for (iterator I = RegsBegin, E = RegsEnd; I != E; ++I)
|
for (iterator I = RegsBegin, E = RegsEnd; I != E; ++I)
|
||||||
RegSet.insert(*I);
|
RegSet.insert(*I);
|
||||||
@@ -132,8 +137,32 @@ public:
|
|||||||
return I;
|
return I;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// hasSubClass - return true if the specified TargetRegisterClass is a
|
/// subregclasses_begin / subregclasses_end - Loop over all of
|
||||||
/// sub-register class of this TargetRegisterClass.
|
/// 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 {
|
bool hasSubClass(const TargetRegisterClass *cs) const {
|
||||||
for (int i = 0; SubClasses[i] != NULL; ++i)
|
for (int i = 0; SubClasses[i] != NULL; ++i)
|
||||||
if (SubClasses[i] == cs)
|
if (SubClasses[i] == cs)
|
||||||
@@ -141,8 +170,8 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// subclasses_begin / subclasses_end - Loop over all of the sub-classes of
|
/// subclasses_begin / subclasses_end - Loop over all of the classes
|
||||||
/// this register class.
|
/// that are proper subsets of this register class.
|
||||||
sc_iterator subclasses_begin() const {
|
sc_iterator subclasses_begin() const {
|
||||||
return SubClasses;
|
return SubClasses;
|
||||||
}
|
}
|
||||||
@@ -154,7 +183,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// hasSuperClass - return true if the specified TargetRegisterClass is a
|
/// 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 {
|
bool hasSuperClass(const TargetRegisterClass *cs) const {
|
||||||
for (int i = 0; SuperClasses[i] != NULL; ++i)
|
for (int i = 0; SuperClasses[i] != NULL; ++i)
|
||||||
if (SuperClasses[i] == cs)
|
if (SuperClasses[i] == cs)
|
||||||
@@ -162,8 +191,8 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// superclasses_begin / superclasses_end - Loop over all of the super-classes
|
/// superclasses_begin / superclasses_end - Loop over all of the classes
|
||||||
/// of this register class.
|
/// that are proper supersets of this register class.
|
||||||
sc_iterator superclasses_begin() const {
|
sc_iterator superclasses_begin() const {
|
||||||
return SuperClasses;
|
return SuperClasses;
|
||||||
}
|
}
|
||||||
@@ -174,8 +203,8 @@ public:
|
|||||||
return I;
|
return I;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isASubClass - return true if this TargetRegisterClass is a sub-class of at
|
/// isASubClass - return true if this TargetRegisterClass is a subset
|
||||||
/// least one other TargetRegisterClass.
|
/// class of at least one other TargetRegisterClass.
|
||||||
bool isASubClass() const {
|
bool isASubClass() const {
|
||||||
return SuperClasses[0] != 0;
|
return SuperClasses[0] != 0;
|
||||||
}
|
}
|
||||||
|
@@ -134,6 +134,12 @@ namespace llvm {
|
|||||||
void EmitSubregNode(SDNode *Node,
|
void EmitSubregNode(SDNode *Node,
|
||||||
DenseMap<SDValue, unsigned> &VRBaseMap);
|
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
|
/// getVR - Return the virtual register corresponding to the specified result
|
||||||
/// of the specified node.
|
/// of the specified node.
|
||||||
unsigned getVR(SDValue Op, DenseMap<SDValue, unsigned> &VRBaseMap);
|
unsigned getVR(SDValue Op, DenseMap<SDValue, unsigned> &VRBaseMap);
|
||||||
@@ -146,6 +152,13 @@ namespace llvm {
|
|||||||
const TargetInstrDesc *II,
|
const TargetInstrDesc *II,
|
||||||
DenseMap<SDValue, unsigned> &VRBaseMap);
|
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
|
/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
|
||||||
/// implicit physical register output.
|
/// implicit physical register output.
|
||||||
void EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone,
|
void EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone,
|
||||||
|
@@ -93,9 +93,13 @@ void ScheduleDAGSDNodes::EmitCopyFromReg(SDNode *Node, unsigned ResNo,
|
|||||||
getInstrOperandRegClass(TRI, II, i+II.getNumDefs());
|
getInstrOperandRegClass(TRI, II, i+II.getNumDefs());
|
||||||
if (!UseRC)
|
if (!UseRC)
|
||||||
UseRC = RC;
|
UseRC = RC;
|
||||||
else if (RC)
|
else if (RC) {
|
||||||
assert(UseRC == RC &&
|
if (UseRC->hasSuperClass(RC))
|
||||||
"Multiple uses expecting different register classes!");
|
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);
|
VRBase = MRI.createVirtualRegister(DstRC);
|
||||||
bool Emitted = TII->copyRegToReg(*BB, InsertPos, VRBase, SrcReg,
|
bool Emitted = TII->copyRegToReg(*BB, InsertPos, VRBase, SrcReg,
|
||||||
DstRC, SrcRC);
|
DstRC, SrcRC);
|
||||||
if (!Emitted) {
|
// If the target didn't handle the copy with different register
|
||||||
cerr << "Unable to issue a copy instruction!\n";
|
// classes and the destination is a subset of the source,
|
||||||
abort();
|
// 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);
|
SDValue Op(Node, ResNo);
|
||||||
@@ -168,9 +176,10 @@ void ScheduleDAGSDNodes::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
|
|||||||
|
|
||||||
for (unsigned i = 0; i < II.getNumDefs(); ++i) {
|
for (unsigned i = 0; i < II.getNumDefs(); ++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 in the same register class, use the CopyToReg'd destination
|
||||||
// a new vreg.
|
// register instead of creating a new vreg.
|
||||||
unsigned VRBase = 0;
|
unsigned VRBase = 0;
|
||||||
|
const TargetRegisterClass *RC = getInstrOperandRegClass(TRI, II, i);
|
||||||
|
|
||||||
if (!IsClone && !IsCloned)
|
if (!IsClone && !IsCloned)
|
||||||
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
|
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) {
|
User->getOperand(2).getResNo() == i) {
|
||||||
unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
|
unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
|
||||||
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
|
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
|
||||||
VRBase = Reg;
|
const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
|
||||||
MI->addOperand(MachineOperand::CreateReg(Reg, true));
|
if (RegRC == RC) {
|
||||||
break;
|
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
|
// Create the result registers for this node and add the result regs to
|
||||||
// the machine instruction.
|
// the machine instruction.
|
||||||
if (VRBase == 0) {
|
if (VRBase == 0) {
|
||||||
const TargetRegisterClass *RC = getInstrOperandRegClass(TRI, II, i);
|
|
||||||
assert(RC && "Isn't a register operand!");
|
assert(RC && "Isn't a register operand!");
|
||||||
VRBase = MRI.createVirtualRegister(RC);
|
VRBase = MRI.createVirtualRegister(RC);
|
||||||
MI->addOperand(MachineOperand::CreateReg(VRBase, true));
|
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
|
/// AddOperand - Add the specified operand to the specified machine instr. II
|
||||||
/// specifies the instruction information for the node, and IIOpNum is the
|
/// 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
|
/// 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,
|
const TargetInstrDesc *II,
|
||||||
DenseMap<SDValue, unsigned> &VRBaseMap) {
|
DenseMap<SDValue, unsigned> &VRBaseMap) {
|
||||||
if (Op.isMachineOpcode()) {
|
if (Op.isMachineOpcode()) {
|
||||||
// Note that this case is redundant with the final else block, but we
|
AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap);
|
||||||
// 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
|
|
||||||
} else if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
|
} else if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
|
||||||
MI->addOperand(MachineOperand::CreateImm(C->getZExtValue()));
|
MI->addOperand(MachineOperand::CreateImm(C->getZExtValue()));
|
||||||
} else if (ConstantFPSDNode *F = dyn_cast<ConstantFPSDNode>(Op)) {
|
} 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));
|
MI->addOperand(MachineOperand::CreateReg(R->getReg(), false));
|
||||||
} else if (GlobalAddressSDNode *TGA = dyn_cast<GlobalAddressSDNode>(Op)) {
|
} else if (GlobalAddressSDNode *TGA = dyn_cast<GlobalAddressSDNode>(Op)) {
|
||||||
MI->addOperand(MachineOperand::CreateGA(TGA->getGlobal(),TGA->getOffset()));
|
MI->addOperand(MachineOperand::CreateGA(TGA->getGlobal(),TGA->getOffset()));
|
||||||
} else if (BasicBlockSDNode *BB = dyn_cast<BasicBlockSDNode>(Op)) {
|
} else if (BasicBlockSDNode *BBNode = dyn_cast<BasicBlockSDNode>(Op)) {
|
||||||
MI->addOperand(MachineOperand::CreateMBB(BB->getBasicBlock()));
|
MI->addOperand(MachineOperand::CreateMBB(BBNode->getBasicBlock()));
|
||||||
} else if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op)) {
|
} else if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op)) {
|
||||||
MI->addOperand(MachineOperand::CreateFI(FI->getIndex()));
|
MI->addOperand(MachineOperand::CreateFI(FI->getIndex()));
|
||||||
} else if (JumpTableSDNode *JT = dyn_cast<JumpTableSDNode>(Op)) {
|
} else if (JumpTableSDNode *JT = dyn_cast<JumpTableSDNode>(Op)) {
|
||||||
@@ -319,19 +337,35 @@ void ScheduleDAGSDNodes::AddOperand(MachineInstr *MI, SDValue Op,
|
|||||||
assert(Op.getValueType() != MVT::Other &&
|
assert(Op.getValueType() != MVT::Other &&
|
||||||
Op.getValueType() != MVT::Flag &&
|
Op.getValueType() != MVT::Flag &&
|
||||||
"Chain and flag operands should occur at end of operand list!");
|
"Chain and flag operands should occur at end of operand list!");
|
||||||
unsigned VReg = getVR(Op, VRBaseMap);
|
AddRegisterOperand(MI, Op, IIOpNum, II, 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
|
/// getSubRegisterRegClass - Returns the register class of specified register
|
||||||
// to be able to handle it. This handles things like copies from ST(0) to
|
/// class' "SubIdx"'th sub-register class.
|
||||||
// an FP vreg on x86.
|
static const TargetRegisterClass*
|
||||||
assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?");
|
getSubRegisterRegClass(const TargetRegisterClass *TRC, unsigned SubIdx) {
|
||||||
if (II && !II->isVariadic()) {
|
// Pick the register class of the subregister
|
||||||
assert(getInstrOperandRegClass(TRI, *II, IIOpNum) &&
|
TargetRegisterInfo::regclass_iterator I =
|
||||||
"Don't have operand info for this instruction!");
|
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.
|
/// EmitSubregNode - Generate machine code for subreg nodes.
|
||||||
@@ -364,13 +398,15 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
|
|||||||
TII->get(TargetInstrInfo::EXTRACT_SUBREG));
|
TII->get(TargetInstrInfo::EXTRACT_SUBREG));
|
||||||
|
|
||||||
// Figure out the register class to create for the destreg.
|
// 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) {
|
if (VRBase) {
|
||||||
// Grab the destination register
|
// Grab the destination register
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
const TargetRegisterClass *DRC = MRI.getRegClass(VRBase);
|
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");
|
"Source subregister and destination must have the same class");
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
@@ -389,6 +425,7 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
|
|||||||
SDValue N0 = Node->getOperand(0);
|
SDValue N0 = Node->getOperand(0);
|
||||||
SDValue N1 = Node->getOperand(1);
|
SDValue N1 = Node->getOperand(1);
|
||||||
SDValue N2 = Node->getOperand(2);
|
SDValue N2 = Node->getOperand(2);
|
||||||
|
unsigned SubReg = getVR(N1, VRBaseMap);
|
||||||
unsigned SubIdx = cast<ConstantSDNode>(N2)->getZExtValue();
|
unsigned SubIdx = cast<ConstantSDNode>(N2)->getZExtValue();
|
||||||
|
|
||||||
|
|
||||||
@@ -397,7 +434,8 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
|
|||||||
if (VRBase) {
|
if (VRBase) {
|
||||||
TRC = MRI.getRegClass(VRBase);
|
TRC = MRI.getRegClass(VRBase);
|
||||||
} else {
|
} 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");
|
assert(TRC && "Couldn't determine register class for insert_subreg");
|
||||||
VRBase = MRI.createVirtualRegister(TRC); // Create the reg
|
VRBase = MRI.createVirtualRegister(TRC); // Create the reg
|
||||||
}
|
}
|
||||||
@@ -426,6 +464,39 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
|
|||||||
assert(isNew && "Node emitted out of order - early");
|
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.
|
/// EmitNode - Generate machine code for an node and needed dependencies.
|
||||||
///
|
///
|
||||||
void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
|
void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
|
||||||
@@ -442,6 +513,12 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle COPY_TO_SUBCLASS specially.
|
||||||
|
if (Opc == TargetInstrInfo::COPY_TO_SUBCLASS) {
|
||||||
|
EmitCopyToSubclassNode(Node, VRBaseMap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (Opc == TargetInstrInfo::IMPLICIT_DEF)
|
if (Opc == TargetInstrInfo::IMPLICIT_DEF)
|
||||||
// We want a unique VR for each IMPLICIT_DEF use.
|
// We want a unique VR for each IMPLICIT_DEF use.
|
||||||
return;
|
return;
|
||||||
@@ -532,12 +609,17 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
|
|||||||
else
|
else
|
||||||
DstTRC = TRI->getPhysicalRegisterRegClass(DestReg,
|
DstTRC = TRI->getPhysicalRegisterRegClass(DestReg,
|
||||||
Node->getOperand(1).getValueType());
|
Node->getOperand(1).getValueType());
|
||||||
|
|
||||||
bool Emitted = TII->copyRegToReg(*BB, InsertPos, DestReg, SrcReg,
|
bool Emitted = TII->copyRegToReg(*BB, InsertPos, DestReg, SrcReg,
|
||||||
DstTRC, SrcTRC);
|
DstTRC, SrcTRC);
|
||||||
if (!Emitted) {
|
// If the target didn't handle the copy with different register
|
||||||
cerr << "Unable to issue a copy instruction!\n";
|
// classes and the destination is a subset of the source,
|
||||||
abort();
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
case ISD::CopyFromReg: {
|
case ISD::CopyFromReg: {
|
||||||
|
@@ -33,8 +33,9 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
|
|||||||
R->getName() == "EXTRACT_SUBREG" ||
|
R->getName() == "EXTRACT_SUBREG" ||
|
||||||
R->getName() == "INSERT_SUBREG" ||
|
R->getName() == "INSERT_SUBREG" ||
|
||||||
R->getName() == "IMPLICIT_DEF" ||
|
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");
|
BitsInit *BI = R->getValueAsBitsInit("Inst");
|
||||||
|
|
||||||
unsigned numBits = BI->getNumBits();
|
unsigned numBits = BI->getNumBits();
|
||||||
@@ -109,7 +110,8 @@ void CodeEmitterGen::run(std::ostream &o) {
|
|||||||
R->getName() == "EXTRACT_SUBREG" ||
|
R->getName() == "EXTRACT_SUBREG" ||
|
||||||
R->getName() == "INSERT_SUBREG" ||
|
R->getName() == "INSERT_SUBREG" ||
|
||||||
R->getName() == "IMPLICIT_DEF" ||
|
R->getName() == "IMPLICIT_DEF" ||
|
||||||
R->getName() == "SUBREG_TO_REG") {
|
R->getName() == "SUBREG_TO_REG" ||
|
||||||
|
R->getName() == "COPY_TO_SUBCLASS") {
|
||||||
o << " 0U,\n";
|
o << " 0U,\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -146,8 +148,9 @@ void CodeEmitterGen::run(std::ostream &o) {
|
|||||||
InstName == "EXTRACT_SUBREG" ||
|
InstName == "EXTRACT_SUBREG" ||
|
||||||
InstName == "INSERT_SUBREG" ||
|
InstName == "INSERT_SUBREG" ||
|
||||||
InstName == "IMPLICIT_DEF" ||
|
InstName == "IMPLICIT_DEF" ||
|
||||||
InstName == "SUBREG_TO_REG") continue;
|
InstName == "SUBREG_TO_REG" ||
|
||||||
|
InstName == "COPY_TO_SUBCLASS") continue;
|
||||||
|
|
||||||
BitsInit *BI = R->getValueAsBitsInit("Inst");
|
BitsInit *BI = R->getValueAsBitsInit("Inst");
|
||||||
const std::vector<RecordVal> &Vals = R->getValues();
|
const std::vector<RecordVal> &Vals = R->getValues();
|
||||||
CodeGenInstruction &CGI = Target.getInstruction(InstName);
|
CodeGenInstruction &CGI = Target.getInstruction(InstName);
|
||||||
|
@@ -884,6 +884,12 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
|
|||||||
MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
|
MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
|
||||||
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
|
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
|
||||||
return MadeChange;
|
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)) {
|
} else if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {
|
||||||
bool MadeChange = false;
|
bool MadeChange = false;
|
||||||
|
|
||||||
|
@@ -344,7 +344,12 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
|
|||||||
if (I == Instructions.end())
|
if (I == Instructions.end())
|
||||||
throw "Could not find 'SUBREG_TO_REG' instruction!";
|
throw "Could not find 'SUBREG_TO_REG' instruction!";
|
||||||
const CodeGenInstruction *SUBREG_TO_REG = &I->second;
|
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.
|
// Print out the rest of the instructions now.
|
||||||
NumberedInstructions.push_back(PHI);
|
NumberedInstructions.push_back(PHI);
|
||||||
NumberedInstructions.push_back(INLINEASM);
|
NumberedInstructions.push_back(INLINEASM);
|
||||||
@@ -356,6 +361,7 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
|
|||||||
NumberedInstructions.push_back(INSERT_SUBREG);
|
NumberedInstructions.push_back(INSERT_SUBREG);
|
||||||
NumberedInstructions.push_back(IMPLICIT_DEF);
|
NumberedInstructions.push_back(IMPLICIT_DEF);
|
||||||
NumberedInstructions.push_back(SUBREG_TO_REG);
|
NumberedInstructions.push_back(SUBREG_TO_REG);
|
||||||
|
NumberedInstructions.push_back(COPY_TO_SUBCLASS);
|
||||||
for (inst_iterator II = inst_begin(), E = inst_end(); II != E; ++II)
|
for (inst_iterator II = inst_begin(), E = inst_end(); II != E; ++II)
|
||||||
if (&II->second != PHI &&
|
if (&II->second != PHI &&
|
||||||
&II->second != INLINEASM &&
|
&II->second != INLINEASM &&
|
||||||
@@ -366,7 +372,8 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
|
|||||||
&II->second != EXTRACT_SUBREG &&
|
&II->second != EXTRACT_SUBREG &&
|
||||||
&II->second != INSERT_SUBREG &&
|
&II->second != INSERT_SUBREG &&
|
||||||
&II->second != IMPLICIT_DEF &&
|
&II->second != IMPLICIT_DEF &&
|
||||||
&II->second != SUBREG_TO_REG)
|
&II->second != SUBREG_TO_REG &&
|
||||||
|
&II->second != COPY_TO_SUBCLASS)
|
||||||
NumberedInstructions.push_back(&II->second);
|
NumberedInstructions.push_back(&II->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -918,6 +918,15 @@ public:
|
|||||||
getEnumName(N->getTypeNum(0)) + ");");
|
getEnumName(N->getTypeNum(0)) + ");");
|
||||||
NodeOps.push_back("Tmp" + utostr(ResNo));
|
NodeOps.push_back("Tmp" + utostr(ResNo));
|
||||||
return NodeOps;
|
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())) {
|
} else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
|
||||||
unsigned ResNo = TmpNo++;
|
unsigned ResNo = TmpNo++;
|
||||||
|
@@ -340,7 +340,8 @@ void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
|
|||||||
R->getName() != "EXTRACT_SUBREG" &&
|
R->getName() != "EXTRACT_SUBREG" &&
|
||||||
R->getName() != "INSERT_SUBREG" &&
|
R->getName() != "INSERT_SUBREG" &&
|
||||||
R->getName() != "IMPLICIT_DEF" &&
|
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 '" +
|
throw R->getName() + " doesn't have a field named '" +
|
||||||
Val->getValue() + "'!";
|
Val->getValue() + "'!";
|
||||||
return;
|
return;
|
||||||
|
@@ -240,8 +240,85 @@ void RegisterInfoEmitter::run(std::ostream &OS) {
|
|||||||
<< RegisterClasses[i].getName() << "RegClass;\n";
|
<< RegisterClasses[i].getName() << "RegClass;\n";
|
||||||
|
|
||||||
std::map<unsigned, std::set<unsigned> > SuperClassMap;
|
std::map<unsigned, std::set<unsigned> > SuperClassMap;
|
||||||
|
std::map<unsigned, std::set<unsigned> > SuperRegClassMap;
|
||||||
OS << "\n";
|
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
|
// Emit the sub-classes array for each RegisterClass
|
||||||
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
|
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
|
||||||
const CodeGenRegisterClass &RC = RegisterClasses[rc];
|
const CodeGenRegisterClass &RC = RegisterClasses[rc];
|
||||||
@@ -323,6 +400,8 @@ void RegisterInfoEmitter::run(std::ostream &OS) {
|
|||||||
<< RC.getName() + "VTs" << ", "
|
<< RC.getName() + "VTs" << ", "
|
||||||
<< RC.getName() + "Subclasses" << ", "
|
<< RC.getName() + "Subclasses" << ", "
|
||||||
<< RC.getName() + "Superclasses" << ", "
|
<< RC.getName() + "Superclasses" << ", "
|
||||||
|
<< RC.getName() + "SubRegClasses" << ", "
|
||||||
|
<< RC.getName() + "SuperRegClasses" << ", "
|
||||||
<< RC.SpillSize/8 << ", "
|
<< RC.SpillSize/8 << ", "
|
||||||
<< RC.SpillAlignment/8 << ", "
|
<< RC.SpillAlignment/8 << ", "
|
||||||
<< RC.CopyCost << ", "
|
<< RC.CopyCost << ", "
|
||||||
|
Reference in New Issue
Block a user