aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/SelectionDAG
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-04-13 15:38:05 +0000
committerDan Gohman <gohman@apple.com>2009-04-13 15:38:05 +0000
commitf8c7394781f7cf27ac52ca087e289436d36844da (patch)
treeedffc35fe9d9eb709e5582e809b3ad24363847fa /lib/CodeGen/SelectionDAG
parent8433df36fb9566a00e643a6cb8f5e77af453ea81 (diff)
downloadexternal_llvm-f8c7394781f7cf27ac52ca087e289436d36844da.zip
external_llvm-f8c7394781f7cf27ac52ca087e289436d36844da.tar.gz
external_llvm-f8c7394781f7cf27ac52ca087e289436d36844da.tar.bz2
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
Diffstat (limited to 'lib/CodeGen/SelectionDAG')
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h13
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp232
2 files changed, 170 insertions, 75 deletions
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
index af3adaa..cd969dc 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 abeb7f4..084ecb7 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: {